ngwr 14.7.0 → 14.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +66 -332
- package/alert/styles/_index.scss +10 -0
- package/avatar/styles/_index.scss +18 -7
- package/badge/styles/_index.scss +7 -0
- package/badge/styles/_tag.scss +7 -1
- package/bar-chart/styles/_index.scss +1 -0
- package/button/styles/_index.scss +6 -0
- package/calendar-heatmap/styles/_index.scss +1 -0
- package/cascader/styles/_rules.scss +87 -15
- package/checkbox/styles/_index.scss +4 -0
- package/command-palette/styles/_index.scss +1 -1
- package/date-picker/styles/_index.scss +30 -0
- package/density/styles/_index.scss +4 -2
- package/divider/styles/_index.scss +2 -0
- package/donut-chart/styles/_index.scss +10 -0
- package/dropdown/styles/_index.scss +67 -5
- package/editor/styles/_index.scss +441 -0
- package/event-calendar/styles/_index.scss +209 -35
- package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -1
- package/fesm2022/ngwr-action-sheet.mjs +3 -3
- package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-affix.mjs.map +1 -1
- package/fesm2022/ngwr-alert.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-anchor.mjs.map +1 -1
- package/fesm2022/ngwr-aurora.mjs +3 -3
- package/fesm2022/ngwr-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-badge.mjs +28 -13
- package/fesm2022/ngwr-badge.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart.mjs +31 -6
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text.mjs +3 -3
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +3 -3
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +6 -6
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-burger.mjs.map +1 -1
- package/fesm2022/ngwr-button-testing.mjs.map +1 -1
- package/fesm2022/ngwr-button.mjs +6 -6
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +61 -6
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +3 -3
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +9 -9
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel-testing.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +6 -6
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader-testing.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +4 -4
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +18 -8
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +3 -3
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +3 -3
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-clipboard.mjs.map +1 -1
- package/fesm2022/ngwr-collapse-testing.mjs.map +1 -1
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-collapse.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker.mjs +6 -6
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +3 -3
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-compare.mjs.map +1 -1
- package/fesm2022/ngwr-confetti.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs.map +1 -1
- package/fesm2022/ngwr-config.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu.mjs +12 -12
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-cookie.mjs.map +1 -1
- package/fesm2022/ngwr-counter.mjs +6 -6
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapters-fns.mjs +3 -3
- package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
- package/fesm2022/ngwr-date-adapters-luxon.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +721 -62
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-date.mjs +3 -3
- package/fesm2022/ngwr-date.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
- package/fesm2022/ngwr-density.mjs +6 -6
- package/fesm2022/ngwr-density.mjs.map +1 -1
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-descriptions.mjs.map +1 -1
- package/fesm2022/ngwr-dialog-testing.mjs.map +1 -1
- package/fesm2022/ngwr-dialog.mjs +15 -15
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-directives.mjs.map +1 -1
- package/fesm2022/ngwr-divider.mjs +3 -3
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +48 -6
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +6 -6
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer-testing.mjs.map +1 -1
- package/fesm2022/ngwr-drawer.mjs +18 -18
- package/fesm2022/ngwr-drawer.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +174 -25
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-editor-testing.mjs +568 -0
- package/fesm2022/ngwr-editor-testing.mjs.map +1 -0
- package/fesm2022/ngwr-editor.mjs +2601 -0
- package/fesm2022/ngwr-editor.mjs.map +1 -0
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-empty.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +14 -7
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +3 -3
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +3 -3
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-form-testing.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +61 -10
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge-testing.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +35 -6
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +3 -3
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +3 -3
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-graph-testing.mjs.map +1 -1
- package/fesm2022/ngwr-graph.mjs +6 -6
- package/fesm2022/ngwr-graph.mjs.map +1 -1
- package/fesm2022/ngwr-hotkey.mjs +6 -6
- package/fesm2022/ngwr-hotkey.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ar.mjs +31 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +31 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +31 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +39 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +31 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +31 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +31 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +31 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +31 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +31 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +31 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +31 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +31 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +31 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +31 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +31 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +31 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +31 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +31 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +31 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-TW.mjs +31 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +31 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +9 -9
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -1
- package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-icon.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +3 -3
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +15 -3
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +3 -3
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +15 -15
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-keyboard.mjs.map +1 -1
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +3 -3
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-layout.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +3 -3
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +18 -7
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +6 -6
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar-router.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +6 -6
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown-testing.mjs.map +1 -1
- package/fesm2022/ngwr-markdown.mjs +798 -17
- package/fesm2022/ngwr-markdown.mjs.map +1 -1
- package/fesm2022/ngwr-marquee-testing.mjs.map +1 -1
- package/fesm2022/ngwr-marquee.mjs +3 -3
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-media.mjs.map +1 -1
- package/fesm2022/ngwr-mention-testing.mjs.map +1 -1
- package/fesm2022/ngwr-mention.mjs +6 -6
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-meta.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group-testing.mjs +7 -3
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +26 -6
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-overlay.mjs +6 -6
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +13 -5
- package/fesm2022/ngwr-page-header.mjs.map +1 -1
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +3 -3
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-platform.mjs +9 -9
- package/fesm2022/ngwr-platform.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +578 -16
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-progress.mjs.map +1 -1
- package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
- package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
- package/fesm2022/ngwr-qr.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio-testing.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-radio.mjs.map +1 -1
- package/fesm2022/ngwr-rating-testing.mjs.map +1 -1
- package/fesm2022/ngwr-rating.mjs +3 -3
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-result.mjs +12 -12
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text.mjs +3 -3
- package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
- package/fesm2022/ngwr-schema-form.mjs +3 -3
- package/fesm2022/ngwr-schema-form.mjs.map +1 -1
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-segmented-testing.mjs.map +1 -1
- package/fesm2022/ngwr-segmented.mjs +3 -3
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select-testing.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +12 -12
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +6 -6
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +10 -3
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-skeleton.mjs.map +1 -1
- package/fesm2022/ngwr-slider-testing.mjs.map +1 -1
- package/fesm2022/ngwr-slider.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +84 -10
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +3 -3
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
- package/fesm2022/ngwr-split-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-split-text.mjs +3 -3
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter-testing.mjs.map +1 -1
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-splitter.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card.mjs +6 -6
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +6 -6
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-star-border-testing.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +3 -3
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +9 -9
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +6 -6
- package/fesm2022/ngwr-stepper.mjs.map +1 -1
- package/fesm2022/ngwr-storage.mjs +3 -3
- package/fesm2022/ngwr-storage.mjs.map +1 -1
- package/fesm2022/ngwr-switch-testing.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table-testing.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +18 -18
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-router.mjs +3 -3
- package/fesm2022/ngwr-tabs-router.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +6 -6
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea-testing.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +3 -3
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-theme.mjs +3 -3
- package/fesm2022/ngwr-theme.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +6 -6
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-timeline.mjs.map +1 -1
- package/fesm2022/ngwr-toast-testing.mjs.map +1 -1
- package/fesm2022/ngwr-toast.mjs +9 -9
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +10 -3
- package/fesm2022/ngwr-toolbar.mjs.map +1 -1
- package/fesm2022/ngwr-tour-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tour.mjs +6 -6
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer-testing.mjs.map +1 -1
- package/fesm2022/ngwr-transfer.mjs +3 -3
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +3 -3
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +3 -3
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-typography.mjs +7 -3
- package/fesm2022/ngwr-typography.mjs.map +1 -1
- package/fesm2022/ngwr-utils.mjs.map +1 -1
- package/fesm2022/ngwr-validators.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves-testing.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +3 -3
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window-testing.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +12 -12
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/form/styles/_index.scss +16 -1
- package/gauge/styles/_index.scss +1 -0
- package/i18n/ar.json +32 -1
- package/i18n/cs.json +32 -1
- package/i18n/de.json +32 -1
- package/i18n/en.json +32 -1
- package/i18n/es.json +32 -1
- package/i18n/fr.json +32 -1
- package/i18n/he.json +32 -1
- package/i18n/hi.json +32 -1
- package/i18n/id.json +32 -1
- package/i18n/it.json +32 -1
- package/i18n/ja.json +32 -1
- package/i18n/ko.json +32 -1
- package/i18n/nl.json +32 -1
- package/i18n/pl.json +32 -1
- package/i18n/pt.json +32 -1
- package/i18n/ru.json +32 -1
- package/i18n/sv.json +32 -1
- package/i18n/tr.json +32 -1
- package/i18n/uk.json +32 -1
- package/i18n/vi.json +32 -1
- package/i18n/zh-TW.json +32 -1
- package/i18n/zh.json +32 -1
- package/input/styles/_index.scss +24 -1
- package/input-number/styles/_index.scss +69 -0
- package/input-otp/styles/_index.scss +5 -5
- package/line-chart/styles/_index.scss +30 -2
- package/llms-full.txt +14 -4
- package/llms.txt +188 -132
- package/mcp/providers.js +2 -2
- package/mcp/server.js +1 -1
- package/meter-group/styles/_index.scss +1 -0
- package/overlay/styles/_arrow.scss +30 -2
- package/package.json +43 -2
- package/page-header/styles/_index.scss +37 -1
- package/pagination/styles/_index.scss +9 -5
- package/popover/styles/_index.scss +73 -5
- package/progress/styles/_index.scss +4 -0
- package/radio/styles/_index.scss +4 -1
- package/schematics/use/symbol-map.json +1 -0
- package/select/styles/_index.scss +51 -12
- package/sidebar/styles/_index.scss +44 -2
- package/skeleton/styles/_index.scss +3 -0
- package/skills/ngwr/SKILL.md +5 -5
- package/skills/ngwr/references/catalog.md +2 -0
- package/skills/ngwr/references/setup.md +3 -3
- package/sparkline/styles/_index.scss +19 -0
- package/styles.scss +1 -0
- package/table/styles/_index.scss +7 -0
- package/textarea/styles/_index.scss +12 -3
- package/theme/styles/_colors.scss +39 -13
- package/theme/styles/_contrast.scss +9 -7
- package/toast/styles/_index.scss +4 -0
- package/toolbar/styles/_index.scss +35 -1
- package/tree/styles/_index.scss +46 -7
- package/types/ngwr-badge.d.ts +22 -7
- package/types/ngwr-bar-chart.d.ts +19 -1
- package/types/ngwr-calendar-heatmap.d.ts +29 -1
- package/types/ngwr-checkbox.d.ts +2 -0
- package/types/ngwr-config.d.ts +12 -0
- package/types/ngwr-date-picker.d.ts +308 -43
- package/types/ngwr-donut-chart.d.ts +24 -1
- package/types/ngwr-dropdown.d.ts +22 -2
- package/types/ngwr-editor-testing.d.ts +378 -0
- package/types/ngwr-editor.d.ts +449 -0
- package/types/ngwr-event-calendar.d.ts +8 -0
- package/types/ngwr-form.d.ts +35 -5
- package/types/ngwr-gauge.d.ts +20 -1
- package/types/ngwr-input-number.d.ts +7 -0
- package/types/ngwr-line-chart.d.ts +9 -1
- package/types/ngwr-markdown.d.ts +61 -2
- package/types/ngwr-meter-group-testing.d.ts +3 -2
- package/types/ngwr-meter-group.d.ts +14 -1
- package/types/ngwr-page-header.d.ts +10 -2
- package/types/ngwr-popover.d.ts +154 -3
- package/types/ngwr-sidebar.d.ts +7 -0
- package/types/ngwr-sparkline.d.ts +43 -1
- package/types/ngwr-toolbar.d.ts +7 -0
- package/types/ngwr-typography.d.ts +4 -0
- package/types/ngwr-version.d.ts +1 -1
- package/typography/styles/_index.scss +16 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-stepper-testing.mjs","sources":["../../../projects/lib/stepper/testing/wr-stepper-harness-text.ts","../../../projects/lib/stepper/testing/wr-step-harness.ts","../../../projects/lib/stepper/testing/wr-stepper-harness.ts","../../../projects/lib/stepper/testing/ngwr-stepper-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\n/**\n * Collapse the whitespace inside a header or a step body to the line a user reads.\n *\n * `TestElement.text()` only trims the ends, and neither of the two things read here\n * is one text node: a header's label span holds the label, the \"optional\" badge and\n * the description as siblings, and a step body is whatever the consumer projected.\n * The template's own indentation is not the problem — Angular's default\n * `preserveWhitespaces: false` drops whitespace-only text nodes at compile time —\n * but a value carrying a newline is, and so is a consumer app compiled with\n * `preserveWhitespaces: true`. Every run becomes one space so a spec can assert the\n * rendered line either way.\n */\nexport function wrStepperHarnessText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrStepHarnessFilters } from './interfaces';\nimport { wrStepperHarnessText } from './wr-stepper-harness-text';\n\n/**\n * Test harness for one step of a `<wr-stepper>` — the step as the HEADER STRIP\n * publishes it: its label, its state, and the one control that navigates to it.\n *\n * A step is two pieces of DOM in two different places. The `<wr-step>` the consumer\n * wrote is projected into the stepper's body region; the header this harness hosts on\n * is generated next to it, in the `<ol>` above. Nothing links the two — no\n * `aria-controls`, no id on the body — so `WrStepperHarness.getActiveStepText()` is\n * where the body is read, and this answers what the wizard says about the step.\n *\n * Two states that look alike here are deliberately separate, because the component\n * treats them separately: {@link isDisabled} is the step's own `disabled` input\n * (switched off, whatever else happens), and {@link isReachable} is whether a click\n * would land right now — which a `linear` stepper takes away from every step ahead of\n * the gate without disabling any of them.\n *\n * @example\n * ```ts\n * const [review] = await stepper.getSteps({ label: 'Review' });\n *\n * expect(await review.isOptional()).toBe(true);\n * expect(await review.isReachable()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrStepHarness extends ComponentHarness {\n /**\n * The header `<li>`, which is the whole step as far as the strip is concerned.\n *\n * Not `.wr-stepper__header-button`: the state modifiers (`--active`, `--completed`,\n * `--disabled`) land on the `<li>`, and the button is a child of it.\n */\n static hostSelector = '.wr-stepper__header';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrStepHarnessFilters = {}): HarnessPredicate<WrStepHarness> {\n return new HarnessPredicate(WrStepHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('active', options.active, async (harness, active) => (await harness.isActive()) === active)\n .addOption(\n 'completed',\n options.completed,\n async (harness, completed) => (await harness.isCompleted()) === completed\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption(\n 'reachable',\n options.reachable,\n async (harness, reachable) => (await harness.isReachable()) === reachable\n )\n .addOption('optional', options.optional, async (harness, optional) => (await harness.isOptional()) === optional);\n }\n\n private readonly button = this.locatorFor('button.wr-stepper__header-button');\n\n /**\n * The step's label, and only the label.\n *\n * The \"optional\" badge and the description are siblings of the label text inside\n * the same span, so both are excluded — a step addressed by label should be\n * addressable whether or not it also carries a description.\n */\n async getLabel(): Promise<string> {\n const label = await this.locatorFor('.wr-stepper__label')();\n return wrStepperHarnessText(await label.text({ exclude: '.wr-stepper__optional, .wr-stepper__description' }));\n }\n\n /** The secondary line under the label, or `null` when the step defines none. */\n async getDescription(): Promise<string | null> {\n const description = await this.locatorForOptional('.wr-stepper__description')();\n return description ? wrStepperHarnessText(await description.text()) : null;\n }\n\n /** Whether the header flags the step as optional. */\n async isOptional(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-stepper__optional')()) !== null;\n }\n\n /**\n * What a screen reader announces for the header button.\n *\n * The indicator is excluded because it is `aria-hidden`: the step number and the\n * completed tick are decoration, deliberately, since the label and\n * `aria-current=\"step\"` already carry what they would repeat. What IS announced is\n * the label plus the \"optional\" badge and the description — so this is the method\n * that notices when one of those stops being part of the name.\n */\n async getAccessibleName(): Promise<string> {\n const button = await this.button();\n return wrStepperHarnessText(await button.text({ exclude: '.wr-stepper__indicator' }));\n }\n\n /**\n * Whether this is the step the wizard is showing.\n *\n * From `aria-current=\"step\"` rather than the `--active` class, because that is the\n * only place the wizard's position is published to a screen reader, and the two can\n * only ever disagree by way of a bug.\n */\n async isActive(): Promise<boolean> {\n return (await (await this.button()).getAttribute('aria-current')) === 'step';\n }\n\n /**\n * Whether the step is shown as done.\n *\n * Read from the `--completed` class, and there is no ARIA alternative to prefer:\n * completion reaches the page as that class plus a tick glyph that is\n * `aria-hidden`, so a screen-reader user hears the label and nothing else. The\n * class is the whole of what exists.\n *\n * Completion is derived from the active index — every step before it — unless a\n * step's own `completed` input overrides it, which is how a `linear` wizard opens\n * its gate. So a step after the active one can be completed too.\n */\n async isCompleted(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper__header--completed');\n }\n\n /**\n * Whether the step is switched off by its own `disabled` input.\n *\n * The `--disabled` class is exactly that input, which is why it is read here rather\n * than the button's `disabled`: the button is also disabled for a step that is\n * merely behind a `linear` gate, and those are different facts about the wizard.\n * See {@link isReachable} for the one about right now.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper__header--disabled');\n }\n\n /**\n * Whether a click on this header would move the wizard here.\n *\n * Read from the button's `disabled` PROPERTY, because that is the enforcement and\n * not the paint: the component disables the header for a step its own input\n * switched off AND for one a `linear` gate has not opened yet. It is also what puts\n * the header in or out of the tab order — a `disabled` button cannot be focused at\n * all, so an unreachable step is off the keyboard entirely rather than focusable and\n * inert the way `aria-disabled` would leave it.\n */\n async isReachable(): Promise<boolean> {\n return !(await (await this.button()).getProperty<boolean>('disabled'));\n }\n\n /**\n * Navigate to this step by clicking its header, the way a user does.\n *\n * A click, not a keypress: the header is a real `<button>`, so Enter and Space\n * activate it through the browser's native activation — behaviour jsdom does not\n * implement, leaving nothing for a key to drive. A no-arg CDK click needs no\n * coordinate and no hit test, so the absent layout costs nothing here.\n *\n * Throws when the header refuses, rather than clicking and resolving quietly: the\n * component's guard would drop the click and the wizard would still be showing the\n * old step three assertions later. Reach for `WrStepperHarness.goTo()` when you\n * want the failure to name WHICH earlier step is holding the gate shut.\n */\n async select(): Promise<void> {\n if (!(await this.isReachable())) {\n throw new Error(\n `WrStepHarness.select(): the header for \"${await this.getLabel()}\" refuses a click — the step carries ` +\n '`disabled`, or the stepper is `linear` and an earlier step has not reported itself complete.'\n );\n }\n await (await this.button()).click();\n }\n\n /** Move keyboard focus to the header. A header that is not reachable cannot take it. */\n async focus(): Promise<void> {\n return (await this.button()).focus();\n }\n\n /** Whether the header currently has focus. */\n async isFocused(): Promise<boolean> {\n return (await this.button()).isFocused();\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrStepHarnessFilters, WrStepperHarnessFilters } from './interfaces';\nimport { WrStepHarness } from './wr-step-harness';\nimport { wrStepperHarnessText } from './wr-stepper-harness-text';\n\n/**\n * Test harness for `<wr-stepper>` — the root of a two-part family with\n * {@link WrStepHarness}, which is one step of it.\n *\n * Steps are addressed by their index or their LABEL, the two things a consumer can\n * see; there is no key or id on a `<wr-step>` to address it by.\n *\n * Navigation here always goes through the HEADER STRIP, because that is the only\n * control the component renders — a wizard's Next and Back buttons are the\n * consumer's own, and they call `WrStepper.next()` / `prev()`. That distinction is\n * not cosmetic: the imperative API does NOT consult `linear`, so it walks straight\n * past a gate that refuses the equivalent header click. {@link next} and\n * {@link goTo} therefore refuse exactly where a user would be refused, and a spec\n * covering the wizard's own buttons should drive those buttons (through their own\n * harness) instead of these.\n *\n * @example\n * ```ts\n * const wizard = await loader.getHarness(WrStepperHarness);\n *\n * expect(await wizard.getStepLabels()).toEqual(['Account', 'Address', 'Review']);\n * expect(await wizard.canGoTo(2)).toBe(false);\n * await wizard.goToLabel('Address');\n * expect(await wizard.getActiveStepText()).toBe('Address body');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrStepperHarness extends ComponentHarness {\n static hostSelector = 'wr-stepper';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrStepperHarnessFilters = {}): HarnessPredicate<WrStepperHarness> {\n return new HarnessPredicate(WrStepperHarness, options)\n .addOption('stepLabel', options.stepLabel, async (harness, label) => {\n for (const stepLabel of await harness.getStepLabels()) {\n if (await HarnessPredicate.stringMatches(stepLabel, label)) return true;\n }\n return false;\n })\n .addOption(\n 'orientation',\n options.orientation,\n async (harness, orientation) => (await harness.getOrientation()) === orientation\n )\n .addOption('linear', options.linear, async (harness, linear) => (await harness.isLinear()) === linear);\n }\n\n private readonly headerList = this.locatorFor('ol.wr-stepper__headers');\n\n /**\n * The layout direction the stepper was ASKED for.\n *\n * Unusually for this library both values carry a class, so neither is read as the\n * absence of the other. What the class cannot tell you is how the strip actually\n * laid itself out: a `responsive` horizontal stepper drops to the vertical layout\n * when its own box is too narrow, and that reflow is a container query — the class\n * never changes. No unit test can see the difference in any case, jsdom having no\n * layout at all; assert the opt-in with {@link isResponsive} instead.\n */\n async getOrientation(): Promise<'horizontal' | 'vertical'> {\n return (await (await this.host()).hasClass('wr-stepper--vertical')) ? 'vertical' : 'horizontal';\n }\n\n /** Whether the stepper locks the steps after the last completed one. */\n async isLinear(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper--linear');\n }\n\n /** Whether the stepper may reflow to the vertical layout in a narrow container. */\n async isResponsive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper--responsive');\n }\n\n /**\n * The role the header strip announces — `list`.\n *\n * An `<ol>` is a list already, so the explicit role looks redundant and is not: the\n * stylesheet removes the markers, and Safari drops list semantics from a list with\n * `list-style: none`. Losing it costs the \"list, 3 items\" a VoiceOver user hears,\n * which is how they learn how long the wizard is before starting it.\n */\n async getListRole(): Promise<string | null> {\n return (await this.headerList()).getAttribute('role');\n }\n\n /** The wizard's steps, in order. */\n async getSteps(filters: WrStepHarnessFilters = {}): Promise<WrStepHarness[]> {\n return this.locatorForAll(WrStepHarness.with(filters))();\n }\n\n /** The label of every step, in order. */\n async getStepLabels(): Promise<string[]> {\n const steps = await this.getSteps();\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /**\n * The index of the step the wizard is showing, from the header announcing\n * `aria-current=\"step\"`.\n *\n * Throws when no header does, which is a state a stepper can genuinely be in: one\n * with no `<wr-step>` children renders its (empty) header strip and no body. A `-1`\n * here would be read as \"the first step\" by the next line of a spec. An\n * out-of-range `active` is NOT such a state — `WrStepper` clamps the two-way model\n * back into the step list, not only inside `goTo()`.\n */\n async getActiveIndex(): Promise<number> {\n const steps = await this.getSteps();\n for (let index = 0; index < steps.length; index++) {\n if (await steps[index].isActive()) return index;\n }\n\n throw new Error(\n 'WrStepperHarness.getActiveIndex(): no header announces `aria-current=\"step\"` — this stepper has ' +\n 'no <wr-step> children, so there is no step for it to be on. An out-of-range `active` cannot ' +\n 'produce this: WrStepper clamps the bound index to the step list.'\n );\n }\n\n /** The label of the step the wizard is showing. Throws when there is no current step. */\n async getActiveLabel(): Promise<string> {\n const steps = await this.getSteps();\n return steps[await this.getActiveIndex()].getLabel();\n }\n\n /** The labels of the steps shown as done, in order. Derived completion and overrides both. */\n async getCompletedLabels(): Promise<string[]> {\n const steps = await this.getSteps({ completed: true });\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /**\n * The labels of the headers a Tab press can reach, in order.\n *\n * A stepper does NOT rove focus: unlike a tab strip, the header list is not one tab\n * stop with arrow keys inside it — every reachable header is its own stop, and the\n * component authors no `tabindex` at all. So the question \"which step is active\" has\n * two different answers, and this is the other one: the current step is not\n * necessarily in this list. A step disabled by its own input keeps\n * `aria-current=\"step\"` while its button drops out of the tab order entirely, and a\n * `linear` stepper takes every locked header off the keyboard the same way.\n */\n async getTabStopLabels(): Promise<string[]> {\n const steps = await this.getSteps({ reachable: true });\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /** The label of the header that currently has focus, or `null` when focus is elsewhere. */\n async getFocusedLabel(): Promise<string | null> {\n for (const step of await this.getSteps()) {\n if (await step.isFocused()) return step.getLabel();\n }\n return null;\n }\n\n /**\n * Whether the wizard would let a user navigate to this step right now — the question\n * a `linear` stepper exists to answer `false` to.\n *\n * Throws for an index that is not a step, rather than answering `false`: \"you cannot\n * go there\" and \"there is no there\" are different findings.\n */\n async canGoTo(index: number): Promise<boolean> {\n return (await this.stepAt(index)).isReachable();\n }\n\n /**\n * Navigate to the step at `index` by clicking its header.\n *\n * Throws when the wizard refuses, naming the cause — the step's own `disabled`, or\n * the `linear` gate and which earlier step is holding it shut. Silence would be\n * worse than a failure here: the component drops a click on a locked header without\n * a sound, so a spec would go on to assert against the step it was already showing.\n */\n async goTo(index: number): Promise<void> {\n const step = await this.stepAt(index);\n\n if (!(await step.isReachable())) {\n throw new Error(\n `WrStepperHarness.goTo(${index}): the header for \"${await step.getLabel()}\" refuses a click — ` +\n `${await this.refusal(index)}. Note that \\`WrStepper.goTo()\\` and \\`next()\\` move anyway: the gate is ` +\n \"on the header click, so a wizard's own Next button has to check for itself.\"\n );\n }\n\n await step.select();\n\n if (!(await step.isActive())) {\n throw new Error(\n `WrStepperHarness.goTo(${index}): the header for \"${await step.getLabel()}\" was clicked and the wizard ` +\n 'is still showing another step — its `active` model reached nothing, so a two-way `[(active)]` binding ' +\n 'is overwriting it or the click is not wired.'\n );\n }\n }\n\n /**\n * Navigate to the step with this label — a string matches exactly, a RegExp is\n * tested. Throws naming the labels that do exist when nothing matches.\n */\n async goToLabel(label: string | RegExp): Promise<void> {\n const labels = await this.getStepLabels();\n for (let index = 0; index < labels.length; index++) {\n if (await HarnessPredicate.stringMatches(labels[index], label)) return this.goTo(index);\n }\n\n throw new Error(\n `WrStepperHarness.goToLabel(): no step is labelled ${JSON.stringify(String(label))}. This wizard has: ` +\n `${labels.join(', ')}.`\n );\n }\n\n /**\n * Move to the next step through its header — subject to the same gate a user is.\n *\n * In a `linear` wizard that gate is shut until the CURRENT step reports itself\n * complete (its own `completed` input; derived completion only ever covers steps\n * before the active one), so this throws there. That is not the harness being\n * strict: it is the header a user has, and the reason a linear wizard needs its own\n * Next button, which calls `WrStepper.next()` and is not gated at all.\n *\n * Throws on the last step, where the component's own `next()` clamps in silence.\n */\n async next(): Promise<void> {\n const index = await this.getActiveIndex();\n const steps = await this.getSteps();\n\n if (index === steps.length - 1) {\n throw new Error(\n `WrStepperHarness.next(): the wizard is already on its last step (\"${await steps[index].getLabel()}\") — ` +\n 'there is nothing after it. `WrStepper.next()` clamps silently instead of saying so.'\n );\n }\n\n await this.goTo(index + 1);\n }\n\n /**\n * Move to the previous step through its header. Throws on the first step, where\n * `WrStepper.prev()` clamps in silence.\n *\n * Going back is normally allowed even in a `linear` wizard — every step at or before\n * the active one is reachable — but a step its own input disabled stays out of\n * reach in both directions.\n */\n async previous(): Promise<void> {\n const index = await this.getActiveIndex();\n\n if (index === 0) {\n throw new Error(\n 'WrStepperHarness.previous(): the wizard is already on its first step — there is nothing before it. ' +\n '`WrStepper.prev()` clamps silently instead of saying so.'\n );\n }\n\n await this.goTo(index - 1);\n }\n\n /**\n * The text of the step body the wizard is showing.\n *\n * Which body shows is CSS-only: every `<wr-step>` renders, and the stepper hides all\n * but one with `display: none` through the `--active` class. So this reads the class,\n * and in a unit test it has to — jsdom loads no stylesheet, which makes\n * `fixture.nativeElement.textContent` the text of ALL the steps at once and any\n * \"is the body showing\" assertion built on it meaningless.\n */\n async getActiveStepText(): Promise<string> {\n const active = await this.locatorForOptional('.wr-stepper__body .wr-step--active')();\n if (!active) {\n throw new Error(\n 'WrStepperHarness.getActiveStepText(): no step body is showing — the bound `active` index is outside ' +\n 'the step list, or this stepper has no <wr-step> children.'\n );\n }\n return wrStepperHarnessText(await active.text());\n }\n\n /**\n * The text of EVERY step body, in order, showing or not.\n *\n * The list being complete is the point: a step is hidden by a class rather than\n * dropped by an `@if`, so it mounts once and keeps its state — a half-filled form on\n * step 1 is still filled after a trip to step 3. Anything that turned the body into\n * a conditional block would keep every other assertion in a spec passing and quietly\n * reset the wizard.\n */\n async getStepTexts(): Promise<string[]> {\n const bodies = await this.locatorForAll('.wr-stepper__body > wr-step')();\n return Promise.all(bodies.map(async body => wrStepperHarnessText(await body.text())));\n }\n\n /** The step at `index`, or a failure that says how long the wizard is. */\n private async stepAt(index: number): Promise<WrStepHarness> {\n const steps = await this.getSteps();\n const step = steps[index];\n if (!step) {\n throw new Error(\n `WrStepperHarness: there is no step ${index} — this wizard has ${steps.length} ` +\n `${steps.length === 1 ? 'step' : 'steps'}${steps.length ? `: ${(await this.getStepLabels()).join(', ')}` : ''}.`\n );\n }\n return step;\n }\n\n /** Why the header at `index` is refusing a click, in the component's own order of causes. */\n private async refusal(index: number): Promise<string> {\n const steps = await this.getSteps();\n\n // The step's own input wins in the component too: `isReachable()` answers `false`\n // for a disabled step before it ever looks at the gate.\n if (await steps[index].isDisabled()) return 'the step carries `disabled`';\n\n if (await this.isLinear()) {\n for (let before = 0; before < index; before++) {\n if (!(await steps[before].isCompleted())) {\n return (\n 'the stepper is `linear` and step ' +\n `${before + 1} (\"${await steps[before].getLabel()}\") has not reported itself complete`\n );\n }\n }\n }\n\n return 'its header button is disabled';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAEH;;;;;;;;;;;AAWG;AACG,SAAU,oBAAoB,CAAC,IAAY,EAAA;IAC/C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE;AACzC;;ACrBA;;;;;AAKG;AAOH;;;;;;;;;;;;;;;;;;;;;;;;;AAyBG;AACG,MAAO,aAAc,SAAQ,gBAAgB,CAAA;AACjD;;;;;AAKG;AACH,IAAA,OAAO,YAAY,GAAG,qBAAqB;;AAG3C,IAAA,OAAO,IAAI,CAAC,OAAA,GAAgC,EAAE,EAAA;AAC5C,QAAA,OAAO,IAAI,gBAAgB,CAAC,aAAa,EAAE,OAAO;aAC/C,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;aAC/G,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,MAAM,MAAM;aACpG,SAAS,CACR,WAAW,EACX,OAAO,CAAC,SAAS,EACjB,OAAO,OAAO,EAAE,SAAS,KAAK,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,SAAS;aAE1E,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ;aAC9G,SAAS,CACR,WAAW,EACX,OAAO,CAAC,SAAS,EACjB,OAAO,OAAO,EAAE,SAAS,KAAK,CAAC,MAAM,OAAO,CAAC,WAAW,EAAE,MAAM,SAAS;aAE1E,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEiB,IAAA,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,kCAAkC,CAAC;AAE7E;;;;;;AAMG;AACH,IAAA,MAAM,QAAQ,GAAA;QACZ,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,oBAAoB,CAAC,EAAE;AAC3D,QAAA,OAAO,oBAAoB,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,iDAAiD,EAAE,CAAC,CAAC;IAC/G;;AAGA,IAAA,MAAM,cAAc,GAAA;QAClB,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,0BAA0B,CAAC,EAAE;AAC/E,QAAA,OAAO,WAAW,GAAG,oBAAoB,CAAC,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI;IAC5E;;AAGA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,EAAE,MAAM,IAAI;IAC5E;AAEA;;;;;;;;AAQG;AACH,IAAA,MAAM,iBAAiB,GAAA;AACrB,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;AAClC,QAAA,OAAO,oBAAoB,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,wBAAwB,EAAE,CAAC,CAAC;IACvF;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,YAAY,CAAC,cAAc,CAAC,MAAM,MAAM;IAC9E;AAEA;;;;;;;;;;;AAWG;AACH,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,+BAA+B,CAAC;IACtE;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,8BAA8B,CAAC;IACrE;AAEA;;;;;;;;;AASG;AACH,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,OAAO,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC,CAAC;IACxE;AAEA;;;;;;;;;;;;AAYG;AACH,IAAA,MAAM,MAAM,GAAA;QACV,IAAI,EAAE,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,CAAA,wCAAA,EAA2C,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA,qCAAA,CAAuC;AACrG,gBAAA,8FAA8F,CACjG;QACH;QACA,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE;IACrC;;AAGA,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE;IACtC;;AAGA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE;IAC1C;;;AC7LF;;;;;AAKG;AAQH;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;AACG,MAAO,gBAAiB,SAAQ,gBAAgB,CAAA;AACpD,IAAA,OAAO,YAAY,GAAG,YAAY;;AAGlC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAmC,EAAE,EAAA;AAC/C,QAAA,OAAO,IAAI,gBAAgB,CAAC,gBAAgB,EAAE,OAAO;AAClD,aAAA,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,SAAS,EAAE,OAAO,OAAO,EAAE,KAAK,KAAI;YAClE,KAAK,MAAM,SAAS,IAAI,MAAM,OAAO,CAAC,aAAa,EAAE,EAAE;gBACrD,IAAI,MAAM,gBAAgB,CAAC,aAAa,CAAC,SAAS,EAAE,KAAK,CAAC;AAAE,oBAAA,OAAO,IAAI;YACzE;AACA,YAAA,OAAO,KAAK;AACd,QAAA,CAAC;aACA,SAAS,CACR,aAAa,EACb,OAAO,CAAC,WAAW,EACnB,OAAO,OAAO,EAAE,WAAW,KAAK,CAAC,MAAM,OAAO,CAAC,cAAc,EAAE,MAAM,WAAW;aAEjF,SAAS,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM,OAAO,CAAC,QAAQ,EAAE,MAAM,MAAM,CAAC;IAC1G;AAEiB,IAAA,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC;AAEvE;;;;;;;;;AASG;AACH,IAAA,MAAM,cAAc,GAAA;QAClB,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,sBAAsB,CAAC,IAAI,UAAU,GAAG,YAAY;IACjG;;AAGA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,oBAAoB,CAAC;IAC3D;;AAGA,IAAA,MAAM,YAAY,GAAA;AAChB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,wBAAwB,CAAC;IAC/D;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IACvD;;AAGA,IAAA,MAAM,QAAQ,CAAC,OAAA,GAAgC,EAAE,EAAA;AAC/C,QAAA,OAAO,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE;IAC1D;;AAGA,IAAA,MAAM,aAAa,GAAA;AACjB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;AACnC,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxD;AAEA;;;;;;;;;AASG;AACH,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;AACnC,QAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;AACjD,YAAA,IAAI,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE;AAAE,gBAAA,OAAO,KAAK;QACjD;QAEA,MAAM,IAAI,KAAK,CACb,kGAAkG;YAChG,8FAA8F;AAC9F,YAAA,kEAAkE,CACrE;IACH;;AAGA,IAAA,MAAM,cAAc,GAAA;AAClB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;QACnC,OAAO,KAAK,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtD;;AAGA,IAAA,MAAM,kBAAkB,GAAA;AACtB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACtD,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxD;AAEA;;;;;;;;;;AAUG;AACH,IAAA,MAAM,gBAAgB,GAAA;AACpB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AACtD,QAAA,OAAO,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC;IACxD;;AAGA,IAAA,MAAM,eAAe,GAAA;QACnB,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE;AACxC,YAAA,IAAI,MAAM,IAAI,CAAC,SAAS,EAAE;AAAE,gBAAA,OAAO,IAAI,CAAC,QAAQ,EAAE;QACpD;AACA,QAAA,OAAO,IAAI;IACb;AAEA;;;;;;AAMG;IACH,MAAM,OAAO,CAAC,KAAa,EAAA;AACzB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE;IACjD;AAEA;;;;;;;AAOG;IACH,MAAM,IAAI,CAAC,KAAa,EAAA;QACtB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;QAErC,IAAI,EAAE,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE;YAC/B,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,KAAK,CAAA,mBAAA,EAAsB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA,oBAAA,CAAsB;AAC7F,gBAAA,CAAA,EAAG,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA,yEAAA,CAA2E;AACvG,gBAAA,6EAA6E,CAChF;QACH;AAEA,QAAA,MAAM,IAAI,CAAC,MAAM,EAAE;QAEnB,IAAI,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE;YAC5B,MAAM,IAAI,KAAK,CACb,CAAA,sBAAA,EAAyB,KAAK,CAAA,mBAAA,EAAsB,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAA,6BAAA,CAA+B;gBACtG,wGAAwG;AACxG,gBAAA,8CAA8C,CACjD;QACH;IACF;AAEA;;;AAGG;IACH,MAAM,SAAS,CAAC,KAAsB,EAAA;AACpC,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;AACzC,QAAA,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;YAClD,IAAI,MAAM,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;AAAE,gBAAA,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QACzF;AAEA,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,kDAAA,EAAqD,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA,mBAAA,CAAqB;YACrG,CAAA,EAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA,CAAA,CAAG,CAC1B;IACH;AAEA;;;;;;;;;;AAUG;AACH,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE;AACzC,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;QAEnC,IAAI,KAAK,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;AAC9B,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,kEAAA,EAAqE,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAA,KAAA,CAAO;AACvG,gBAAA,qFAAqF,CACxF;QACH;QAEA,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC5B;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,cAAc,EAAE;AAEzC,QAAA,IAAI,KAAK,KAAK,CAAC,EAAE;YACf,MAAM,IAAI,KAAK,CACb,qGAAqG;AACnG,gBAAA,0DAA0D,CAC7D;QACH;QAEA,MAAM,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;IAC5B;AAEA;;;;;;;;AAQG;AACH,IAAA,MAAM,iBAAiB,GAAA;QACrB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,oCAAoC,CAAC,EAAE;QACpF,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,KAAK,CACb,sGAAsG;AACpG,gBAAA,2DAA2D,CAC9D;QACH;QACA,OAAO,oBAAoB,CAAC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IAClD;AAEA;;;;;;;;AAQG;AACH,IAAA,MAAM,YAAY,GAAA;QAChB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAAC,EAAE;QACxE,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAM,IAAI,KAAI,oBAAoB,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACvF;;IAGQ,MAAM,MAAM,CAAC,KAAa,EAAA;AAChC,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;AACnC,QAAA,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE;YACT,MAAM,IAAI,KAAK,CACb,CAAA,mCAAA,EAAsC,KAAK,CAAA,mBAAA,EAAsB,KAAK,CAAC,MAAM,CAAA,CAAA,CAAG;AAC9E,gBAAA,CAAA,EAAG,KAAK,CAAC,MAAM,KAAK,CAAC,GAAG,MAAM,GAAG,OAAO,CAAA,EAAG,KAAK,CAAC,MAAM,GAAG,CAAA,EAAA,EAAK,CAAC,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,CAAA,CAAA,CAAG,CACnH;QACH;AACA,QAAA,OAAO,IAAI;IACb;;IAGQ,MAAM,OAAO,CAAC,KAAa,EAAA;AACjC,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;;;AAInC,QAAA,IAAI,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE;AAAE,YAAA,OAAO,6BAA6B;AAEzE,QAAA,IAAI,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE;AACzB,YAAA,KAAK,IAAI,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,KAAK,EAAE,MAAM,EAAE,EAAE;AAC7C,gBAAA,IAAI,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE;AACxC,oBAAA,QACE,mCAAmC;AACnC,wBAAA,CAAA,EAAG,MAAM,GAAG,CAAC,CAAA,GAAA,EAAM,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA,mCAAA,CAAqC;gBAE1F;YACF;QACF;AAEA,QAAA,OAAO,+BAA+B;IACxC;;;ACnVF;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"ngwr-stepper-testing.mjs","sources":["../../../projects/lib/stepper/testing/wr-stepper-harness-text.ts","../../../projects/lib/stepper/testing/wr-step-harness.ts","../../../projects/lib/stepper/testing/wr-stepper-harness.ts","../../../projects/lib/stepper/testing/ngwr-stepper-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\n/**\n * Collapse the whitespace inside a header or a step body to the line a user reads.\n *\n * `TestElement.text()` only trims the ends, and neither of the two things read here\n * is one text node: a header's label span holds the label, the \"optional\" badge and\n * the description as siblings, and a step body is whatever the consumer projected.\n * The template's own indentation is not the problem — Angular's default\n * `preserveWhitespaces: false` drops whitespace-only text nodes at compile time —\n * but a value carrying a newline is, and so is a consumer app compiled with\n * `preserveWhitespaces: true`. Every run becomes one space so a spec can assert the\n * rendered line either way.\n */\nexport function wrStepperHarnessText(text: string): string {\n return text.replace(/\\s+/g, ' ').trim();\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrStepHarnessFilters } from './interfaces';\nimport { wrStepperHarnessText } from './wr-stepper-harness-text';\n\n/**\n * Test harness for one step of a `<wr-stepper>` — the step as the HEADER STRIP\n * publishes it: its label, its state, and the one control that navigates to it.\n *\n * A step is two pieces of DOM in two different places. The `<wr-step>` the consumer\n * wrote is projected into the stepper's body region; the header this harness hosts on\n * is generated next to it, in the `<ol>` above. Nothing links the two — no\n * `aria-controls`, no id on the body — so `WrStepperHarness.getActiveStepText()` is\n * where the body is read, and this answers what the wizard says about the step.\n *\n * Two states that look alike here are deliberately separate, because the component\n * treats them separately: {@link isDisabled} is the step's own `disabled` input\n * (switched off, whatever else happens), and {@link isReachable} is whether a click\n * would land right now — which a `linear` stepper takes away from every step ahead of\n * the gate without disabling any of them.\n *\n * @example\n * ```ts\n * const [review] = await stepper.getSteps({ label: 'Review' });\n *\n * expect(await review.isOptional()).toBe(true);\n * expect(await review.isReachable()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrStepHarness extends ComponentHarness {\n /**\n * The header `<li>`, which is the whole step as far as the strip is concerned.\n *\n * Not `.wr-stepper__header-button`: the state modifiers (`--active`, `--completed`,\n * `--disabled`) land on the `<li>`, and the button is a child of it.\n */\n static hostSelector = '.wr-stepper__header';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrStepHarnessFilters = {}): HarnessPredicate<WrStepHarness> {\n return new HarnessPredicate(WrStepHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('active', options.active, async (harness, active) => (await harness.isActive()) === active)\n .addOption(\n 'completed',\n options.completed,\n async (harness, completed) => (await harness.isCompleted()) === completed\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption(\n 'reachable',\n options.reachable,\n async (harness, reachable) => (await harness.isReachable()) === reachable\n )\n .addOption('optional', options.optional, async (harness, optional) => (await harness.isOptional()) === optional);\n }\n\n private readonly button = this.locatorFor('button.wr-stepper__header-button');\n\n /**\n * The step's label, and only the label.\n *\n * The \"optional\" badge and the description are siblings of the label text inside\n * the same span, so both are excluded — a step addressed by label should be\n * addressable whether or not it also carries a description.\n */\n async getLabel(): Promise<string> {\n const label = await this.locatorFor('.wr-stepper__label')();\n return wrStepperHarnessText(await label.text({ exclude: '.wr-stepper__optional, .wr-stepper__description' }));\n }\n\n /** The secondary line under the label, or `null` when the step defines none. */\n async getDescription(): Promise<string | null> {\n const description = await this.locatorForOptional('.wr-stepper__description')();\n return description ? wrStepperHarnessText(await description.text()) : null;\n }\n\n /** Whether the header flags the step as optional. */\n async isOptional(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-stepper__optional')()) !== null;\n }\n\n /**\n * What a screen reader announces for the header button.\n *\n * The indicator is excluded because it is `aria-hidden`: the step number and the\n * completed tick are decoration, deliberately, since the label and\n * `aria-current=\"step\"` already carry what they would repeat. What IS announced is\n * the label plus the \"optional\" badge and the description — so this is the method\n * that notices when one of those stops being part of the name.\n */\n async getAccessibleName(): Promise<string> {\n const button = await this.button();\n return wrStepperHarnessText(await button.text({ exclude: '.wr-stepper__indicator' }));\n }\n\n /**\n * Whether this is the step the wizard is showing.\n *\n * From `aria-current=\"step\"` rather than the `--active` class, because that is the\n * only place the wizard's position is published to a screen reader, and the two can\n * only ever disagree by way of a bug.\n */\n async isActive(): Promise<boolean> {\n return (await (await this.button()).getAttribute('aria-current')) === 'step';\n }\n\n /**\n * Whether the step is shown as done.\n *\n * Read from the `--completed` class, and there is no ARIA alternative to prefer:\n * completion reaches the page as that class plus a tick glyph that is\n * `aria-hidden`, so a screen-reader user hears the label and nothing else. The\n * class is the whole of what exists.\n *\n * Completion is derived from the active index — every step before it — unless a\n * step's own `completed` input overrides it, which is how a `linear` wizard opens\n * its gate. So a step after the active one can be completed too.\n */\n async isCompleted(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper__header--completed');\n }\n\n /**\n * Whether the step is switched off by its own `disabled` input.\n *\n * The `--disabled` class is exactly that input, which is why it is read here rather\n * than the button's `disabled`: the button is also disabled for a step that is\n * merely behind a `linear` gate, and those are different facts about the wizard.\n * See {@link isReachable} for the one about right now.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper__header--disabled');\n }\n\n /**\n * Whether a click on this header would move the wizard here.\n *\n * Read from the button's `disabled` PROPERTY, because that is the enforcement and\n * not the paint: the component disables the header for a step its own input\n * switched off AND for one a `linear` gate has not opened yet. It is also what puts\n * the header in or out of the tab order — a `disabled` button cannot be focused at\n * all, so an unreachable step is off the keyboard entirely rather than focusable and\n * inert the way `aria-disabled` would leave it.\n */\n async isReachable(): Promise<boolean> {\n return !(await (await this.button()).getProperty<boolean>('disabled'));\n }\n\n /**\n * Navigate to this step by clicking its header, the way a user does.\n *\n * A click, not a keypress: the header is a real `<button>`, so Enter and Space\n * activate it through the browser's native activation — behaviour jsdom does not\n * implement, leaving nothing for a key to drive. A no-arg CDK click needs no\n * coordinate and no hit test, so the absent layout costs nothing here.\n *\n * Throws when the header refuses, rather than clicking and resolving quietly: the\n * component's guard would drop the click and the wizard would still be showing the\n * old step three assertions later. Reach for `WrStepperHarness.goTo()` when you\n * want the failure to name WHICH earlier step is holding the gate shut.\n */\n async select(): Promise<void> {\n if (!(await this.isReachable())) {\n throw new Error(\n `WrStepHarness.select(): the header for \"${await this.getLabel()}\" refuses a click — the step carries ` +\n '`disabled`, or the stepper is `linear` and an earlier step has not reported itself complete.'\n );\n }\n await (await this.button()).click();\n }\n\n /** Move keyboard focus to the header. A header that is not reachable cannot take it. */\n async focus(): Promise<void> {\n return (await this.button()).focus();\n }\n\n /** Whether the header currently has focus. */\n async isFocused(): Promise<boolean> {\n return (await this.button()).isFocused();\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrStepHarnessFilters, WrStepperHarnessFilters } from './interfaces';\nimport { WrStepHarness } from './wr-step-harness';\nimport { wrStepperHarnessText } from './wr-stepper-harness-text';\n\n/**\n * Test harness for `<wr-stepper>` — the root of a two-part family with\n * {@link WrStepHarness}, which is one step of it.\n *\n * Steps are addressed by their index or their LABEL, the two things a consumer can\n * see; there is no key or id on a `<wr-step>` to address it by.\n *\n * Navigation here always goes through the HEADER STRIP, because that is the only\n * control the component renders — a wizard's Next and Back buttons are the\n * consumer's own, and they call `WrStepper.next()` / `prev()`. That distinction is\n * not cosmetic: the imperative API does NOT consult `linear`, so it walks straight\n * past a gate that refuses the equivalent header click. {@link next} and\n * {@link goTo} therefore refuse exactly where a user would be refused, and a spec\n * covering the wizard's own buttons should drive those buttons (through their own\n * harness) instead of these.\n *\n * @example\n * ```ts\n * const wizard = await loader.getHarness(WrStepperHarness);\n *\n * expect(await wizard.getStepLabels()).toEqual(['Account', 'Address', 'Review']);\n * expect(await wizard.canGoTo(2)).toBe(false);\n * await wizard.goToLabel('Address');\n * expect(await wizard.getActiveStepText()).toBe('Address body');\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrStepperHarness extends ComponentHarness {\n static hostSelector = 'wr-stepper';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrStepperHarnessFilters = {}): HarnessPredicate<WrStepperHarness> {\n return new HarnessPredicate(WrStepperHarness, options)\n .addOption('stepLabel', options.stepLabel, async (harness, label) => {\n for (const stepLabel of await harness.getStepLabels()) {\n if (await HarnessPredicate.stringMatches(stepLabel, label)) return true;\n }\n return false;\n })\n .addOption(\n 'orientation',\n options.orientation,\n async (harness, orientation) => (await harness.getOrientation()) === orientation\n )\n .addOption('linear', options.linear, async (harness, linear) => (await harness.isLinear()) === linear);\n }\n\n private readonly headerList = this.locatorFor('ol.wr-stepper__headers');\n\n /**\n * The layout direction the stepper was ASKED for.\n *\n * Unusually for this library both values carry a class, so neither is read as the\n * absence of the other. What the class cannot tell you is how the strip actually\n * laid itself out: a `responsive` horizontal stepper drops to the vertical layout\n * when its own box is too narrow, and that reflow is a container query — the class\n * never changes. No unit test can see the difference in any case, jsdom having no\n * layout at all; assert the opt-in with {@link isResponsive} instead.\n */\n async getOrientation(): Promise<'horizontal' | 'vertical'> {\n return (await (await this.host()).hasClass('wr-stepper--vertical')) ? 'vertical' : 'horizontal';\n }\n\n /** Whether the stepper locks the steps after the last completed one. */\n async isLinear(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper--linear');\n }\n\n /** Whether the stepper may reflow to the vertical layout in a narrow container. */\n async isResponsive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-stepper--responsive');\n }\n\n /**\n * The role the header strip announces — `list`.\n *\n * An `<ol>` is a list already, so the explicit role looks redundant and is not: the\n * stylesheet removes the markers, and Safari drops list semantics from a list with\n * `list-style: none`. Losing it costs the \"list, 3 items\" a VoiceOver user hears,\n * which is how they learn how long the wizard is before starting it.\n */\n async getListRole(): Promise<string | null> {\n return (await this.headerList()).getAttribute('role');\n }\n\n /** The wizard's steps, in order. */\n async getSteps(filters: WrStepHarnessFilters = {}): Promise<WrStepHarness[]> {\n return this.locatorForAll(WrStepHarness.with(filters))();\n }\n\n /** The label of every step, in order. */\n async getStepLabels(): Promise<string[]> {\n const steps = await this.getSteps();\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /**\n * The index of the step the wizard is showing, from the header announcing\n * `aria-current=\"step\"`.\n *\n * Throws when no header does, which is a state a stepper can genuinely be in: one\n * with no `<wr-step>` children renders its (empty) header strip and no body. A `-1`\n * here would be read as \"the first step\" by the next line of a spec. An\n * out-of-range `active` is NOT such a state — `WrStepper` clamps the two-way model\n * back into the step list, not only inside `goTo()`.\n */\n async getActiveIndex(): Promise<number> {\n const steps = await this.getSteps();\n for (let index = 0; index < steps.length; index++) {\n if (await steps[index].isActive()) return index;\n }\n\n throw new Error(\n 'WrStepperHarness.getActiveIndex(): no header announces `aria-current=\"step\"` — this stepper has ' +\n 'no <wr-step> children, so there is no step for it to be on. An out-of-range `active` cannot ' +\n 'produce this: WrStepper clamps the bound index to the step list.'\n );\n }\n\n /** The label of the step the wizard is showing. Throws when there is no current step. */\n async getActiveLabel(): Promise<string> {\n const steps = await this.getSteps();\n return steps[await this.getActiveIndex()].getLabel();\n }\n\n /** The labels of the steps shown as done, in order. Derived completion and overrides both. */\n async getCompletedLabels(): Promise<string[]> {\n const steps = await this.getSteps({ completed: true });\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /**\n * The labels of the headers a Tab press can reach, in order.\n *\n * A stepper does NOT rove focus: unlike a tab strip, the header list is not one tab\n * stop with arrow keys inside it — every reachable header is its own stop, and the\n * component authors no `tabindex` at all. So the question \"which step is active\" has\n * two different answers, and this is the other one: the current step is not\n * necessarily in this list. A step disabled by its own input keeps\n * `aria-current=\"step\"` while its button drops out of the tab order entirely, and a\n * `linear` stepper takes every locked header off the keyboard the same way.\n */\n async getTabStopLabels(): Promise<string[]> {\n const steps = await this.getSteps({ reachable: true });\n return Promise.all(steps.map(step => step.getLabel()));\n }\n\n /** The label of the header that currently has focus, or `null` when focus is elsewhere. */\n async getFocusedLabel(): Promise<string | null> {\n for (const step of await this.getSteps()) {\n if (await step.isFocused()) return step.getLabel();\n }\n return null;\n }\n\n /**\n * Whether the wizard would let a user navigate to this step right now — the question\n * a `linear` stepper exists to answer `false` to.\n *\n * Throws for an index that is not a step, rather than answering `false`: \"you cannot\n * go there\" and \"there is no there\" are different findings.\n */\n async canGoTo(index: number): Promise<boolean> {\n return (await this.stepAt(index)).isReachable();\n }\n\n /**\n * Navigate to the step at `index` by clicking its header.\n *\n * Throws when the wizard refuses, naming the cause — the step's own `disabled`, or\n * the `linear` gate and which earlier step is holding it shut. Silence would be\n * worse than a failure here: the component drops a click on a locked header without\n * a sound, so a spec would go on to assert against the step it was already showing.\n */\n async goTo(index: number): Promise<void> {\n const step = await this.stepAt(index);\n\n if (!(await step.isReachable())) {\n throw new Error(\n `WrStepperHarness.goTo(${index}): the header for \"${await step.getLabel()}\" refuses a click — ` +\n `${await this.refusal(index)}. Note that \\`WrStepper.goTo()\\` and \\`next()\\` move anyway: the gate is ` +\n \"on the header click, so a wizard's own Next button has to check for itself.\"\n );\n }\n\n await step.select();\n\n if (!(await step.isActive())) {\n throw new Error(\n `WrStepperHarness.goTo(${index}): the header for \"${await step.getLabel()}\" was clicked and the wizard ` +\n 'is still showing another step — its `active` model reached nothing, so a two-way `[(active)]` binding ' +\n 'is overwriting it or the click is not wired.'\n );\n }\n }\n\n /**\n * Navigate to the step with this label — a string matches exactly, a RegExp is\n * tested. Throws naming the labels that do exist when nothing matches.\n */\n async goToLabel(label: string | RegExp): Promise<void> {\n const labels = await this.getStepLabels();\n for (let index = 0; index < labels.length; index++) {\n if (await HarnessPredicate.stringMatches(labels[index], label)) return this.goTo(index);\n }\n\n throw new Error(\n `WrStepperHarness.goToLabel(): no step is labelled ${JSON.stringify(String(label))}. This wizard has: ` +\n `${labels.join(', ')}.`\n );\n }\n\n /**\n * Move to the next step through its header — subject to the same gate a user is.\n *\n * In a `linear` wizard that gate is shut until the CURRENT step reports itself\n * complete (its own `completed` input; derived completion only ever covers steps\n * before the active one), so this throws there. That is not the harness being\n * strict: it is the header a user has, and the reason a linear wizard needs its own\n * Next button, which calls `WrStepper.next()` and is not gated at all.\n *\n * Throws on the last step, where the component's own `next()` clamps in silence.\n */\n async next(): Promise<void> {\n const index = await this.getActiveIndex();\n const steps = await this.getSteps();\n\n if (index === steps.length - 1) {\n throw new Error(\n `WrStepperHarness.next(): the wizard is already on its last step (\"${await steps[index].getLabel()}\") — ` +\n 'there is nothing after it. `WrStepper.next()` clamps silently instead of saying so.'\n );\n }\n\n await this.goTo(index + 1);\n }\n\n /**\n * Move to the previous step through its header. Throws on the first step, where\n * `WrStepper.prev()` clamps in silence.\n *\n * Going back is normally allowed even in a `linear` wizard — every step at or before\n * the active one is reachable — but a step its own input disabled stays out of\n * reach in both directions.\n */\n async previous(): Promise<void> {\n const index = await this.getActiveIndex();\n\n if (index === 0) {\n throw new Error(\n 'WrStepperHarness.previous(): the wizard is already on its first step — there is nothing before it. ' +\n '`WrStepper.prev()` clamps silently instead of saying so.'\n );\n }\n\n await this.goTo(index - 1);\n }\n\n /**\n * The text of the step body the wizard is showing.\n *\n * Which body shows is CSS-only: every `<wr-step>` renders, and the stepper hides all\n * but one with `display: none` through the `--active` class. So this reads the class,\n * and in a unit test it has to — jsdom loads no stylesheet, which makes\n * `fixture.nativeElement.textContent` the text of ALL the steps at once and any\n * \"is the body showing\" assertion built on it meaningless.\n */\n async getActiveStepText(): Promise<string> {\n const active = await this.locatorForOptional('.wr-stepper__body .wr-step--active')();\n if (!active) {\n throw new Error(\n 'WrStepperHarness.getActiveStepText(): no step body is showing — the bound `active` index is outside ' +\n 'the step list, or this stepper has no <wr-step> children.'\n );\n }\n return wrStepperHarnessText(await active.text());\n }\n\n /**\n * The text of EVERY step body, in order, showing or not.\n *\n * The list being complete is the point: a step is hidden by a class rather than\n * dropped by an `@if`, so it mounts once and keeps its state — a half-filled form on\n * step 1 is still filled after a trip to step 3. Anything that turned the body into\n * a conditional block would keep every other assertion in a spec passing and quietly\n * reset the wizard.\n */\n async getStepTexts(): Promise<string[]> {\n const bodies = await this.locatorForAll('.wr-stepper__body > wr-step')();\n return Promise.all(bodies.map(async body => wrStepperHarnessText(await body.text())));\n }\n\n /** The step at `index`, or a failure that says how long the wizard is. */\n private async stepAt(index: number): Promise<WrStepHarness> {\n const steps = await this.getSteps();\n const step = steps[index];\n if (!step) {\n throw new Error(\n `WrStepperHarness: there is no step ${index} — this wizard has ${steps.length} ` +\n `${steps.length === 1 ? 'step' : 'steps'}${steps.length ? `: ${(await this.getStepLabels()).join(', ')}` : ''}.`\n );\n }\n return step;\n }\n\n /** Why the header at `index` is refusing a click, in the component's own order of causes. */\n private async refusal(index: number): Promise<string> {\n const steps = await this.getSteps();\n\n // The step's own input wins in the component too: `isReachable()` answers `false`\n // for a disabled step before it ever looks at the gate.\n if (await steps[index].isDisabled()) return 'the step carries `disabled`';\n\n if (await this.isLinear()) {\n for (let before = 0; before < index; before++) {\n if (!(await steps[before].isCompleted())) {\n return (\n 'the stepper is `linear` and step ' +\n `${before + 1} (\"${await steps[before].getLabel()}\") has not reported itself complete`\n );\n }\n }\n }\n\n return 'its header button is disabled';\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -55,10 +55,10 @@ class WrStep {
|
|
|
55
55
|
stepper = inject(WR_STEPPER);
|
|
56
56
|
isActive = computed(() => this._index() === this.stepper.active(), /* @ts-ignore */
|
|
57
57
|
...(ngDevMode ? [{ debugName: "isActive" }] : /* istanbul ignore next */ []));
|
|
58
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
59
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
58
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStep, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
59
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: WrStep, isStandalone: true, selector: "wr-step", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, description: { classPropertyName: "description", publicName: "description", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, completed: { classPropertyName: "completed", publicName: "completed", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.wr-step--active": "isActive()" }, classAttribute: "wr-step" }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
60
60
|
}
|
|
61
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
61
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStep, decorators: [{
|
|
62
62
|
type: Component,
|
|
63
63
|
args: [{
|
|
64
64
|
selector: 'wr-step',
|
|
@@ -192,8 +192,8 @@ class WrStepper {
|
|
|
192
192
|
prev() {
|
|
193
193
|
this.goTo(this.active() - 1);
|
|
194
194
|
}
|
|
195
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
196
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
195
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStepper, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
196
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrStepper, isStandalone: true, selector: "wr-stepper", inputs: { active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, linear: { classPropertyName: "linear", publicName: "linear", isSignal: true, isRequired: false, transformFunction: null }, responsive: { classPropertyName: "responsive", publicName: "responsive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { active: "activeChange" }, host: { properties: { "class": "classes()" } }, providers: [
|
|
197
197
|
{
|
|
198
198
|
provide: WR_STEPPER,
|
|
199
199
|
// eslint-disable-next-line @angular-eslint/no-forward-ref
|
|
@@ -201,7 +201,7 @@ class WrStepper {
|
|
|
201
201
|
},
|
|
202
202
|
], queries: [{ propertyName: "steps", predicate: WrStep, isSignal: true }], ngImport: i0, template: "<ol class=\"wr-stepper__headers\" role=\"list\">\n @for (step of steps(); track $index) {\n <li\n class=\"wr-stepper__header\"\n [class.wr-stepper__header--active]=\"$index === active()\"\n [class.wr-stepper__header--completed]=\"isCompleted($index)\"\n [class.wr-stepper__header--reachable]=\"isReachable($index)\"\n [class.wr-stepper__header--disabled]=\"step.disabled()\"\n >\n <button\n type=\"button\"\n class=\"wr-stepper__header-button\"\n [disabled]=\"!isReachable($index) || step.disabled()\"\n [attr.aria-current]=\"$index === active() ? 'step' : null\"\n (click)=\"onHeaderClick($index)\"\n >\n <span class=\"wr-stepper__indicator\" aria-hidden=\"true\">\n @if (isCompleted($index)) {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\">\n <path\n d=\"M3 7.5 L6 10.5 L11 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n <span class=\"wr-stepper__label\">\n {{ step.label() }}\n @if (step.optional()) {\n <small class=\"wr-stepper__optional\">{{ optionalLabel() }}</small>\n }\n @if (step.description()) {\n <small class=\"wr-stepper__description\">{{ step.description() }}</small>\n }\n </span>\n </button>\n @if (!$last) {\n <span class=\"wr-stepper__connector\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n</ol>\n\n<div class=\"wr-stepper__body\">\n <ng-content />\n</div>\n", encapsulation: i0.ViewEncapsulation.None });
|
|
203
203
|
}
|
|
204
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
204
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStepper, decorators: [{
|
|
205
205
|
type: Component,
|
|
206
206
|
args: [{ selector: 'wr-stepper', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, providers: [
|
|
207
207
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-stepper.mjs","sources":["../../../projects/lib/stepper/tokens.ts","../../../projects/lib/stepper/step.ts","../../../projects/lib/stepper/stepper.ts","../../../projects/lib/stepper/stepper.html","../../../projects/lib/stepper/ngwr-stepper.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type Signal } from '@angular/core';\n\n/** Surface a {@link WrStepper} provides for its child `<wr-step>`s. */\nexport interface WrStepperContext {\n /** Index of the currently visible step. */\n readonly active: Signal<number>;\n /** Linear mode — steps after the latest completed one are locked. */\n readonly linear: Signal<boolean>;\n}\n\nexport const WR_STEPPER = new InjectionToken<WrStepperContext>('WR_STEPPER');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, inject, input, signal } from '@angular/core';\n\nimport { WR_STEPPER } from './tokens';\n\n/**\n * One step in a {@link WrStepper}. Project as a child:\n *\n * ```html\n * <wr-stepper>\n * <wr-step label=\"Account\"> … </wr-step>\n * <wr-step label=\"Profile\" description=\"Optional\"> … </wr-step>\n * </wr-stepper>\n * ```\n *\n * The stepper hides every step except the active one via a host class —\n * each step still mounts once, so component state survives navigation.\n *\n * @see https://ngwr.dev/reference/components/stepper\n */\n@Component({\n selector: 'wr-step',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-step',\n '[class.wr-step--active]': 'isActive()',\n },\n})\nexport class WrStep {\n /** Header label. */\n readonly label = input<string>('');\n\n /** Secondary text shown under the label. */\n readonly description = input<string>('');\n\n /** Marks the step as optional in the header. */\n readonly optional = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Override completion state. When unset, the stepper auto-derives it\n * from the active index (any step before `active` is completed).\n */\n readonly completed = input<boolean | null>(null);\n\n /** Disables the header — also blocks header clicks. */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Stepper-assigned index. Set by the parent when contentChildren updates. */\n readonly _index = signal(-1);\n\n private readonly stepper = inject(WR_STEPPER);\n\n protected readonly isActive = computed(() => this._index() === this.stepper.active());\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n ViewEncapsulation,\n computed,\n contentChildren,\n effect,\n forwardRef,\n input,\n model,\n signal,\n} from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport { WrStep } from './step';\nimport { WR_STEPPER, type WrStepperContext } from './tokens';\n\n/** A label with no consumer input to forward — see `optionalLabel` below. */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\n/**\n * Multi-step wizard container. Children are `<wr-step>` components — the\n * stepper renders one numbered header per step (with connectors) and the\n * body of the currently active one.\n *\n * Two-way bind `[(active)]` to the active step index. Set `linear=\"true\"`\n * to forbid jumping past incomplete steps.\n *\n * @example\n * ```html\n * <wr-stepper [(active)]=\"step\" linear>\n * <wr-step label=\"Account\">…</wr-step>\n * <wr-step label=\"Profile\">…</wr-step>\n * <wr-step label=\"Confirm\">…</wr-step>\n * </wr-stepper>\n * ```\n *\n * @see https://ngwr.dev/reference/components/stepper\n */\n@Component({\n selector: 'wr-stepper',\n templateUrl: './stepper.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: WR_STEPPER,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrStepper),\n },\n ],\n})\nexport class WrStepper implements WrStepperContext {\n /** Index of the currently visible step. */\n readonly active = model(0);\n\n /** Layout direction. @default 'horizontal' */\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n\n /** Lock steps after the latest completed one. @default false */\n readonly linear = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Drop a horizontal stepper to a vertical layout when its own box is too\n * narrow for the row (a container query on its own width, not the\n * viewport — so it adapts inside a narrow column or side panel). No effect\n * when `orientation` is already `vertical`. @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n\n protected readonly steps = contentChildren(WrStep);\n\n /**\n * The \"optional\" badge sits INSIDE the header button's label span, so the word\n * is part of the step's accessible name — a hard-coded literal announced English\n * to every locale, not just showed it. Catalog-only rather than an input: the\n * badge is one word shared by every step, and an app that wants other wording\n * overrides `stepper.optional` once instead of on every `<wr-step>`.\n */\n protected readonly optionalLabel = useI18nText(NO_OVERRIDE, 'stepper.optional', 'optional');\n\n protected readonly classes = computed(() => {\n const parts = ['wr-stepper', `wr-stepper--${this.orientation()}`];\n if (this.linear()) parts.push('wr-stepper--linear');\n if (this.responsive()) parts.push('wr-stepper--responsive');\n return parts.join(' ');\n });\n\n constructor() {\n // Push each step's index down so it can compute its own active state.\n effect(() => {\n this.steps().forEach((step, i) => step._index.set(i));\n });\n\n // `active` is a plain `model`, so `[(active)]` and an `@if`-shrunk step list\n // both write into it unchecked — only `goTo` clamped. Out of range no step\n // matches `.wr-step--active`, and since `.wr-step` is `display: none` until it\n // does, the stepper renders its header row over an empty body with no header\n // carrying `aria-current=\"step\"`. Same guard as `wr-carousel`; the `last < 0`\n // return keeps it quiet until `contentChildren` resolves.\n effect(() => {\n const last = this.steps().length - 1;\n if (last < 0) return;\n const clamped = Math.min(Math.max(0, this.active()), last);\n if (clamped !== this.active()) this.active.set(clamped);\n });\n }\n\n /** Is the step at `index` considered completed? */\n protected isCompleted(index: number): boolean {\n const override = this.steps()[index]?.completed();\n if (override !== null && override !== undefined) return override;\n return index < this.active();\n }\n\n /** Is the step at `index` reachable for direct header clicks? */\n protected isReachable(index: number): boolean {\n if (this.steps()[index]?.disabled()) return false;\n if (!this.linear()) return true;\n if (index <= this.active()) return true;\n for (let i = 0; i < index; i++) {\n if (!this.isCompleted(i)) return false;\n }\n return true;\n }\n\n protected onHeaderClick(index: number): void {\n if (this.isReachable(index)) this.goTo(index);\n }\n\n // Imperative API\n\n goTo(index: number): void {\n const last = this.steps().length - 1;\n if (last < 0) return;\n const clamped = Math.min(Math.max(0, index), last);\n this.active.set(clamped);\n }\n\n next(): void {\n this.goTo(this.active() + 1);\n }\n\n prev(): void {\n this.goTo(this.active() - 1);\n }\n}\n","<ol class=\"wr-stepper__headers\" role=\"list\">\n @for (step of steps(); track $index) {\n <li\n class=\"wr-stepper__header\"\n [class.wr-stepper__header--active]=\"$index === active()\"\n [class.wr-stepper__header--completed]=\"isCompleted($index)\"\n [class.wr-stepper__header--reachable]=\"isReachable($index)\"\n [class.wr-stepper__header--disabled]=\"step.disabled()\"\n >\n <button\n type=\"button\"\n class=\"wr-stepper__header-button\"\n [disabled]=\"!isReachable($index) || step.disabled()\"\n [attr.aria-current]=\"$index === active() ? 'step' : null\"\n (click)=\"onHeaderClick($index)\"\n >\n <span class=\"wr-stepper__indicator\" aria-hidden=\"true\">\n @if (isCompleted($index)) {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\">\n <path\n d=\"M3 7.5 L6 10.5 L11 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n <span class=\"wr-stepper__label\">\n {{ step.label() }}\n @if (step.optional()) {\n <small class=\"wr-stepper__optional\">{{ optionalLabel() }}</small>\n }\n @if (step.description()) {\n <small class=\"wr-stepper__description\">{{ step.description() }}</small>\n }\n </span>\n </button>\n @if (!$last) {\n <span class=\"wr-stepper__connector\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n</ol>\n\n<div class=\"wr-stepper__body\">\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-stepper.mjs","sources":["../../../projects/lib/stepper/tokens.ts","../../../projects/lib/stepper/step.ts","../../../projects/lib/stepper/stepper.ts","../../../projects/lib/stepper/stepper.html","../../../projects/lib/stepper/ngwr-stepper.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken, type Signal } from '@angular/core';\n\n/** Surface a {@link WrStepper} provides for its child `<wr-step>`s. */\nexport interface WrStepperContext {\n /** Index of the currently visible step. */\n readonly active: Signal<number>;\n /** Linear mode — steps after the latest completed one are locked. */\n readonly linear: Signal<boolean>;\n}\n\nexport const WR_STEPPER = new InjectionToken<WrStepperContext>('WR_STEPPER');\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, inject, input, signal } from '@angular/core';\n\nimport { WR_STEPPER } from './tokens';\n\n/**\n * One step in a {@link WrStepper}. Project as a child:\n *\n * ```html\n * <wr-stepper>\n * <wr-step label=\"Account\"> … </wr-step>\n * <wr-step label=\"Profile\" description=\"Optional\"> … </wr-step>\n * </wr-stepper>\n * ```\n *\n * The stepper hides every step except the active one via a host class —\n * each step still mounts once, so component state survives navigation.\n *\n * @see https://ngwr.dev/reference/components/stepper\n */\n@Component({\n selector: 'wr-step',\n template: '<ng-content />',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-step',\n '[class.wr-step--active]': 'isActive()',\n },\n})\nexport class WrStep {\n /** Header label. */\n readonly label = input<string>('');\n\n /** Secondary text shown under the label. */\n readonly description = input<string>('');\n\n /** Marks the step as optional in the header. */\n readonly optional = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Override completion state. When unset, the stepper auto-derives it\n * from the active index (any step before `active` is completed).\n */\n readonly completed = input<boolean | null>(null);\n\n /** Disables the header — also blocks header clicks. */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Stepper-assigned index. Set by the parent when contentChildren updates. */\n readonly _index = signal(-1);\n\n private readonly stepper = inject(WR_STEPPER);\n\n protected readonly isActive = computed(() => this._index() === this.stepper.active());\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n ViewEncapsulation,\n computed,\n contentChildren,\n effect,\n forwardRef,\n input,\n model,\n signal,\n} from '@angular/core';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport { WrStep } from './step';\nimport { WR_STEPPER, type WrStepperContext } from './tokens';\n\n/** A label with no consumer input to forward — see `optionalLabel` below. */\nconst NO_OVERRIDE = signal<string | null>(null).asReadonly();\n\n/**\n * Multi-step wizard container. Children are `<wr-step>` components — the\n * stepper renders one numbered header per step (with connectors) and the\n * body of the currently active one.\n *\n * Two-way bind `[(active)]` to the active step index. Set `linear=\"true\"`\n * to forbid jumping past incomplete steps.\n *\n * @example\n * ```html\n * <wr-stepper [(active)]=\"step\" linear>\n * <wr-step label=\"Account\">…</wr-step>\n * <wr-step label=\"Profile\">…</wr-step>\n * <wr-step label=\"Confirm\">…</wr-step>\n * </wr-stepper>\n * ```\n *\n * @see https://ngwr.dev/reference/components/stepper\n */\n@Component({\n selector: 'wr-stepper',\n templateUrl: './stepper.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n providers: [\n {\n provide: WR_STEPPER,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrStepper),\n },\n ],\n})\nexport class WrStepper implements WrStepperContext {\n /** Index of the currently visible step. */\n readonly active = model(0);\n\n /** Layout direction. @default 'horizontal' */\n readonly orientation = input<'horizontal' | 'vertical'>('horizontal');\n\n /** Lock steps after the latest completed one. @default false */\n readonly linear = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Drop a horizontal stepper to a vertical layout when its own box is too\n * narrow for the row (a container query on its own width, not the\n * viewport — so it adapts inside a narrow column or side panel). No effect\n * when `orientation` is already `vertical`. @default false\n */\n readonly responsive = input(false, { transform: coerceBooleanProperty });\n\n protected readonly steps = contentChildren(WrStep);\n\n /**\n * The \"optional\" badge sits INSIDE the header button's label span, so the word\n * is part of the step's accessible name — a hard-coded literal announced English\n * to every locale, not just showed it. Catalog-only rather than an input: the\n * badge is one word shared by every step, and an app that wants other wording\n * overrides `stepper.optional` once instead of on every `<wr-step>`.\n */\n protected readonly optionalLabel = useI18nText(NO_OVERRIDE, 'stepper.optional', 'optional');\n\n protected readonly classes = computed(() => {\n const parts = ['wr-stepper', `wr-stepper--${this.orientation()}`];\n if (this.linear()) parts.push('wr-stepper--linear');\n if (this.responsive()) parts.push('wr-stepper--responsive');\n return parts.join(' ');\n });\n\n constructor() {\n // Push each step's index down so it can compute its own active state.\n effect(() => {\n this.steps().forEach((step, i) => step._index.set(i));\n });\n\n // `active` is a plain `model`, so `[(active)]` and an `@if`-shrunk step list\n // both write into it unchecked — only `goTo` clamped. Out of range no step\n // matches `.wr-step--active`, and since `.wr-step` is `display: none` until it\n // does, the stepper renders its header row over an empty body with no header\n // carrying `aria-current=\"step\"`. Same guard as `wr-carousel`; the `last < 0`\n // return keeps it quiet until `contentChildren` resolves.\n effect(() => {\n const last = this.steps().length - 1;\n if (last < 0) return;\n const clamped = Math.min(Math.max(0, this.active()), last);\n if (clamped !== this.active()) this.active.set(clamped);\n });\n }\n\n /** Is the step at `index` considered completed? */\n protected isCompleted(index: number): boolean {\n const override = this.steps()[index]?.completed();\n if (override !== null && override !== undefined) return override;\n return index < this.active();\n }\n\n /** Is the step at `index` reachable for direct header clicks? */\n protected isReachable(index: number): boolean {\n if (this.steps()[index]?.disabled()) return false;\n if (!this.linear()) return true;\n if (index <= this.active()) return true;\n for (let i = 0; i < index; i++) {\n if (!this.isCompleted(i)) return false;\n }\n return true;\n }\n\n protected onHeaderClick(index: number): void {\n if (this.isReachable(index)) this.goTo(index);\n }\n\n // Imperative API\n\n goTo(index: number): void {\n const last = this.steps().length - 1;\n if (last < 0) return;\n const clamped = Math.min(Math.max(0, index), last);\n this.active.set(clamped);\n }\n\n next(): void {\n this.goTo(this.active() + 1);\n }\n\n prev(): void {\n this.goTo(this.active() - 1);\n }\n}\n","<ol class=\"wr-stepper__headers\" role=\"list\">\n @for (step of steps(); track $index) {\n <li\n class=\"wr-stepper__header\"\n [class.wr-stepper__header--active]=\"$index === active()\"\n [class.wr-stepper__header--completed]=\"isCompleted($index)\"\n [class.wr-stepper__header--reachable]=\"isReachable($index)\"\n [class.wr-stepper__header--disabled]=\"step.disabled()\"\n >\n <button\n type=\"button\"\n class=\"wr-stepper__header-button\"\n [disabled]=\"!isReachable($index) || step.disabled()\"\n [attr.aria-current]=\"$index === active() ? 'step' : null\"\n (click)=\"onHeaderClick($index)\"\n >\n <span class=\"wr-stepper__indicator\" aria-hidden=\"true\">\n @if (isCompleted($index)) {\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\">\n <path\n d=\"M3 7.5 L6 10.5 L11 4.5\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.75\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n } @else {\n {{ $index + 1 }}\n }\n </span>\n <span class=\"wr-stepper__label\">\n {{ step.label() }}\n @if (step.optional()) {\n <small class=\"wr-stepper__optional\">{{ optionalLabel() }}</small>\n }\n @if (step.description()) {\n <small class=\"wr-stepper__description\">{{ step.description() }}</small>\n }\n </span>\n </button>\n @if (!$last) {\n <span class=\"wr-stepper__connector\" aria-hidden=\"true\"></span>\n }\n </li>\n }\n</ol>\n\n<div class=\"wr-stepper__body\">\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -314,10 +314,10 @@ class WrStorage {
|
|
|
314
314
|
this.listenerInstalled = false;
|
|
315
315
|
});
|
|
316
316
|
}
|
|
317
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
318
|
-
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.
|
|
317
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStorage, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
318
|
+
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.7", ngImport: i0, type: WrStorage });
|
|
319
319
|
}
|
|
320
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
320
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrStorage, decorators: [{
|
|
321
321
|
type: Service
|
|
322
322
|
}] });
|
|
323
323
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-storage.mjs","sources":["../../../projects/lib/storage/storage-config.ts","../../../projects/lib/storage/storage-engine.ts","../../../projects/lib/storage/storage.ts","../../../projects/lib/storage/provide-wr-storage.ts","../../../projects/lib/storage/ngwr-storage.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageConfigResolved } from './interfaces';\n\nexport const DEFAULT_WR_STORAGE_CONFIG: WrStorageConfigResolved = {\n prefix: '',\n json: true,\n ttl: 0,\n};\n\nexport const WR_STORAGE_CONFIG = new InjectionToken<WrStorageConfigResolved>('WR_STORAGE_CONFIG', {\n providedIn: 'root',\n factory: () => DEFAULT_WR_STORAGE_CONFIG,\n});\n\nexport type { WrStorageConfig, WrStorageConfigResolved } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageEngine } from './interfaces';\n\n/**\n * Probe a `Storage` candidate to confirm it's writable. Safari private\n * mode, disabled cookies, and storage-blocked iframes all throw on\n * `setItem` — fall back to memory in those cases.\n */\nfunction probe(engine: WrStorageEngine): boolean {\n try {\n const k = '__wr_storage_probe__';\n engine.setItem(k, '1');\n engine.removeItem(k);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * In-memory implementation of `Storage`. Used as the SSR / private-mode\n * fallback. Exported so consumers can opt into it explicitly for tests.\n */\nexport function createMemoryStorage(): WrStorageEngine {\n const map = new Map<string, string>();\n return {\n get length(): number {\n return map.size;\n },\n clear(): void {\n map.clear();\n },\n getItem(key: string): string | null {\n return map.has(key) ? map.get(key)! : null;\n },\n key(i: number): string | null {\n return Array.from(map.keys())[i] ?? null;\n },\n removeItem(key: string): void {\n map.delete(key);\n },\n setItem(key: string, value: string): void {\n map.set(key, value);\n },\n };\n}\n\n/**\n * Injection token for the active storage engine. Override at any\n * injector level to swap engines (e.g. a feature module uses\n * `sessionStorage`; the rest uses `localStorage`):\n *\n * ```ts\n * providers: [{ provide: WR_STORAGE_ENGINE, useValue: sessionStorage }]\n * ```\n *\n * The default factory returns `localStorage` in the browser when it's\n * actually writable, an in-memory map otherwise.\n */\nexport const WR_STORAGE_ENGINE = new InjectionToken<WrStorageEngine>('WR_STORAGE_ENGINE', {\n providedIn: 'root',\n factory: () => {\n if (typeof localStorage === 'undefined') return createMemoryStorage();\n return probe(localStorage) ? localStorage : createMemoryStorage();\n },\n});\n\nexport type { WrStorageEngine } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport { DestroyRef, Service, PLATFORM_ID, type Signal, type WritableSignal, inject, signal } from '@angular/core';\n\nimport type { WrStorageEnvelope } from './interfaces';\nimport { WR_STORAGE_CONFIG } from './storage-config';\nimport { WR_STORAGE_ENGINE } from './storage-engine';\n\nfunction isEnvelope(x: unknown): x is WrStorageEnvelope {\n return x !== null && typeof x === 'object' && 'v' in x;\n}\n\n/**\n * Reactive key/value storage on top of any `Storage`-compatible engine.\n *\n * - **Swap engines** through {@link WR_STORAGE_ENGINE} or\n * {@link provideWrStorage}. Default: `localStorage` with an in-memory\n * fallback for SSR / private mode.\n * - **Namespacing** via `prefix` (config) — every key is transparently\n * prefixed on read / write.\n * - **TTL** per-call or default — values past their expiry are removed\n * lazily on the next `get` / `watch` read.\n * - **Reactive watch** — `watch(key)` returns a `Signal` that updates on\n * local writes and cross-tab `storage` events.\n * - **On-disk format** — values are wrapped in a {@link WrStorageEnvelope}\n * (`{\"v\":…,\"e\":…}`) while `json` is on. Anything reading the same key from\n * outside Angular has to unwrap it.\n *\n * SSR-safe: the default engine factory returns an in-memory shim when\n * `localStorage` is unavailable, so reads always work.\n *\n * @example\n * ```ts\n * const store = inject(WrStorage);\n *\n * store.set('user', { name: 'Ada' });\n * store.get<{ name: string }>('user'); // { name: 'Ada' }\n *\n * store.set('cart', items, { ttl: 60_000 }); // expires in 60s\n *\n * const theme = store.watch<'light' | 'dark'>('theme', 'light');\n * effect(() => console.log('theme is', theme()));\n * ```\n *\n * @see https://ngwr.dev/reference/services/storage\n */\n@Service()\nexport class WrStorage {\n private readonly engine = inject(WR_STORAGE_ENGINE);\n private readonly config = inject(WR_STORAGE_CONFIG);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal.\n *\n * The fallback is kept alongside the signal because every refresh has to read\n * the key the same way `watch` first did. Refreshing without it made `get` and\n * `watch` disagree about what an ABSENT key means: after a `remove()` the\n * signal went to `null` while `get(key, fallback)` still answered with the\n * default, so a consumer watching `'theme'` with a `'light'` fallback got no\n * theme at all rather than the light one.\n */\n private readonly watchers = new Map<string, { readonly sig: WritableSignal<unknown>; readonly fallback: unknown }>();\n private listenerInstalled = false;\n\n // Public API\n\n /** Is `key` present (regardless of value / expiry)? */\n has(key: string): boolean {\n return this.engine.getItem(this.fullKey(key)) !== null;\n }\n\n /**\n * Read `key`. Returns `fallback` (default `null`) when the key is\n * missing or expired. Expired values are also removed as a side effect.\n */\n get<T = unknown>(key: string, fallback: T | null = null): T | null {\n const fk = this.fullKey(key);\n const raw = this.engine.getItem(fk);\n if (raw === null) return fallback;\n\n if (!this.config.json) return raw as unknown as T;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // Non-JSON value written by external code — return as-is.\n return raw as unknown as T;\n }\n\n if (!isEnvelope(parsed)) return parsed as T;\n\n if (parsed.e !== undefined && parsed.e < Date.now()) {\n this.remove(key);\n return fallback;\n }\n return parsed.v as T;\n }\n\n /**\n * Write `value` at `key`. Per-call `ttl` (ms) overrides the config\n * default. JSON-serializable values only when `json` is on (the default).\n *\n * What lands in the engine is a {@link WrStorageEnvelope} —\n * `{\"v\":<value>}`, plus `\"e\"` when a TTL applies — not the bare value. Code\n * outside Angular that reads the same key has to unwrap it; see the envelope's\n * own docs for the exact format.\n */\n set<T = unknown>(key: string, value: T, opts?: { ttl?: number }): void {\n const fk = this.fullKey(key);\n let serialized: string;\n\n if (this.config.json) {\n const ttl = opts?.ttl ?? this.config.ttl;\n const env: WrStorageEnvelope<T> = ttl ? { v: value, e: Date.now() + ttl } : { v: value };\n try {\n serialized = JSON.stringify(env);\n } catch (err) {\n // eslint-disable-next-line no-console -- intentional diagnostic for unserialisable values\n console.warn('[ngwr/storage] value not JSON-serializable', err);\n return;\n }\n } else {\n serialized = String(value);\n }\n\n try {\n this.engine.setItem(fk, serialized);\n } catch (err) {\n // Quota exceeded / disabled / cleared mid-write — log + carry on.\n // eslint-disable-next-line no-console -- intentional diagnostic on storage write failure\n console.warn('[ngwr/storage] setItem failed', err);\n return;\n }\n this.notify(key);\n }\n\n /** Remove `key`. No-op when absent. */\n remove(key: string): void {\n this.engine.removeItem(this.fullKey(key));\n this.notify(key);\n }\n\n /**\n * Clear every key owned by this prefix. When `prefix` is empty this\n * defers to `engine.clear()` (clears everything — be careful with\n * shared storage).\n */\n clear(): void {\n const p = this.config.prefix;\n if (p) {\n for (const fk of this.rawKeys()) this.engine.removeItem(fk);\n } else {\n this.engine.clear();\n }\n // Refresh every active watcher — they may have just been cleared.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n }\n\n /** All known keys under our prefix, with the prefix stripped. */\n keys(): readonly string[] {\n const p = this.config.prefix;\n return this.rawKeys().map(k => (p ? k.slice(p.length) : k));\n }\n\n /**\n * Reactive read of `key`. Updates when this instance writes to the key,\n * when `clear()` runs, and when another tab updates `localStorage`\n * under the same prefix. Returned signal is shared per key — calling\n * `watch(k)` twice returns the same signal.\n */\n watch<T = unknown>(key: string, fallback: T | null = null): Signal<T | null> {\n const existing = this.watchers.get(key);\n if (existing) return (existing.sig as WritableSignal<T | null>).asReadonly();\n\n const sig = signal<T | null>(this.get<T>(key, fallback));\n this.watchers.set(key, { sig: sig, fallback });\n this.installCrossTabListener();\n return sig.asReadonly();\n }\n\n // Internals\n\n private fullKey(key: string): string {\n return this.config.prefix + key;\n }\n\n private notify(key: string): void {\n const entry = this.watchers.get(key);\n if (entry) entry.sig.set(this.get(key, entry.fallback));\n }\n\n private rawKeys(): string[] {\n const p = this.config.prefix;\n const out: string[] = [];\n for (let i = 0; i < this.engine.length; i++) {\n const k = this.engine.key(i);\n if (k === null) continue;\n if (!p || k.startsWith(p)) out.push(k);\n }\n return out;\n }\n\n private installCrossTabListener(): void {\n if (!this.isBrowser || this.listenerInstalled) return;\n this.listenerInstalled = true;\n\n const handler = (event: StorageEvent): void => {\n // `storage` only fires for `localStorage` / `sessionStorage`, and\n // only for changes from OTHER tabs. Local writes are handled by\n // `notify()` in `set`/`remove`/`clear`.\n if (event.key === null) {\n // Storage cleared from another tab.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n return;\n }\n const p = this.config.prefix;\n if (p && !event.key.startsWith(p)) return;\n this.notify(p ? event.key.slice(p.length) : event.key);\n };\n\n window.addEventListener('storage', handler);\n\n // The listener belongs to THIS injector. Root-provided it lives as long as\n // the page, but a route or component that lists `WrStorage` in its own\n // `providers` used to leave the handler on the window after its injector was\n // gone — still driving the watcher signals of a destroyed instance, and\n // holding the instance and every signal in it reachable for the life of the\n // page. Same bug `WrHotkey` already fixed once.\n this.destroyRef.onDestroy(() => {\n window.removeEventListener('storage', handler);\n this.listenerInstalled = false;\n });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, type Provider, makeEnvironmentProviders } from '@angular/core';\n\nimport {\n DEFAULT_WR_STORAGE_CONFIG,\n WR_STORAGE_CONFIG,\n type WrStorageConfig,\n type WrStorageConfigResolved,\n} from './storage-config';\nimport { WR_STORAGE_ENGINE, type WrStorageEngine } from './storage-engine';\n\n/**\n * Configure {@link WrStorage}. All fields optional — merged with defaults.\n *\n * @example Override the engine globally (e.g. session storage)\n * ```ts\n * provideWrStorage({ engine: sessionStorage })\n * ```\n *\n * @example Lazy engine factory (e.g. wrap localStorage with encryption)\n * ```ts\n * provideWrStorage({ engine: () => new EncryptedStorage(localStorage, key) })\n * ```\n *\n * @example Namespace + auto-expire\n * ```ts\n * provideWrStorage({ prefix: 'myapp:', ttl: 24 * 60 * 60 * 1000 })\n * ```\n */\nexport interface ProvideWrStorageOptions extends WrStorageConfig {\n /**\n * Storage engine. Either an instance (eager) or a factory (lazy —\n * called inside the injection context the first time `WR_STORAGE_ENGINE`\n * is read). Defaults to {@link WR_STORAGE_ENGINE}'s factory\n * (`localStorage` with in-memory fallback).\n */\n readonly engine?: WrStorageEngine | (() => WrStorageEngine);\n}\n\nexport function provideWrStorage(options: ProvideWrStorageOptions = {}): EnvironmentProviders {\n const { engine, ...config } = options;\n\n const merged: WrStorageConfigResolved = { ...DEFAULT_WR_STORAGE_CONFIG, ...config };\n\n const providers: Provider[] = [{ provide: WR_STORAGE_CONFIG, useValue: merged }];\n\n if (engine !== undefined) {\n providers.push(\n typeof engine === 'function'\n ? { provide: WR_STORAGE_ENGINE, useFactory: engine }\n : { provide: WR_STORAGE_ENGINE, useValue: engine }\n );\n }\n\n return makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-storage.mjs","sources":["../../../projects/lib/storage/storage-config.ts","../../../projects/lib/storage/storage-engine.ts","../../../projects/lib/storage/storage.ts","../../../projects/lib/storage/provide-wr-storage.ts","../../../projects/lib/storage/ngwr-storage.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageConfigResolved } from './interfaces';\n\nexport const DEFAULT_WR_STORAGE_CONFIG: WrStorageConfigResolved = {\n prefix: '',\n json: true,\n ttl: 0,\n};\n\nexport const WR_STORAGE_CONFIG = new InjectionToken<WrStorageConfigResolved>('WR_STORAGE_CONFIG', {\n providedIn: 'root',\n factory: () => DEFAULT_WR_STORAGE_CONFIG,\n});\n\nexport type { WrStorageConfig, WrStorageConfigResolved } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { InjectionToken } from '@angular/core';\n\nimport type { WrStorageEngine } from './interfaces';\n\n/**\n * Probe a `Storage` candidate to confirm it's writable. Safari private\n * mode, disabled cookies, and storage-blocked iframes all throw on\n * `setItem` — fall back to memory in those cases.\n */\nfunction probe(engine: WrStorageEngine): boolean {\n try {\n const k = '__wr_storage_probe__';\n engine.setItem(k, '1');\n engine.removeItem(k);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * In-memory implementation of `Storage`. Used as the SSR / private-mode\n * fallback. Exported so consumers can opt into it explicitly for tests.\n */\nexport function createMemoryStorage(): WrStorageEngine {\n const map = new Map<string, string>();\n return {\n get length(): number {\n return map.size;\n },\n clear(): void {\n map.clear();\n },\n getItem(key: string): string | null {\n return map.has(key) ? map.get(key)! : null;\n },\n key(i: number): string | null {\n return Array.from(map.keys())[i] ?? null;\n },\n removeItem(key: string): void {\n map.delete(key);\n },\n setItem(key: string, value: string): void {\n map.set(key, value);\n },\n };\n}\n\n/**\n * Injection token for the active storage engine. Override at any\n * injector level to swap engines (e.g. a feature module uses\n * `sessionStorage`; the rest uses `localStorage`):\n *\n * ```ts\n * providers: [{ provide: WR_STORAGE_ENGINE, useValue: sessionStorage }]\n * ```\n *\n * The default factory returns `localStorage` in the browser when it's\n * actually writable, an in-memory map otherwise.\n */\nexport const WR_STORAGE_ENGINE = new InjectionToken<WrStorageEngine>('WR_STORAGE_ENGINE', {\n providedIn: 'root',\n factory: () => {\n if (typeof localStorage === 'undefined') return createMemoryStorage();\n return probe(localStorage) ? localStorage : createMemoryStorage();\n },\n});\n\nexport type { WrStorageEngine } from './interfaces';\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport { DestroyRef, Service, PLATFORM_ID, type Signal, type WritableSignal, inject, signal } from '@angular/core';\n\nimport type { WrStorageEnvelope } from './interfaces';\nimport { WR_STORAGE_CONFIG } from './storage-config';\nimport { WR_STORAGE_ENGINE } from './storage-engine';\n\nfunction isEnvelope(x: unknown): x is WrStorageEnvelope {\n return x !== null && typeof x === 'object' && 'v' in x;\n}\n\n/**\n * Reactive key/value storage on top of any `Storage`-compatible engine.\n *\n * - **Swap engines** through {@link WR_STORAGE_ENGINE} or\n * {@link provideWrStorage}. Default: `localStorage` with an in-memory\n * fallback for SSR / private mode.\n * - **Namespacing** via `prefix` (config) — every key is transparently\n * prefixed on read / write.\n * - **TTL** per-call or default — values past their expiry are removed\n * lazily on the next `get` / `watch` read.\n * - **Reactive watch** — `watch(key)` returns a `Signal` that updates on\n * local writes and cross-tab `storage` events.\n * - **On-disk format** — values are wrapped in a {@link WrStorageEnvelope}\n * (`{\"v\":…,\"e\":…}`) while `json` is on. Anything reading the same key from\n * outside Angular has to unwrap it.\n *\n * SSR-safe: the default engine factory returns an in-memory shim when\n * `localStorage` is unavailable, so reads always work.\n *\n * @example\n * ```ts\n * const store = inject(WrStorage);\n *\n * store.set('user', { name: 'Ada' });\n * store.get<{ name: string }>('user'); // { name: 'Ada' }\n *\n * store.set('cart', items, { ttl: 60_000 }); // expires in 60s\n *\n * const theme = store.watch<'light' | 'dark'>('theme', 'light');\n * effect(() => console.log('theme is', theme()));\n * ```\n *\n * @see https://ngwr.dev/reference/services/storage\n */\n@Service()\nexport class WrStorage {\n private readonly engine = inject(WR_STORAGE_ENGINE);\n private readonly config = inject(WR_STORAGE_CONFIG);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n /**\n * Per-key watchers. Shared so multiple `watch(k)` calls reuse one signal.\n *\n * The fallback is kept alongside the signal because every refresh has to read\n * the key the same way `watch` first did. Refreshing without it made `get` and\n * `watch` disagree about what an ABSENT key means: after a `remove()` the\n * signal went to `null` while `get(key, fallback)` still answered with the\n * default, so a consumer watching `'theme'` with a `'light'` fallback got no\n * theme at all rather than the light one.\n */\n private readonly watchers = new Map<string, { readonly sig: WritableSignal<unknown>; readonly fallback: unknown }>();\n private listenerInstalled = false;\n\n // Public API\n\n /** Is `key` present (regardless of value / expiry)? */\n has(key: string): boolean {\n return this.engine.getItem(this.fullKey(key)) !== null;\n }\n\n /**\n * Read `key`. Returns `fallback` (default `null`) when the key is\n * missing or expired. Expired values are also removed as a side effect.\n */\n get<T = unknown>(key: string, fallback: T | null = null): T | null {\n const fk = this.fullKey(key);\n const raw = this.engine.getItem(fk);\n if (raw === null) return fallback;\n\n if (!this.config.json) return raw as unknown as T;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n // Non-JSON value written by external code — return as-is.\n return raw as unknown as T;\n }\n\n if (!isEnvelope(parsed)) return parsed as T;\n\n if (parsed.e !== undefined && parsed.e < Date.now()) {\n this.remove(key);\n return fallback;\n }\n return parsed.v as T;\n }\n\n /**\n * Write `value` at `key`. Per-call `ttl` (ms) overrides the config\n * default. JSON-serializable values only when `json` is on (the default).\n *\n * What lands in the engine is a {@link WrStorageEnvelope} —\n * `{\"v\":<value>}`, plus `\"e\"` when a TTL applies — not the bare value. Code\n * outside Angular that reads the same key has to unwrap it; see the envelope's\n * own docs for the exact format.\n */\n set<T = unknown>(key: string, value: T, opts?: { ttl?: number }): void {\n const fk = this.fullKey(key);\n let serialized: string;\n\n if (this.config.json) {\n const ttl = opts?.ttl ?? this.config.ttl;\n const env: WrStorageEnvelope<T> = ttl ? { v: value, e: Date.now() + ttl } : { v: value };\n try {\n serialized = JSON.stringify(env);\n } catch (err) {\n // eslint-disable-next-line no-console -- intentional diagnostic for unserialisable values\n console.warn('[ngwr/storage] value not JSON-serializable', err);\n return;\n }\n } else {\n serialized = String(value);\n }\n\n try {\n this.engine.setItem(fk, serialized);\n } catch (err) {\n // Quota exceeded / disabled / cleared mid-write — log + carry on.\n // eslint-disable-next-line no-console -- intentional diagnostic on storage write failure\n console.warn('[ngwr/storage] setItem failed', err);\n return;\n }\n this.notify(key);\n }\n\n /** Remove `key`. No-op when absent. */\n remove(key: string): void {\n this.engine.removeItem(this.fullKey(key));\n this.notify(key);\n }\n\n /**\n * Clear every key owned by this prefix. When `prefix` is empty this\n * defers to `engine.clear()` (clears everything — be careful with\n * shared storage).\n */\n clear(): void {\n const p = this.config.prefix;\n if (p) {\n for (const fk of this.rawKeys()) this.engine.removeItem(fk);\n } else {\n this.engine.clear();\n }\n // Refresh every active watcher — they may have just been cleared.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n }\n\n /** All known keys under our prefix, with the prefix stripped. */\n keys(): readonly string[] {\n const p = this.config.prefix;\n return this.rawKeys().map(k => (p ? k.slice(p.length) : k));\n }\n\n /**\n * Reactive read of `key`. Updates when this instance writes to the key,\n * when `clear()` runs, and when another tab updates `localStorage`\n * under the same prefix. Returned signal is shared per key — calling\n * `watch(k)` twice returns the same signal.\n */\n watch<T = unknown>(key: string, fallback: T | null = null): Signal<T | null> {\n const existing = this.watchers.get(key);\n if (existing) return (existing.sig as WritableSignal<T | null>).asReadonly();\n\n const sig = signal<T | null>(this.get<T>(key, fallback));\n this.watchers.set(key, { sig: sig, fallback });\n this.installCrossTabListener();\n return sig.asReadonly();\n }\n\n // Internals\n\n private fullKey(key: string): string {\n return this.config.prefix + key;\n }\n\n private notify(key: string): void {\n const entry = this.watchers.get(key);\n if (entry) entry.sig.set(this.get(key, entry.fallback));\n }\n\n private rawKeys(): string[] {\n const p = this.config.prefix;\n const out: string[] = [];\n for (let i = 0; i < this.engine.length; i++) {\n const k = this.engine.key(i);\n if (k === null) continue;\n if (!p || k.startsWith(p)) out.push(k);\n }\n return out;\n }\n\n private installCrossTabListener(): void {\n if (!this.isBrowser || this.listenerInstalled) return;\n this.listenerInstalled = true;\n\n const handler = (event: StorageEvent): void => {\n // `storage` only fires for `localStorage` / `sessionStorage`, and\n // only for changes from OTHER tabs. Local writes are handled by\n // `notify()` in `set`/`remove`/`clear`.\n if (event.key === null) {\n // Storage cleared from another tab.\n for (const [k, entry] of this.watchers) entry.sig.set(this.get(k, entry.fallback));\n return;\n }\n const p = this.config.prefix;\n if (p && !event.key.startsWith(p)) return;\n this.notify(p ? event.key.slice(p.length) : event.key);\n };\n\n window.addEventListener('storage', handler);\n\n // The listener belongs to THIS injector. Root-provided it lives as long as\n // the page, but a route or component that lists `WrStorage` in its own\n // `providers` used to leave the handler on the window after its injector was\n // gone — still driving the watcher signals of a destroyed instance, and\n // holding the instance and every signal in it reachable for the life of the\n // page. Same bug `WrHotkey` already fixed once.\n this.destroyRef.onDestroy(() => {\n window.removeEventListener('storage', handler);\n this.listenerInstalled = false;\n });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { type EnvironmentProviders, type Provider, makeEnvironmentProviders } from '@angular/core';\n\nimport {\n DEFAULT_WR_STORAGE_CONFIG,\n WR_STORAGE_CONFIG,\n type WrStorageConfig,\n type WrStorageConfigResolved,\n} from './storage-config';\nimport { WR_STORAGE_ENGINE, type WrStorageEngine } from './storage-engine';\n\n/**\n * Configure {@link WrStorage}. All fields optional — merged with defaults.\n *\n * @example Override the engine globally (e.g. session storage)\n * ```ts\n * provideWrStorage({ engine: sessionStorage })\n * ```\n *\n * @example Lazy engine factory (e.g. wrap localStorage with encryption)\n * ```ts\n * provideWrStorage({ engine: () => new EncryptedStorage(localStorage, key) })\n * ```\n *\n * @example Namespace + auto-expire\n * ```ts\n * provideWrStorage({ prefix: 'myapp:', ttl: 24 * 60 * 60 * 1000 })\n * ```\n */\nexport interface ProvideWrStorageOptions extends WrStorageConfig {\n /**\n * Storage engine. Either an instance (eager) or a factory (lazy —\n * called inside the injection context the first time `WR_STORAGE_ENGINE`\n * is read). Defaults to {@link WR_STORAGE_ENGINE}'s factory\n * (`localStorage` with in-memory fallback).\n */\n readonly engine?: WrStorageEngine | (() => WrStorageEngine);\n}\n\nexport function provideWrStorage(options: ProvideWrStorageOptions = {}): EnvironmentProviders {\n const { engine, ...config } = options;\n\n const merged: WrStorageConfigResolved = { ...DEFAULT_WR_STORAGE_CONFIG, ...config };\n\n const providers: Provider[] = [{ provide: WR_STORAGE_CONFIG, useValue: merged }];\n\n if (engine !== undefined) {\n providers.push(\n typeof engine === 'function'\n ? { provide: WR_STORAGE_ENGINE, useFactory: engine }\n : { provide: WR_STORAGE_ENGINE, useValue: engine }\n );\n }\n\n return makeEnvironmentProviders(providers);\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-switch-testing.mjs","sources":["../../../projects/lib/switch/testing/wr-switch-harness.ts","../../../projects/lib/switch/testing/ngwr-switch-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrSwitchHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-switch>`.\n *\n * The track and thumb are painted `<span>`s; the state lives on a real\n * `<input type=\"checkbox\" role=\"switch\">` inside the label, and that is what this\n * reads and clicks. The role is why a switch is not a checkbox to a screen reader,\n * and {@link isOn} is named after it rather than after `checked` for the same\n * reason — a spec that reads \"the switch is on\" says what the user sees.\n *\n * @example\n * ```ts\n * const dark = await loader.getHarness(WrSwitchHarness.with({ label: 'Dark mode' }));\n * await dark.turnOn();\n * expect(await dark.isOn()).toBe(true);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrSwitchHarness extends ComponentHarness {\n static hostSelector = 'wr-switch';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrSwitchHarnessFilters = {}): HarnessPredicate<WrSwitchHarness> {\n return new HarnessPredicate(WrSwitchHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('on', options.on, async (harness, on) => (await harness.isOn()) === on)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly input = this.locatorFor('input.wr-switch__input');\n\n /** The projected label text, trimmed. */\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-switch__label')()).text();\n }\n\n /** Whether the switch is on. */\n async isOn(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('checked');\n }\n\n async isDisabled(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('disabled');\n }\n\n /** What a screen reader is told this control is — `switch`, not `checkbox`. */\n async getRole(): Promise<string | null> {\n return (await this.input()).getAttribute('role');\n }\n\n /** Flip the switch. A disabled switch does not move; assert rather than assume. */\n async toggle(): Promise<void> {\n return (await this.input()).click();\n }\n\n async turnOn(): Promise<void> {\n if (!(await this.isOn())) await this.toggle();\n }\n\n async turnOff(): Promise<void> {\n if (await this.isOn()) await this.toggle();\n }\n\n async focus(): Promise<void> {\n return (await this.input()).focus();\n }\n\n async isFocused(): Promise<boolean> {\n return (await this.input()).isFocused();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;;;;;;AAiBG;AACG,MAAO,eAAgB,SAAQ,gBAAgB,CAAA;AACnD,IAAA,OAAO,YAAY,GAAG,WAAW;;AAGjC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAkC,EAAE,EAAA;AAC9C,QAAA,OAAO,IAAI,gBAAgB,CAAC,eAAe,EAAE,OAAO;aACjD,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;aAC/G,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,OAAO,EAAE,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE;aAChF,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEiB,IAAA,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC;;AAGlE,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,EAAE,IAAI,EAAE;IAC9D;;AAGA,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,WAAW,CAAU,SAAS,CAAC;IAC7D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC9D;;AAGA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IAClD;;AAGA,IAAA,MAAM,MAAM,GAAA;QACV,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE;IACrC;AAEA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;AAAE,YAAA,MAAM,IAAI,CAAC,MAAM,EAAE;IAC/C;AAEA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE;AAAE,YAAA,MAAM,IAAI,CAAC,MAAM,EAAE;IAC5C;AAEA,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE;IACrC;AAEA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE;IACzC;;;AChFF;;AAEG
|
|
1
|
+
{"version":3,"file":"ngwr-switch-testing.mjs","sources":["../../../projects/lib/switch/testing/wr-switch-harness.ts","../../../projects/lib/switch/testing/ngwr-switch-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';\n\nimport type { WrSwitchHarnessFilters } from './interfaces';\n\n/**\n * Test harness for `<wr-switch>`.\n *\n * The track and thumb are painted `<span>`s; the state lives on a real\n * `<input type=\"checkbox\" role=\"switch\">` inside the label, and that is what this\n * reads and clicks. The role is why a switch is not a checkbox to a screen reader,\n * and {@link isOn} is named after it rather than after `checked` for the same\n * reason — a spec that reads \"the switch is on\" says what the user sees.\n *\n * @example\n * ```ts\n * const dark = await loader.getHarness(WrSwitchHarness.with({ label: 'Dark mode' }));\n * await dark.turnOn();\n * expect(await dark.isOn()).toBe(true);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrSwitchHarness extends ComponentHarness {\n static hostSelector = 'wr-switch';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrSwitchHarnessFilters = {}): HarnessPredicate<WrSwitchHarness> {\n return new HarnessPredicate(WrSwitchHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('on', options.on, async (harness, on) => (await harness.isOn()) === on)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly input = this.locatorFor('input.wr-switch__input');\n\n /** The projected label text, trimmed. */\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-switch__label')()).text();\n }\n\n /** Whether the switch is on. */\n async isOn(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('checked');\n }\n\n async isDisabled(): Promise<boolean> {\n return (await this.input()).getProperty<boolean>('disabled');\n }\n\n /** What a screen reader is told this control is — `switch`, not `checkbox`. */\n async getRole(): Promise<string | null> {\n return (await this.input()).getAttribute('role');\n }\n\n /** Flip the switch. A disabled switch does not move; assert rather than assume. */\n async toggle(): Promise<void> {\n return (await this.input()).click();\n }\n\n async turnOn(): Promise<void> {\n if (!(await this.isOn())) await this.toggle();\n }\n\n async turnOff(): Promise<void> {\n if (await this.isOn()) await this.toggle();\n }\n\n async focus(): Promise<void> {\n return (await this.input()).focus();\n }\n\n async isFocused(): Promise<boolean> {\n return (await this.input()).isFocused();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;AAAA;;;;;AAKG;AAMH;;;;;;;;;;;;;;;;;AAiBG;AACG,MAAO,eAAgB,SAAQ,gBAAgB,CAAA;AACnD,IAAA,OAAO,YAAY,GAAG,WAAW;;AAGjC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAkC,EAAE,EAAA;AAC9C,QAAA,OAAO,IAAI,gBAAgB,CAAC,eAAe,EAAE,OAAO;aACjD,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,KAAK,CAAC;aAC/G,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE,OAAO,OAAO,EAAE,EAAE,KAAK,CAAC,MAAM,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE;aAChF,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEiB,IAAA,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,wBAAwB,CAAC;;AAGlE,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,EAAE,EAAE,IAAI,EAAE;IAC9D;;AAGA,IAAA,MAAM,IAAI,GAAA;AACR,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,WAAW,CAAU,SAAS,CAAC;IAC7D;AAEA,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,WAAW,CAAU,UAAU,CAAC;IAC9D;;AAGA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,YAAY,CAAC,MAAM,CAAC;IAClD;;AAGA,IAAA,MAAM,MAAM,GAAA;QACV,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE;IACrC;AAEA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,IAAI,EAAE,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;AAAE,YAAA,MAAM,IAAI,CAAC,MAAM,EAAE;IAC/C;AAEA,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,IAAI,MAAM,IAAI,CAAC,IAAI,EAAE;AAAE,YAAA,MAAM,IAAI,CAAC,MAAM,EAAE;IAC5C;AAEA,IAAA,MAAM,KAAK,GAAA;QACT,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE;IACrC;AAEA,IAAA,MAAM,SAAS,GAAA;QACb,OAAO,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE;IACzC;;;AChFF;;AAEG;;"}
|
package/fesm2022/ngwr-switch.mjs
CHANGED
|
@@ -94,10 +94,10 @@ class WrSwitch {
|
|
|
94
94
|
onInputBlur() {
|
|
95
95
|
this.touch.emit();
|
|
96
96
|
}
|
|
97
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
98
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.
|
|
97
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrSwitch, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
98
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.7", type: WrSwitch, isStandalone: true, selector: "wr-switch", inputs: { ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, checked: { classPropertyName: "checked", publicName: "checked", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { checked: "checkedChange", touch: "touch" }, host: { properties: { "class": "classes()", "attr.id": "null" } }, ngImport: i0, template: "<label class=\"wr-switch__label\" [for]=\"id()\">\n <input\n class=\"wr-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onInputClick($event)\"\n (change)=\"onInputChange($event)\"\n (blur)=\"onInputBlur()\"\n />\n\n <span class=\"wr-switch__track\" aria-hidden=\"true\">\n <span class=\"wr-switch__thumb\"></span>\n </span>\n\n <span class=\"wr-switch__text\">\n <ng-content />\n </span>\n</label>\n", encapsulation: i0.ViewEncapsulation.None });
|
|
99
99
|
}
|
|
100
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
100
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrSwitch, decorators: [{
|
|
101
101
|
type: Component,
|
|
102
102
|
args: [{ selector: 'wr-switch', encapsulation: ViewEncapsulation.None, host: {
|
|
103
103
|
'[class]': 'classes()',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-switch.mjs","sources":["../../../projects/lib/switch/switch.ts","../../../projects/lib/switch/switch.html","../../../projects/lib/switch/ngwr-switch.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input, model, output } from '@angular/core';\nimport type { FormCheckboxControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useFormFieldAria } from 'ngwr/form';\nimport { randomId } from 'ngwr/utils';\n\n/**\n * Boolean toggle with an iOS-style slider.\n *\n * A signal-forms native control: it implements `FormCheckboxControl`, so\n * `[formField]` binds straight to its `checked` model — no\n * `ControlValueAccessor` in between. `[(checked)]` works standalone.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-switch [formField]=\"form.notifications\">Notifications</wr-switch>\n *\n * <!-- standalone two-way binding -->\n * <wr-switch [(checked)]=\"enabled\">Notifications</wr-switch>\n * ```\n *\n * @see https://ngwr.dev/reference/components/switch\n */\nexport type WrSwitchSize = 'sm' | 'md' | 'lg';\n\n@Component({\n selector: 'wr-switch',\n templateUrl: './switch.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n // The `id` input belongs to the native input, not to this element — a static\n // `id=\"x\"` would otherwise be written here too and leave the document with\n // two elements sharing it, which is what broke `<label for>`.\n '[attr.id]': 'null',\n },\n})\nexport class WrSwitch implements FormCheckboxControl {\n /**\n * Accessible name for a switch used WITHOUT projected text. The wrapping\n * `<label>` names the control whenever content is projected; with none, the\n * label is empty and the input has no name at all.\n */\n readonly ariaLabel = input<string | null>(null);\n\n /**\n * Stable id used to associate the native input with its label. Lands on the\n * inner `<input>`; the host never keeps it.\n */\n readonly id = input<string>(randomId('wr-switch'));\n\n /**\n * Disable the switch. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse edits while staying focusable and submittable. Bound automatically\n * from the field's readonly state when used with `[formField]`.\n *\n * A native checkbox ignores the `readonly` attribute, so this cancels the\n * click's activation behaviour instead — which covers Space too, since the key\n * arrives as a click — and mirrors the state as `aria-readonly`, which role\n * `switch` supports.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** The surrounding `<wr-form-field>`'s error state. @internal */\n protected readonly fieldAria = useFormFieldAria();\n\n /**\n * Control size — shares the `--wr-control-*` contract. Unset falls back to the\n * `switch.size` app default from `provideWrConfig()`. @default 'md'\n */\n readonly size = input<WrSwitchSize | null>(null);\n\n /** `size`, then the app config, then `md`. @internal */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.switch?.size, 'md');\n\n /** On / off state. Bound by `[formField]`, or two-way via `[(checked)]`. */\n readonly checked = model<boolean>(false);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n protected readonly classes = computed(() => {\n const parts = ['wr-switch'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-switch--${size}`);\n if (this.checked()) parts.push('wr-switch--checked');\n if (this.disabled()) parts.push('wr-switch--disabled');\n else if (this.readonly()) parts.push('wr-switch--readonly');\n return parts.join(' ');\n });\n\n // Template handlers\n\n /**\n * Cancel the toggle while readonly. `change` never fires for a click whose\n * default was prevented, so this is the only guard the pointer and Space paths\n * need; `onInputChange` keeps its own for a synthetic `change`.\n */\n protected onInputClick(event: Event): void {\n if (this.readonly()) event.preventDefault();\n }\n\n protected onInputChange(event: Event): void {\n if (this.readonly()) {\n // A synthetic `change` cannot be prevented — put the DOM back instead.\n (event.target as HTMLInputElement).checked = this.checked();\n return;\n }\n this.checked.set((event.target as HTMLInputElement).checked);\n }\n\n protected onInputBlur(): void {\n this.touch.emit();\n }\n}\n","<label class=\"wr-switch__label\" [for]=\"id()\">\n <input\n class=\"wr-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onInputClick($event)\"\n (change)=\"onInputChange($event)\"\n (blur)=\"onInputBlur()\"\n />\n\n <span class=\"wr-switch__track\" aria-hidden=\"true\">\n <span class=\"wr-switch__thumb\"></span>\n </span>\n\n <span class=\"wr-switch__text\">\n <ng-content />\n </span>\n</label>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;AAKG;MA0CU,QAAQ,CAAA;AACnB;;;;AAIG;IACM,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;AAE/C;;;AAGG;AACM,IAAA,EAAE,GAAG,KAAK,CAAS,QAAQ,CAAC,WAAW,CAAC;2EAAC;AAElD;;;;;AAKG;IACM,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;AAEtE;;;;;;;;;;AAUG;IACM,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAGnD,SAAS,GAAG,gBAAgB,EAAE;AAEjD;;;AAGG;IACM,IAAI,GAAG,KAAK,CAAsB,IAAI;6EAAC;;AAG7B,IAAA,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;;IAG7E,OAAO,GAAG,KAAK,CAAU,KAAK;gFAAC;;IAG/B,KAAK,GAAG,MAAM,EAAQ;AAEZ,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE;QAChC,IAAI,IAAI,KAAK,IAAI;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAA,CAAE,CAAC;QACnD,IAAI,IAAI,CAAC,OAAO,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;QACpD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;aACjD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAC3D,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;;AAIF;;;;AAIG;AACO,IAAA,YAAY,CAAC,KAAY,EAAA;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,KAAK,CAAC,cAAc,EAAE;IAC7C;AAEU,IAAA,aAAa,CAAC,KAAY,EAAA;AAClC,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;;YAElB,KAAK,CAAC,MAA2B,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;YAC3D;QACF;QACA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,OAAO,CAAC;IAC9D;IAEU,WAAW,GAAA;AACnB,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;IACnB;uGArFW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,m7BC/CrB,stBAyBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDsBa,QAAQ,EAAA,UAAA,EAAA,CAAA;kBAZpB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,EAAA,aAAA,EAEN,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,SAAS,EAAE,WAAW;;;;AAItB,wBAAA,WAAW,EAAE,MAAM;AACpB,qBAAA,EAAA,QAAA,EAAA,stBAAA,EAAA;;;AE7CH;;AAEG
|
|
1
|
+
{"version":3,"file":"ngwr-switch.mjs","sources":["../../../projects/lib/switch/switch.ts","../../../projects/lib/switch/switch.html","../../../projects/lib/switch/ngwr-switch.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, input, model, output } from '@angular/core';\nimport type { FormCheckboxControl } from '@angular/forms/signals';\n\nimport { useConfigValue } from 'ngwr/config';\nimport { useFormFieldAria } from 'ngwr/form';\nimport { randomId } from 'ngwr/utils';\n\n/**\n * Boolean toggle with an iOS-style slider.\n *\n * A signal-forms native control: it implements `FormCheckboxControl`, so\n * `[formField]` binds straight to its `checked` model — no\n * `ControlValueAccessor` in between. `[(checked)]` works standalone.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-switch [formField]=\"form.notifications\">Notifications</wr-switch>\n *\n * <!-- standalone two-way binding -->\n * <wr-switch [(checked)]=\"enabled\">Notifications</wr-switch>\n * ```\n *\n * @see https://ngwr.dev/reference/components/switch\n */\nexport type WrSwitchSize = 'sm' | 'md' | 'lg';\n\n@Component({\n selector: 'wr-switch',\n templateUrl: './switch.html',\n encapsulation: ViewEncapsulation.None,\n host: {\n '[class]': 'classes()',\n // The `id` input belongs to the native input, not to this element — a static\n // `id=\"x\"` would otherwise be written here too and leave the document with\n // two elements sharing it, which is what broke `<label for>`.\n '[attr.id]': 'null',\n },\n})\nexport class WrSwitch implements FormCheckboxControl {\n /**\n * Accessible name for a switch used WITHOUT projected text. The wrapping\n * `<label>` names the control whenever content is projected; with none, the\n * label is empty and the input has no name at all.\n */\n readonly ariaLabel = input<string | null>(null);\n\n /**\n * Stable id used to associate the native input with its label. Lands on the\n * inner `<input>`; the host never keeps it.\n */\n readonly id = input<string>(randomId('wr-switch'));\n\n /**\n * Disable the switch. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /**\n * Refuse edits while staying focusable and submittable. Bound automatically\n * from the field's readonly state when used with `[formField]`.\n *\n * A native checkbox ignores the `readonly` attribute, so this cancels the\n * click's activation behaviour instead — which covers Space too, since the key\n * arrives as a click — and mirrors the state as `aria-readonly`, which role\n * `switch` supports.\n *\n * @default false\n */\n readonly readonly = input(false, { transform: coerceBooleanProperty });\n\n /** The surrounding `<wr-form-field>`'s error state. @internal */\n protected readonly fieldAria = useFormFieldAria();\n\n /**\n * Control size — shares the `--wr-control-*` contract. Unset falls back to the\n * `switch.size` app default from `provideWrConfig()`. @default 'md'\n */\n readonly size = input<WrSwitchSize | null>(null);\n\n /** `size`, then the app config, then `md`. @internal */\n protected readonly resolvedSize = useConfigValue(this.size, c => c.switch?.size, 'md');\n\n /** On / off state. Bound by `[formField]`, or two-way via `[(checked)]`. */\n readonly checked = model<boolean>(false);\n\n /** Emitted on blur so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n protected readonly classes = computed(() => {\n const parts = ['wr-switch'];\n const size = this.resolvedSize();\n if (size !== 'md') parts.push(`wr-switch--${size}`);\n if (this.checked()) parts.push('wr-switch--checked');\n if (this.disabled()) parts.push('wr-switch--disabled');\n else if (this.readonly()) parts.push('wr-switch--readonly');\n return parts.join(' ');\n });\n\n // Template handlers\n\n /**\n * Cancel the toggle while readonly. `change` never fires for a click whose\n * default was prevented, so this is the only guard the pointer and Space paths\n * need; `onInputChange` keeps its own for a synthetic `change`.\n */\n protected onInputClick(event: Event): void {\n if (this.readonly()) event.preventDefault();\n }\n\n protected onInputChange(event: Event): void {\n if (this.readonly()) {\n // A synthetic `change` cannot be prevented — put the DOM back instead.\n (event.target as HTMLInputElement).checked = this.checked();\n return;\n }\n this.checked.set((event.target as HTMLInputElement).checked);\n }\n\n protected onInputBlur(): void {\n this.touch.emit();\n }\n}\n","<label class=\"wr-switch__label\" [for]=\"id()\">\n <input\n class=\"wr-switch__input\"\n type=\"checkbox\"\n role=\"switch\"\n [id]=\"id()\"\n [attr.aria-label]=\"ariaLabel()\"\n [checked]=\"checked()\"\n [disabled]=\"disabled()\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onInputClick($event)\"\n (change)=\"onInputChange($event)\"\n (blur)=\"onInputBlur()\"\n />\n\n <span class=\"wr-switch__track\" aria-hidden=\"true\">\n <span class=\"wr-switch__thumb\"></span>\n </span>\n\n <span class=\"wr-switch__text\">\n <ng-content />\n </span>\n</label>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;AAKG;MA0CU,QAAQ,CAAA;AACnB;;;;AAIG;IACM,SAAS,GAAG,KAAK,CAAgB,IAAI;kFAAC;AAE/C;;;AAGG;AACM,IAAA,EAAE,GAAG,KAAK,CAAS,QAAQ,CAAC,WAAW,CAAC;2EAAC;AAElD;;;;;AAKG;IACM,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;AAEtE;;;;;;;;;;AAUG;IACM,QAAQ,GAAG,KAAK,CAAC,KAAK,gFAAI,SAAS,EAAE,qBAAqB,EAAA,CAAG;;IAGnD,SAAS,GAAG,gBAAgB,EAAE;AAEjD;;;AAGG;IACM,IAAI,GAAG,KAAK,CAAsB,IAAI;6EAAC;;AAG7B,IAAA,YAAY,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC;;IAG7E,OAAO,GAAG,KAAK,CAAU,KAAK;gFAAC;;IAG/B,KAAK,GAAG,MAAM,EAAQ;AAEZ,IAAA,OAAO,GAAG,QAAQ,CAAC,MAAK;AACzC,QAAA,MAAM,KAAK,GAAG,CAAC,WAAW,CAAC;AAC3B,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,EAAE;QAChC,IAAI,IAAI,KAAK,IAAI;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAA,CAAE,CAAC;QACnD,IAAI,IAAI,CAAC,OAAO,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;QACpD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;aACjD,IAAI,IAAI,CAAC,QAAQ,EAAE;AAAE,YAAA,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC;AAC3D,QAAA,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;IACxB,CAAC;gFAAC;;AAIF;;;;AAIG;AACO,IAAA,YAAY,CAAC,KAAY,EAAA;QACjC,IAAI,IAAI,CAAC,QAAQ,EAAE;YAAE,KAAK,CAAC,cAAc,EAAE;IAC7C;AAEU,IAAA,aAAa,CAAC,KAAY,EAAA;AAClC,QAAA,IAAI,IAAI,CAAC,QAAQ,EAAE,EAAE;;YAElB,KAAK,CAAC,MAA2B,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE;YAC3D;QACF;QACA,IAAI,CAAC,OAAO,CAAC,GAAG,CAAE,KAAK,CAAC,MAA2B,CAAC,OAAO,CAAC;IAC9D;IAEU,WAAW,GAAA;AACnB,QAAA,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;IACnB;uGArFW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,m7BC/CrB,stBAyBA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FDsBa,QAAQ,EAAA,UAAA,EAAA,CAAA;kBAZpB,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,EAAA,aAAA,EAEN,iBAAiB,CAAC,IAAI,EAAA,IAAA,EAC/B;AACJ,wBAAA,SAAS,EAAE,WAAW;;;;AAItB,wBAAA,WAAW,EAAE,MAAM;AACpB,qBAAA,EAAA,QAAA,EAAA,stBAAA,EAAA;;;AE7CH;;AAEG;;"}
|