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
|
@@ -8,15 +8,19 @@
|
|
|
8
8
|
/// one of the 120-odd style entries that referenced tokens without pulling the
|
|
9
9
|
/// layer that declares them: `@use 'ngwr/event-calendar'` on its own emitted
|
|
10
10
|
/// 5.5 kB of rules carrying 57 unresolved `var(--wr-*)` references, so the grid
|
|
11
|
-
/// lines (`box-shadow`, hence no fallback) vanished and the text fell
|
|
12
|
-
/// black. The ten other entries that skip the load — `affix`, `density`
|
|
13
|
-
/// eight canvas / text-animation ones — reference no token at all, which
|
|
14
|
-
/// a sweep for "who is missing it" is not enough on its own.
|
|
11
|
+
/// lines (then a `box-shadow`, hence no fallback) vanished and the text fell
|
|
12
|
+
/// back to black. The ten other entries that skip the load — `affix`, `density`
|
|
13
|
+
/// and the eight canvas / text-animation ones — reference no token at all, which
|
|
14
|
+
/// is why a sweep for "who is missing it" is not enough on its own.
|
|
15
15
|
///
|
|
16
|
-
/// Grid lines are
|
|
17
|
-
///
|
|
18
|
-
///
|
|
19
|
-
///
|
|
16
|
+
/// Grid lines are borders on an absolutely positioned `::after`, never on the
|
|
17
|
+
/// cell itself. A border on the cell would take up layout space, and the whole
|
|
18
|
+
/// chip model depends on cell boxes being exactly contiguous: a band's
|
|
19
|
+
/// `calc(var(--span) * 100%)` is only the right width if one cell ends precisely
|
|
20
|
+
/// where the next begins. They used to be `box-shadow: inset`, which costs no
|
|
21
|
+
/// space either but has no logical form — and each cell drew its line on the
|
|
22
|
+
/// physical right and bottom whether or not that edge was the frame, so the last
|
|
23
|
+
/// column and the last row painted a second hairline against the grid's own.
|
|
20
24
|
@use '../../theme/styles';
|
|
21
25
|
|
|
22
26
|
.wr-event-calendar {
|
|
@@ -29,6 +33,17 @@
|
|
|
29
33
|
// dark enough that `--wr-color-on-surface-muted` on top of it lands at 3.6:1.
|
|
30
34
|
--wr-event-calendar-fill: var(--wr-color-fill);
|
|
31
35
|
--wr-event-calendar-cols: 7;
|
|
36
|
+
// A chip is a 20px strip carrying a 3px accent on its leading edge, and the
|
|
37
|
+
// library's small radius (6px) bent that accent into a bracket. Half of it
|
|
38
|
+
// keeps the corner soft and the accent straight, and still follows a theme
|
|
39
|
+
// that re-tunes `--wr-border-radius-sm`.
|
|
40
|
+
--wr-event-calendar-chip-radius: calc(var(--wr-border-radius-sm) / 2);
|
|
41
|
+
// Space above the first chip (below the day number, or below the header rule
|
|
42
|
+
// in the all-day band) and between stacked chips.
|
|
43
|
+
--wr-event-calendar-chip-gap: 0.25rem;
|
|
44
|
+
// How far a chip stands in from the lines of the cell it sits in — on both
|
|
45
|
+
// inline sides, and below a timed chip so back-to-back events do not merge.
|
|
46
|
+
--wr-event-calendar-chip-inset: 0.125rem;
|
|
32
47
|
|
|
33
48
|
display: flex;
|
|
34
49
|
flex-direction: column;
|
|
@@ -75,6 +90,9 @@
|
|
|
75
90
|
display: grid;
|
|
76
91
|
overflow: hidden;
|
|
77
92
|
border-radius: var(--wr-border-radius-base);
|
|
93
|
+
// The frame, spread OUTSIDE the box. It owns the four outer edges, which is
|
|
94
|
+
// why no cell draws a line on a side that meets it (see the grid lines
|
|
95
|
+
// below).
|
|
78
96
|
box-shadow: 0 0 0 1px var(--wr-event-calendar-line);
|
|
79
97
|
|
|
80
98
|
&--month {
|
|
@@ -82,7 +100,15 @@
|
|
|
82
100
|
}
|
|
83
101
|
|
|
84
102
|
&--time {
|
|
85
|
-
|
|
103
|
+
// The hook is the gutter's FLOOR, not its width. A fixed 3.75rem could not
|
|
104
|
+
// hold "09:00 AM" at the label's own padding, so the label wrapped onto a
|
|
105
|
+
// second line, the rows carrying one grew to 36px while the slot cells
|
|
106
|
+
// stayed 24px, and every column line broke for 12px at every hour — and a
|
|
107
|
+
// timed chip, sized in percentages of one 24px slot, ended short of its
|
|
108
|
+
// own end time by 12px per hour it crossed.
|
|
109
|
+
grid-template-columns:
|
|
110
|
+
minmax(var(--wr-event-calendar-gutter), max-content)
|
|
111
|
+
repeat(var(--wr-event-calendar-cols), minmax(0, 1fr));
|
|
86
112
|
}
|
|
87
113
|
}
|
|
88
114
|
|
|
@@ -94,13 +120,13 @@
|
|
|
94
120
|
|
|
95
121
|
&__weekday,
|
|
96
122
|
&__colhead {
|
|
123
|
+
position: relative;
|
|
97
124
|
padding: 0.5rem 0.375rem;
|
|
98
125
|
font-size: var(--wr-text-xs);
|
|
99
126
|
font-weight: var(--wr-font-weight-medium);
|
|
100
127
|
color: var(--wr-color-on-surface-muted);
|
|
101
128
|
text-align: center;
|
|
102
129
|
background: var(--wr-event-calendar-fill);
|
|
103
|
-
box-shadow: inset 0 -1px 0 var(--wr-event-calendar-line);
|
|
104
130
|
}
|
|
105
131
|
|
|
106
132
|
&__colhead {
|
|
@@ -122,11 +148,36 @@
|
|
|
122
148
|
&__gutter {
|
|
123
149
|
padding: 0 0.5rem;
|
|
124
150
|
font-size: var(--wr-text-xs);
|
|
151
|
+
// One line box exactly one em tall, so the nudge below centres the label on
|
|
152
|
+
// its line and the label can never make a slot row taller than the slot.
|
|
153
|
+
line-height: 1;
|
|
125
154
|
color: var(--wr-color-on-surface-muted);
|
|
126
155
|
text-align: end;
|
|
156
|
+
white-space: nowrap;
|
|
127
157
|
// Nudged up so the label reads as the line it labels, not the band below it.
|
|
158
|
+
// The transform moves the box, so the gutter draws no line of its own — the
|
|
159
|
+
// divider is the first day column's (see the grid lines below).
|
|
128
160
|
transform: translateY(-0.5em);
|
|
129
|
-
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// The all-day label names a band, not a line: its top level with the first
|
|
164
|
+
// chip's. Not centred on the chip — the first hour's label below is centred on
|
|
165
|
+
// the band's bottom rule, and a centred "All day" ran into it.
|
|
166
|
+
//
|
|
167
|
+
// And it does not size the column. The hour labels have to stay on one line,
|
|
168
|
+
// because a wrapped one grows its row; this label only grows the all-day row,
|
|
169
|
+
// which is a floor anyway. Left to `nowrap`, "Toute la journée" widened the
|
|
170
|
+
// French gutter from 72px to 107px and took a fifth off every day column at
|
|
171
|
+
// phone width, and the English label overrode a smaller gutter hook. A wrapped
|
|
172
|
+
// label grows the row through its bottom padding instead: the first hour's
|
|
173
|
+
// label is lifted 0.5em into this row, and the other 0.5em is the space a
|
|
174
|
+
// one-line "All day" already leaves above it. Without it the second line of
|
|
175
|
+
// "Toute la journée" overlapped "08:00 AM".
|
|
176
|
+
&__row--allday > &__gutter {
|
|
177
|
+
contain: inline-size;
|
|
178
|
+
padding-block: var(--wr-event-calendar-chip-gap) 1em;
|
|
179
|
+
white-space: normal;
|
|
180
|
+
transform: none;
|
|
130
181
|
}
|
|
131
182
|
|
|
132
183
|
&__cell {
|
|
@@ -137,7 +188,6 @@
|
|
|
137
188
|
position: relative;
|
|
138
189
|
min-width: 0;
|
|
139
190
|
cursor: pointer;
|
|
140
|
-
box-shadow: inset -1px -1px 0 var(--wr-event-calendar-line);
|
|
141
191
|
|
|
142
192
|
&:focus-visible {
|
|
143
193
|
z-index: 2;
|
|
@@ -146,7 +196,18 @@
|
|
|
146
196
|
}
|
|
147
197
|
|
|
148
198
|
&--day {
|
|
149
|
-
|
|
199
|
+
// A floor that knows the lanes. Every chip is absolutely positioned, so
|
|
200
|
+
// nothing in flow made the cell tall enough for its last lane: a third
|
|
201
|
+
// chip hung into the next week's row. `--wr-event-calendar-lanes` is the
|
|
202
|
+
// number of lanes the week row fills, set on the row and inherited through
|
|
203
|
+
// its `display: contents`.
|
|
204
|
+
min-height: max(
|
|
205
|
+
5.5rem,
|
|
206
|
+
calc(
|
|
207
|
+
1.75rem + var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lanes, 0) *
|
|
208
|
+
(var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
|
|
209
|
+
)
|
|
210
|
+
);
|
|
150
211
|
padding: 0.25rem;
|
|
151
212
|
}
|
|
152
213
|
|
|
@@ -164,22 +225,92 @@
|
|
|
164
225
|
}
|
|
165
226
|
|
|
166
227
|
&--allday {
|
|
167
|
-
|
|
168
|
-
|
|
228
|
+
// Same rule as a day cell: the band has no ceiling on lanes, and a second
|
|
229
|
+
// all-day event used to spill over the first hour of the grid.
|
|
230
|
+
min-height: calc(
|
|
231
|
+
var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lanes, 1) *
|
|
232
|
+
(var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
|
|
233
|
+
);
|
|
169
234
|
}
|
|
170
235
|
|
|
171
236
|
&--slot {
|
|
172
|
-
height
|
|
173
|
-
|
|
237
|
+
// A floor rather than a height, so a row that grows anyway stretches its
|
|
238
|
+
// cells with it instead of leaving their lines short.
|
|
239
|
+
min-height: var(--wr-event-calendar-slot-height);
|
|
174
240
|
}
|
|
241
|
+
}
|
|
175
242
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
243
|
+
// ------------------------------------------------------------- grid lines
|
|
244
|
+
//
|
|
245
|
+
// One hairline per edge, and one owner per line. A cell draws the line on its
|
|
246
|
+
// inline END and its block END, and draws nothing where that edge is the
|
|
247
|
+
// frame; the time grid draws hour lines on the block START of a major row,
|
|
248
|
+
// except where a header or the all-day band already put a rule there. Logical
|
|
249
|
+
// sides throughout, so the lines follow the columns under `dir="rtl"`.
|
|
250
|
+
&__weekday,
|
|
251
|
+
&__colhead,
|
|
252
|
+
&__cell {
|
|
253
|
+
&::after {
|
|
254
|
+
position: absolute;
|
|
255
|
+
inset: 0;
|
|
256
|
+
pointer-events: none;
|
|
257
|
+
content: '';
|
|
258
|
+
border: 0 solid var(--wr-event-calendar-line);
|
|
180
259
|
}
|
|
181
260
|
}
|
|
182
261
|
|
|
262
|
+
&__weekday::after,
|
|
263
|
+
&__colhead::after {
|
|
264
|
+
border-block-end-width: 1px;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
&__cell--day::after,
|
|
268
|
+
&__cell--allday::after {
|
|
269
|
+
border-inline-end-width: 1px;
|
|
270
|
+
border-block-end-width: 1px;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
&__cell--slot::after {
|
|
274
|
+
border-inline-end-width: 1px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
&__cell--major::after {
|
|
278
|
+
border-block-start-width: 1px;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// The divider between the gutter and the days. The first day column draws it,
|
|
282
|
+
// in every row, because the gutter's labels are moved with a transform that
|
|
283
|
+
// would carry any line of the gutter's own up with them — it used to stop
|
|
284
|
+
// 0.5em short of the grid's bottom edge.
|
|
285
|
+
&__gutter + &__colhead::after,
|
|
286
|
+
&__gutter + &__cell::after {
|
|
287
|
+
border-inline-start-width: 1px;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// The first slot row sits directly under the header rule or the all-day rule.
|
|
291
|
+
&__row:first-child + &__row > &__cell--major::after,
|
|
292
|
+
&__row--allday + &__row > &__cell--major::after {
|
|
293
|
+
border-block-start-width: 0;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Edges that meet the frame.
|
|
297
|
+
&__row > :last-child::after {
|
|
298
|
+
border-inline-end-width: 0;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
&__row:last-child > &__cell::after {
|
|
302
|
+
border-block-end-width: 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Under the focus ring, never over it. A focused cell takes `z-index: 2`, so
|
|
306
|
+
// it is a stacking context, and Chromium paints a positioned `::after` inside
|
|
307
|
+
// one AFTER the cell's own outline: the inset ring lost its outer pixel on
|
|
308
|
+
// every side the cell draws a line on. A negative z-index still paints above
|
|
309
|
+
// the cell's background, so a muted day keeps its lines.
|
|
310
|
+
&__cell:focus-visible::after {
|
|
311
|
+
z-index: -1;
|
|
312
|
+
}
|
|
313
|
+
|
|
183
314
|
&__daynum {
|
|
184
315
|
display: inline-flex;
|
|
185
316
|
align-items: center;
|
|
@@ -207,7 +338,7 @@
|
|
|
207
338
|
background: color-mix(in srgb, var(--wr-event-calendar-color) 18%, transparent);
|
|
208
339
|
border: 0;
|
|
209
340
|
border-inline-start: 3px solid var(--wr-event-calendar-color);
|
|
210
|
-
border-radius: var(--wr-
|
|
341
|
+
border-radius: var(--wr-event-calendar-chip-radius);
|
|
211
342
|
transition: filter var(--wr-transition-short);
|
|
212
343
|
|
|
213
344
|
&:hover {
|
|
@@ -221,19 +352,31 @@
|
|
|
221
352
|
}
|
|
222
353
|
|
|
223
354
|
&--band {
|
|
224
|
-
inset-inline-start:
|
|
355
|
+
inset-inline-start: var(--wr-event-calendar-chip-inset);
|
|
356
|
+
// `offset` is where the chips start — below the day number in a month
|
|
357
|
+
// cell, at the top of the all-day band — and the first lane keeps one gap
|
|
358
|
+
// clear of it, the way every later lane keeps one clear of the chip above.
|
|
225
359
|
top: calc(
|
|
226
|
-
var(--wr-event-calendar-offset) + var(--wr-event-calendar-lane) *
|
|
227
|
-
(var(--wr-event-calendar-band-height) +
|
|
360
|
+
var(--wr-event-calendar-offset) + var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lane) *
|
|
361
|
+
(var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
|
|
228
362
|
);
|
|
229
363
|
// Reaching across `--span` cells: each is exactly 100% of this one,
|
|
230
364
|
// because the grid has no gaps and the lines cost no layout space.
|
|
231
|
-
width: calc(var(--wr-event-calendar-span) * 100% -
|
|
365
|
+
width: calc(var(--wr-event-calendar-span) * 100% - 2 * var(--wr-event-calendar-chip-inset));
|
|
232
366
|
height: var(--wr-event-calendar-band-height);
|
|
233
367
|
padding: 0 0.375rem;
|
|
234
368
|
}
|
|
235
369
|
|
|
236
370
|
&--time {
|
|
371
|
+
// The template writes the lane geometry as custom properties rather than
|
|
372
|
+
// as `inset-inline-start` / `width` / `height` directly, so the inset can
|
|
373
|
+
// be taken off here: an inline style cannot be adjusted by a stylesheet,
|
|
374
|
+
// and a chip filling its lane to the pixel covered the column line and
|
|
375
|
+
// touched its neighbour in the next lane and the event after it. `top`
|
|
376
|
+
// needs no adjustment and stays an inline `top`.
|
|
377
|
+
inset-inline-start: calc(var(--wr-event-calendar-inline-start) + var(--wr-event-calendar-chip-inset));
|
|
378
|
+
width: calc(var(--wr-event-calendar-inline-size) - 2 * var(--wr-event-calendar-chip-inset));
|
|
379
|
+
height: calc(var(--wr-event-calendar-block-size) - var(--wr-event-calendar-chip-inset));
|
|
237
380
|
padding: 0.125rem 0.25rem;
|
|
238
381
|
// The clock and the title share a line while there is room for both and
|
|
239
382
|
// the title drops below it when there is not. `flex-direction: column`
|
|
@@ -250,6 +393,10 @@
|
|
|
250
393
|
row-gap: 0;
|
|
251
394
|
min-height: 1.25rem;
|
|
252
395
|
white-space: normal;
|
|
396
|
+
// The chip's height is set from outside and never from its content, so
|
|
397
|
+
// size containment costs nothing, and it lets the title ask how many lines
|
|
398
|
+
// the chip holds (see `&-title`).
|
|
399
|
+
container: wr-event-calendar-chip / size;
|
|
253
400
|
}
|
|
254
401
|
|
|
255
402
|
// A segment clipped by the edge of the view loses the rounding on that side,
|
|
@@ -280,8 +427,8 @@
|
|
|
280
427
|
// one-slot event has — so the label was clipped through its own digits.
|
|
281
428
|
white-space: nowrap;
|
|
282
429
|
// The muted role is calibrated against the plain surface, and the chip
|
|
283
|
-
// puts an 18% wash of the event colour under it (
|
|
284
|
-
// the whole margin: 4.18–4.28:1 across the shipped demo colours, under AA
|
|
430
|
+
// puts an 18% wash of the event colour under it (its `background`) — which
|
|
431
|
+
// spent the whole margin: 4.18–4.28:1 across the shipped demo colours, under AA
|
|
285
432
|
// in LIGHT for every one of them. Mixing toward the page's own ink is the
|
|
286
433
|
// `-ink` recipe: `--wr-color-on-surface` flips per theme, so one
|
|
287
434
|
// declaration darkens on a light tint and lightens on a dark one. 85% is
|
|
@@ -307,18 +454,28 @@
|
|
|
307
454
|
// The one thing in a day cell that is NOT absolutely positioned, and it has
|
|
308
455
|
// to stay that way. Its lane is `maxLanes` — one past the last chip — so
|
|
309
456
|
// absolute put it at 1.75rem + 3 x 1.375rem = 5.875rem inside a cell whose
|
|
310
|
-
// floor
|
|
457
|
+
// floor was 5.5rem: the entire button landed in the following week's row,
|
|
311
458
|
// which comes later in the DOM and (correctly, per the `__cell` note above)
|
|
312
459
|
// has no z-index to lose to it, so it swallowed every click. A block box in
|
|
313
|
-
// flow lands
|
|
314
|
-
// precisely the 1.75rem the chips offset by, so only the
|
|
315
|
-
// skipped — and makes the cell GROW to hold it instead.
|
|
316
|
-
// cell is a floor, not a size; the row stretches its
|
|
460
|
+
// flow lands exactly where that lane would start — the day-number line box is
|
|
461
|
+
// precisely the 1.75rem the chips offset by, so only the first gap and the
|
|
462
|
+
// lanes have to be skipped — and makes the cell GROW to hold it instead.
|
|
463
|
+
// `min-height` on the cell is a floor, not a size; the row stretches its
|
|
464
|
+
// siblings to match.
|
|
465
|
+
//
|
|
466
|
+
// It is as tall as a chip. At its own 18px line its centre sat 23px below the
|
|
467
|
+
// centre of the chip above it, one pixel short of the 24px WCAG 2.5.8's
|
|
468
|
+
// spacing exception asks for. axe flagged both targets wherever the cell was
|
|
469
|
+
// narrow enough to put the two centres nearly in line.
|
|
317
470
|
&__more {
|
|
318
471
|
display: block;
|
|
319
472
|
width: fit-content;
|
|
320
|
-
|
|
321
|
-
margin-
|
|
473
|
+
min-height: var(--wr-event-calendar-band-height);
|
|
474
|
+
margin-top: calc(
|
|
475
|
+
var(--wr-event-calendar-chip-gap) + var(--wr-event-calendar-lane) *
|
|
476
|
+
(var(--wr-event-calendar-band-height) + var(--wr-event-calendar-chip-gap))
|
|
477
|
+
);
|
|
478
|
+
margin-inline-start: var(--wr-event-calendar-chip-inset);
|
|
322
479
|
padding: 0 0.375rem;
|
|
323
480
|
font: inherit;
|
|
324
481
|
font-size: var(--wr-text-xs);
|
|
@@ -354,3 +511,20 @@
|
|
|
354
511
|
user-select: none;
|
|
355
512
|
}
|
|
356
513
|
}
|
|
514
|
+
|
|
515
|
+
// A timed chip with room for ONE line: two of the chip's 1.2 line boxes are
|
|
516
|
+
// 2.4em, and the query measures the content box. There the title stays on the
|
|
517
|
+
// clock's line and ends in an ellipsis. Left to wrap, it dropped to a second
|
|
518
|
+
// line that started 14.4px down a 16px content box, so a one-slot chip showed
|
|
519
|
+
// the top of the title's letters and nothing else. On the docs page that
|
|
520
|
+
// happened at 1280px wide, where the week columns are 118px. A chip narrower
|
|
521
|
+
// than its clock plus the gap still wraps the title, because a container query
|
|
522
|
+
// cannot turn off `flex-wrap` on the chip itself; at that width the clock is
|
|
523
|
+
// already cut off.
|
|
524
|
+
@container wr-event-calendar-chip (height < 2.4em) {
|
|
525
|
+
.wr-event-calendar__chip-title {
|
|
526
|
+
flex: 1 1 0;
|
|
527
|
+
min-width: 0;
|
|
528
|
+
white-space: nowrap;
|
|
529
|
+
}
|
|
530
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-action-sheet-testing.mjs","sources":["../../../projects/lib/action-sheet/testing/wr-action-sheet-action-harness.ts","../../../projects/lib/action-sheet/testing/wr-action-sheet-harness.ts","../../../projects/lib/action-sheet/testing/ngwr-action-sheet-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 { WrActionSheetAction } from 'ngwr/action-sheet';\n\nimport type { WrActionSheetActionHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one row inside a {@link WrActionSheetHarness}.\n *\n * A row is a real `<button>`, not an ARIA-decorated div, so `disabled` is the\n * property rather than an attribute and the CDK refuses to click it — which is the\n * behaviour a spec wants asserted, since the component ALSO checks `disabled`\n * inside its own handler. Either guard alone would keep a disabled row inert; both\n * being there means removing one is invisible until the other is removed too, and\n * {@link click} is where that shows up.\n *\n * **Clicking a row closes the sheet.** The component emits `action` and clears\n * `open` in the same call, so a harness held across a {@link click} is pointed at a\n * detached element the moment it returns — read what you need first, and get a\n * fresh harness afterwards if the sheet was reopened.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrActionSheetActionHarness extends ComponentHarness {\n /** The class every row carries, cancel rows included. */\n static hostSelector = '.wr-action-sheet__action';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrActionSheetActionHarnessFilters = {}): HarnessPredicate<WrActionSheetActionHarness> {\n return new HarnessPredicate(WrActionSheetActionHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('role', options.role, async (harness, role) => (await harness.getRole()) === role)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n /**\n * The row's label, trimmed.\n *\n * Read from `.wr-action-sheet__label` rather than from the button, so a leading\n * icon can never join it. The icon contributes no text today — it is an `<svg>` —\n * but an icon set that ships a `<title>` for its own accessibility would, and the\n * label element is the thing that actually holds the string.\n */\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-action-sheet__label')()).text();\n }\n\n /**\n * The row's visual role, as the component painted it.\n *\n * `default` is returned for a row the caller left unroled, which is what the\n * component does with the value: only `destructive` and `cancel` change anything,\n * and everything else falls through to the plain row. The two modifiers are\n * mutually exclusive by construction — `cancel` rows are filtered into their own\n * group before the destructive class is ever considered — so reading them in\n * either order gives the same answer.\n */\n async getRole(): Promise<NonNullable<WrActionSheetAction['role']>> {\n const host = await this.host();\n if (await host.hasClass('wr-action-sheet__action--cancel')) return 'cancel';\n if (await host.hasClass('wr-action-sheet__action--destructive')) return 'destructive';\n return 'default';\n }\n\n /**\n * Whether the row refuses interaction, from the button's own `disabled` property\n * — the thing the CDK consults before dispatching a click, and the DOM before\n * delivering one.\n *\n * There is no `aria-disabled` to fall back to here, and none is wanted: the row is\n * a native button, where the property already carries the state to assistive tech.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('disabled');\n }\n\n /** Whether the row draws a leading icon. */\n async hasIcon(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__icon')()) !== null;\n }\n\n /**\n * The icon's registered name, or `null` on a row without one.\n *\n * From `wr-icon`'s reflected `data-icon`, which is the only place the name reaches\n * the DOM — the rendered `<svg>` carries no trace of which entry of the set it\n * came from.\n */\n async getIconName(): Promise<string | null> {\n const icon = await this.locatorForOptional('.wr-action-sheet__icon')();\n return icon ? icon.getAttribute('data-icon') : null;\n }\n\n /**\n * Pick this row — emitting `action` and closing the sheet.\n *\n * Throws on a disabled row instead of quietly doing nothing. The click would not\n * land anyway (the DOM swallows it), so the alternative is a spec that reads as\n * \"picked the row\" and asserts a sheet that never moved.\n */\n async click(): Promise<void> {\n if (await this.isDisabled()) {\n throw new Error(\n `WrActionSheetActionHarness.click(): \"${await this.getLabel()}\" is disabled. The DOM swallows a click ` +\n 'on a disabled button and the component checks `disabled` again before emitting, so nothing would ' +\n 'happen — assert isDisabled() instead.'\n );\n }\n await (await this.host()).click();\n }\n\n /** Move keyboard focus to the row. */\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n /** Whether the row currently holds focus. */\n async isFocused(): Promise<boolean> {\n return (await this.host()).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, TestKey } from '@angular/cdk/testing';\n\nimport type { WrActionSheetActionHarnessFilters, WrActionSheetHarnessFilters } from './interfaces';\nimport { WrActionSheetActionHarness } from './wr-action-sheet-action-harness';\n\n/**\n * One `.wr-action-sheet__group` — internal, and the only way to read the rows of ONE\n * group: a `TestElement` cannot be queried into, so scoping to a child element means\n * a harness anchored on it.\n */\nclass GroupHarness extends ComponentHarness {\n static hostSelector = '.wr-action-sheet__group';\n\n async getLabels(): Promise<string[]> {\n const labels = await this.locatorForAll('.wr-action-sheet__label')();\n return Promise.all(labels.map(label => label.text()));\n }\n}\n\n/**\n * Test harness for an open `<wr-action-sheet>` — the iOS-style bottom sheet of\n * choices.\n *\n * The sheet renders through `<wr-drawer>`, so its rows are in the NGWR overlay\n * container rather than in the fixture: load this from\n * `TestbedHarnessEnvironment.documentRootLoader()`. A fixture-scoped loader finds\n * nothing at all — the `<wr-action-sheet>` host element itself holds no content and\n * the drawer it wraps is `display: none`.\n *\n * The anchor is `.wr-action-sheet`, the sheet's own root inside the drawer panel,\n * which makes each instance self-scoping: two sheets open at once are two hosts, and\n * every query here descends from one of them. That is worth stating because it is\n * NOT how the drawer harness underneath has to work — a drawer publishes no link to\n * the overlay it opened, so `WrDrawerHarness` anchors on the shared pane and scopes\n * by id.\n *\n * **What belongs to the drawer, not here.** Dismissal by backdrop click or by the ✕\n * button, the modal role, the focus trap and the panel's position are all the\n * drawer's surface, and `WrDrawerHarness` from the same root loader answers them.\n * {@link sendEscape} is the one exception, kept because dismissing without choosing\n * is a documented behaviour of the sheet itself: it closes and emits NOTHING, which\n * is the assertion most specs are actually after.\n *\n * @example\n * ```ts\n * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);\n * const sheet = await rootLoader.getHarness(WrActionSheetHarness);\n *\n * expect(await sheet.getActionLabels()).toEqual(['Take Photo', 'Delete', 'Cancel']);\n * await sheet.select({ label: 'Delete' });\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrActionSheetHarness extends ComponentHarness {\n /** The sheet's root inside the drawer panel. A closed sheet renders none. */\n static hostSelector = '.wr-action-sheet';\n\n /** Build a predicate that narrows the query — sheets can be stacked. */\n static with(options: WrActionSheetHarnessFilters = {}): HarnessPredicate<WrActionSheetHarness> {\n return new HarnessPredicate(WrActionSheetHarness, options)\n .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title))\n .addOption('message', options.message, (harness, message) =>\n HarnessPredicate.stringMatches(harness.getMessage(), message)\n )\n .addOption('accessibleName', options.accessibleName, (harness, name) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), name)\n );\n }\n\n /**\n * Whether this sheet is still open.\n *\n * A harness can only be obtained while the sheet is open — closing disposes the\n * overlay and everything in it — so this is the answer for a harness you are\n * already HOLDING: it flips to `false` after a pick or a dismissal, where a fresh\n * `getHarnessOrNull()` comes back `null`.\n *\n * Attachment is the test rather than a class, because disposal removes the element\n * without changing anything on it.\n */\n async isOpen(): Promise<boolean> {\n return (await this.host()).matchesSelector('body .wr-action-sheet');\n }\n\n /** The visible heading, or `null` when the sheet was opened without a `title`. */\n async getTitle(): Promise<string | null> {\n const title = await this.locatorForOptional('.wr-action-sheet__title')();\n return title ? title.text() : null;\n }\n\n /** The muted sub-heading, or `null` when the sheet has no `message`. */\n async getMessage(): Promise<string | null> {\n const message = await this.locatorForOptional('.wr-action-sheet__message')();\n return message ? message.text() : null;\n }\n\n /**\n * The name the dialog announces.\n *\n * The sheet always publishes one, and for an untitled sheet it is INVISIBLE: the\n * component renders a screen-reader-only `[wrDrawerTitle]` carrying\n * `actionSheet.label` (English default `Actions`), because a bottom sheet is an\n * `aria-modal` dialog and an unnamed one is announced as nothing at all. Nothing\n * on screen changes when that string is wrong or missing, which is exactly why it\n * is worth an assertion.\n *\n * Read from `.wr-drawer__title` — the class the title directive applies — so the\n * one query answers for both shapes: the visible heading carries it too.\n */\n async getAccessibleName(): Promise<string> {\n return (await this.locatorFor('.wr-drawer__title')()).text();\n }\n\n /** Whether the announced name comes from a visible heading rather than the fallback. */\n async isTitleVisible(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__title')()) !== null;\n }\n\n /**\n * Whether the dialog is actually WIRED to that name — the drawer panel's\n * `aria-labelledby` resolving to this sheet's own title element, and to nothing\n * else on the page.\n *\n * {@link getAccessibleName} only proves a string exists in the markup; a screen\n * reader reads it only if the reference points at it. The two are separate\n * failures and the second is silent: the title renders, the sheet looks right, and\n * the dialog is announced as unnamed. Worth its own assertion because the drawer\n * resolves the reference AFTER attaching the panel rather than while rendering it,\n * so a title that arrives late is named late or not at all.\n *\n * Counted across the document as well, because two panels answering to one id hand\n * every reference to whichever comes first — which is how a second sheet ends up\n * announcing the first one's title.\n */\n async isNamed(): Promise<boolean> {\n const id = await (await this.locatorFor('.wr-drawer__title')()).getAttribute('id');\n if (!id) return false;\n\n const root = this.documentRootLocatorFactory();\n const named = await root.locatorForAll(`[aria-labelledby=\"${id}\"]`)();\n const titles = await root.locatorForAll(`[id=\"${id}\"]`)();\n return named.length === 1 && titles.length === 1;\n }\n\n /** The rows this sheet offers, in DOM order — cancel rows last, in their own group. */\n async getActions(filters: WrActionSheetActionHarnessFilters = {}): Promise<WrActionSheetActionHarness[]> {\n return this.locatorForAll(WrActionSheetActionHarness.with(filters))();\n }\n\n /** The labels of every row, in DOM order. */\n async getActionLabels(): Promise<string[]> {\n const actions = await this.getActions();\n return Promise.all(actions.map(action => action.getLabel()));\n }\n\n /**\n * The labels grouped the way the sheet lays them out: the main group first, then\n * the cancel group when there is one.\n *\n * The grouping is the component's whole visual contract — a `cancel` row is pulled\n * out of the list and pinned to the bottom with a gap above it — and it is\n * invisible to {@link getActionLabels}, which flattens the two. A cancel row that\n * stopped being separated would still come last in DOM order, so the flat list\n * cannot catch it.\n */\n async getActionGroups(): Promise<string[][]> {\n const groups = await this.locatorForAll(GroupHarness)();\n return Promise.all(groups.map(group => group.getLabels()));\n }\n\n /**\n * Whether the sheet drew a separate bottom group — true exactly when at least one\n * row was given `role: 'cancel'`, since the component omits the group entirely\n * rather than rendering an empty one.\n */\n async hasCancelGroup(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__group--cancel')()) !== null;\n }\n\n /**\n * Pick the first row matching the filters.\n *\n * Throws when nothing matches, naming what the sheet does offer — the alternative\n * is a silent no-op followed by an assertion about a sheet that never moved. A\n * disabled match throws too, from the row harness.\n */\n async select(filters: WrActionSheetActionHarnessFilters): Promise<void> {\n const [action] = await this.getActions(filters);\n if (!action) {\n const offered = await this.getActionLabels();\n throw new Error(\n `WrActionSheetHarness.select(): no row matched ${JSON.stringify(filters)}. ` +\n `The sheet offers: ${offered.join(', ')}.`\n );\n }\n await action.click();\n }\n\n /**\n * Press Escape — dismissing the sheet WITHOUT emitting `action`.\n *\n * The key never needs to reach the sheet itself: the drawer underneath listens\n * through the CDK's keyboard dispatcher, which keeps one document listener and\n * hands the event to the top-most overlay. So with sheets stacked this dismisses\n * the top one whichever harness it is called on.\n */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\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-action-sheet-testing.mjs","sources":["../../../projects/lib/action-sheet/testing/wr-action-sheet-action-harness.ts","../../../projects/lib/action-sheet/testing/wr-action-sheet-harness.ts","../../../projects/lib/action-sheet/testing/ngwr-action-sheet-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 { WrActionSheetAction } from 'ngwr/action-sheet';\n\nimport type { WrActionSheetActionHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one row inside a {@link WrActionSheetHarness}.\n *\n * A row is a real `<button>`, not an ARIA-decorated div, so `disabled` is the\n * property rather than an attribute and the CDK refuses to click it — which is the\n * behaviour a spec wants asserted, since the component ALSO checks `disabled`\n * inside its own handler. Either guard alone would keep a disabled row inert; both\n * being there means removing one is invisible until the other is removed too, and\n * {@link click} is where that shows up.\n *\n * **Clicking a row closes the sheet.** The component emits `action` and clears\n * `open` in the same call, so a harness held across a {@link click} is pointed at a\n * detached element the moment it returns — read what you need first, and get a\n * fresh harness afterwards if the sheet was reopened.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrActionSheetActionHarness extends ComponentHarness {\n /** The class every row carries, cancel rows included. */\n static hostSelector = '.wr-action-sheet__action';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrActionSheetActionHarnessFilters = {}): HarnessPredicate<WrActionSheetActionHarness> {\n return new HarnessPredicate(WrActionSheetActionHarness, options)\n .addOption('label', options.label, (harness, label) => HarnessPredicate.stringMatches(harness.getLabel(), label))\n .addOption('role', options.role, async (harness, role) => (await harness.getRole()) === role)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n /**\n * The row's label, trimmed.\n *\n * Read from `.wr-action-sheet__label` rather than from the button, so a leading\n * icon can never join it. The icon contributes no text today — it is an `<svg>` —\n * but an icon set that ships a `<title>` for its own accessibility would, and the\n * label element is the thing that actually holds the string.\n */\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-action-sheet__label')()).text();\n }\n\n /**\n * The row's visual role, as the component painted it.\n *\n * `default` is returned for a row the caller left unroled, which is what the\n * component does with the value: only `destructive` and `cancel` change anything,\n * and everything else falls through to the plain row. The two modifiers are\n * mutually exclusive by construction — `cancel` rows are filtered into their own\n * group before the destructive class is ever considered — so reading them in\n * either order gives the same answer.\n */\n async getRole(): Promise<NonNullable<WrActionSheetAction['role']>> {\n const host = await this.host();\n if (await host.hasClass('wr-action-sheet__action--cancel')) return 'cancel';\n if (await host.hasClass('wr-action-sheet__action--destructive')) return 'destructive';\n return 'default';\n }\n\n /**\n * Whether the row refuses interaction, from the button's own `disabled` property\n * — the thing the CDK consults before dispatching a click, and the DOM before\n * delivering one.\n *\n * There is no `aria-disabled` to fall back to here, and none is wanted: the row is\n * a native button, where the property already carries the state to assistive tech.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).getProperty<boolean>('disabled');\n }\n\n /** Whether the row draws a leading icon. */\n async hasIcon(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__icon')()) !== null;\n }\n\n /**\n * The icon's registered name, or `null` on a row without one.\n *\n * From `wr-icon`'s reflected `data-icon`, which is the only place the name reaches\n * the DOM — the rendered `<svg>` carries no trace of which entry of the set it\n * came from.\n */\n async getIconName(): Promise<string | null> {\n const icon = await this.locatorForOptional('.wr-action-sheet__icon')();\n return icon ? icon.getAttribute('data-icon') : null;\n }\n\n /**\n * Pick this row — emitting `action` and closing the sheet.\n *\n * Throws on a disabled row instead of quietly doing nothing. The click would not\n * land anyway (the DOM swallows it), so the alternative is a spec that reads as\n * \"picked the row\" and asserts a sheet that never moved.\n */\n async click(): Promise<void> {\n if (await this.isDisabled()) {\n throw new Error(\n `WrActionSheetActionHarness.click(): \"${await this.getLabel()}\" is disabled. The DOM swallows a click ` +\n 'on a disabled button and the component checks `disabled` again before emitting, so nothing would ' +\n 'happen — assert isDisabled() instead.'\n );\n }\n await (await this.host()).click();\n }\n\n /** Move keyboard focus to the row. */\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n /** Whether the row currently holds focus. */\n async isFocused(): Promise<boolean> {\n return (await this.host()).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, TestKey } from '@angular/cdk/testing';\n\nimport type { WrActionSheetActionHarnessFilters, WrActionSheetHarnessFilters } from './interfaces';\nimport { WrActionSheetActionHarness } from './wr-action-sheet-action-harness';\n\n/**\n * One `.wr-action-sheet__group` — internal, and the only way to read the rows of ONE\n * group: a `TestElement` cannot be queried into, so scoping to a child element means\n * a harness anchored on it.\n */\nclass GroupHarness extends ComponentHarness {\n static hostSelector = '.wr-action-sheet__group';\n\n async getLabels(): Promise<string[]> {\n const labels = await this.locatorForAll('.wr-action-sheet__label')();\n return Promise.all(labels.map(label => label.text()));\n }\n}\n\n/**\n * Test harness for an open `<wr-action-sheet>` — the iOS-style bottom sheet of\n * choices.\n *\n * The sheet renders through `<wr-drawer>`, so its rows are in the NGWR overlay\n * container rather than in the fixture: load this from\n * `TestbedHarnessEnvironment.documentRootLoader()`. A fixture-scoped loader finds\n * nothing at all — the `<wr-action-sheet>` host element itself holds no content and\n * the drawer it wraps is `display: none`.\n *\n * The anchor is `.wr-action-sheet`, the sheet's own root inside the drawer panel,\n * which makes each instance self-scoping: two sheets open at once are two hosts, and\n * every query here descends from one of them. That is worth stating because it is\n * NOT how the drawer harness underneath has to work — a drawer publishes no link to\n * the overlay it opened, so `WrDrawerHarness` anchors on the shared pane and scopes\n * by id.\n *\n * **What belongs to the drawer, not here.** Dismissal by backdrop click or by the ✕\n * button, the modal role, the focus trap and the panel's position are all the\n * drawer's surface, and `WrDrawerHarness` from the same root loader answers them.\n * {@link sendEscape} is the one exception, kept because dismissing without choosing\n * is a documented behaviour of the sheet itself: it closes and emits NOTHING, which\n * is the assertion most specs are actually after.\n *\n * @example\n * ```ts\n * const rootLoader = TestbedHarnessEnvironment.documentRootLoader(fixture);\n * const sheet = await rootLoader.getHarness(WrActionSheetHarness);\n *\n * expect(await sheet.getActionLabels()).toEqual(['Take Photo', 'Delete', 'Cancel']);\n * await sheet.select({ label: 'Delete' });\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrActionSheetHarness extends ComponentHarness {\n /** The sheet's root inside the drawer panel. A closed sheet renders none. */\n static hostSelector = '.wr-action-sheet';\n\n /** Build a predicate that narrows the query — sheets can be stacked. */\n static with(options: WrActionSheetHarnessFilters = {}): HarnessPredicate<WrActionSheetHarness> {\n return new HarnessPredicate(WrActionSheetHarness, options)\n .addOption('title', options.title, (harness, title) => HarnessPredicate.stringMatches(harness.getTitle(), title))\n .addOption('message', options.message, (harness, message) =>\n HarnessPredicate.stringMatches(harness.getMessage(), message)\n )\n .addOption('accessibleName', options.accessibleName, (harness, name) =>\n HarnessPredicate.stringMatches(harness.getAccessibleName(), name)\n );\n }\n\n /**\n * Whether this sheet is still open.\n *\n * A harness can only be obtained while the sheet is open — closing disposes the\n * overlay and everything in it — so this is the answer for a harness you are\n * already HOLDING: it flips to `false` after a pick or a dismissal, where a fresh\n * `getHarnessOrNull()` comes back `null`.\n *\n * Attachment is the test rather than a class, because disposal removes the element\n * without changing anything on it.\n */\n async isOpen(): Promise<boolean> {\n return (await this.host()).matchesSelector('body .wr-action-sheet');\n }\n\n /** The visible heading, or `null` when the sheet was opened without a `title`. */\n async getTitle(): Promise<string | null> {\n const title = await this.locatorForOptional('.wr-action-sheet__title')();\n return title ? title.text() : null;\n }\n\n /** The muted sub-heading, or `null` when the sheet has no `message`. */\n async getMessage(): Promise<string | null> {\n const message = await this.locatorForOptional('.wr-action-sheet__message')();\n return message ? message.text() : null;\n }\n\n /**\n * The name the dialog announces.\n *\n * The sheet always publishes one, and for an untitled sheet it is INVISIBLE: the\n * component renders a screen-reader-only `[wrDrawerTitle]` carrying\n * `actionSheet.label` (English default `Actions`), because a bottom sheet is an\n * `aria-modal` dialog and an unnamed one is announced as nothing at all. Nothing\n * on screen changes when that string is wrong or missing, which is exactly why it\n * is worth an assertion.\n *\n * Read from `.wr-drawer__title` — the class the title directive applies — so the\n * one query answers for both shapes: the visible heading carries it too.\n */\n async getAccessibleName(): Promise<string> {\n return (await this.locatorFor('.wr-drawer__title')()).text();\n }\n\n /** Whether the announced name comes from a visible heading rather than the fallback. */\n async isTitleVisible(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__title')()) !== null;\n }\n\n /**\n * Whether the dialog is actually WIRED to that name — the drawer panel's\n * `aria-labelledby` resolving to this sheet's own title element, and to nothing\n * else on the page.\n *\n * {@link getAccessibleName} only proves a string exists in the markup; a screen\n * reader reads it only if the reference points at it. The two are separate\n * failures and the second is silent: the title renders, the sheet looks right, and\n * the dialog is announced as unnamed. Worth its own assertion because the drawer\n * resolves the reference AFTER attaching the panel rather than while rendering it,\n * so a title that arrives late is named late or not at all.\n *\n * Counted across the document as well, because two panels answering to one id hand\n * every reference to whichever comes first — which is how a second sheet ends up\n * announcing the first one's title.\n */\n async isNamed(): Promise<boolean> {\n const id = await (await this.locatorFor('.wr-drawer__title')()).getAttribute('id');\n if (!id) return false;\n\n const root = this.documentRootLocatorFactory();\n const named = await root.locatorForAll(`[aria-labelledby=\"${id}\"]`)();\n const titles = await root.locatorForAll(`[id=\"${id}\"]`)();\n return named.length === 1 && titles.length === 1;\n }\n\n /** The rows this sheet offers, in DOM order — cancel rows last, in their own group. */\n async getActions(filters: WrActionSheetActionHarnessFilters = {}): Promise<WrActionSheetActionHarness[]> {\n return this.locatorForAll(WrActionSheetActionHarness.with(filters))();\n }\n\n /** The labels of every row, in DOM order. */\n async getActionLabels(): Promise<string[]> {\n const actions = await this.getActions();\n return Promise.all(actions.map(action => action.getLabel()));\n }\n\n /**\n * The labels grouped the way the sheet lays them out: the main group first, then\n * the cancel group when there is one.\n *\n * The grouping is the component's whole visual contract — a `cancel` row is pulled\n * out of the list and pinned to the bottom with a gap above it — and it is\n * invisible to {@link getActionLabels}, which flattens the two. A cancel row that\n * stopped being separated would still come last in DOM order, so the flat list\n * cannot catch it.\n */\n async getActionGroups(): Promise<string[][]> {\n const groups = await this.locatorForAll(GroupHarness)();\n return Promise.all(groups.map(group => group.getLabels()));\n }\n\n /**\n * Whether the sheet drew a separate bottom group — true exactly when at least one\n * row was given `role: 'cancel'`, since the component omits the group entirely\n * rather than rendering an empty one.\n */\n async hasCancelGroup(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-action-sheet__group--cancel')()) !== null;\n }\n\n /**\n * Pick the first row matching the filters.\n *\n * Throws when nothing matches, naming what the sheet does offer — the alternative\n * is a silent no-op followed by an assertion about a sheet that never moved. A\n * disabled match throws too, from the row harness.\n */\n async select(filters: WrActionSheetActionHarnessFilters): Promise<void> {\n const [action] = await this.getActions(filters);\n if (!action) {\n const offered = await this.getActionLabels();\n throw new Error(\n `WrActionSheetHarness.select(): no row matched ${JSON.stringify(filters)}. ` +\n `The sheet offers: ${offered.join(', ')}.`\n );\n }\n await action.click();\n }\n\n /**\n * Press Escape — dismissing the sheet WITHOUT emitting `action`.\n *\n * The key never needs to reach the sheet itself: the drawer underneath listens\n * through the CDK's keyboard dispatcher, which keeps one document listener and\n * hands the event to the top-most overlay. So with sheets stacked this dismisses\n * the top one whichever harness it is called on.\n */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -75,10 +75,10 @@ class WrActionSheet {
|
|
|
75
75
|
this.action.emit(item);
|
|
76
76
|
this.open.set(false);
|
|
77
77
|
}
|
|
78
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
79
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
78
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrActionSheet, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
79
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.7", type: WrActionSheet, isStandalone: true, selector: "wr-action-sheet", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, actions: { classPropertyName: "actions", publicName: "actions", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, titleFallback: { classPropertyName: "titleFallback", publicName: "titleFallback", isSignal: true, isRequired: false, transformFunction: null }, message: { classPropertyName: "message", publicName: "message", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", action: "action" }, ngImport: i0, template: "<wr-drawer [(open)]=\"open\" position=\"bottom\" height=\"auto\" rounded showHandle safeArea maxHeight=\"90dvh\">\n <div class=\"wr-action-sheet\">\n @if (title() || message()) {\n <div class=\"wr-action-sheet__header\">\n @if (title()) {\n <div class=\"wr-action-sheet__title\" wrDrawerTitle>{{ title() }}</div>\n }\n @if (message()) {\n <div class=\"wr-action-sheet__message\">{{ message() }}</div>\n }\n </div>\n }\n <!-- The drawer opens as an aria-modal dialog; name it via wrDrawerTitle.\n When there is no visible title, a screen-reader-only fallback keeps the\n dialog from being announced as unnamed. -->\n @if (!title()) {\n <span class=\"wr-action-sheet__sr-only\" wrDrawerTitle>{{ resolvedTitleFallback() }}</span>\n }\n\n <div class=\"wr-action-sheet__group\">\n @for (item of mainActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action\"\n [class.wr-action-sheet__action--destructive]=\"item.role === 'destructive'\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-action-sheet__icon\" [name]=\"item.icon\" />\n }\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n\n @if (cancelActions().length) {\n <div class=\"wr-action-sheet__group wr-action-sheet__group--cancel\">\n @for (item of cancelActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action wr-action-sheet__action--cancel\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n }\n </div>\n</wr-drawer>\n", dependencies: [{ kind: "component", type: WrDrawer, selector: "wr-drawer", inputs: ["open", "position", "width", "height", "maxHeight", "rounded", "showHandle", "safeArea", "hasBackdrop", "closeOnBackdropClick", "closeOnEscape", "closable", "closeLabel"], outputs: ["openChange"] }, { kind: "directive", type: WrDrawerTitle, selector: "[wrDrawerTitle]" }, { kind: "component", type: WrIcon, selector: "wr-icon", inputs: ["name"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
80
80
|
}
|
|
81
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
81
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrActionSheet, decorators: [{
|
|
82
82
|
type: Component,
|
|
83
83
|
args: [{ selector: 'wr-action-sheet', encapsulation: ViewEncapsulation.None, imports: [WrDrawer, WrDrawerTitle, WrIcon], template: "<wr-drawer [(open)]=\"open\" position=\"bottom\" height=\"auto\" rounded showHandle safeArea maxHeight=\"90dvh\">\n <div class=\"wr-action-sheet\">\n @if (title() || message()) {\n <div class=\"wr-action-sheet__header\">\n @if (title()) {\n <div class=\"wr-action-sheet__title\" wrDrawerTitle>{{ title() }}</div>\n }\n @if (message()) {\n <div class=\"wr-action-sheet__message\">{{ message() }}</div>\n }\n </div>\n }\n <!-- The drawer opens as an aria-modal dialog; name it via wrDrawerTitle.\n When there is no visible title, a screen-reader-only fallback keeps the\n dialog from being announced as unnamed. -->\n @if (!title()) {\n <span class=\"wr-action-sheet__sr-only\" wrDrawerTitle>{{ resolvedTitleFallback() }}</span>\n }\n\n <div class=\"wr-action-sheet__group\">\n @for (item of mainActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action\"\n [class.wr-action-sheet__action--destructive]=\"item.role === 'destructive'\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-action-sheet__icon\" [name]=\"item.icon\" />\n }\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n\n @if (cancelActions().length) {\n <div class=\"wr-action-sheet__group wr-action-sheet__group--cancel\">\n @for (item of cancelActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action wr-action-sheet__action--cancel\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n }\n </div>\n</wr-drawer>\n" }]
|
|
84
84
|
}], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], actions: [{ type: i0.Input, args: [{ isSignal: true, alias: "actions", required: false }] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], titleFallback: [{ type: i0.Input, args: [{ isSignal: true, alias: "titleFallback", required: false }] }], message: [{ type: i0.Input, args: [{ isSignal: true, alias: "message", required: false }] }], action: [{ type: i0.Output, args: ["action"] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-action-sheet.mjs","sources":["../../../projects/lib/action-sheet/action-sheet.ts","../../../projects/lib/action-sheet/action-sheet.html","../../../projects/lib/action-sheet/ngwr-action-sheet.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 { Component, ViewEncapsulation, computed, inject, input, model, output } from '@angular/core';\n\nimport { WrDrawer, WrDrawerTitle } from 'ngwr/drawer';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrIcon } from 'ngwr/icon';\nimport { WrHaptics } from 'ngwr/platform';\n\nimport type { WrActionSheetAction } from './interfaces';\n\n/**\n * iOS-style action sheet — a bottom sheet offering a short list of choices.\n * A thin preset over {@link WrDrawer} (bottom position, rounded, grab handle,\n * safe-area padding), driven by data rather than projected content.\n *\n * Pass `actions`; picking one emits `action` and closes the sheet. Rows with\n * `role: 'destructive'` are painted in the danger colour, and `role: 'cancel'`\n * rows drop to a separate group at the bottom. Dismissing via the backdrop,\n * `Escape`, or a swipe-down closes without emitting. Picking fires a light\n * {@link WrHaptics} tick.\n *\n * @example\n * ```html\n * <wr-action-sheet\n * [(open)]=\"sheetOpen\"\n * title=\"Photo\"\n * [actions]=\"[\n * { label: 'Take Photo', icon: 'camera', value: 'camera' },\n * { label: 'Choose from Library', icon: 'image', value: 'library' },\n * { label: 'Delete', role: 'destructive', value: 'delete' },\n * { label: 'Cancel', role: 'cancel' },\n * ]\"\n * (action)=\"onPick($event)\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/action-sheet\n */\n@Component({\n selector: 'wr-action-sheet',\n templateUrl: './action-sheet.html',\n encapsulation: ViewEncapsulation.None,\n imports: [WrDrawer, WrDrawerTitle, WrIcon],\n})\nexport class WrActionSheet {\n private readonly haptics = inject(WrHaptics);\n\n /** Whether the sheet is open. Two-way. @default false */\n readonly open = model<boolean>(false);\n\n /** The rows to offer. */\n readonly actions = input<readonly WrActionSheetAction[]>([]);\n\n /** Optional bold heading above the rows. */\n readonly title = input<string>('');\n\n /**\n * Name announced for the dialog when there is no visible `title`. Falls back to\n * `actionSheet.label`, then `'Actions'` — it used to be that English string,\n * written into the template of a component whose every other string comes from\n * the caller.\n */\n readonly titleFallback = input<string | null>(null);\n\n protected readonly resolvedTitleFallback = useI18nText(this.titleFallback, 'actionSheet.label', 'Actions');\n\n /** Optional muted sub-heading under the title. */\n readonly message = input<string>('');\n\n /** Fires with the chosen row (never fires on a dismiss). */\n readonly action = output<WrActionSheetAction>();\n\n protected readonly mainActions = computed(() => this.actions().filter(a => a.role !== 'cancel'));\n protected readonly cancelActions = computed(() => this.actions().filter(a => a.role === 'cancel'));\n\n protected select(item: WrActionSheetAction): void {\n if (item.disabled) return;\n this.haptics.selection();\n this.action.emit(item);\n this.open.set(false);\n }\n}\n","<wr-drawer [(open)]=\"open\" position=\"bottom\" height=\"auto\" rounded showHandle safeArea maxHeight=\"90dvh\">\n <div class=\"wr-action-sheet\">\n @if (title() || message()) {\n <div class=\"wr-action-sheet__header\">\n @if (title()) {\n <div class=\"wr-action-sheet__title\" wrDrawerTitle>{{ title() }}</div>\n }\n @if (message()) {\n <div class=\"wr-action-sheet__message\">{{ message() }}</div>\n }\n </div>\n }\n <!-- The drawer opens as an aria-modal dialog; name it via wrDrawerTitle.\n When there is no visible title, a screen-reader-only fallback keeps the\n dialog from being announced as unnamed. -->\n @if (!title()) {\n <span class=\"wr-action-sheet__sr-only\" wrDrawerTitle>{{ resolvedTitleFallback() }}</span>\n }\n\n <div class=\"wr-action-sheet__group\">\n @for (item of mainActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action\"\n [class.wr-action-sheet__action--destructive]=\"item.role === 'destructive'\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-action-sheet__icon\" [name]=\"item.icon\" />\n }\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n\n @if (cancelActions().length) {\n <div class=\"wr-action-sheet__group wr-action-sheet__group--cancel\">\n @for (item of cancelActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action wr-action-sheet__action--cancel\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n }\n </div>\n</wr-drawer>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;AAKG;AAWH;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;MAOU,aAAa,CAAA;AACP,IAAA,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;;IAGnC,IAAI,GAAG,KAAK,CAAU,KAAK;6EAAC;;IAG5B,OAAO,GAAG,KAAK,CAAiC,EAAE;gFAAC;;IAGnD,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;AAElC;;;;;AAKG;IACM,aAAa,GAAG,KAAK,CAAgB,IAAI;sFAAC;IAEhC,qBAAqB,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,mBAAmB,EAAE,SAAS,CAAC;;IAGjG,OAAO,GAAG,KAAK,CAAS,EAAE;gFAAC;;IAG3B,MAAM,GAAG,MAAM,EAAuB;IAE5B,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;oFAAC;IAC7E,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;sFAAC;AAExF,IAAA,MAAM,CAAC,IAAyB,EAAA;QACxC,IAAI,IAAI,CAAC,QAAQ;YAAE;AACnB,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;AACxB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACtB;uGApCW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAb,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,aAAa,mwBClD1B,+6DAoDA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDJY,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,SAAA,EAAA,YAAA,EAAA,UAAA,EAAA,aAAA,EAAA,sBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,aAAa,4DAAE,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAE9B,aAAa,EAAA,UAAA,EAAA,CAAA;kBANzB,SAAS;+BACE,iBAAiB,EAAA,aAAA,EAEZ,iBAAiB,CAAC,IAAI,EAAA,OAAA,EAC5B,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,EAAA,QAAA,EAAA,+6DAAA,EAAA;;;AEhD5C;;AAEG
|
|
1
|
+
{"version":3,"file":"ngwr-action-sheet.mjs","sources":["../../../projects/lib/action-sheet/action-sheet.ts","../../../projects/lib/action-sheet/action-sheet.html","../../../projects/lib/action-sheet/ngwr-action-sheet.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 { Component, ViewEncapsulation, computed, inject, input, model, output } from '@angular/core';\n\nimport { WrDrawer, WrDrawerTitle } from 'ngwr/drawer';\nimport { useI18nText } from 'ngwr/i18n';\nimport { WrIcon } from 'ngwr/icon';\nimport { WrHaptics } from 'ngwr/platform';\n\nimport type { WrActionSheetAction } from './interfaces';\n\n/**\n * iOS-style action sheet — a bottom sheet offering a short list of choices.\n * A thin preset over {@link WrDrawer} (bottom position, rounded, grab handle,\n * safe-area padding), driven by data rather than projected content.\n *\n * Pass `actions`; picking one emits `action` and closes the sheet. Rows with\n * `role: 'destructive'` are painted in the danger colour, and `role: 'cancel'`\n * rows drop to a separate group at the bottom. Dismissing via the backdrop,\n * `Escape`, or a swipe-down closes without emitting. Picking fires a light\n * {@link WrHaptics} tick.\n *\n * @example\n * ```html\n * <wr-action-sheet\n * [(open)]=\"sheetOpen\"\n * title=\"Photo\"\n * [actions]=\"[\n * { label: 'Take Photo', icon: 'camera', value: 'camera' },\n * { label: 'Choose from Library', icon: 'image', value: 'library' },\n * { label: 'Delete', role: 'destructive', value: 'delete' },\n * { label: 'Cancel', role: 'cancel' },\n * ]\"\n * (action)=\"onPick($event)\"\n * />\n * ```\n *\n * @see https://ngwr.dev/reference/components/action-sheet\n */\n@Component({\n selector: 'wr-action-sheet',\n templateUrl: './action-sheet.html',\n encapsulation: ViewEncapsulation.None,\n imports: [WrDrawer, WrDrawerTitle, WrIcon],\n})\nexport class WrActionSheet {\n private readonly haptics = inject(WrHaptics);\n\n /** Whether the sheet is open. Two-way. @default false */\n readonly open = model<boolean>(false);\n\n /** The rows to offer. */\n readonly actions = input<readonly WrActionSheetAction[]>([]);\n\n /** Optional bold heading above the rows. */\n readonly title = input<string>('');\n\n /**\n * Name announced for the dialog when there is no visible `title`. Falls back to\n * `actionSheet.label`, then `'Actions'` — it used to be that English string,\n * written into the template of a component whose every other string comes from\n * the caller.\n */\n readonly titleFallback = input<string | null>(null);\n\n protected readonly resolvedTitleFallback = useI18nText(this.titleFallback, 'actionSheet.label', 'Actions');\n\n /** Optional muted sub-heading under the title. */\n readonly message = input<string>('');\n\n /** Fires with the chosen row (never fires on a dismiss). */\n readonly action = output<WrActionSheetAction>();\n\n protected readonly mainActions = computed(() => this.actions().filter(a => a.role !== 'cancel'));\n protected readonly cancelActions = computed(() => this.actions().filter(a => a.role === 'cancel'));\n\n protected select(item: WrActionSheetAction): void {\n if (item.disabled) return;\n this.haptics.selection();\n this.action.emit(item);\n this.open.set(false);\n }\n}\n","<wr-drawer [(open)]=\"open\" position=\"bottom\" height=\"auto\" rounded showHandle safeArea maxHeight=\"90dvh\">\n <div class=\"wr-action-sheet\">\n @if (title() || message()) {\n <div class=\"wr-action-sheet__header\">\n @if (title()) {\n <div class=\"wr-action-sheet__title\" wrDrawerTitle>{{ title() }}</div>\n }\n @if (message()) {\n <div class=\"wr-action-sheet__message\">{{ message() }}</div>\n }\n </div>\n }\n <!-- The drawer opens as an aria-modal dialog; name it via wrDrawerTitle.\n When there is no visible title, a screen-reader-only fallback keeps the\n dialog from being announced as unnamed. -->\n @if (!title()) {\n <span class=\"wr-action-sheet__sr-only\" wrDrawerTitle>{{ resolvedTitleFallback() }}</span>\n }\n\n <div class=\"wr-action-sheet__group\">\n @for (item of mainActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action\"\n [class.wr-action-sheet__action--destructive]=\"item.role === 'destructive'\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n @if (item.icon) {\n <wr-icon class=\"wr-action-sheet__icon\" [name]=\"item.icon\" />\n }\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n\n @if (cancelActions().length) {\n <div class=\"wr-action-sheet__group wr-action-sheet__group--cancel\">\n @for (item of cancelActions(); track $index) {\n <button\n type=\"button\"\n class=\"wr-action-sheet__action wr-action-sheet__action--cancel\"\n [disabled]=\"item.disabled\"\n (click)=\"select(item)\"\n >\n <span class=\"wr-action-sheet__label\">{{ item.label }}</span>\n </button>\n }\n </div>\n }\n </div>\n</wr-drawer>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;;;;AAAA;;;;;AAKG;AAWH;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2BG;MAOU,aAAa,CAAA;AACP,IAAA,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC;;IAGnC,IAAI,GAAG,KAAK,CAAU,KAAK;6EAAC;;IAG5B,OAAO,GAAG,KAAK,CAAiC,EAAE;gFAAC;;IAGnD,KAAK,GAAG,KAAK,CAAS,EAAE;8EAAC;AAElC;;;;;AAKG;IACM,aAAa,GAAG,KAAK,CAAgB,IAAI;sFAAC;IAEhC,qBAAqB,GAAG,WAAW,CAAC,IAAI,CAAC,aAAa,EAAE,mBAAmB,EAAE,SAAS,CAAC;;IAGjG,OAAO,GAAG,KAAK,CAAS,EAAE;gFAAC;;IAG3B,MAAM,GAAG,MAAM,EAAuB;IAE5B,WAAW,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;oFAAC;IAC7E,aAAa,GAAG,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC;sFAAC;AAExF,IAAA,MAAM,CAAC,IAAyB,EAAA;QACxC,IAAI,IAAI,CAAC,QAAQ;YAAE;AACnB,QAAA,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;AACxB,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AACtB,QAAA,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;IACtB;uGApCW,aAAa,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAb,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,aAAa,mwBClD1B,+6DAoDA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDJY,QAAQ,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,CAAA,MAAA,EAAA,UAAA,EAAA,OAAA,EAAA,QAAA,EAAA,WAAA,EAAA,SAAA,EAAA,YAAA,EAAA,UAAA,EAAA,aAAA,EAAA,sBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,YAAA,CAAA,EAAA,OAAA,EAAA,CAAA,YAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,aAAa,4DAAE,MAAM,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,MAAA,CAAA,EAAA,CAAA,EAAA,aAAA,EAAA,EAAA,CAAA,iBAAA,CAAA,IAAA,EAAA,CAAA;;2FAE9B,aAAa,EAAA,UAAA,EAAA,CAAA;kBANzB,SAAS;+BACE,iBAAiB,EAAA,aAAA,EAEZ,iBAAiB,CAAC,IAAI,EAAA,OAAA,EAC5B,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,CAAC,EAAA,QAAA,EAAA,+6DAAA,EAAA;;;AEhD5C;;AAEG;;"}
|
package/fesm2022/ngwr-affix.mjs
CHANGED
|
@@ -119,10 +119,10 @@ class WrAffix {
|
|
|
119
119
|
});
|
|
120
120
|
});
|
|
121
121
|
}
|
|
122
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
123
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.
|
|
122
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrAffix, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
123
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.7", type: WrAffix, isStandalone: true, selector: "[wrAffix]", inputs: { offsetTop: { classPropertyName: "offsetTop", publicName: "wrAffixOffsetTop", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { affixChange: "wrAffixChange" }, host: { properties: { "style.position": "\"sticky\"", "style.top.px": "offsetTop()" }, classAttribute: "wr-affix" }, ngImport: i0 });
|
|
124
124
|
}
|
|
125
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.7", ngImport: i0, type: WrAffix, decorators: [{
|
|
126
126
|
type: Directive,
|
|
127
127
|
args: [{
|
|
128
128
|
selector: '[wrAffix]',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-affix.mjs","sources":["../../../projects/lib/affix/affix.ts","../../../projects/lib/affix/ngwr-affix.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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n DestroyRef,\n Directive,\n ElementRef,\n Injector,\n PLATFORM_ID,\n afterNextRender,\n effect,\n inject,\n input,\n output,\n} from '@angular/core';\n\n/**\n * Stick-on-scroll directive. Combines native CSS `position: sticky` with\n * an `IntersectionObserver`-driven `wr-affix--active` state class, so consumers\n * can style the element differently while it's pinned (e.g. add a\n * shadow, change the background, shrink the height).\n *\n * The host gets `position: sticky; top: ${offsetTop}px;` inline. A tiny\n * sentinel `<div>` is inserted just before the host — when the sentinel\n * scrolls out of view, the host is \"stuck\" and gets `wr-affix--active`\n * + an `(wrAffixChange)` emission.\n *\n * Works inside any scroll container without configuration — CSS sticky\n * picks the nearest scrollable ancestor automatically.\n *\n * @example\n * ```html\n * <header wrAffix [wrAffixOffsetTop]=\"0\">\n * <!-- adds a shadow once stuck -->\n * </header>\n * ```\n *\n * ```scss\n * header.wr-affix.wr-affix--active {\n * box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n * }\n * ```\n */\n@Directive({\n selector: '[wrAffix]',\n host: {\n class: 'wr-affix',\n '[style.position]': '\"sticky\"',\n '[style.top.px]': 'offsetTop()',\n },\n})\nexport class WrAffix {\n /** Pixels from the top of the scroll container when stuck. @default 0 */\n readonly offsetTop = input(0, {\n alias: 'wrAffixOffsetTop',\n transform: (v: unknown): number => coerceNumberProperty(v, 0),\n });\n\n /** Emits `true` when the element becomes affixed, `false` when it unsticks. */\n // eslint-disable-next-line @angular-eslint/no-output-rename -- keep wr-prefixed binding to match `[wrAffix]`\n readonly affixChange = output<boolean>({ alias: 'wrAffixChange' });\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n /**\n * `afterNextRender`'s callback is not an injection context, and the observer\n * cannot exist before the sentinel it watches — so the effect that rebuilds it\n * is handed the injector explicitly.\n */\n private readonly injector = inject(Injector);\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const el = this.host.nativeElement;\n const parent = el.parentElement;\n if (!parent) return;\n\n // Sentinel: an empty zero-height block placed immediately before\n // the host. When the sentinel scrolls out of view, the host is\n // necessarily \"stuck\" at the configured offset.\n const sentinel = el.ownerDocument.createElement('div');\n sentinel.className = 'wr-affix__sentinel';\n sentinel.setAttribute('aria-hidden', 'true');\n sentinel.style.cssText = 'height:0;width:100%;margin:0;padding:0;pointer-events:none;';\n parent.insertBefore(sentinel, el);\n\n // The observer reports STATE, not transitions: it delivers an entry for the\n // sentinel as soon as it starts watching it — before anything has scrolled —\n // and can repeat a state the host is already in (a resize, another crossing of\n // the same threshold). `affixChange` is documented as the transition, so it\n // only fires on one. The starting state is \"not affixed\", which is what the\n // element already renders as, so that first entry is silent.\n let affixed = false;\n\n let observer: IntersectionObserver | null = null;\n\n // `rootMargin` is fixed for an observer's lifetime, so a changed offset means\n // a NEW observer. Without this the two halves of the offset drifted apart:\n // `[style.top.px]` is a live binding, so a header that animates its offset\n // pinned at the new line while still flipping state at the old one.\n // Re-observing re-delivers the current state, which the transition guard\n // above absorbs when nothing has actually changed.\n effect(\n onCleanup => {\n const offset = this.offsetTop();\n\n observer = new IntersectionObserver(\n ([entry]) => {\n // NOT `!entry.isIntersecting` on its own. A sentinel is outside\n // the root in TWO directions, and only one of them means the\n // header has stuck: above the line because the page scrolled past\n // it, or below it because the host simply starts further down the\n // page than the first screen. The bare negation called both\n // \"affixed\", so any sticky element below the fold reported\n // `affixed = true` and painted `.wr-affix--active` on its very\n // first observer callback — before a pixel had scrolled — and\n // emitted a transition that never happened.\n //\n // `rootBounds.top` is the offset line (the negative `rootMargin`\n // above moves it), so a sentinel above it has genuinely gone by.\n const rootTop = entry.rootBounds?.top ?? offset;\n const next = !entry.isIntersecting && entry.boundingClientRect.top < rootTop;\n if (next === affixed) return;\n\n affixed = next;\n el.classList.toggle('wr-affix--active', next);\n this.affixChange.emit(next);\n },\n {\n // Trigger when the sentinel's top crosses the offset line.\n rootMargin: `-${offset}px 0px 0px 0px`,\n threshold: [0],\n }\n );\n observer.observe(sentinel);\n\n onCleanup(() => observer?.disconnect());\n },\n { injector: this.injector }\n );\n\n this.destroyRef.onDestroy(() => {\n observer?.disconnect();\n sentinel.remove();\n el.classList.remove('wr-affix--active');\n });\n });\n }\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-affix.mjs","sources":["../../../projects/lib/affix/affix.ts","../../../projects/lib/affix/ngwr-affix.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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n DestroyRef,\n Directive,\n ElementRef,\n Injector,\n PLATFORM_ID,\n afterNextRender,\n effect,\n inject,\n input,\n output,\n} from '@angular/core';\n\n/**\n * Stick-on-scroll directive. Combines native CSS `position: sticky` with\n * an `IntersectionObserver`-driven `wr-affix--active` state class, so consumers\n * can style the element differently while it's pinned (e.g. add a\n * shadow, change the background, shrink the height).\n *\n * The host gets `position: sticky; top: ${offsetTop}px;` inline. A tiny\n * sentinel `<div>` is inserted just before the host — when the sentinel\n * scrolls out of view, the host is \"stuck\" and gets `wr-affix--active`\n * + an `(wrAffixChange)` emission.\n *\n * Works inside any scroll container without configuration — CSS sticky\n * picks the nearest scrollable ancestor automatically.\n *\n * @example\n * ```html\n * <header wrAffix [wrAffixOffsetTop]=\"0\">\n * <!-- adds a shadow once stuck -->\n * </header>\n * ```\n *\n * ```scss\n * header.wr-affix.wr-affix--active {\n * box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);\n * }\n * ```\n */\n@Directive({\n selector: '[wrAffix]',\n host: {\n class: 'wr-affix',\n '[style.position]': '\"sticky\"',\n '[style.top.px]': 'offsetTop()',\n },\n})\nexport class WrAffix {\n /** Pixels from the top of the scroll container when stuck. @default 0 */\n readonly offsetTop = input(0, {\n alias: 'wrAffixOffsetTop',\n transform: (v: unknown): number => coerceNumberProperty(v, 0),\n });\n\n /** Emits `true` when the element becomes affixed, `false` when it unsticks. */\n // eslint-disable-next-line @angular-eslint/no-output-rename -- keep wr-prefixed binding to match `[wrAffix]`\n readonly affixChange = output<boolean>({ alias: 'wrAffixChange' });\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n /**\n * `afterNextRender`'s callback is not an injection context, and the observer\n * cannot exist before the sentinel it watches — so the effect that rebuilds it\n * is handed the injector explicitly.\n */\n private readonly injector = inject(Injector);\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const el = this.host.nativeElement;\n const parent = el.parentElement;\n if (!parent) return;\n\n // Sentinel: an empty zero-height block placed immediately before\n // the host. When the sentinel scrolls out of view, the host is\n // necessarily \"stuck\" at the configured offset.\n const sentinel = el.ownerDocument.createElement('div');\n sentinel.className = 'wr-affix__sentinel';\n sentinel.setAttribute('aria-hidden', 'true');\n sentinel.style.cssText = 'height:0;width:100%;margin:0;padding:0;pointer-events:none;';\n parent.insertBefore(sentinel, el);\n\n // The observer reports STATE, not transitions: it delivers an entry for the\n // sentinel as soon as it starts watching it — before anything has scrolled —\n // and can repeat a state the host is already in (a resize, another crossing of\n // the same threshold). `affixChange` is documented as the transition, so it\n // only fires on one. The starting state is \"not affixed\", which is what the\n // element already renders as, so that first entry is silent.\n let affixed = false;\n\n let observer: IntersectionObserver | null = null;\n\n // `rootMargin` is fixed for an observer's lifetime, so a changed offset means\n // a NEW observer. Without this the two halves of the offset drifted apart:\n // `[style.top.px]` is a live binding, so a header that animates its offset\n // pinned at the new line while still flipping state at the old one.\n // Re-observing re-delivers the current state, which the transition guard\n // above absorbs when nothing has actually changed.\n effect(\n onCleanup => {\n const offset = this.offsetTop();\n\n observer = new IntersectionObserver(\n ([entry]) => {\n // NOT `!entry.isIntersecting` on its own. A sentinel is outside\n // the root in TWO directions, and only one of them means the\n // header has stuck: above the line because the page scrolled past\n // it, or below it because the host simply starts further down the\n // page than the first screen. The bare negation called both\n // \"affixed\", so any sticky element below the fold reported\n // `affixed = true` and painted `.wr-affix--active` on its very\n // first observer callback — before a pixel had scrolled — and\n // emitted a transition that never happened.\n //\n // `rootBounds.top` is the offset line (the negative `rootMargin`\n // above moves it), so a sentinel above it has genuinely gone by.\n const rootTop = entry.rootBounds?.top ?? offset;\n const next = !entry.isIntersecting && entry.boundingClientRect.top < rootTop;\n if (next === affixed) return;\n\n affixed = next;\n el.classList.toggle('wr-affix--active', next);\n this.affixChange.emit(next);\n },\n {\n // Trigger when the sentinel's top crosses the offset line.\n rootMargin: `-${offset}px 0px 0px 0px`,\n threshold: [0],\n }\n );\n observer.observe(sentinel);\n\n onCleanup(() => observer?.disconnect());\n },\n { injector: this.injector }\n );\n\n this.destroyRef.onDestroy(() => {\n observer?.disconnect();\n sentinel.remove();\n el.classList.remove('wr-affix--active');\n });\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|