ngwr 11.1.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/burger/styles/_index.scss +1 -1
- package/button/styles/_index.scss +2 -2
- package/calendar/styles/_index.scss +32 -12
- package/calendar-heatmap/styles/_index.scss +20 -0
- package/carousel/styles/_index.scss +23 -1
- package/cascader/styles/_index.scss +15 -3
- package/checkbox/styles/_index.scss +2 -2
- package/circular-text/styles/_index.scss +11 -0
- package/collapse/styles/_index.scss +2 -2
- package/color-picker/styles/_index.scss +3 -3
- package/command-palette/styles/_index.scss +12 -0
- package/compare/styles/_index.scss +18 -2
- package/context-menu/styles/_index.scss +21 -2
- package/date-picker/styles/_index.scss +5 -5
- package/descriptions/styles/_index.scss +1 -1
- package/drag-drop/styles/_index.scss +28 -1
- package/drawer/styles/_index.scss +37 -0
- package/dropdown/styles/_index.scss +2 -2
- package/event-calendar/styles/_index.scss +67 -10
- package/fesm2022/ngwr-action-sheet-testing.mjs +313 -0
- package/fesm2022/ngwr-action-sheet-testing.mjs.map +1 -0
- package/fesm2022/ngwr-action-sheet.mjs +3 -3
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +3 -3
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-aurora.mjs +3 -3
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs +3 -3
- package/fesm2022/ngwr-badge.mjs +6 -6
- package/fesm2022/ngwr-bar-chart-testing.mjs +107 -0
- package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-bar-chart.mjs +3 -3
- package/fesm2022/ngwr-blur-text-testing.mjs +203 -0
- package/fesm2022/ngwr-blur-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-blur-text.mjs +18 -4
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow-testing.mjs +325 -0
- package/fesm2022/ngwr-border-glow-testing.mjs.map +1 -0
- package/fesm2022/ngwr-border-glow.mjs +4 -4
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +29 -17
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-button.mjs +6 -6
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs +95 -0
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -0
- package/fesm2022/ngwr-calendar-heatmap.mjs +17 -5
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-testing.mjs +368 -0
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -0
- package/fesm2022/ngwr-calendar.mjs +228 -10
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +10 -10
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +124 -24
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +60 -5
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +14 -6
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text-testing.mjs +230 -0
- package/fesm2022/ngwr-circular-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-circular-text.mjs +4 -4
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +27 -7
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-color-picker-testing.mjs +452 -0
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -0
- package/fesm2022/ngwr-color-picker.mjs +126 -10
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +14 -5
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs +31 -6
- package/fesm2022/ngwr-confetti.mjs.map +1 -1
- package/fesm2022/ngwr-config.mjs +9 -0
- package/fesm2022/ngwr-config.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu-testing.mjs +30 -11
- package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu.mjs +358 -48
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +25 -9
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/{ngwr-date-adapter-fns.mjs → ngwr-date-adapters-fns.mjs} +37 -10
- package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -0
- package/fesm2022/{ngwr-date-adapter-luxon.mjs → ngwr-date-adapters-luxon.mjs} +5 -5
- package/fesm2022/ngwr-date-adapters-luxon.mjs.map +1 -0
- package/fesm2022/ngwr-date-picker-testing.mjs +21 -85
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +119 -37
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/{ngwr-date-adapter.mjs → ngwr-date.mjs} +36 -10
- package/fesm2022/ngwr-date.mjs.map +1 -0
- package/fesm2022/ngwr-decrypt-text-testing.mjs +261 -0
- package/fesm2022/ngwr-decrypt-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-decrypt-text.mjs +9 -4
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
- package/fesm2022/ngwr-density.mjs +6 -6
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-dialog.mjs +73 -18
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-divider.mjs +52 -5
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart-testing.mjs +97 -0
- package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-donut-chart.mjs +7 -7
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +160 -11
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer.mjs +156 -64
- package/fesm2022/ngwr-drawer.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +58 -12
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-event-calendar-testing.mjs +446 -0
- package/fesm2022/ngwr-event-calendar-testing.mjs.map +1 -0
- package/fesm2022/ngwr-event-calendar.mjs +66 -28
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text-testing.mjs +220 -0
- package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-falling-text.mjs +75 -46
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +3 -3
- package/fesm2022/ngwr-form.mjs +32 -15
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text-testing.mjs +134 -0
- package/fesm2022/ngwr-fuzzy-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-fuzzy-text.mjs +21 -11
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge-testing.mjs +86 -0
- package/fesm2022/ngwr-gauge-testing.mjs.map +1 -0
- package/fesm2022/ngwr-gauge.mjs +3 -3
- package/fesm2022/ngwr-glitch-text-testing.mjs +215 -0
- package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-glitch-text.mjs +7 -7
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text-testing.mjs +258 -0
- package/fesm2022/ngwr-gradient-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-gradient-text.mjs +4 -4
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-hotkey.mjs +24 -9
- package/fesm2022/ngwr-hotkey.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +87 -1
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +69 -1
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +26 -15
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-image-cropper-testing.mjs +200 -0
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -0
- package/fesm2022/ngwr-image-cropper.mjs +156 -11
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number-testing.mjs +15 -10
- package/fesm2022/ngwr-input-number-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +89 -15
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp-testing.mjs +12 -6
- package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +24 -5
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +15 -15
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-knob-testing.mjs +220 -0
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -0
- package/fesm2022/ngwr-knob.mjs +3 -3
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox-testing.mjs +223 -0
- package/fesm2022/ngwr-lightbox-testing.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox.mjs +11 -4
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart-testing.mjs +119 -0
- package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -0
- package/fesm2022/ngwr-line-chart.mjs +73 -26
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +7 -7
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +7 -7
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown.mjs +66 -8
- package/fesm2022/ngwr-markdown.mjs.map +1 -1
- package/fesm2022/ngwr-marquee-testing.mjs +336 -0
- package/fesm2022/ngwr-marquee-testing.mjs.map +1 -0
- package/fesm2022/ngwr-marquee.mjs +4 -4
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-mention.mjs +108 -13
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-meter-group-testing.mjs +100 -0
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -0
- package/fesm2022/ngwr-meter-group.mjs +3 -3
- package/fesm2022/ngwr-overlay.mjs +34 -7
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +3 -3
- package/fesm2022/ngwr-pagination-testing.mjs +6 -6
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +17 -13
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +39 -26
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-platform.mjs +9 -9
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popover-testing.mjs +7 -2
- package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +169 -33
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs +42 -5
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-rating.mjs +3 -3
- package/fesm2022/ngwr-result.mjs +21 -30
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text-testing.mjs +220 -0
- package/fesm2022/ngwr-rotating-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-rotating-text.mjs +4 -4
- package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-segmented-testing.mjs +14 -1
- package/fesm2022/ngwr-segmented-testing.mjs.map +1 -1
- package/fesm2022/ngwr-segmented.mjs +29 -6
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +227 -43
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text-testing.mjs +237 -0
- package/fesm2022/ngwr-shiny-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-shiny-text.mjs +11 -9
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +31 -16
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +143 -14
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline-testing.mjs +76 -0
- package/fesm2022/ngwr-sparkline-testing.mjs.map +1 -0
- package/fesm2022/ngwr-sparkline.mjs +3 -3
- package/fesm2022/ngwr-speed-dial-testing.mjs +281 -0
- package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -0
- package/fesm2022/ngwr-speed-dial.mjs +27 -12
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-splash-cursor-testing.mjs +89 -0
- package/fesm2022/ngwr-splash-cursor-testing.mjs.map +1 -0
- package/fesm2022/ngwr-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-split-text-testing.mjs +224 -0
- package/fesm2022/ngwr-split-text-testing.mjs.map +1 -0
- package/fesm2022/ngwr-split-text.mjs +31 -5
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter-testing.mjs +245 -0
- package/fesm2022/ngwr-splitter-testing.mjs.map +1 -0
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-spotlight-card-testing.mjs +368 -0
- package/fesm2022/ngwr-spotlight-card-testing.mjs.map +1 -0
- package/fesm2022/ngwr-spotlight-card.mjs +7 -7
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +6 -6
- package/fesm2022/ngwr-star-border-testing.mjs +172 -0
- package/fesm2022/ngwr-star-border-testing.mjs.map +1 -0
- package/fesm2022/ngwr-star-border.mjs +4 -4
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +9 -9
- package/fesm2022/ngwr-stepper-testing.mjs +8 -8
- package/fesm2022/ngwr-stepper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +33 -8
- package/fesm2022/ngwr-stepper.mjs.map +1 -1
- package/fesm2022/ngwr-storage.mjs +17 -5
- package/fesm2022/ngwr-storage.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-table.mjs +110 -40
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-testing.mjs +11 -10
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +51 -11
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +3 -3
- package/fesm2022/ngwr-theme.mjs +181 -4
- package/fesm2022/ngwr-theme.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card-testing.mjs +190 -0
- package/fesm2022/ngwr-tilt-card-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tilt-card.mjs +26 -8
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast.mjs +44 -15
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tour-testing.mjs +173 -0
- package/fesm2022/ngwr-tour-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tour.mjs +34 -10
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer.mjs +3 -3
- package/fesm2022/ngwr-tree.mjs +36 -11
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter-testing.mjs +242 -0
- package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -0
- package/fesm2022/ngwr-typewriter.mjs +13 -5
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-utils.mjs +5 -2
- package/fesm2022/ngwr-utils.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 +4 -4
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves-testing.mjs +128 -0
- package/fesm2022/ngwr-waves-testing.mjs.map +1 -0
- package/fesm2022/ngwr-waves.mjs +4 -4
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window-testing.mjs +361 -0
- package/fesm2022/ngwr-window-testing.mjs.map +1 -0
- package/fesm2022/ngwr-window.mjs +175 -31
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/file-upload/styles/_index.scss +2 -2
- package/glitch-text/styles/_index.scss +27 -12
- package/i18n/en.json +71 -7
- package/i18n/ru.json +71 -7
- package/image-cropper/styles/_index.scss +19 -0
- package/input/styles/_index.scss +2 -2
- package/input-number/styles/_index.scss +2 -2
- package/input-otp/styles/_index.scss +9 -2
- package/knob/styles/_index.scss +1 -1
- package/lightbox/styles/_index.scss +16 -2
- package/line-chart/styles/_index.scss +28 -14
- package/list/styles/_index.scss +1 -1
- package/llms-full.txt +161 -19
- package/llms.txt +45 -10
- package/markdown/styles/_index.scss +3 -3
- package/mcp/api.js +6 -4
- package/mcp/catalog.js +40 -3
- package/mcp/providers.js +42 -0
- package/mcp/tools.js +22 -30
- package/meter-group/styles/_index.scss +1 -1
- package/overlay/styles/_index.scss +33 -1
- package/package.json +161 -12
- package/pagination/styles/_index.scss +23 -1
- package/popover/styles/_index.scss +16 -7
- package/progress/styles/_index.scss +1 -1
- package/radio/styles/_index.scss +2 -2
- package/rating/styles/_index.scss +1 -1
- package/schematics/collection.json +1 -1
- package/schematics/migrations/v12/index.js +65 -0
- package/schematics/migrations/v7/index.js +12 -1
- package/schematics/migrations/v8/index.js +10 -1
- package/schematics/migrations.json +5 -0
- package/schematics/ng-add/index.js +8 -3
- package/schematics/provider/index.js +80 -13
- package/schematics/use/index.js +9 -129
- package/schematics/use/rule.js +206 -0
- package/schematics/use/symbol-map.json +4 -4
- package/segmented/styles/_index.scss +14 -3
- package/select/styles/_index.scss +14 -2
- package/sidebar/styles/_index.scss +12 -10
- package/skills/ngwr/SKILL.md +117 -0
- package/skills/ngwr/references/catalog.md +212 -0
- package/skills/ngwr/references/setup.md +78 -0
- package/slider/styles/_index.scss +1 -1
- package/speed-dial/styles/_index.scss +1 -1
- package/stepper/styles/_index.scss +12 -3
- package/switch/styles/_index.scss +2 -2
- package/table/styles/_index.scss +61 -12
- package/tabs/styles/_index.scss +1 -1
- package/textarea/styles/_index.scss +1 -1
- package/theme/styles/_colors.scss +142 -56
- package/theme/styles/_dark.scss +46 -3
- package/theme/styles/_focus.scss +28 -5
- package/theme/styles/_mixins.scss +1 -1
- package/theme/styles/_variables.scss +67 -0
- package/transfer/styles/_index.scss +26 -3
- package/tree/styles/_index.scss +29 -6
- package/types/ngwr-action-sheet-testing.d.ts +260 -0
- package/types/ngwr-bar-chart-testing.d.ts +85 -0
- package/types/ngwr-blur-text-testing.d.ts +180 -0
- package/types/ngwr-blur-text.d.ts +20 -4
- package/types/ngwr-border-glow-testing.d.ts +219 -0
- package/types/ngwr-breadcrumbs.d.ts +17 -10
- package/types/ngwr-calendar-heatmap-testing.d.ts +79 -0
- package/types/ngwr-calendar-testing.d.ts +277 -0
- package/types/ngwr-calendar.d.ts +76 -0
- package/types/ngwr-carousel.d.ts +85 -6
- package/types/ngwr-cascader.d.ts +17 -0
- package/types/ngwr-checkbox.d.ts +13 -0
- package/types/ngwr-circular-text-testing.d.ts +196 -0
- package/types/ngwr-click-spark.d.ts +4 -0
- package/types/ngwr-color-picker-testing.d.ts +299 -0
- package/types/ngwr-color-picker.d.ts +34 -2
- package/types/ngwr-confetti.d.ts +8 -0
- package/types/ngwr-config.d.ts +10 -1
- package/types/ngwr-context-menu-testing.d.ts +24 -11
- package/types/ngwr-context-menu.d.ts +71 -1
- package/types/ngwr-counter.d.ts +1 -0
- package/types/{ngwr-date-adapter-fns.d.ts → ngwr-date-adapters-fns.d.ts} +33 -6
- package/types/{ngwr-date-adapter-luxon.d.ts → ngwr-date-adapters-luxon.d.ts} +1 -1
- package/types/ngwr-date-picker-testing.d.ts +17 -72
- package/types/ngwr-date-picker.d.ts +8 -4
- package/types/{ngwr-date-adapter.d.ts → ngwr-date.d.ts} +24 -5
- package/types/ngwr-decrypt-text-testing.d.ts +222 -0
- package/types/ngwr-dialog.d.ts +38 -1
- package/types/ngwr-divider.d.ts +25 -0
- package/types/ngwr-donut-chart-testing.d.ts +83 -0
- package/types/ngwr-donut-chart.d.ts +3 -3
- package/types/ngwr-drag-drop.d.ts +56 -2
- package/types/ngwr-drawer.d.ts +68 -5
- package/types/ngwr-dropdown.d.ts +9 -0
- package/types/ngwr-event-calendar-testing.d.ts +301 -0
- package/types/ngwr-event-calendar.d.ts +17 -8
- package/types/ngwr-falling-text-testing.d.ts +188 -0
- package/types/ngwr-falling-text.d.ts +1 -1
- package/types/ngwr-form.d.ts +12 -2
- package/types/ngwr-fuzzy-text-testing.d.ts +130 -0
- package/types/ngwr-gauge-testing.d.ts +71 -0
- package/types/ngwr-glitch-text-testing.d.ts +201 -0
- package/types/ngwr-gradient-text-testing.d.ts +186 -0
- package/types/ngwr-i18n.d.ts +13 -4
- package/types/ngwr-image-cropper-testing.d.ts +173 -0
- package/types/ngwr-image-cropper.d.ts +71 -5
- package/types/ngwr-input-number-testing.d.ts +15 -10
- package/types/ngwr-input-number.d.ts +44 -5
- package/types/ngwr-input-otp-testing.d.ts +12 -6
- package/types/ngwr-input-otp.d.ts +15 -1
- package/types/ngwr-knob-testing.d.ts +150 -0
- package/types/ngwr-lightbox-testing.d.ts +154 -0
- package/types/ngwr-lightbox.d.ts +6 -0
- package/types/ngwr-line-chart-testing.d.ts +93 -0
- package/types/ngwr-line-chart.d.ts +20 -3
- package/types/ngwr-markdown.d.ts +11 -0
- package/types/ngwr-marquee-testing.d.ts +280 -0
- package/types/ngwr-mention.d.ts +32 -0
- package/types/ngwr-meter-group-testing.d.ts +77 -0
- package/types/ngwr-overlay.d.ts +20 -1
- package/types/ngwr-pagination-testing.d.ts +4 -4
- package/types/ngwr-pipes.d.ts +1 -1
- package/types/ngwr-popover-testing.d.ts +7 -2
- package/types/ngwr-popover.d.ts +1 -0
- package/types/ngwr-result.d.ts +6 -0
- package/types/ngwr-rotating-text-testing.d.ts +191 -0
- package/types/ngwr-segmented-testing.d.ts +9 -0
- package/types/ngwr-segmented.d.ts +21 -1
- package/types/ngwr-select.d.ts +100 -6
- package/types/ngwr-shiny-text-testing.d.ts +165 -0
- package/types/ngwr-shiny-text.d.ts +4 -2
- package/types/ngwr-sidebar.d.ts +14 -5
- package/types/ngwr-slider.d.ts +84 -1
- package/types/ngwr-sparkline-testing.d.ts +69 -0
- package/types/ngwr-speed-dial-testing.d.ts +199 -0
- package/types/ngwr-speed-dial.d.ts +22 -3
- package/types/ngwr-splash-cursor-testing.d.ts +95 -0
- package/types/ngwr-split-text-testing.d.ts +209 -0
- package/types/ngwr-split-text.d.ts +21 -0
- package/types/ngwr-splitter-testing.d.ts +174 -0
- package/types/ngwr-spotlight-card-testing.d.ts +303 -0
- package/types/ngwr-star-border-testing.d.ts +135 -0
- package/types/ngwr-stepper-testing.d.ts +5 -5
- package/types/ngwr-stepper.d.ts +8 -0
- package/types/ngwr-storage.d.ts +1 -0
- package/types/ngwr-table.d.ts +114 -12
- package/types/ngwr-tabs-testing.d.ts +11 -10
- package/types/ngwr-tabs.d.ts +2 -0
- package/types/ngwr-theme.d.ts +82 -1
- package/types/ngwr-tilt-card-testing.d.ts +158 -0
- package/types/ngwr-tilt-card.d.ts +2 -0
- package/types/ngwr-toast.d.ts +14 -5
- package/types/ngwr-tour-testing.d.ts +143 -0
- package/types/ngwr-tour.d.ts +22 -4
- package/types/ngwr-tree.d.ts +12 -4
- package/types/ngwr-typewriter-testing.d.ts +211 -0
- package/types/ngwr-utils.d.ts +5 -2
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-waves-testing.d.ts +121 -0
- package/types/ngwr-window-testing.d.ts +263 -0
- package/types/ngwr-window.d.ts +66 -21
- package/typography/styles/_index.scss +1 -1
- package/window/styles/_index.scss +116 -42
- package/fesm2022/ngwr-date-adapter-fns.mjs.map +0 -1
- package/fesm2022/ngwr-date-adapter-luxon.mjs.map +0 -1
- package/fesm2022/ngwr-date-adapter.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-calendar-heatmap.mjs","sources":["../../../projects/lib/calendar-heatmap/calendar-heatmap.ts","../../../projects/lib/calendar-heatmap/calendar-heatmap.html","../../../projects/lib/calendar-heatmap/ngwr-calendar-heatmap.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, inject, input } from '@angular/core';\n\nimport { WR_DATE_LOCALE } from 'ngwr/date-adapter';\nimport { useI18nText } from 'ngwr/i18n';\n\nimport type { WrHeatmapDatum } from './interfaces';\n\ninterface Cell {\n readonly iso: string;\n readonly value: number;\n readonly intensity: number;\n readonly week: number;\n readonly day: number;\n}\n\nfunction toIso(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n}\n\nfunction parseInput(value: string | Date): Date {\n return value instanceof Date ? new Date(value) : new Date(`${value}T00:00:00`);\n}\n\n/** Which rows carry a weekday label: three of seven, or they do not fit. */\nconst LABELLED_ROWS = new Set([1, 3, 5]);\n\n/**\n * GitHub-style year-grid heatmap. One column per ISO week, one row per\n * weekday — cells coloured by `value` relative to the data set's max.\n *\n * @example\n * ```html\n * <wr-calendar-heatmap [data]=\"contributions\" />\n * <wr-calendar-heatmap [data]=\"data\" [endDate]=\"today\" [weeks]=\"26\" color=\"#10b981\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/calendar-heatmap\n */\n@Component({\n selector: 'wr-calendar-heatmap',\n templateUrl: './calendar-heatmap.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-calendar-heatmap' },\n})\nexport class WrCalendarHeatmap {\n readonly data = input<readonly WrHeatmapDatum[]>([]);\n\n /**\n * Accessible name of the whole grid. Its cells are bare spans whose `title` a screen\n * reader on a role-less element does not read, so the map used to be several hundred\n * anonymous nodes with no name. Falls back to `calendarHeatmap.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'calendarHeatmap.label', 'Calendar heatmap');\n\n /** Last day to render. @default today */\n readonly endDate = input<string | Date | null>(null);\n\n /** Number of weeks (columns) to render. @default 53 */\n readonly weeks = input(53, { transform: (v: unknown): number => Math.max(4, coerceNumberProperty(v, 53)) });\n\n /** Cell side in CSS pixels. @default 11 */\n readonly cellSize = input(11, { transform: (v: unknown): number => Math.max(4, coerceNumberProperty(v, 11)) });\n\n /** Pixel gap between cells. @default 2 */\n readonly cellGap = input(2, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 2)) });\n\n /** Cell fill colour at full intensity. @default primary */\n readonly color = input<string>('var(--wr-color-primary)');\n\n /** Background colour for zero-value days. @default light tint */\n readonly emptyColor = input<string>('rgba(var(--wr-color-light-rgb), 0.5)');\n\n /** Show the weekday + month labels around the grid. @default true */\n readonly showLabels = input(true, { transform: coerceBooleanProperty });\n\n private readonly locale = inject(WR_DATE_LOCALE);\n\n /**\n * Weekday names from the locale rather than a hard-coded English list — the row order is\n * Sunday-first, matching the grid's own alignment, so 7 Jan 2024 (a Sunday) is the\n * reference. Rows without a label stay blank on purpose: seven labels do not fit.\n */\n protected readonly weekdayLabels = computed<readonly string[]>(() => {\n const formatter = new Intl.DateTimeFormat(this.locale, { weekday: 'short' });\n const sunday = new Date(2024, 0, 7);\n return Array.from({ length: 7 }, (_, row) => {\n if (!LABELLED_ROWS.has(row)) return '';\n const day = new Date(sunday);\n day.setDate(sunday.getDate() + row);\n return formatter.format(day);\n });\n });\n\n private readonly monthNames = computed<readonly string[]>(() => {\n const formatter = new Intl.DateTimeFormat(this.locale, { month: 'short' });\n return Array.from({ length: 12 }, (_, month) => formatter.format(new Date(2024, month, 15)));\n });\n\n protected readonly cells = computed<readonly Cell[]>(() => {\n const end = this.endDate() ? parseInput(this.endDate()!) : new Date();\n end.setHours(0, 0, 0, 0);\n const weeks = this.weeks();\n const totalDays = weeks * 7;\n\n // Build value lookup.\n const map = new Map<string, number>();\n for (const d of this.data()) {\n const iso = toIso(parseInput(d.date));\n map.set(iso, (map.get(iso) ?? 0) + d.value);\n }\n const max = [...map.values()].reduce((a, b) => Math.max(a, b), 0);\n\n // Walk backwards from end day; arrange into columns by week, rows by weekday.\n const out: Cell[] = [];\n const start = new Date(end);\n start.setDate(end.getDate() - totalDays + 1);\n // Align start so column 0 begins on a Sunday (matches GitHub).\n start.setDate(start.getDate() - start.getDay());\n\n const cursor = new Date(start);\n let column = 0;\n while (cursor <= end) {\n for (let row = 0; row < 7; row++) {\n const iso = toIso(cursor);\n const value = map.get(iso) ?? 0;\n const intensity = max > 0 ? Math.min(1, value / max) : 0;\n out.push({ iso, value, intensity, week: column, day: row });\n cursor.setDate(cursor.getDate() + 1);\n }\n column++;\n }\n return out;\n });\n\n protected readonly monthLabels = computed(() => {\n // Pull the first cell of each visible month → render a label centered\n // over its column.\n const cells = this.cells();\n const seen = new Set<string>();\n return cells\n .filter(cell => {\n const date = new Date(`${cell.iso}T00:00:00`);\n if (date.getDate() !== 1) return false;\n const key = `${date.getFullYear()}-${date.getMonth()}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n })\n .map(cell => ({\n label: this.monthNames()[new Date(`${cell.iso}T00:00:00`).getMonth()],\n week: cell.week,\n }));\n });\n\n protected readonly columnCount = computed(() => {\n const cells = this.cells();\n return cells.length === 0 ? 0 : cells[cells.length - 1].week + 1;\n });\n\n protected colorFor(intensity: number): string {\n if (intensity === 0) return this.emptyColor();\n return this.color();\n }\n\n protected opacityFor(intensity: number): number {\n if (intensity === 0) return 1;\n // 4 levels — match the GitHub aesthetic.\n if (intensity < 0.25) return 0.25;\n if (intensity < 0.5) return 0.5;\n if (intensity < 0.75) return 0.75;\n return 1;\n }\n}\n\nexport type { WrHeatmapDatum } from './interfaces';\n","<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div class=\"wr-calendar-heatmap__cells\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [title]=\"`${cell.iso}: ${cell.value}`\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-calendar-heatmap.mjs","sources":["../../../projects/lib/calendar-heatmap/calendar-heatmap.ts","../../../projects/lib/calendar-heatmap/calendar-heatmap.html","../../../projects/lib/calendar-heatmap/ngwr-calendar-heatmap.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport { Component, ViewEncapsulation, computed, inject, input } from '@angular/core';\n\nimport { WR_DATE_LOCALE } from 'ngwr/date';\nimport { useI18nText } from 'ngwr/i18n';\n\nimport type { WrHeatmapDatum } from './interfaces';\n\ninterface Cell {\n readonly iso: string;\n readonly value: number;\n readonly intensity: number;\n readonly week: number;\n readonly day: number;\n}\n\nfunction toIso(d: Date): string {\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n}\n\nfunction parseInput(value: string | Date): Date {\n return value instanceof Date ? new Date(value) : new Date(`${value}T00:00:00`);\n}\n\n/** Which rows carry a weekday label: three of seven, or they do not fit. */\nconst LABELLED_ROWS = new Set([1, 3, 5]);\n\n/**\n * A day's contribution, with anything non-finite read as `0`.\n *\n * One `NaN` used to flatten the entire rendered window rather than its own day:\n * `Math.max(a, NaN)` is `NaN`, so the data set's maximum became `NaN`, `max > 0`\n * was false, and every cell fell to intensity 0 — a map that reads as a stretch\n * with no activity at all. The bad day also printed the literal text `NaN` in its\n * `title`.\n */\nfunction amount(raw: number): number {\n return Number.isFinite(raw) ? raw : 0;\n}\n\n/**\n * GitHub-style year-grid heatmap. One column per ISO week, one row per\n * weekday — cells coloured by `value` relative to the data set's max.\n *\n * @example\n * ```html\n * <wr-calendar-heatmap [data]=\"contributions\" />\n * <wr-calendar-heatmap [data]=\"data\" [endDate]=\"today\" [weeks]=\"26\" color=\"#10b981\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/calendar-heatmap\n */\n@Component({\n selector: 'wr-calendar-heatmap',\n templateUrl: './calendar-heatmap.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-calendar-heatmap' },\n})\nexport class WrCalendarHeatmap {\n readonly data = input<readonly WrHeatmapDatum[]>([]);\n\n /**\n * Accessible name of the whole grid. Its cells are bare spans whose `title` a screen\n * reader on a role-less element does not read, so the map used to be several hundred\n * anonymous nodes with no name. Falls back to `calendarHeatmap.label`.\n */\n readonly ariaLabel = input<string | null>(null);\n\n protected readonly resolvedAriaLabel = useI18nText(this.ariaLabel, 'calendarHeatmap.label', 'Calendar heatmap');\n\n /** Last day to render. @default today */\n readonly endDate = input<string | Date | null>(null);\n\n /** Number of weeks (columns) to render. @default 53 */\n readonly weeks = input(53, { transform: (v: unknown): number => Math.max(4, coerceNumberProperty(v, 53)) });\n\n /** Cell side in CSS pixels. @default 11 */\n readonly cellSize = input(11, { transform: (v: unknown): number => Math.max(4, coerceNumberProperty(v, 11)) });\n\n /** Pixel gap between cells. @default 2 */\n readonly cellGap = input(2, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 2)) });\n\n /** Cell fill colour at full intensity. @default primary */\n readonly color = input<string>('var(--wr-color-primary)');\n\n /** Background colour for zero-value days. @default light tint */\n readonly emptyColor = input<string>('rgba(var(--wr-color-light-rgb), 0.5)');\n\n /** Show the weekday + month labels around the grid. @default true */\n readonly showLabels = input(true, { transform: coerceBooleanProperty });\n\n private readonly locale = inject(WR_DATE_LOCALE);\n\n /**\n * Weekday names from the locale rather than a hard-coded English list — the row order is\n * Sunday-first, matching the grid's own alignment, so 7 Jan 2024 (a Sunday) is the\n * reference. Rows without a label stay blank on purpose: seven labels do not fit.\n */\n protected readonly weekdayLabels = computed<readonly string[]>(() => {\n const formatter = new Intl.DateTimeFormat(this.locale, { weekday: 'short' });\n const sunday = new Date(2024, 0, 7);\n return Array.from({ length: 7 }, (_, row) => {\n if (!LABELLED_ROWS.has(row)) return '';\n const day = new Date(sunday);\n day.setDate(sunday.getDate() + row);\n return formatter.format(day);\n });\n });\n\n private readonly monthNames = computed<readonly string[]>(() => {\n const formatter = new Intl.DateTimeFormat(this.locale, { month: 'short' });\n return Array.from({ length: 12 }, (_, month) => formatter.format(new Date(2024, month, 15)));\n });\n\n protected readonly cells = computed<readonly Cell[]>(() => {\n const end = this.endDate() ? parseInput(this.endDate()!) : new Date();\n end.setHours(0, 0, 0, 0);\n const weeks = this.weeks();\n const totalDays = weeks * 7;\n\n // Build value lookup.\n const map = new Map<string, number>();\n for (const d of this.data()) {\n const iso = toIso(parseInput(d.date));\n map.set(iso, (map.get(iso) ?? 0) + amount(d.value));\n }\n const max = [...map.values()].reduce((a, b) => Math.max(a, b), 0);\n\n // Walk backwards from end day; arrange into columns by week, rows by weekday.\n const out: Cell[] = [];\n const start = new Date(end);\n start.setDate(end.getDate() - totalDays + 1);\n // Align start so column 0 begins on a Sunday (matches GitHub).\n start.setDate(start.getDate() - start.getDay());\n\n const cursor = new Date(start);\n let column = 0;\n while (cursor <= end) {\n for (let row = 0; row < 7; row++) {\n const iso = toIso(cursor);\n const value = map.get(iso) ?? 0;\n const intensity = max > 0 ? Math.min(1, value / max) : 0;\n out.push({ iso, value, intensity, week: column, day: row });\n cursor.setDate(cursor.getDate() + 1);\n }\n column++;\n }\n return out;\n });\n\n protected readonly monthLabels = computed(() => {\n // Pull the first cell of each visible month → render a label centered\n // over its column.\n const cells = this.cells();\n const seen = new Set<string>();\n return cells\n .filter(cell => {\n const date = new Date(`${cell.iso}T00:00:00`);\n if (date.getDate() !== 1) return false;\n const key = `${date.getFullYear()}-${date.getMonth()}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n })\n .map(cell => ({\n label: this.monthNames()[new Date(`${cell.iso}T00:00:00`).getMonth()],\n week: cell.week,\n }));\n });\n\n protected readonly columnCount = computed(() => {\n const cells = this.cells();\n return cells.length === 0 ? 0 : cells[cells.length - 1].week + 1;\n });\n\n protected colorFor(intensity: number): string {\n if (intensity === 0) return this.emptyColor();\n return this.color();\n }\n\n protected opacityFor(intensity: number): number {\n if (intensity === 0) return 1;\n // 4 levels — match the GitHub aesthetic.\n if (intensity < 0.25) return 0.25;\n if (intensity < 0.5) return 0.5;\n if (intensity < 0.75) return 0.75;\n return 1;\n }\n}\n\nexport type { WrHeatmapDatum } from './interfaces';\n","<div\n class=\"wr-calendar-heatmap__grid\"\n role=\"img\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [style.--wr-heatmap-cell-size.px]=\"cellSize()\"\n [style.--wr-heatmap-cell-gap.px]=\"cellGap()\"\n [style.--wr-heatmap-columns]=\"columnCount()\"\n>\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__weekdays\">\n @for (label of weekdayLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__weekday\">{{ label }}</span>\n }\n </div>\n }\n\n <div class=\"wr-calendar-heatmap__cells\">\n @for (cell of cells(); track cell.iso) {\n <span\n class=\"wr-calendar-heatmap__cell\"\n [style.background]=\"colorFor(cell.intensity)\"\n [style.opacity]=\"opacityFor(cell.intensity)\"\n [style.grid-column]=\"cell.week + 1\"\n [style.grid-row]=\"cell.day + 1\"\n [title]=\"`${cell.iso}: ${cell.value}`\"\n aria-hidden=\"true\"\n ></span>\n }\n </div>\n\n @if (showLabels()) {\n <div class=\"wr-calendar-heatmap__months\">\n @for (m of monthLabels(); track $index) {\n <span class=\"wr-calendar-heatmap__month\" [style.grid-column]=\"m.week + 1\">{{ m.label }}</span>\n }\n </div>\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Test harness for one day cell of a `<wr-calendar>` grid.
|
|
11
|
+
*
|
|
12
|
+
* The cell belongs to the calendar, and a date-picker's popup is a calendar in an
|
|
13
|
+
* overlay — so this is the harness for both, re-exported from
|
|
14
|
+
* `ngwr/date-picker/testing` under the name it shipped as
|
|
15
|
+
* (`WrDatePickerDayHarness`). Reach it through `WrCalendarHarness.getDays()`, or
|
|
16
|
+
* through `WrDatePickerHarness.getDay()` / `getDays()`, which scope it to ONE
|
|
17
|
+
* picker's panel — those cells are in the shared overlay container, so a bare query
|
|
18
|
+
* would answer with whichever picker opened first.
|
|
19
|
+
*
|
|
20
|
+
* State is read the way a screen reader reads it (`role`, `aria-selected`,
|
|
21
|
+
* `aria-disabled`) with the `.wr-calendar__day--*` modifiers filling in what
|
|
22
|
+
* ARIA has no word for: today, the spill days of the neighbouring months, and
|
|
23
|
+
* the interior of a picked range.
|
|
24
|
+
*
|
|
25
|
+
* @see https://ngwr.dev/guides/testing
|
|
26
|
+
*/
|
|
27
|
+
class WrCalendarDayHarness extends ComponentHarness {
|
|
28
|
+
static hostSelector = '.wr-calendar__day';
|
|
29
|
+
/** Build a predicate that narrows the query. */
|
|
30
|
+
static with(options = {}) {
|
|
31
|
+
return new HarnessPredicate(WrCalendarDayHarness, options)
|
|
32
|
+
.addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))
|
|
33
|
+
.addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)
|
|
34
|
+
.addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)
|
|
35
|
+
.addOption('inRange', options.inRange, async (harness, inRange) => (await harness.isInRange()) === inRange);
|
|
36
|
+
}
|
|
37
|
+
/** The day number as rendered. */
|
|
38
|
+
async getText() {
|
|
39
|
+
return (await this.host()).text();
|
|
40
|
+
}
|
|
41
|
+
/** The day number as a number, for mapping a list of cells to dates. */
|
|
42
|
+
async getDayOfMonth() {
|
|
43
|
+
return Number(await this.getText());
|
|
44
|
+
}
|
|
45
|
+
/** `'gridcell'` — the cell is a button, and the grid semantics are what a spec should assert. */
|
|
46
|
+
async getRole() {
|
|
47
|
+
return (await this.host()).getAttribute('role');
|
|
48
|
+
}
|
|
49
|
+
/** Whether this day is (one end of) the current selection. */
|
|
50
|
+
async isSelected() {
|
|
51
|
+
return (await (await this.host()).getAttribute('aria-selected')) === 'true';
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Whether the day refuses selection — `min` / `max` or `dateFilter` ruled it
|
|
55
|
+
* out, or the whole calendar is disabled.
|
|
56
|
+
*/
|
|
57
|
+
async isDisabled() {
|
|
58
|
+
return (await (await this.host()).getAttribute('aria-disabled')) === 'true';
|
|
59
|
+
}
|
|
60
|
+
/** Whether the cell is today's date. */
|
|
61
|
+
async isToday() {
|
|
62
|
+
return (await this.host()).hasClass('wr-calendar__day--today');
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Whether the cell belongs to a neighbouring month. The grid is always 6x7, so
|
|
66
|
+
* every month is padded with days that are selectable but not "in" the month —
|
|
67
|
+
* which is why `WrDatePickerHarness.getDay` and {@link WrCalendarHarness.getDay} skip them.
|
|
68
|
+
*/
|
|
69
|
+
async isOutOfMonth() {
|
|
70
|
+
return (await this.host()).hasClass('wr-calendar__day--out-of-month');
|
|
71
|
+
}
|
|
72
|
+
/** Whether the day lies strictly between the two ends of a picked range. */
|
|
73
|
+
async isInRange() {
|
|
74
|
+
return (await this.host()).hasClass('wr-calendar__day--in-range');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Whether this is the roving cell — the grid's single tab stop, and where the
|
|
78
|
+
* arrow keys move from.
|
|
79
|
+
*
|
|
80
|
+
* At most ONE cell answers `true`, and it is not always one: the calendar's
|
|
81
|
+
* roving date does not follow `next()` / `previous()`, so a grid navigated away
|
|
82
|
+
* from that month has no active cell (and, deliberately or not, no tab stop)
|
|
83
|
+
* until a cell is clicked or the arrows move it.
|
|
84
|
+
*/
|
|
85
|
+
async isActive() {
|
|
86
|
+
return (await this.host()).hasClass('wr-calendar__day--focused');
|
|
87
|
+
}
|
|
88
|
+
/** Click the cell. A disabled cell swallows the click — assert, do not assume. */
|
|
89
|
+
async click() {
|
|
90
|
+
return (await this.host()).click();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* @license
|
|
96
|
+
*
|
|
97
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
98
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
99
|
+
*/
|
|
100
|
+
const ARROWS = {
|
|
101
|
+
left: TestKey.LEFT_ARROW,
|
|
102
|
+
right: TestKey.RIGHT_ARROW,
|
|
103
|
+
up: TestKey.UP_ARROW,
|
|
104
|
+
down: TestKey.DOWN_ARROW,
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Test harness for `<wr-calendar>` — the standalone month grid, and the one
|
|
108
|
+
* `<wr-date-picker>` puts in an overlay.
|
|
109
|
+
*
|
|
110
|
+
* **It is three views behind one header.** Clicking the header label walks
|
|
111
|
+
* `day → month → year`, and each view renders something different: a
|
|
112
|
+
* `role="grid"` of day cells, or a `role="listbox"` of chips. Every day method
|
|
113
|
+
* throws off the day view rather than answering `[]`, which would read as "this
|
|
114
|
+
* month has no days".
|
|
115
|
+
*
|
|
116
|
+
* **The roving cell is not the selection.** The grid has one tab stop and the
|
|
117
|
+
* arrows move it; it starts on the selected date, or on today when nothing is
|
|
118
|
+
* picked. And it does NOT follow {@link next} / {@link previous} — a grid paged
|
|
119
|
+
* away from the roving month has no active cell at all, and so no tab stop, until
|
|
120
|
+
* a key or a click puts one back. That is the component's behaviour, and
|
|
121
|
+
* {@link getActiveDayNumber} is how a spec sees it.
|
|
122
|
+
*
|
|
123
|
+
* **Keys go to the host, not to a cell.** The component listens on its own element,
|
|
124
|
+
* so {@link pressArrow} works whether or not jsdom managed to put real focus
|
|
125
|
+
* anywhere — which it often does not, since the calendar moves focus in an
|
|
126
|
+
* `afterNextRender` and a disabled cell cannot take it.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* const calendar = await loader.getHarness(WrCalendarHarness);
|
|
131
|
+
*
|
|
132
|
+
* expect(await calendar.getHeaderLabel()).toBe('March 2026');
|
|
133
|
+
* await (await calendar.getDay(14)).click();
|
|
134
|
+
* expect(await calendar.getSelectedDayNumbers()).toEqual([14]);
|
|
135
|
+
* ```
|
|
136
|
+
*
|
|
137
|
+
* @see https://ngwr.dev/guides/testing
|
|
138
|
+
*/
|
|
139
|
+
class WrCalendarHarness extends ComponentHarness {
|
|
140
|
+
static hostSelector = 'wr-calendar';
|
|
141
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
142
|
+
static with(options = {}) {
|
|
143
|
+
return new HarnessPredicate(WrCalendarHarness, options)
|
|
144
|
+
.addOption('headerLabel', options.headerLabel, (harness, label) => HarnessPredicate.stringMatches(harness.getHeaderLabel(), label))
|
|
145
|
+
.addOption('mode', options.mode, async (harness, mode) => (await harness.getMode()) === mode)
|
|
146
|
+
.addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);
|
|
147
|
+
}
|
|
148
|
+
header = this.locatorFor('.wr-calendar__label');
|
|
149
|
+
prevButton = this.locatorFor('.wr-calendar__nav--prev');
|
|
150
|
+
nextButton = this.locatorFor('.wr-calendar__nav--next');
|
|
151
|
+
/** Which sub-view is showing. */
|
|
152
|
+
async getView() {
|
|
153
|
+
if ((await this.locatorForOptional('.wr-calendar__months')()) !== null)
|
|
154
|
+
return 'month';
|
|
155
|
+
if ((await this.locatorForOptional('.wr-calendar__years')()) !== null)
|
|
156
|
+
return 'year';
|
|
157
|
+
return 'day';
|
|
158
|
+
}
|
|
159
|
+
/** Single- or range-selection, from the host modifier. */
|
|
160
|
+
async getMode() {
|
|
161
|
+
return (await (await this.host()).hasClass('wr-calendar--range')) ? 'range' : 'single';
|
|
162
|
+
}
|
|
163
|
+
/** Whether the whole calendar refuses interaction. */
|
|
164
|
+
async isDisabled() {
|
|
165
|
+
return (await this.host()).hasClass('wr-calendar--disabled');
|
|
166
|
+
}
|
|
167
|
+
/** The header text — `March 2026`, `2026`, or `2016 – 2027` depending on the view. */
|
|
168
|
+
async getHeaderLabel() {
|
|
169
|
+
return (await this.header()).text();
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Click the header — stepping `day → month → year`.
|
|
173
|
+
*
|
|
174
|
+
* The year view is the end of the walk: the header is disabled there, so this
|
|
175
|
+
* throws rather than clicking a button the DOM would ignore.
|
|
176
|
+
*/
|
|
177
|
+
async clickHeader() {
|
|
178
|
+
const header = await this.header();
|
|
179
|
+
if (await header.getProperty('disabled')) {
|
|
180
|
+
throw new Error(`WrCalendarHarness.clickHeader(): the header is disabled — the calendar is on the ` +
|
|
181
|
+
`${await this.getView()} view, which is where the walk stops (or the whole calendar is disabled).`);
|
|
182
|
+
}
|
|
183
|
+
await header.click();
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Step back — a month, a year or twelve years, depending on the view.
|
|
187
|
+
*
|
|
188
|
+
* The roving day cell does NOT come along: paging is a view change, not a
|
|
189
|
+
* navigation, and the tab stop stays on the month it was in.
|
|
190
|
+
*/
|
|
191
|
+
async previous() {
|
|
192
|
+
await (await this.prevButton()).click();
|
|
193
|
+
}
|
|
194
|
+
/** Step forward — a month, a year or twelve years, depending on the view. */
|
|
195
|
+
async next() {
|
|
196
|
+
await (await this.nextButton()).click();
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* The back arrow's accessible name, which changes with the view — the arrows are
|
|
200
|
+
* icon-only, so this is the only name they have.
|
|
201
|
+
*/
|
|
202
|
+
async getPreviousLabel() {
|
|
203
|
+
return (await this.prevButton()).getAttribute('aria-label');
|
|
204
|
+
}
|
|
205
|
+
/** The forward arrow's accessible name. */
|
|
206
|
+
async getNextLabel() {
|
|
207
|
+
return (await this.nextButton()).getAttribute('aria-label');
|
|
208
|
+
}
|
|
209
|
+
/** The weekday column headers, in the order the adapter's first day of week puts them. */
|
|
210
|
+
async getWeekdayNames() {
|
|
211
|
+
await this.requireView('day', 'getWeekdayNames');
|
|
212
|
+
const names = await this.locatorForAll('.wr-calendar__weekday')();
|
|
213
|
+
return Promise.all(names.map(name => name.text()));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Every day cell, in DOM order — 42 of them, since the grid is always six weeks.
|
|
217
|
+
*
|
|
218
|
+
* That includes the spill days of the neighbouring months, which are selectable
|
|
219
|
+
* and not "in" the month; {@link getDay} skips them, and
|
|
220
|
+
* `WrCalendarDayHarness.isOutOfMonth()` tells them apart.
|
|
221
|
+
*/
|
|
222
|
+
async getDays(filters = {}) {
|
|
223
|
+
await this.requireView('day', 'getDays');
|
|
224
|
+
return this.locatorForAll(WrCalendarDayHarness.with(filters))();
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The cell for a day of THIS month.
|
|
228
|
+
*
|
|
229
|
+
* The number alone is ambiguous — a 42-cell grid shows most numbers twice — so
|
|
230
|
+
* the spill days are skipped rather than matched, which is what "the 3rd" means
|
|
231
|
+
* to someone reading the calendar.
|
|
232
|
+
*/
|
|
233
|
+
async getDay(dayOfMonth) {
|
|
234
|
+
for (const day of await this.getDays({ text: String(dayOfMonth) })) {
|
|
235
|
+
if (!(await day.isOutOfMonth()))
|
|
236
|
+
return day;
|
|
237
|
+
}
|
|
238
|
+
throw new Error(`WrCalendarHarness.getDay(${dayOfMonth}): no such day in ${await this.getHeaderLabel()}. Only cells of ` +
|
|
239
|
+
'the displayed month count — the grid spills into its neighbours, and those are skipped.');
|
|
240
|
+
}
|
|
241
|
+
/** The day numbers currently selected — one in single mode, both ends in range mode. */
|
|
242
|
+
async getSelectedDayNumbers() {
|
|
243
|
+
const selected = await this.getDays({ selected: true });
|
|
244
|
+
return Promise.all(selected.map(day => day.getDayOfMonth()));
|
|
245
|
+
}
|
|
246
|
+
/** The day numbers strictly inside a picked range — never the ends. */
|
|
247
|
+
async getInRangeDayNumbers() {
|
|
248
|
+
const inRange = await this.getDays({ inRange: true });
|
|
249
|
+
return Promise.all(inRange.map(day => day.getDayOfMonth()));
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* The day number holding the roving tab stop, or `null` when the grid has none.
|
|
253
|
+
*
|
|
254
|
+
* `null` is a real answer, not a failure: paging with {@link next} leaves the
|
|
255
|
+
* roving date behind in another month, and the grid then has no `tabindex="0"`
|
|
256
|
+
* at all until a key or a click puts one back.
|
|
257
|
+
*/
|
|
258
|
+
async getActiveDayNumber() {
|
|
259
|
+
for (const day of await this.getDays()) {
|
|
260
|
+
if (await day.isActive())
|
|
261
|
+
return day.getDayOfMonth();
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
/** The month chips, with their state. Throws off the month view. */
|
|
266
|
+
async getMonths() {
|
|
267
|
+
await this.requireView('month', 'getMonths');
|
|
268
|
+
return this.readChips();
|
|
269
|
+
}
|
|
270
|
+
/** The year chips, with their state. Throws off the year view. */
|
|
271
|
+
async getYears() {
|
|
272
|
+
await this.requireView('year', 'getYears');
|
|
273
|
+
return this.readChips();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Click a month or year chip by its printed label — which drops the calendar back
|
|
277
|
+
* one view, the way clicking the header climbed up.
|
|
278
|
+
*
|
|
279
|
+
* Throws on the day view, where there are no chips, and on a label the view does
|
|
280
|
+
* not offer, naming what it does.
|
|
281
|
+
*/
|
|
282
|
+
async selectChip(label) {
|
|
283
|
+
const view = await this.getView();
|
|
284
|
+
if (view === 'day') {
|
|
285
|
+
throw new Error('WrCalendarHarness.selectChip(): the calendar is on the day view, which has no chips. Click the ' +
|
|
286
|
+
'header first — it walks day → month → year.');
|
|
287
|
+
}
|
|
288
|
+
for (const chip of await this.locatorForAll('.wr-calendar__chip')()) {
|
|
289
|
+
if ((await chip.text()) === label) {
|
|
290
|
+
await chip.click();
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
const offered = (await this.readChips()).map(chip => chip.label);
|
|
295
|
+
throw new Error(`WrCalendarHarness.selectChip("${label}"): the ${view} view offers: ${offered.join(', ')}.`);
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Press an arrow key — one day left or right, one WEEK up or down.
|
|
299
|
+
*
|
|
300
|
+
* Sent to the host, where the component listens, so this does not depend on jsdom
|
|
301
|
+
* having managed to focus a cell. Under `dir="rtl"` the horizontal pair mirrors:
|
|
302
|
+
* ArrowRight goes back a day, because the grid itself is mirrored.
|
|
303
|
+
*/
|
|
304
|
+
async pressArrow(arrow) {
|
|
305
|
+
await (await this.host()).sendKeys(ARROWS[arrow]);
|
|
306
|
+
}
|
|
307
|
+
/** Press Home — the first day of the roving cell's week, not of the month. */
|
|
308
|
+
async pressHome() {
|
|
309
|
+
await (await this.host()).sendKeys(TestKey.HOME);
|
|
310
|
+
}
|
|
311
|
+
/** Press End — the last day of the roving cell's week. */
|
|
312
|
+
async pressEnd() {
|
|
313
|
+
await (await this.host()).sendKeys(TestKey.END);
|
|
314
|
+
}
|
|
315
|
+
/** Press PageUp — a month back, or a YEAR back with `shift`. */
|
|
316
|
+
async pressPageUp(options = {}) {
|
|
317
|
+
const host = await this.host();
|
|
318
|
+
await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_UP) : host.sendKeys(TestKey.PAGE_UP));
|
|
319
|
+
}
|
|
320
|
+
/** Press PageDown — a month on, or a YEAR on with `shift`. */
|
|
321
|
+
async pressPageDown(options = {}) {
|
|
322
|
+
const host = await this.host();
|
|
323
|
+
await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_DOWN) : host.sendKeys(TestKey.PAGE_DOWN));
|
|
324
|
+
}
|
|
325
|
+
/** Press Enter — picking the roving day, exactly as clicking it would. */
|
|
326
|
+
async pressEnter() {
|
|
327
|
+
await (await this.host()).sendKeys(TestKey.ENTER);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* The role of the element that owns the day rows.
|
|
331
|
+
*
|
|
332
|
+
* Worth asserting rather than assuming: the grid is NOT the host. The host also
|
|
333
|
+
* holds the nav header, and a `role="grid"` may only own rows — so the role sits
|
|
334
|
+
* on the body, and the weekday strip is a row inside it rather than a sibling.
|
|
335
|
+
*/
|
|
336
|
+
async getGridRole() {
|
|
337
|
+
const body = await this.locatorForOptional('.wr-calendar__body')();
|
|
338
|
+
return body ? body.getAttribute('role') : null;
|
|
339
|
+
}
|
|
340
|
+
/** How many week rows the grid renders — always six, which is what keeps it from reflowing. */
|
|
341
|
+
async getWeekCount() {
|
|
342
|
+
await this.requireView('day', 'getWeekCount');
|
|
343
|
+
return (await this.locatorForAll('.wr-calendar__week')()).length;
|
|
344
|
+
}
|
|
345
|
+
async readChips() {
|
|
346
|
+
const chips = await this.locatorForAll('.wr-calendar__chip')();
|
|
347
|
+
return Promise.all(chips.map(async (chip) => ({
|
|
348
|
+
label: await chip.text(),
|
|
349
|
+
selected: (await chip.getAttribute('aria-selected')) === 'true',
|
|
350
|
+
current: await chip.hasClass('wr-calendar__chip--current'),
|
|
351
|
+
disabled: (await chip.getAttribute('aria-disabled')) === 'true',
|
|
352
|
+
})));
|
|
353
|
+
}
|
|
354
|
+
async requireView(view, method) {
|
|
355
|
+
const current = await this.getView();
|
|
356
|
+
if (current === view)
|
|
357
|
+
return;
|
|
358
|
+
throw new Error(`WrCalendarHarness.${method}(): the calendar is showing the ${current} view, not the ${view} one — those ` +
|
|
359
|
+
'elements are not rendered at all. The header walks day → month → year; clicking a chip walks back down.');
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Generated bundle index. Do not edit.
|
|
365
|
+
*/
|
|
366
|
+
|
|
367
|
+
export { WrCalendarDayHarness, WrCalendarHarness };
|
|
368
|
+
//# sourceMappingURL=ngwr-calendar-testing.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngwr-calendar-testing.mjs","sources":["../../../projects/lib/calendar/testing/wr-calendar-day-harness.ts","../../../projects/lib/calendar/testing/wr-calendar-harness.ts","../../../projects/lib/calendar/testing/ngwr-calendar-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 { WrCalendarDayHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one day cell of a `<wr-calendar>` grid.\n *\n * The cell belongs to the calendar, and a date-picker's popup is a calendar in an\n * overlay — so this is the harness for both, re-exported from\n * `ngwr/date-picker/testing` under the name it shipped as\n * (`WrDatePickerDayHarness`). Reach it through `WrCalendarHarness.getDays()`, or\n * through `WrDatePickerHarness.getDay()` / `getDays()`, which scope it to ONE\n * picker's panel — those cells are in the shared overlay container, so a bare query\n * would answer with whichever picker opened first.\n *\n * State is read the way a screen reader reads it (`role`, `aria-selected`,\n * `aria-disabled`) with the `.wr-calendar__day--*` modifiers filling in what\n * ARIA has no word for: today, the spill days of the neighbouring months, and\n * the interior of a picked range.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCalendarDayHarness extends ComponentHarness {\n static hostSelector = '.wr-calendar__day';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCalendarDayHarnessFilters = {}): HarnessPredicate<WrCalendarDayHarness> {\n return new HarnessPredicate(WrCalendarDayHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('selected', options.selected, async (harness, selected) => (await harness.isSelected()) === selected)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('inRange', options.inRange, async (harness, inRange) => (await harness.isInRange()) === inRange);\n }\n\n /** The day number as rendered. */\n async getText(): Promise<string> {\n return (await this.host()).text();\n }\n\n /** The day number as a number, for mapping a list of cells to dates. */\n async getDayOfMonth(): Promise<number> {\n return Number(await this.getText());\n }\n\n /** `'gridcell'` — the cell is a button, and the grid semantics are what a spec should assert. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** Whether this day is (one end of) the current selection. */\n async isSelected(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-selected')) === 'true';\n }\n\n /**\n * Whether the day refuses selection — `min` / `max` or `dateFilter` ruled it\n * out, or the whole calendar is disabled.\n */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /** Whether the cell is today's date. */\n async isToday(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--today');\n }\n\n /**\n * Whether the cell belongs to a neighbouring month. The grid is always 6x7, so\n * every month is padded with days that are selectable but not \"in\" the month —\n * which is why `WrDatePickerHarness.getDay` and {@link WrCalendarHarness.getDay} skip them.\n */\n async isOutOfMonth(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--out-of-month');\n }\n\n /** Whether the day lies strictly between the two ends of a picked range. */\n async isInRange(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--in-range');\n }\n\n /**\n * Whether this is the roving cell — the grid's single tab stop, and where the\n * arrow keys move from.\n *\n * At most ONE cell answers `true`, and it is not always one: the calendar's\n * roving date does not follow `next()` / `previous()`, so a grid navigated away\n * from that month has no active cell (and, deliberately or not, no tab stop)\n * until a cell is clicked or the arrows move it.\n */\n async isActive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar__day--focused');\n }\n\n /** Click the cell. A disabled cell swallows the click — assert, do not assume. */\n async click(): Promise<void> {\n return (await this.host()).click();\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, type TestElement } from '@angular/cdk/testing';\n\nimport type { WrCalendarMode } from 'ngwr/calendar';\n\nimport type {\n WrCalendarChip,\n WrCalendarDayHarnessFilters,\n WrCalendarHarnessFilters,\n WrCalendarView,\n} from './interfaces';\nimport { WrCalendarDayHarness } from './wr-calendar-day-harness';\n\n/** The arrow keys, by the direction a user would say out loud. */\ntype Arrow = 'left' | 'right' | 'up' | 'down';\n\nconst ARROWS: Record<Arrow, TestKey> = {\n left: TestKey.LEFT_ARROW,\n right: TestKey.RIGHT_ARROW,\n up: TestKey.UP_ARROW,\n down: TestKey.DOWN_ARROW,\n};\n\n/**\n * Test harness for `<wr-calendar>` — the standalone month grid, and the one\n * `<wr-date-picker>` puts in an overlay.\n *\n * **It is three views behind one header.** Clicking the header label walks\n * `day → month → year`, and each view renders something different: a\n * `role=\"grid\"` of day cells, or a `role=\"listbox\"` of chips. Every day method\n * throws off the day view rather than answering `[]`, which would read as \"this\n * month has no days\".\n *\n * **The roving cell is not the selection.** The grid has one tab stop and the\n * arrows move it; it starts on the selected date, or on today when nothing is\n * picked. And it does NOT follow {@link next} / {@link previous} — a grid paged\n * away from the roving month has no active cell at all, and so no tab stop, until\n * a key or a click puts one back. That is the component's behaviour, and\n * {@link getActiveDayNumber} is how a spec sees it.\n *\n * **Keys go to the host, not to a cell.** The component listens on its own element,\n * so {@link pressArrow} works whether or not jsdom managed to put real focus\n * anywhere — which it often does not, since the calendar moves focus in an\n * `afterNextRender` and a disabled cell cannot take it.\n *\n * @example\n * ```ts\n * const calendar = await loader.getHarness(WrCalendarHarness);\n *\n * expect(await calendar.getHeaderLabel()).toBe('March 2026');\n * await (await calendar.getDay(14)).click();\n * expect(await calendar.getSelectedDayNumbers()).toEqual([14]);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCalendarHarness extends ComponentHarness {\n static hostSelector = 'wr-calendar';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrCalendarHarnessFilters = {}): HarnessPredicate<WrCalendarHarness> {\n return new HarnessPredicate(WrCalendarHarness, options)\n .addOption('headerLabel', options.headerLabel, (harness, label) =>\n HarnessPredicate.stringMatches(harness.getHeaderLabel(), label)\n )\n .addOption('mode', options.mode, async (harness, mode) => (await harness.getMode()) === mode)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly header = this.locatorFor('.wr-calendar__label');\n private readonly prevButton = this.locatorFor('.wr-calendar__nav--prev');\n private readonly nextButton = this.locatorFor('.wr-calendar__nav--next');\n\n /** Which sub-view is showing. */\n async getView(): Promise<WrCalendarView> {\n if ((await this.locatorForOptional('.wr-calendar__months')()) !== null) return 'month';\n if ((await this.locatorForOptional('.wr-calendar__years')()) !== null) return 'year';\n return 'day';\n }\n\n /** Single- or range-selection, from the host modifier. */\n async getMode(): Promise<WrCalendarMode> {\n return (await (await this.host()).hasClass('wr-calendar--range')) ? 'range' : 'single';\n }\n\n /** Whether the whole calendar refuses interaction. */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-calendar--disabled');\n }\n\n /** The header text — `March 2026`, `2026`, or `2016 – 2027` depending on the view. */\n async getHeaderLabel(): Promise<string> {\n return (await this.header()).text();\n }\n\n /**\n * Click the header — stepping `day → month → year`.\n *\n * The year view is the end of the walk: the header is disabled there, so this\n * throws rather than clicking a button the DOM would ignore.\n */\n async clickHeader(): Promise<void> {\n const header = await this.header();\n if (await header.getProperty<boolean>('disabled')) {\n throw new Error(\n `WrCalendarHarness.clickHeader(): the header is disabled — the calendar is on the ` +\n `${await this.getView()} view, which is where the walk stops (or the whole calendar is disabled).`\n );\n }\n await header.click();\n }\n\n /**\n * Step back — a month, a year or twelve years, depending on the view.\n *\n * The roving day cell does NOT come along: paging is a view change, not a\n * navigation, and the tab stop stays on the month it was in.\n */\n async previous(): Promise<void> {\n await (await this.prevButton()).click();\n }\n\n /** Step forward — a month, a year or twelve years, depending on the view. */\n async next(): Promise<void> {\n await (await this.nextButton()).click();\n }\n\n /**\n * The back arrow's accessible name, which changes with the view — the arrows are\n * icon-only, so this is the only name they have.\n */\n async getPreviousLabel(): Promise<string | null> {\n return (await this.prevButton()).getAttribute('aria-label');\n }\n\n /** The forward arrow's accessible name. */\n async getNextLabel(): Promise<string | null> {\n return (await this.nextButton()).getAttribute('aria-label');\n }\n\n /** The weekday column headers, in the order the adapter's first day of week puts them. */\n async getWeekdayNames(): Promise<string[]> {\n await this.requireView('day', 'getWeekdayNames');\n const names = await this.locatorForAll('.wr-calendar__weekday')();\n return Promise.all(names.map(name => name.text()));\n }\n\n /**\n * Every day cell, in DOM order — 42 of them, since the grid is always six weeks.\n *\n * That includes the spill days of the neighbouring months, which are selectable\n * and not \"in\" the month; {@link getDay} skips them, and\n * `WrCalendarDayHarness.isOutOfMonth()` tells them apart.\n */\n async getDays(filters: WrCalendarDayHarnessFilters = {}): Promise<WrCalendarDayHarness[]> {\n await this.requireView('day', 'getDays');\n return this.locatorForAll(WrCalendarDayHarness.with(filters))();\n }\n\n /**\n * The cell for a day of THIS month.\n *\n * The number alone is ambiguous — a 42-cell grid shows most numbers twice — so\n * the spill days are skipped rather than matched, which is what \"the 3rd\" means\n * to someone reading the calendar.\n */\n async getDay(dayOfMonth: number): Promise<WrCalendarDayHarness> {\n for (const day of await this.getDays({ text: String(dayOfMonth) })) {\n if (!(await day.isOutOfMonth())) return day;\n }\n throw new Error(\n `WrCalendarHarness.getDay(${dayOfMonth}): no such day in ${await this.getHeaderLabel()}. Only cells of ` +\n 'the displayed month count — the grid spills into its neighbours, and those are skipped.'\n );\n }\n\n /** The day numbers currently selected — one in single mode, both ends in range mode. */\n async getSelectedDayNumbers(): Promise<number[]> {\n const selected = await this.getDays({ selected: true });\n return Promise.all(selected.map(day => day.getDayOfMonth()));\n }\n\n /** The day numbers strictly inside a picked range — never the ends. */\n async getInRangeDayNumbers(): Promise<number[]> {\n const inRange = await this.getDays({ inRange: true });\n return Promise.all(inRange.map(day => day.getDayOfMonth()));\n }\n\n /**\n * The day number holding the roving tab stop, or `null` when the grid has none.\n *\n * `null` is a real answer, not a failure: paging with {@link next} leaves the\n * roving date behind in another month, and the grid then has no `tabindex=\"0\"`\n * at all until a key or a click puts one back.\n */\n async getActiveDayNumber(): Promise<number | null> {\n for (const day of await this.getDays()) {\n if (await day.isActive()) return day.getDayOfMonth();\n }\n return null;\n }\n\n /** The month chips, with their state. Throws off the month view. */\n async getMonths(): Promise<WrCalendarChip[]> {\n await this.requireView('month', 'getMonths');\n return this.readChips();\n }\n\n /** The year chips, with their state. Throws off the year view. */\n async getYears(): Promise<WrCalendarChip[]> {\n await this.requireView('year', 'getYears');\n return this.readChips();\n }\n\n /**\n * Click a month or year chip by its printed label — which drops the calendar back\n * one view, the way clicking the header climbed up.\n *\n * Throws on the day view, where there are no chips, and on a label the view does\n * not offer, naming what it does.\n */\n async selectChip(label: string): Promise<void> {\n const view = await this.getView();\n if (view === 'day') {\n throw new Error(\n 'WrCalendarHarness.selectChip(): the calendar is on the day view, which has no chips. Click the ' +\n 'header first — it walks day → month → year.'\n );\n }\n\n for (const chip of await this.locatorForAll('.wr-calendar__chip')()) {\n if ((await chip.text()) === label) {\n await chip.click();\n return;\n }\n }\n\n const offered = (await this.readChips()).map(chip => chip.label);\n throw new Error(`WrCalendarHarness.selectChip(\"${label}\"): the ${view} view offers: ${offered.join(', ')}.`);\n }\n\n /**\n * Press an arrow key — one day left or right, one WEEK up or down.\n *\n * Sent to the host, where the component listens, so this does not depend on jsdom\n * having managed to focus a cell. Under `dir=\"rtl\"` the horizontal pair mirrors:\n * ArrowRight goes back a day, because the grid itself is mirrored.\n */\n async pressArrow(arrow: Arrow): Promise<void> {\n await (await this.host()).sendKeys(ARROWS[arrow]);\n }\n\n /** Press Home — the first day of the roving cell's week, not of the month. */\n async pressHome(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.HOME);\n }\n\n /** Press End — the last day of the roving cell's week. */\n async pressEnd(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.END);\n }\n\n /** Press PageUp — a month back, or a YEAR back with `shift`. */\n async pressPageUp(options: { shift?: boolean } = {}): Promise<void> {\n const host = await this.host();\n await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_UP) : host.sendKeys(TestKey.PAGE_UP));\n }\n\n /** Press PageDown — a month on, or a YEAR on with `shift`. */\n async pressPageDown(options: { shift?: boolean } = {}): Promise<void> {\n const host = await this.host();\n await (options.shift ? host.sendKeys({ shift: true }, TestKey.PAGE_DOWN) : host.sendKeys(TestKey.PAGE_DOWN));\n }\n\n /** Press Enter — picking the roving day, exactly as clicking it would. */\n async pressEnter(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ENTER);\n }\n\n /**\n * The role of the element that owns the day rows.\n *\n * Worth asserting rather than assuming: the grid is NOT the host. The host also\n * holds the nav header, and a `role=\"grid\"` may only own rows — so the role sits\n * on the body, and the weekday strip is a row inside it rather than a sibling.\n */\n async getGridRole(): Promise<string | null> {\n const body = await this.locatorForOptional('.wr-calendar__body')();\n return body ? body.getAttribute('role') : null;\n }\n\n /** How many week rows the grid renders — always six, which is what keeps it from reflowing. */\n async getWeekCount(): Promise<number> {\n await this.requireView('day', 'getWeekCount');\n return (await this.locatorForAll('.wr-calendar__week')()).length;\n }\n\n private async readChips(): Promise<WrCalendarChip[]> {\n const chips = await this.locatorForAll('.wr-calendar__chip')();\n\n return Promise.all(\n chips.map(async (chip: TestElement) => ({\n label: await chip.text(),\n selected: (await chip.getAttribute('aria-selected')) === 'true',\n current: await chip.hasClass('wr-calendar__chip--current'),\n disabled: (await chip.getAttribute('aria-disabled')) === 'true',\n }))\n );\n }\n\n private async requireView(view: WrCalendarView, method: string): Promise<void> {\n const current = await this.getView();\n if (current === view) return;\n\n throw new Error(\n `WrCalendarHarness.${method}(): the calendar is showing the ${current} view, not the ${view} one — those ` +\n 'elements are not rendered at all. The header walks day → month → year; clicking a chip walks back down.'\n );\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|