ngwr 10.2.1 → 11.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 +39 -19
- package/anchor/styles/_index.scss +4 -4
- package/back-top/styles/_index.scss +6 -1
- package/blur-text/styles/_index.scss +13 -0
- package/button/styles/_index.scss +11 -6
- package/carousel/styles/_index.scss +13 -2
- package/cascader/styles/_index.scss +2 -2
- package/circular-text/styles/_index.scss +2 -0
- package/collapse/styles/_index.scss +1 -1
- package/color-picker/styles/_index.scss +6 -1
- package/compare/styles/_index.scss +1 -2
- package/context-menu/styles/_index.scss +6 -1
- package/descriptions/styles/_index.scss +2 -2
- package/dialog/styles/_index.scss +7 -0
- package/drawer/styles/_index.scss +20 -1
- package/dropdown/styles/_index.scss +19 -5
- package/empty/styles/_index.scss +10 -0
- package/fesm2022/ngwr-action-sheet.mjs +13 -3
- package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
- package/fesm2022/ngwr-affix.mjs +40 -13
- package/fesm2022/ngwr-affix.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +18 -6
- package/fesm2022/ngwr-anchor.mjs.map +1 -1
- package/fesm2022/ngwr-aurora.mjs +2 -2
- package/fesm2022/ngwr-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-avatar.mjs +31 -7
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +6 -2
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-badge.mjs +1 -1
- package/fesm2022/ngwr-badge.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart.mjs +30 -9
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text.mjs +2 -2
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +2 -2
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +9 -4
- package/fesm2022/ngwr-burger.mjs.map +1 -1
- package/fesm2022/ngwr-button-testing.mjs +96 -0
- package/fesm2022/ngwr-button-testing.mjs.map +1 -0
- package/fesm2022/ngwr-button.mjs +31 -14
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +20 -1
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +2 -2
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel-testing.mjs +377 -0
- package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
- package/fesm2022/ngwr-carousel.mjs +67 -13
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader-testing.mjs +534 -0
- package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
- package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
- package/fesm2022/ngwr-checkbox.mjs +9 -3
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +2 -2
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +2 -2
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-collapse-testing.mjs +368 -0
- package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
- package/fesm2022/ngwr-color-picker.mjs +134 -14
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
- package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
- package/fesm2022/ngwr-command-palette.mjs +58 -8
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +103 -13
- package/fesm2022/ngwr-compare.mjs.map +1 -1
- package/fesm2022/ngwr-config.mjs +106 -0
- package/fesm2022/ngwr-config.mjs.map +1 -0
- package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
- package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
- package/fesm2022/ngwr-context-menu.mjs +94 -8
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +5 -1
- package/fesm2022/ngwr-cookie.mjs.map +1 -1
- package/fesm2022/ngwr-counter.mjs +11 -3
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
- package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter.mjs +54 -8
- package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
- package/fesm2022/ngwr-date-picker.mjs +73 -3
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +27 -9
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
- package/fesm2022/ngwr-dialog-testing.mjs +89 -0
- package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
- package/fesm2022/ngwr-directives.mjs +36 -12
- package/fesm2022/ngwr-directives.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +22 -5
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer-testing.mjs +250 -0
- package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
- package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
- package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
- package/fesm2022/ngwr-dropdown.mjs +10 -2
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +24 -7
- package/fesm2022/ngwr-empty.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +57 -10
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +2 -2
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
- package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
- package/fesm2022/ngwr-form-testing.mjs +451 -0
- package/fesm2022/ngwr-form-testing.mjs.map +1 -0
- package/fesm2022/ngwr-form.mjs +19 -3
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +19 -5
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +2 -2
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +2 -2
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +50 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +48 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +23 -0
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number-testing.mjs +306 -0
- package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input-number.mjs +35 -3
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
- package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input-otp.mjs +36 -5
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input-testing.mjs +102 -0
- package/fesm2022/ngwr-input-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input.mjs +47 -10
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +44 -8
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +21 -5
- package/fesm2022/ngwr-layout.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +33 -6
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +17 -4
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +2 -2
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown-testing.mjs +516 -0
- package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
- package/fesm2022/ngwr-markdown.mjs +1492 -0
- package/fesm2022/ngwr-markdown.mjs.map +1 -0
- package/fesm2022/ngwr-marquee.mjs +17 -6
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-mention-testing.mjs +513 -0
- package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
- package/fesm2022/ngwr-mention.mjs +10 -1
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +22 -7
- package/fesm2022/ngwr-meta.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +19 -5
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-overlay.mjs +41 -1
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-pagination-testing.mjs +389 -0
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
- package/fesm2022/ngwr-pagination.mjs +14 -2
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
- package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
- package/fesm2022/ngwr-popconfirm.mjs +95 -17
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover-testing.mjs +316 -0
- package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
- package/fesm2022/ngwr-popover.mjs +21 -3
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
- package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
- package/fesm2022/ngwr-qr.mjs +13 -3
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio-testing.mjs +392 -0
- package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
- package/fesm2022/ngwr-radio.mjs +10 -3
- package/fesm2022/ngwr-radio.mjs.map +1 -1
- package/fesm2022/ngwr-rating-testing.mjs +384 -0
- package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
- package/fesm2022/ngwr-rating.mjs +37 -2
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-segmented-testing.mjs +512 -0
- package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
- package/fesm2022/ngwr-select-testing.mjs +268 -0
- package/fesm2022/ngwr-select-testing.mjs.map +1 -0
- package/fesm2022/ngwr-select.mjs +87 -16
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +2 -2
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +65 -12
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-slider-testing.mjs +478 -0
- package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
- package/fesm2022/ngwr-slider.mjs +57 -13
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +26 -6
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +37 -4
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +12 -3
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor.mjs +2 -2
- package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
- package/fesm2022/ngwr-split-text.mjs +2 -2
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter.mjs +70 -9
- package/fesm2022/ngwr-splitter.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card.mjs +2 -2
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +2 -2
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +24 -7
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper-testing.mjs +477 -0
- package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
- package/fesm2022/ngwr-switch-testing.mjs +77 -0
- package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
- package/fesm2022/ngwr-switch.mjs +9 -3
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table-testing.mjs +580 -0
- package/fesm2022/ngwr-table-testing.mjs.map +1 -0
- package/fesm2022/ngwr-table.mjs +87 -14
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-testing.mjs +617 -0
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tabs.mjs +38 -6
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea-testing.mjs +238 -0
- package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
- package/fesm2022/ngwr-textarea.mjs +32 -4
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +2 -2
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-toast-testing.mjs +101 -0
- package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
- package/fesm2022/ngwr-toast.mjs +2 -2
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-tour.mjs +61 -9
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer-testing.mjs +538 -0
- package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
- package/fesm2022/ngwr-transfer.mjs +45 -14
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree-testing.mjs +734 -0
- package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tree.mjs +73 -7
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +5 -3
- package/fesm2022/ngwr-typewriter.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 +31 -5
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +3 -3
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +8 -0
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/gauge/styles/_index.scss +1 -1
- package/glitch-text/styles/_index.scss +4 -0
- package/i18n/en.json +48 -0
- package/i18n/ru.json +48 -0
- package/image-cropper/styles/_index.scss +13 -1
- package/input/styles/_index.scss +2 -2
- package/input-number/styles/_index.scss +7 -2
- package/knob/styles/_index.scss +8 -1
- package/layout/styles/_index.scss +3 -3
- package/lightbox/styles/_index.scss +10 -2
- package/line-chart/styles/_index.scss +6 -0
- package/llms-full.txt +151 -4
- package/llms.txt +57 -8
- package/loading-bar/styles/_index.scss +1 -2
- package/markdown/styles/_index.scss +296 -0
- package/marquee/styles/_index.scss +12 -0
- package/mcp/api.js +512 -0
- package/mcp/catalog.js +157 -0
- package/mcp/server.js +273 -0
- package/mcp/tools.js +366 -0
- package/meter-group/styles/_index.scss +1 -1
- package/package.json +186 -35
- package/pagination/styles/_index.scss +6 -6
- package/popover/styles/_index.scss +37 -5
- package/rating/styles/_index.scss +10 -0
- package/schematics/use/symbol-map.json +2 -0
- package/segmented/styles/_index.scss +7 -0
- package/select/styles/_index.scss +29 -9
- package/sidebar/styles/_index.scss +30 -5
- package/slider/styles/_index.scss +15 -0
- package/speed-dial/styles/_index.scss +20 -0
- package/split-text/styles/_index.scss +13 -0
- package/star-border/styles/_index.scss +2 -0
- package/stepper/styles/_index.scss +1 -1
- package/styles/_grid.scss +4 -4
- package/styles.scss +1 -0
- package/switch/styles/_index.scss +5 -3
- package/table/styles/_index.scss +22 -11
- package/tabs/styles/_index.scss +11 -1
- package/textarea/styles/_index.scss +5 -0
- package/theme/styles/_colors.scss +29 -13
- package/theme/styles/_dark.scss +11 -3
- package/theme/styles/_mixins.scss +3 -0
- package/timeline/styles/_index.scss +2 -2
- package/toast/styles/_index.scss +17 -8
- package/toolbar/styles/_index.scss +3 -3
- package/tour/styles/_index.scss +7 -1
- package/tree/styles/_index.scss +5 -3
- package/types/ngwr-action-sheet.d.ts +9 -1
- package/types/ngwr-affix.d.ts +7 -1
- package/types/ngwr-anchor.d.ts +8 -1
- package/types/ngwr-avatar.d.ts +13 -3
- package/types/ngwr-bar-chart.d.ts +16 -0
- package/types/ngwr-burger.d.ts +6 -2
- package/types/ngwr-button-testing.d.ts +85 -0
- package/types/ngwr-button.d.ts +26 -10
- package/types/ngwr-calendar-heatmap.d.ts +16 -2
- package/types/ngwr-calendar.d.ts +10 -0
- package/types/ngwr-carousel-testing.d.ts +257 -0
- package/types/ngwr-carousel.d.ts +20 -4
- package/types/ngwr-cascader-testing.d.ts +392 -0
- package/types/ngwr-checkbox-testing.d.ts +77 -0
- package/types/ngwr-checkbox.d.ts +7 -2
- package/types/ngwr-collapse-testing.d.ts +290 -0
- package/types/ngwr-color-picker.d.ts +20 -11
- package/types/ngwr-command-palette-testing.d.ts +437 -0
- package/types/ngwr-command-palette.d.ts +25 -2
- package/types/ngwr-compare.d.ts +50 -2
- package/types/ngwr-config.d.ts +176 -0
- package/types/ngwr-context-menu-testing.d.ts +401 -0
- package/types/ngwr-context-menu.d.ts +65 -17
- package/types/ngwr-counter.d.ts +6 -1
- package/types/ngwr-date-adapter-luxon.d.ts +26 -0
- package/types/ngwr-date-picker-testing.d.ts +518 -0
- package/types/ngwr-date-picker.d.ts +4 -0
- package/types/ngwr-dialog-testing.d.ts +79 -0
- package/types/ngwr-directives.d.ts +10 -1
- package/types/ngwr-donut-chart.d.ts +8 -1
- package/types/ngwr-drawer-testing.d.ts +196 -0
- package/types/ngwr-dropdown-testing.d.ts +202 -0
- package/types/ngwr-dropdown.d.ts +7 -1
- package/types/ngwr-empty.d.ts +19 -4
- package/types/ngwr-event-calendar.d.ts +26 -1
- package/types/ngwr-file-upload-testing.d.ts +194 -0
- package/types/ngwr-form-testing.d.ts +379 -0
- package/types/ngwr-form.d.ts +17 -0
- package/types/ngwr-gauge.d.ts +13 -1
- package/types/ngwr-image-cropper.d.ts +10 -0
- package/types/ngwr-input-number-testing.d.ts +226 -0
- package/types/ngwr-input-number.d.ts +29 -1
- package/types/ngwr-input-otp-testing.d.ts +299 -0
- package/types/ngwr-input-otp.d.ts +23 -2
- package/types/ngwr-input-testing.d.ts +84 -0
- package/types/ngwr-input.d.ts +20 -6
- package/types/ngwr-knob.d.ts +18 -0
- package/types/ngwr-layout.d.ts +1 -0
- package/types/ngwr-lightbox.d.ts +17 -3
- package/types/ngwr-line-chart.d.ts +9 -2
- package/types/ngwr-markdown-testing.d.ts +462 -0
- package/types/ngwr-markdown.d.ts +534 -0
- package/types/ngwr-marquee.d.ts +12 -2
- package/types/ngwr-mention-testing.d.ts +359 -0
- package/types/ngwr-meta.d.ts +4 -2
- package/types/ngwr-meter-group.d.ts +11 -1
- package/types/ngwr-overlay.d.ts +33 -2
- package/types/ngwr-pagination-testing.d.ts +291 -0
- package/types/ngwr-pagination.d.ts +1 -0
- package/types/ngwr-popconfirm-testing.d.ts +235 -0
- package/types/ngwr-popconfirm.d.ts +31 -21
- package/types/ngwr-popover-testing.d.ts +221 -0
- package/types/ngwr-popover.d.ts +9 -0
- package/types/ngwr-pull-to-refresh.d.ts +7 -0
- package/types/ngwr-qr.d.ts +9 -1
- package/types/ngwr-radio-testing.d.ts +296 -0
- package/types/ngwr-radio.d.ts +8 -2
- package/types/ngwr-rating-testing.d.ts +291 -0
- package/types/ngwr-rating.d.ts +23 -0
- package/types/ngwr-segmented-testing.d.ts +401 -0
- package/types/ngwr-select-testing.d.ts +175 -0
- package/types/ngwr-select.d.ts +45 -4
- package/types/ngwr-sidebar.d.ts +17 -2
- package/types/ngwr-slider-testing.d.ts +329 -0
- package/types/ngwr-slider.d.ts +35 -1
- package/types/ngwr-sparkline.d.ts +12 -2
- package/types/ngwr-speed-dial.d.ts +17 -18
- package/types/ngwr-spinner.d.ts +8 -1
- package/types/ngwr-splitter.d.ts +24 -1
- package/types/ngwr-statistic.d.ts +12 -2
- package/types/ngwr-stepper-testing.d.ts +346 -0
- package/types/ngwr-switch-testing.d.ts +66 -0
- package/types/ngwr-switch.d.ts +7 -2
- package/types/ngwr-table-testing.d.ts +423 -0
- package/types/ngwr-table.d.ts +42 -0
- package/types/ngwr-tabs-testing.d.ts +470 -0
- package/types/ngwr-tabs.d.ts +9 -0
- package/types/ngwr-textarea-testing.d.ts +184 -0
- package/types/ngwr-textarea.d.ts +7 -2
- package/types/ngwr-toast-testing.d.ts +80 -0
- package/types/ngwr-tour.d.ts +27 -0
- package/types/ngwr-transfer-testing.d.ts +444 -0
- package/types/ngwr-transfer.d.ts +16 -1
- package/types/ngwr-tree-testing.d.ts +501 -0
- package/types/ngwr-tree.d.ts +33 -0
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-virtual-scroll.d.ts +13 -1
- package/typewriter/styles/_index.scss +1 -1
- package/typography/styles/_index.scss +1 -1
- package/window/styles/_index.scss +32 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-cookie.mjs","sources":["../../../projects/lib/cookie/cookie.ts","../../../projects/lib/cookie/ngwr-cookie.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 { DOCUMENT } from '@angular/common';\nimport { Service, inject } from '@angular/core';\n\nimport type { WrCookieOptions } from './interfaces';\n\nconst DEFAULT_OPTS: Required<Pick<WrCookieOptions, 'path' | 'sameSite'>> = {\n path: '/',\n sameSite: 'Lax',\n};\n\n/**\n * Thin, SSR-safe `document.cookie` wrapper modelled after {@link WrStorage}.\n *\n * - Read/write/delete cookies through a typed API.\n * - `set()` serialises `expires` as either an HTTP-date or `Max-Age`.\n * - Every method short-circuits when there's no DOM (SSR / unit tests\n * without a document) — reads return the fallback, writes are no-ops.\n *\n * @example\n * ```ts\n * const cookies = inject(WrCookie);\n *\n * cookies.set('theme', 'dark', { expires: 60 * 60 * 24 * 30 }); // 30 days\n * cookies.get('theme'); // 'dark'\n * cookies.has('theme'); // true\n * cookies.remove('theme');\n * cookies.keys(); // readonly string[]\n * ```\n *\n * @see https://ngwr.dev/reference/services/cookie\n */\n@Service()\nexport class WrCookie {\n private readonly doc = inject(DOCUMENT);\n\n /**\n * `document.cookie`, or `''` when it cannot be read. Mirrors the guard on\n * `set()`: under SSR the server DOM has no cookie support and throws on the\n * getter, and sandboxed iframes reject access too.\n */\n private read(): string {\n try {\n return this.doc.cookie;\n } catch {\n return '';\n }\n }\n\n /** Is `key` present (regardless of value)? */\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n /** Read `key`. Returns `fallback` (default `null`) when the key is missing. */\n get(key: string, fallback: string | null = null): string | null {\n const raw = this.read();\n if (!raw) return fallback;\n const needle = `${encodeURIComponent(key)}=`;\n for (const part of raw.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(needle)) {\n try {\n return decodeURIComponent(trimmed.slice(needle.length));\n } catch {\n return trimmed.slice(needle.length);\n }\n }\n }\n return fallback;\n }\n\n /** Write `key=value` with optional attributes. */\n set(key: string, value: string, options?: WrCookieOptions): void {\n const opts = { ...DEFAULT_OPTS, ...options };\n const parts: string[] = [`${encodeURIComponent(key)}=${encodeURIComponent(value)}`];\n\n if (opts.expires !== undefined) {\n if (opts.expires instanceof Date) {\n parts.push(`expires=${opts.expires.toUTCString()}`);\n } else {\n parts.push(`max-age=${Math.max(0, Math.floor(opts.expires))}`);\n }\n }\n\n parts.push(`path=${opts.path}`);\n if (opts.domain) parts.push(`domain=${opts.domain}`);\n if (opts.secure) parts.push('secure');\n parts.push(`samesite=${opts.sameSite}`);\n\n try {\n this.doc.cookie = parts.join('; ');\n } catch {\n // SSR / sandboxed iframes: silently no-op.\n }\n }\n\n /** Remove `key`. Path / domain must match what was used in `set()`. */\n remove(key: string, options?: Pick<WrCookieOptions, 'path' | 'domain'>): void {\n this.set(key, '', { ...options, expires: new Date(0) });\n }\n\n /** Every cookie key visible to this document. */\n keys(): readonly string[] {\n const raw = this.read();\n if (!raw) return [];\n const out: string[] = [];\n for (const part of raw.split(';')) {\n const trimmed = part.trim();\n const eq = trimmed.indexOf('=');\n if (eq < 0) continue;\n try {\n out.push(decodeURIComponent(trimmed.slice(0, eq)));\n } catch {\n out.push(trimmed.slice(0, eq));\n }\n }\n return out;\n }\n\n /** Remove every cookie visible to this document. Uses `path: '/'`. */\n clear(): void {\n for (const k of this.keys()) this.remove(k);\n }\n}\n\nexport type { WrCookieOptions } from './interfaces';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;;AAAA;;;;;AAKG;AAOH,MAAM,YAAY,GAAyD;AACzE,IAAA,IAAI,EAAE,GAAG;AACT,IAAA,QAAQ,EAAE,KAAK;CAChB;AAED;;;;;;;;;;;;;;;;;;;;AAoBG;MAEU,QAAQ,CAAA;AACF,IAAA,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC;AAEvC;;;;AAIG;IACK,IAAI,GAAA;AACV,QAAA,IAAI;AACF,YAAA,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM;QACxB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,EAAE;QACX;IACF;;AAGA,IAAA,GAAG,CAAC,GAAW,EAAA;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI;IAC/B;;AAGA,IAAA,GAAG,CAAC,GAAW,EAAE,QAAA,GAA0B,IAAI,EAAA;AAC7C,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,EAAE;AACvB,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,QAAQ;QACzB,MAAM,MAAM,GAAG,CAAA,EAAG,kBAAkB,CAAC,GAAG,CAAC,GAAG;QAC5C,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;AACjC,YAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE;AAC3B,YAAA,IAAI,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;AAC9B,gBAAA,IAAI;oBACF,OAAO,kBAAkB,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;gBACzD;AAAE,gBAAA,MAAM;oBACN,OAAO,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC;YACF;QACF;AACA,QAAA,OAAO,QAAQ;IACjB;;AAGA,IAAA,GAAG,CAAC,GAAW,EAAE,KAAa,EAAE,OAAyB,EAAA;QACvD,MAAM,IAAI,GAAG,EAAE,GAAG,YAAY,EAAE,GAAG,OAAO,EAAE;AAC5C,QAAA,MAAM,KAAK,GAAa,CAAC,CAAA,EAAG,kBAAkB,CAAC,GAAG,CAAC,CAAA,CAAA,EAAI,kBAAkB,CAAC,KAAK,CAAC,CAAA,CAAE,CAAC;AAEnF,QAAA,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE;AAC9B,YAAA,IAAI,IAAI,CAAC,OAAO,YAAY,IAAI,EAAE;AAChC,gBAAA,KAAK,CAAC,IAAI,CAAC,CAAA,QAAA,EAAW,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAA,CAAE,CAAC;YACrD;iBAAO;gBACL,KAAK,CAAC,IAAI,CAAC,CAAA,QAAA,EAAW,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAA,CAAE,CAAC;YAChE;QACF;QAEA,KAAK,CAAC,IAAI,CAAC,CAAA,KAAA,EAAQ,IAAI,CAAC,IAAI,CAAA,CAAE,CAAC;QAC/B,IAAI,IAAI,CAAC,MAAM;YAAE,KAAK,CAAC,IAAI,CAAC,CAAA,OAAA,EAAU,IAAI,CAAC,MAAM,CAAA,CAAE,CAAC
|
|
1
|
+
{"version":3,"file":"ngwr-cookie.mjs","sources":["../../../projects/lib/cookie/cookie.ts","../../../projects/lib/cookie/ngwr-cookie.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 { DOCUMENT } from '@angular/common';\nimport { Service, inject } from '@angular/core';\n\nimport type { WrCookieOptions } from './interfaces';\n\nconst DEFAULT_OPTS: Required<Pick<WrCookieOptions, 'path' | 'sameSite'>> = {\n path: '/',\n sameSite: 'Lax',\n};\n\n/**\n * Thin, SSR-safe `document.cookie` wrapper modelled after {@link WrStorage}.\n *\n * - Read/write/delete cookies through a typed API.\n * - `set()` serialises `expires` as either an HTTP-date or `Max-Age`.\n * - Every method short-circuits when there's no DOM (SSR / unit tests\n * without a document) — reads return the fallback, writes are no-ops.\n *\n * @example\n * ```ts\n * const cookies = inject(WrCookie);\n *\n * cookies.set('theme', 'dark', { expires: 60 * 60 * 24 * 30 }); // 30 days\n * cookies.get('theme'); // 'dark'\n * cookies.has('theme'); // true\n * cookies.remove('theme');\n * cookies.keys(); // readonly string[]\n * ```\n *\n * @see https://ngwr.dev/reference/services/cookie\n */\n@Service()\nexport class WrCookie {\n private readonly doc = inject(DOCUMENT);\n\n /**\n * `document.cookie`, or `''` when it cannot be read. Mirrors the guard on\n * `set()`: under SSR the server DOM has no cookie support and throws on the\n * getter, and sandboxed iframes reject access too.\n */\n private read(): string {\n try {\n return this.doc.cookie;\n } catch {\n return '';\n }\n }\n\n /** Is `key` present (regardless of value)? */\n has(key: string): boolean {\n return this.get(key) !== null;\n }\n\n /** Read `key`. Returns `fallback` (default `null`) when the key is missing. */\n get(key: string, fallback: string | null = null): string | null {\n const raw = this.read();\n if (!raw) return fallback;\n const needle = `${encodeURIComponent(key)}=`;\n for (const part of raw.split(';')) {\n const trimmed = part.trim();\n if (trimmed.startsWith(needle)) {\n try {\n return decodeURIComponent(trimmed.slice(needle.length));\n } catch {\n return trimmed.slice(needle.length);\n }\n }\n }\n return fallback;\n }\n\n /** Write `key=value` with optional attributes. */\n set(key: string, value: string, options?: WrCookieOptions): void {\n const opts = { ...DEFAULT_OPTS, ...options };\n const parts: string[] = [`${encodeURIComponent(key)}=${encodeURIComponent(value)}`];\n\n if (opts.expires !== undefined) {\n if (opts.expires instanceof Date) {\n parts.push(`expires=${opts.expires.toUTCString()}`);\n } else {\n parts.push(`max-age=${Math.max(0, Math.floor(opts.expires))}`);\n }\n }\n\n parts.push(`path=${opts.path}`);\n if (opts.domain) parts.push(`domain=${opts.domain}`);\n // `SameSite=None` REQUIRES `Secure`: every modern browser drops the cookie outright\n // without it, so asking for one without the other used to be a silent no-op — the one\n // failure a cookie API must not have. The caller asked for a cross-site cookie, and\n // this is what one is.\n if (opts.secure || opts.sameSite === 'None') parts.push('secure');\n parts.push(`samesite=${opts.sameSite}`);\n\n try {\n this.doc.cookie = parts.join('; ');\n } catch {\n // SSR / sandboxed iframes: silently no-op.\n }\n }\n\n /** Remove `key`. Path / domain must match what was used in `set()`. */\n remove(key: string, options?: Pick<WrCookieOptions, 'path' | 'domain'>): void {\n this.set(key, '', { ...options, expires: new Date(0) });\n }\n\n /** Every cookie key visible to this document. */\n keys(): readonly string[] {\n const raw = this.read();\n if (!raw) return [];\n const out: string[] = [];\n for (const part of raw.split(';')) {\n const trimmed = part.trim();\n const eq = trimmed.indexOf('=');\n if (eq < 0) continue;\n try {\n out.push(decodeURIComponent(trimmed.slice(0, eq)));\n } catch {\n out.push(trimmed.slice(0, eq));\n }\n }\n return out;\n }\n\n /** Remove every cookie visible to this document. Uses `path: '/'`. */\n clear(): void {\n for (const k of this.keys()) this.remove(k);\n }\n}\n\nexport type { WrCookieOptions } from './interfaces';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { coerceNumberProperty } from '@angular/cdk/coercion';
|
|
|
2
2
|
import { isPlatformBrowser } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { input, signal, inject, LOCALE_ID, PLATFORM_ID, computed, DestroyRef, effect, untracked, ViewEncapsulation, Component, output, ElementRef, afterNextRender } from '@angular/core';
|
|
5
|
+
import { WrPlatform } from 'ngwr/platform';
|
|
5
6
|
import { numAttr } from 'ngwr/utils';
|
|
6
7
|
|
|
7
8
|
/** Cubic ease-out — the shared tween curve for counter / count-up. */
|
|
@@ -36,8 +37,11 @@ function easeOutCubic(t) {
|
|
|
36
37
|
*/
|
|
37
38
|
class WrCounter {
|
|
38
39
|
/** Target value. */
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The number to show. Coerced like every other numeric input here — it was the only one
|
|
42
|
+
* without it, and `Intl.NumberFormat().format(NaN)` renders the literal text `NaN`.
|
|
43
|
+
*/
|
|
44
|
+
value = input.required({ ...(ngDevMode ? { debugName: "value" } : /* istanbul ignore next */ {}), transform: (v) => coerceNumberProperty(v, 0) });
|
|
41
45
|
/** Animation mode. @default 'odometer' */
|
|
42
46
|
mode = input('odometer', /* @ts-ignore */
|
|
43
47
|
...(ngDevMode ? [{ debugName: "mode" }] : /* istanbul ignore next */ []));
|
|
@@ -60,6 +64,7 @@ class WrCounter {
|
|
|
60
64
|
...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
|
|
61
65
|
locale = inject(LOCALE_ID);
|
|
62
66
|
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
67
|
+
platform = inject(WrPlatform);
|
|
63
68
|
rafId = null;
|
|
64
69
|
/** Tween-mode formatted output. */
|
|
65
70
|
tweenText = computed(() => this.format(this.current()), /* @ts-ignore */
|
|
@@ -110,7 +115,10 @@ class WrCounter {
|
|
|
110
115
|
// this effect each frame, cancelling + restarting the tween endlessly
|
|
111
116
|
// (the wheels hang mid-roll and only snap once the restarts converge).
|
|
112
117
|
const start = untracked(() => this.current());
|
|
113
|
-
|
|
118
|
+
// Straight to the answer when there is nothing to animate for: no browser, or a
|
|
119
|
+
// reader who asked for less motion. `wr-scroll` already falls back the same way, and a
|
|
120
|
+
// component whose entire purpose is a count-up should be the first to honour it.
|
|
121
|
+
if (!this.isBrowser || this.platform.prefersReducedMotion()) {
|
|
114
122
|
this.current.set(target);
|
|
115
123
|
return;
|
|
116
124
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-counter.mjs","sources":["../../../projects/lib/counter/easing.ts","../../../projects/lib/counter/counter.ts","../../../projects/lib/counter/counter.html","../../../projects/lib/counter/count-up.ts","../../../projects/lib/counter/ngwr-counter.ts"],"sourcesContent":["/** Cubic ease-out — the shared tween curve for counter / count-up. */\nexport function easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCounterMode } from './interfaces';\n\n/** Visual cell in odometer mode — either a 0-9 column or a static glyph. */\ntype Cell = { readonly kind: 'digit'; readonly fraction: number } | { readonly kind: 'static'; readonly char: string };\n\n/**\n * Animated number display with two modes:\n *\n * - **`odometer`** (default) — each digit is a vertical strip of 0-9 that\n * rolls into place, continuously interpolated for smooth motion when the\n * value changes.\n * - **`tween`** — a single eased count-up between the previous and new value,\n * rendered through `Intl.NumberFormat`.\n *\n * Reacts to `[value]` changes — animate from any number to any number.\n *\n * @example\n * ```html\n * <wr-counter [value]=\"123456\" mode=\"odometer\" />\n * <wr-counter [value]=\"9.99\" mode=\"tween\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-counter',\n templateUrl: './counter.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-counter' },\n})\nexport class WrCounter {\n /** Target value. */\n readonly value = input.required<number>();\n\n /** Animation mode. @default 'odometer' */\n readonly mode = input<WrCounterMode>('odometer');\n\n /** Duration (ms). @default 900 */\n readonly duration = input(900, {\n transform: (v: unknown): number => Math.max(100, coerceNumberProperty(v, 900)),\n });\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Group thousands. @default true */\n readonly grouping = input<boolean>(true);\n\n /** Pad integer part to at least this many digits. @default 0 (no padding) */\n readonly minIntegerDigits = input(0, {\n transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)),\n });\n\n private readonly current = signal<number>(0);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private rafId: number | null = null;\n\n /** Tween-mode formatted output. */\n protected readonly tweenText = computed(() => this.format(this.current()));\n\n /**\n * Odometer-mode text for assistive tech and prerendered output. The strip\n * renders every digit 0-9 per column and picks one with a transform, so its\n * markup carries no usable text — screen readers would announce all ten, and\n * static HTML would ship the same noise. This node holds the real value.\n */\n protected readonly odoText = computed(() => `${this.prefix()}${this.format(this.value())}${this.suffix()}`);\n\n /** Odometer cells — one per character in the formatted target string. */\n protected readonly cells = computed<readonly Cell[]>(() => {\n // Build the string with target sign + max length so we can interpolate\n // each digit position smoothly.\n const target = this.value();\n const live = this.current();\n const formattedTarget = this.format(target);\n const formattedLive = this.format(live);\n\n // Right-align so trailing digits line up.\n const maxLen = Math.max(formattedTarget.length, formattedLive.length);\n const padTarget = formattedTarget.padStart(maxLen, ' ');\n const padLive = formattedLive.padStart(maxLen, ' ');\n\n const cells: Cell[] = [];\n for (let i = 0; i < maxLen; i++) {\n const t = padTarget[i];\n const l = padLive[i];\n if (/[0-9]/.test(t) && /[0-9]/.test(l)) {\n // Interpolate the fractional digit so the strip rolls smoothly —\n // multi-digit rollover (9 → 0 carries 1) looks continuous.\n const fraction = this.digitFractionAt(live, target, i, maxLen);\n cells.push({ kind: 'digit', fraction });\n } else {\n cells.push({ kind: 'static', char: t === ' ' ? '' : t });\n }\n }\n return cells;\n });\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.cancel());\n\n effect(() => {\n const target = this.value();\n // Snapshot the current value WITHOUT tracking it — the RAF tick below\n // writes `current` every frame, and tracking it here would re-trigger\n // this effect each frame, cancelling + restarting the tween endlessly\n // (the wheels hang mid-roll and only snap once the restarts converge).\n const start = untracked(() => this.current());\n if (!this.isBrowser) {\n this.current.set(target);\n return;\n }\n this.cancel();\n const startTs = performance.now();\n const dur = this.duration();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / dur);\n // Snap exactly to target on the final frame. Without this,\n // `start + (target - start) * 1` carries FP rounding (e.g.\n // 0.1 + (0.3 - 0.1) * 1 = 0.30000000000000004), so\n // `digitFractionAt`'s `live === target` rest-state check\n // fails — wheels visibly stop on a fractional position and\n // never settle to the clean integer glyph.\n const v = t >= 1 ? target : start + (target - start) * easeOutCubic(t);\n this.current.set(v);\n if (t < 1) this.rafId = requestAnimationFrame(tick);\n else this.rafId = null;\n };\n this.rafId = requestAnimationFrame(tick);\n });\n }\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n private format(n: number): string {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n minimumIntegerDigits: this.minIntegerDigits() || 1,\n useGrouping: this.grouping(),\n }).format(n);\n }\n\n /**\n * Compute the smoothly-interpolated digit (0..10) at column `i` of the\n * formatted live string. Returns the integer digit + a fraction so the\n * strip CSS translate looks like a real rolling odometer.\n */\n private digitFractionAt(live: number, target: number, columnIndex: number, totalLen: number): number {\n // Determine the place value at this column. Account for grouping separators\n // and the decimal point by counting digits to the right of this column in\n // the formatted target.\n const formattedTarget = this.format(target);\n const padded = formattedTarget.padStart(totalLen, ' ');\n const tail = padded.slice(columnIndex + 1);\n const digitsRight = (tail.match(/[0-9]/g) ?? []).length;\n const placePower = digitsRight - this.decimals();\n const place = Math.pow(10, placePower);\n const absLive = Math.abs(live);\n const raw = absLive / place;\n // Modulo 10 gives the digit at this column with fractional rollover —\n // mid-animation this looks like a real wheel rolling between digits.\n const mod = raw - Math.floor(raw / 10) * 10;\n // At rest (live === target) every wheel must rest on an exact integer\n // — otherwise upper digits show as partial (e.g. tens reads \"5.6\"\n // for value 123456, visibly clipping between 5 and 6 in the\n // overflow:hidden window). The continuous-mechanical look is only\n // wanted DURING the tween, not after it settles.\n if (live === target) return Math.floor(mod + 1e-9);\n return mod;\n }\n}\n","@if (mode() === 'tween') {\n <span class=\"wr-counter__tween\">{{ prefix() }}{{ tweenText() }}{{ suffix() }}</span>\n} @else {\n <span class=\"wr-counter__sr-only\">{{ odoText() }}</span>\n <span class=\"wr-counter__odo\" aria-hidden=\"true\">\n @if (prefix()) {\n <span class=\"wr-counter__static\">{{ prefix() }}</span>\n }\n @for (cell of cells(); track $index) {\n @if (cell.kind === 'digit') {\n <span class=\"wr-counter__digit\">\n <span class=\"wr-counter__strip\" [style.transform]=\"`translateY(-${cell.fraction}em)`\">\n <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span\n ><span>7</span><span>8</span><span>9</span>\n </span>\n </span>\n } @else {\n <span class=\"wr-counter__static\">{{ cell.char }}</span>\n }\n }\n @if (suffix()) {\n <span class=\"wr-counter__static\">{{ suffix() }}</span>\n }\n </span>\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 * The spring-physics path is an adaptation of the CountUp effect by\n * David Haz / reactbits.dev (https://www.reactbits.dev/text-animations/count-up).\n * Same critically-damped formula, implemented inline with rAF — no\n * external dependency.\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCountUpDirection, WrCountUpEasing, WrCountUpTrigger } from './interfaces';\n\n/**\n * Animated number tick. Animates from `from` to the current `to`, formatting\n * via `Intl.NumberFormat`. Re-runs whenever `to` changes.\n *\n * @example Basic\n * ```html\n * <wr-count-up [to]=\"12345\" />\n * <wr-count-up [to]=\"9.99\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @example Reactbits-style — spring curve + viewport trigger\n * ```html\n * <wr-count-up [to]=\"100\" easing=\"spring\" trigger=\"visible\" [delay]=\"200\" />\n * ```\n *\n * @example Count down\n * ```html\n * <wr-count-up [from]=\"60\" [to]=\"0\" direction=\"down\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-count-up',\n template: `{{ prefix() }}{{ formatted() }}{{ suffix() }}`,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-count-up' },\n})\nexport class WrCountUp {\n /** Starting value. @default 0 */\n readonly from = input(0, { transform: numAttr(0) });\n\n /** Target value. */\n readonly to = input.required<number>();\n\n /**\n * Animation duration. Units depend on `easing`:\n *\n * - `ease-out` — milliseconds (default 1200, min 100)\n * - `spring` — seconds (tunes spring stiffness; default 2)\n */\n readonly duration = input(1200, { transform: numAttr(1200) });\n\n /** Optional delay (ms) before the animation starts. @default 0 */\n readonly delay = input(0, { transform: numAttr(0) });\n\n /** Animation curve. @default 'ease-out' */\n readonly easing = input<WrCountUpEasing>('ease-out');\n\n /**\n * When to start the animation.\n *\n * - `'mount'` (default) — start as soon as the component is rendered.\n * - `'visible'` — wait for the host to enter the viewport\n * (IntersectionObserver). Useful for long pages or hero numbers\n * below the fold.\n */\n readonly trigger = input<WrCountUpTrigger>('mount');\n\n /** Counting direction. `'down'` swaps `from` ↔ `to`. @default 'up' */\n readonly direction = input<WrCountUpDirection>('up');\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Disable grouping separators (`1,234` → `1234`). @default true (grouping on) */\n readonly grouping = input<boolean>(true);\n\n /** Emits when the animation begins. */\n readonly started = output<void>();\n\n /** Emits when the animation settles. */\n readonly completed = output<void>();\n\n private readonly value = signal<number>(0);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly destroyRef = inject(DestroyRef);\n\n private rafId: number | null = null;\n private delayTimer: ReturnType<typeof setTimeout> | undefined;\n private observer: IntersectionObserver | null = null;\n private hasFiredForVisible = false;\n\n protected readonly formatted = computed(() => {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n useGrouping: this.grouping(),\n }).format(this.value());\n });\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: settle on the value the animation ENDS on. Seeding the start\n // instead would bake the placeholder (usually 0) into prerendered HTML,\n // so readers and crawlers would get 0 rather than the real figure. The\n // browser rewinds to the start and animates once it boots.\n effect(() => this.value.set(this.direction() === 'down' ? this.from() : this.to()));\n return;\n }\n\n // Seed the resting value so first paint shows the start, not 0.\n effect(() => {\n const initial = this.direction() === 'down' ? this.to() : this.from();\n this.value.set(initial);\n });\n\n // Run the animation whenever the `to` target changes (or on first mount).\n // For `trigger=\"visible\"` the first run waits for the IntersectionObserver\n // to fire; subsequent `to` changes re-run immediately.\n effect(() => {\n // Establish dependencies so the effect re-runs on `to` changes.\n this.to();\n this.from();\n this.direction();\n this.duration();\n this.easing();\n this.delay();\n\n if (this.trigger() === 'visible' && !this.hasFiredForVisible) return;\n this.scheduleRun();\n });\n\n afterNextRender(() => {\n if (this.trigger() === 'visible') this.setupViewportTrigger();\n });\n\n this.destroyRef.onDestroy(() => {\n this.cancel();\n // `cancel()` only stops timers and the rAF loop. The IntersectionObserver\n // disconnects itself from inside its callback, which never fires if the\n // host is destroyed before it ever scrolls into view — so it would keep\n // observing a detached element for the life of the page.\n this.observer?.disconnect();\n this.observer = null;\n });\n }\n\n // Scheduling\n\n private setupViewportTrigger(): void {\n this.observer = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasFiredForVisible) {\n obs.disconnect();\n this.hasFiredForVisible = true;\n this.scheduleRun();\n break;\n }\n }\n },\n { threshold: 0, rootMargin: '0px' }\n );\n this.observer.observe(this.host.nativeElement);\n }\n\n private scheduleRun(): void {\n this.cancel();\n const d = this.delay();\n if (d > 0) {\n this.delayTimer = setTimeout(() => this.run(), d);\n } else {\n this.run();\n }\n }\n\n private run(): void {\n const start = this.direction() === 'down' ? this.to() : this.from();\n const end = this.direction() === 'down' ? this.from() : this.to();\n this.started.emit();\n if (this.easing() === 'spring') this.tweenSpring(start, end);\n else this.tweenEaseOut(start, end);\n }\n\n // Tweens\n\n private tweenEaseOut(start: number, target: number): void {\n const duration = Math.max(100, this.duration());\n const startTs = performance.now();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / duration);\n const v = start + (target - start) * easeOutCubic(t);\n this.value.set(v);\n if (t < 1) {\n this.rafId = requestAnimationFrame(tick);\n } else {\n this.completed.emit();\n }\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n /**\n * Critically-damped spring tween. Same formula as `motion/react`'s\n * `useSpring` with mass = 1:\n *\n * damping = 20 + 40 / duration\n * stiffness = 100 / duration\n *\n * We integrate `(spring force − damping force)` each frame until both\n * displacement and velocity fall below epsilon.\n */\n private tweenSpring(start: number, target: number): void {\n const duration = Math.max(0.05, this.duration());\n const damping = 20 + 40 / duration;\n const stiffness = 100 / duration;\n let current = start;\n let velocity = 0;\n let lastTs = 0;\n const epsilon = 0.001 * Math.max(1, Math.abs(target - start));\n\n const step = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const displacement = current - target;\n const accel = -stiffness * displacement - damping * velocity;\n velocity += accel * dt;\n current += velocity * dt;\n this.value.set(current);\n\n if (Math.abs(current - target) < epsilon && Math.abs(velocity) < epsilon * 10) {\n this.value.set(target);\n this.completed.emit();\n return;\n }\n this.rafId = requestAnimationFrame(step);\n };\n this.rafId = requestAnimationFrame(step);\n }\n\n // Cleanup\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n if (this.delayTimer !== undefined) {\n clearTimeout(this.delayTimer);\n this.delayTimer = undefined;\n }\n }\n}\n\nexport type { WrCountUpEasing, WrCountUpTrigger, WrCountUpDirection } from './interfaces';\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-counter.mjs","sources":["../../../projects/lib/counter/easing.ts","../../../projects/lib/counter/counter.ts","../../../projects/lib/counter/counter.html","../../../projects/lib/counter/count-up.ts","../../../projects/lib/counter/ngwr-counter.ts"],"sourcesContent":["/** Cubic ease-out — the shared tween curve for counter / count-up. */\nexport function easeOutCubic(t: number): number {\n return 1 - Math.pow(1 - t, 3);\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 { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n computed,\n effect,\n inject,\n input,\n signal,\n untracked,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCounterMode } from './interfaces';\n\n/** Visual cell in odometer mode — either a 0-9 column or a static glyph. */\ntype Cell = { readonly kind: 'digit'; readonly fraction: number } | { readonly kind: 'static'; readonly char: string };\n\n/**\n * Animated number display with two modes:\n *\n * - **`odometer`** (default) — each digit is a vertical strip of 0-9 that\n * rolls into place, continuously interpolated for smooth motion when the\n * value changes.\n * - **`tween`** — a single eased count-up between the previous and new value,\n * rendered through `Intl.NumberFormat`.\n *\n * Reacts to `[value]` changes — animate from any number to any number.\n *\n * @example\n * ```html\n * <wr-counter [value]=\"123456\" mode=\"odometer\" />\n * <wr-counter [value]=\"9.99\" mode=\"tween\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-counter',\n templateUrl: './counter.html',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-counter' },\n})\nexport class WrCounter {\n /** Target value. */\n /**\n * The number to show. Coerced like every other numeric input here — it was the only one\n * without it, and `Intl.NumberFormat().format(NaN)` renders the literal text `NaN`.\n */\n readonly value = input.required<number, unknown>({\n transform: (v: unknown): number => coerceNumberProperty(v, 0),\n });\n\n /** Animation mode. @default 'odometer' */\n readonly mode = input<WrCounterMode>('odometer');\n\n /** Duration (ms). @default 900 */\n readonly duration = input(900, {\n transform: (v: unknown): number => Math.max(100, coerceNumberProperty(v, 900)),\n });\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Group thousands. @default true */\n readonly grouping = input<boolean>(true);\n\n /** Pad integer part to at least this many digits. @default 0 (no padding) */\n readonly minIntegerDigits = input(0, {\n transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)),\n });\n\n private readonly current = signal<number>(0);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n private rafId: number | null = null;\n\n /** Tween-mode formatted output. */\n protected readonly tweenText = computed(() => this.format(this.current()));\n\n /**\n * Odometer-mode text for assistive tech and prerendered output. The strip\n * renders every digit 0-9 per column and picks one with a transform, so its\n * markup carries no usable text — screen readers would announce all ten, and\n * static HTML would ship the same noise. This node holds the real value.\n */\n protected readonly odoText = computed(() => `${this.prefix()}${this.format(this.value())}${this.suffix()}`);\n\n /** Odometer cells — one per character in the formatted target string. */\n protected readonly cells = computed<readonly Cell[]>(() => {\n // Build the string with target sign + max length so we can interpolate\n // each digit position smoothly.\n const target = this.value();\n const live = this.current();\n const formattedTarget = this.format(target);\n const formattedLive = this.format(live);\n\n // Right-align so trailing digits line up.\n const maxLen = Math.max(formattedTarget.length, formattedLive.length);\n const padTarget = formattedTarget.padStart(maxLen, ' ');\n const padLive = formattedLive.padStart(maxLen, ' ');\n\n const cells: Cell[] = [];\n for (let i = 0; i < maxLen; i++) {\n const t = padTarget[i];\n const l = padLive[i];\n if (/[0-9]/.test(t) && /[0-9]/.test(l)) {\n // Interpolate the fractional digit so the strip rolls smoothly —\n // multi-digit rollover (9 → 0 carries 1) looks continuous.\n const fraction = this.digitFractionAt(live, target, i, maxLen);\n cells.push({ kind: 'digit', fraction });\n } else {\n cells.push({ kind: 'static', char: t === ' ' ? '' : t });\n }\n }\n return cells;\n });\n\n constructor() {\n inject(DestroyRef).onDestroy(() => this.cancel());\n\n effect(() => {\n const target = this.value();\n // Snapshot the current value WITHOUT tracking it — the RAF tick below\n // writes `current` every frame, and tracking it here would re-trigger\n // this effect each frame, cancelling + restarting the tween endlessly\n // (the wheels hang mid-roll and only snap once the restarts converge).\n const start = untracked(() => this.current());\n // Straight to the answer when there is nothing to animate for: no browser, or a\n // reader who asked for less motion. `wr-scroll` already falls back the same way, and a\n // component whose entire purpose is a count-up should be the first to honour it.\n if (!this.isBrowser || this.platform.prefersReducedMotion()) {\n this.current.set(target);\n return;\n }\n this.cancel();\n const startTs = performance.now();\n const dur = this.duration();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / dur);\n // Snap exactly to target on the final frame. Without this,\n // `start + (target - start) * 1` carries FP rounding (e.g.\n // 0.1 + (0.3 - 0.1) * 1 = 0.30000000000000004), so\n // `digitFractionAt`'s `live === target` rest-state check\n // fails — wheels visibly stop on a fractional position and\n // never settle to the clean integer glyph.\n const v = t >= 1 ? target : start + (target - start) * easeOutCubic(t);\n this.current.set(v);\n if (t < 1) this.rafId = requestAnimationFrame(tick);\n else this.rafId = null;\n };\n this.rafId = requestAnimationFrame(tick);\n });\n }\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n }\n\n private format(n: number): string {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n minimumIntegerDigits: this.minIntegerDigits() || 1,\n useGrouping: this.grouping(),\n }).format(n);\n }\n\n /**\n * Compute the smoothly-interpolated digit (0..10) at column `i` of the\n * formatted live string. Returns the integer digit + a fraction so the\n * strip CSS translate looks like a real rolling odometer.\n */\n private digitFractionAt(live: number, target: number, columnIndex: number, totalLen: number): number {\n // Determine the place value at this column. Account for grouping separators\n // and the decimal point by counting digits to the right of this column in\n // the formatted target.\n const formattedTarget = this.format(target);\n const padded = formattedTarget.padStart(totalLen, ' ');\n const tail = padded.slice(columnIndex + 1);\n const digitsRight = (tail.match(/[0-9]/g) ?? []).length;\n const placePower = digitsRight - this.decimals();\n const place = Math.pow(10, placePower);\n const absLive = Math.abs(live);\n const raw = absLive / place;\n // Modulo 10 gives the digit at this column with fractional rollover —\n // mid-animation this looks like a real wheel rolling between digits.\n const mod = raw - Math.floor(raw / 10) * 10;\n // At rest (live === target) every wheel must rest on an exact integer\n // — otherwise upper digits show as partial (e.g. tens reads \"5.6\"\n // for value 123456, visibly clipping between 5 and 6 in the\n // overflow:hidden window). The continuous-mechanical look is only\n // wanted DURING the tween, not after it settles.\n if (live === target) return Math.floor(mod + 1e-9);\n return mod;\n }\n}\n","@if (mode() === 'tween') {\n <span class=\"wr-counter__tween\">{{ prefix() }}{{ tweenText() }}{{ suffix() }}</span>\n} @else {\n <span class=\"wr-counter__sr-only\">{{ odoText() }}</span>\n <span class=\"wr-counter__odo\" aria-hidden=\"true\">\n @if (prefix()) {\n <span class=\"wr-counter__static\">{{ prefix() }}</span>\n }\n @for (cell of cells(); track $index) {\n @if (cell.kind === 'digit') {\n <span class=\"wr-counter__digit\">\n <span class=\"wr-counter__strip\" [style.transform]=\"`translateY(-${cell.fraction}em)`\">\n <span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span\n ><span>7</span><span>8</span><span>9</span>\n </span>\n </span>\n } @else {\n <span class=\"wr-counter__static\">{{ cell.char }}</span>\n }\n }\n @if (suffix()) {\n <span class=\"wr-counter__static\">{{ suffix() }}</span>\n }\n </span>\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 * The spring-physics path is an adaptation of the CountUp effect by\n * David Haz / reactbits.dev (https://www.reactbits.dev/text-animations/count-up).\n * Same critically-damped formula, implemented inline with rAF — no\n * external dependency.\n */\n\nimport { coerceNumberProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n LOCALE_ID,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n effect,\n inject,\n input,\n output,\n signal,\n} from '@angular/core';\n\nimport { numAttr } from 'ngwr/utils';\n\nimport { easeOutCubic } from './easing';\nimport type { WrCountUpDirection, WrCountUpEasing, WrCountUpTrigger } from './interfaces';\n\n/**\n * Animated number tick. Animates from `from` to the current `to`, formatting\n * via `Intl.NumberFormat`. Re-runs whenever `to` changes.\n *\n * @example Basic\n * ```html\n * <wr-count-up [to]=\"12345\" />\n * <wr-count-up [to]=\"9.99\" [decimals]=\"2\" prefix=\"$\" />\n * ```\n *\n * @example Reactbits-style — spring curve + viewport trigger\n * ```html\n * <wr-count-up [to]=\"100\" easing=\"spring\" trigger=\"visible\" [delay]=\"200\" />\n * ```\n *\n * @example Count down\n * ```html\n * <wr-count-up [from]=\"60\" [to]=\"0\" direction=\"down\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/counter\n */\n@Component({\n selector: 'wr-count-up',\n template: `{{ prefix() }}{{ formatted() }}{{ suffix() }}`,\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-count-up' },\n})\nexport class WrCountUp {\n /** Starting value. @default 0 */\n readonly from = input(0, { transform: numAttr(0) });\n\n /** Target value. */\n readonly to = input.required<number>();\n\n /**\n * Animation duration. Units depend on `easing`:\n *\n * - `ease-out` — milliseconds (default 1200, min 100)\n * - `spring` — seconds (tunes spring stiffness; default 2)\n */\n readonly duration = input(1200, { transform: numAttr(1200) });\n\n /** Optional delay (ms) before the animation starts. @default 0 */\n readonly delay = input(0, { transform: numAttr(0) });\n\n /** Animation curve. @default 'ease-out' */\n readonly easing = input<WrCountUpEasing>('ease-out');\n\n /**\n * When to start the animation.\n *\n * - `'mount'` (default) — start as soon as the component is rendered.\n * - `'visible'` — wait for the host to enter the viewport\n * (IntersectionObserver). Useful for long pages or hero numbers\n * below the fold.\n */\n readonly trigger = input<WrCountUpTrigger>('mount');\n\n /** Counting direction. `'down'` swaps `from` ↔ `to`. @default 'up' */\n readonly direction = input<WrCountUpDirection>('up');\n\n /** Fixed number of decimals. @default 0 */\n readonly decimals = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Optional prefix (e.g. `'$'`). */\n readonly prefix = input<string>('');\n\n /** Optional suffix (e.g. `'%'`). */\n readonly suffix = input<string>('');\n\n /** Disable grouping separators (`1,234` → `1234`). @default true (grouping on) */\n readonly grouping = input<boolean>(true);\n\n /** Emits when the animation begins. */\n readonly started = output<void>();\n\n /** Emits when the animation settles. */\n readonly completed = output<void>();\n\n private readonly value = signal<number>(0);\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly locale = inject(LOCALE_ID);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly destroyRef = inject(DestroyRef);\n\n private rafId: number | null = null;\n private delayTimer: ReturnType<typeof setTimeout> | undefined;\n private observer: IntersectionObserver | null = null;\n private hasFiredForVisible = false;\n\n protected readonly formatted = computed(() => {\n return new Intl.NumberFormat(this.locale, {\n minimumFractionDigits: this.decimals(),\n maximumFractionDigits: this.decimals(),\n useGrouping: this.grouping(),\n }).format(this.value());\n });\n\n constructor() {\n if (!this.isBrowser) {\n // SSR: settle on the value the animation ENDS on. Seeding the start\n // instead would bake the placeholder (usually 0) into prerendered HTML,\n // so readers and crawlers would get 0 rather than the real figure. The\n // browser rewinds to the start and animates once it boots.\n effect(() => this.value.set(this.direction() === 'down' ? this.from() : this.to()));\n return;\n }\n\n // Seed the resting value so first paint shows the start, not 0.\n effect(() => {\n const initial = this.direction() === 'down' ? this.to() : this.from();\n this.value.set(initial);\n });\n\n // Run the animation whenever the `to` target changes (or on first mount).\n // For `trigger=\"visible\"` the first run waits for the IntersectionObserver\n // to fire; subsequent `to` changes re-run immediately.\n effect(() => {\n // Establish dependencies so the effect re-runs on `to` changes.\n this.to();\n this.from();\n this.direction();\n this.duration();\n this.easing();\n this.delay();\n\n if (this.trigger() === 'visible' && !this.hasFiredForVisible) return;\n this.scheduleRun();\n });\n\n afterNextRender(() => {\n if (this.trigger() === 'visible') this.setupViewportTrigger();\n });\n\n this.destroyRef.onDestroy(() => {\n this.cancel();\n // `cancel()` only stops timers and the rAF loop. The IntersectionObserver\n // disconnects itself from inside its callback, which never fires if the\n // host is destroyed before it ever scrolls into view — so it would keep\n // observing a detached element for the life of the page.\n this.observer?.disconnect();\n this.observer = null;\n });\n }\n\n // Scheduling\n\n private setupViewportTrigger(): void {\n this.observer = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting && !this.hasFiredForVisible) {\n obs.disconnect();\n this.hasFiredForVisible = true;\n this.scheduleRun();\n break;\n }\n }\n },\n { threshold: 0, rootMargin: '0px' }\n );\n this.observer.observe(this.host.nativeElement);\n }\n\n private scheduleRun(): void {\n this.cancel();\n const d = this.delay();\n if (d > 0) {\n this.delayTimer = setTimeout(() => this.run(), d);\n } else {\n this.run();\n }\n }\n\n private run(): void {\n const start = this.direction() === 'down' ? this.to() : this.from();\n const end = this.direction() === 'down' ? this.from() : this.to();\n this.started.emit();\n if (this.easing() === 'spring') this.tweenSpring(start, end);\n else this.tweenEaseOut(start, end);\n }\n\n // Tweens\n\n private tweenEaseOut(start: number, target: number): void {\n const duration = Math.max(100, this.duration());\n const startTs = performance.now();\n const tick = (now: number): void => {\n const t = Math.min(1, (now - startTs) / duration);\n const v = start + (target - start) * easeOutCubic(t);\n this.value.set(v);\n if (t < 1) {\n this.rafId = requestAnimationFrame(tick);\n } else {\n this.completed.emit();\n }\n };\n this.rafId = requestAnimationFrame(tick);\n }\n\n /**\n * Critically-damped spring tween. Same formula as `motion/react`'s\n * `useSpring` with mass = 1:\n *\n * damping = 20 + 40 / duration\n * stiffness = 100 / duration\n *\n * We integrate `(spring force − damping force)` each frame until both\n * displacement and velocity fall below epsilon.\n */\n private tweenSpring(start: number, target: number): void {\n const duration = Math.max(0.05, this.duration());\n const damping = 20 + 40 / duration;\n const stiffness = 100 / duration;\n let current = start;\n let velocity = 0;\n let lastTs = 0;\n const epsilon = 0.001 * Math.max(1, Math.abs(target - start));\n\n const step = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const displacement = current - target;\n const accel = -stiffness * displacement - damping * velocity;\n velocity += accel * dt;\n current += velocity * dt;\n this.value.set(current);\n\n if (Math.abs(current - target) < epsilon && Math.abs(velocity) < epsilon * 10) {\n this.value.set(target);\n this.completed.emit();\n return;\n }\n this.rafId = requestAnimationFrame(step);\n };\n this.rafId = requestAnimationFrame(step);\n }\n\n // Cleanup\n\n private cancel(): void {\n if (this.rafId !== null) cancelAnimationFrame(this.rafId);\n this.rafId = null;\n if (this.delayTimer !== undefined) {\n clearTimeout(this.delayTimer);\n this.delayTimer = undefined;\n }\n }\n}\n\nexport type { WrCountUpEasing, WrCountUpTrigger, WrCountUpDirection } from './interfaces';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -40,8 +40,26 @@ const TOKEN_MAP = {
|
|
|
40
40
|
a: 'a',
|
|
41
41
|
};
|
|
42
42
|
const TOKEN_RE = /yyyy|yy|MMMM|MMM|MM|M|dd|d|HH|H|hh|h|mm|ss|a/g;
|
|
43
|
+
/**
|
|
44
|
+
* A quoted literal, in Luxon's own syntax: text between single quotes, where
|
|
45
|
+
* `''` is an escaped quote. Split on this and the odd-numbered pieces are the
|
|
46
|
+
* literals — which must reach Luxon untouched.
|
|
47
|
+
*/
|
|
48
|
+
const QUOTED_RE = /('(?:[^']|'')*')/;
|
|
49
|
+
/**
|
|
50
|
+
* Rewrite the library's tokens into Luxon's, LEAVING QUOTED TEXT ALONE.
|
|
51
|
+
*
|
|
52
|
+
* The tokens are mostly shared, but a few are not — `MMMM` is Luxon's standalone
|
|
53
|
+
* `LLLL`, for one — so the pattern is translated on the way in. Doing that over
|
|
54
|
+
* the whole string also rewrote the caller's own literals: `"MMMM 'MMMM'"`, a
|
|
55
|
+
* month name followed by the word, printed "August LLLL". Splitting on quotes
|
|
56
|
+
* first keeps the substitution where it belongs.
|
|
57
|
+
*/
|
|
43
58
|
function translatePattern(pattern) {
|
|
44
|
-
return pattern
|
|
59
|
+
return pattern
|
|
60
|
+
.split(QUOTED_RE)
|
|
61
|
+
.map((part, index) => (index % 2 === 1 ? part : part.replace(TOKEN_RE, t => TOKEN_MAP[t] ?? t)))
|
|
62
|
+
.join('');
|
|
45
63
|
}
|
|
46
64
|
/**
|
|
47
65
|
* {@link WrDateAdapter} backed by Luxon `DateTime`. Use this when you need
|
|
@@ -113,14 +131,44 @@ class WrLuxonAdapter extends WrDateAdapter {
|
|
|
113
131
|
return date.set({ hour: hours, minute: minutes, second: seconds, millisecond: 0 });
|
|
114
132
|
}
|
|
115
133
|
// Comparison
|
|
134
|
+
/**
|
|
135
|
+
* The comparison trio, all three answering the same question: what CALENDAR DAY
|
|
136
|
+
* does each value display?
|
|
137
|
+
*
|
|
138
|
+
* Field comparison rather than Luxon's own helpers, and deliberately. This
|
|
139
|
+
* adapter exists for zone-aware apps, so its values do not all share a zone —
|
|
140
|
+
* the grid is built with `createDate` in the app's zone while the selected value
|
|
141
|
+
* may arrive as `DateTime.utc()`. Two things went wrong when the zone was left
|
|
142
|
+
* in the answer:
|
|
143
|
+
*
|
|
144
|
+
* `compareDate` subtracted `startOf('day')` millis, and `startOf` respects each
|
|
145
|
+
* value's OWN zone, so two values both reading "1 August" came out three hours
|
|
146
|
+
* apart. Non-zero means "different day" to every caller — including
|
|
147
|
+
* `isWithinRange`, which the base class documents as inclusive and which
|
|
148
|
+
* therefore dropped its own endpoint.
|
|
149
|
+
*
|
|
150
|
+
* `hasSame` is the other tempting one-liner, and it asks a third question: it
|
|
151
|
+
* re-expresses one side in the other's zone and tests that instant against the
|
|
152
|
+
* day's bounds. That mostly agrees with a field comparison — but only mostly,
|
|
153
|
+
* and only in this version of luxon, whose `hasSame` keeps the local time
|
|
154
|
+
* while an earlier one kept the instant. Where a date's midnight is ambiguous
|
|
155
|
+
* or missing (Cuba rewinds 01:00 to 00:00 on 2 November 2025) the bounds stop
|
|
156
|
+
* lining up and it answers false for two values a user reads as the same date.
|
|
157
|
+
* The native adapter compares fields; agreeing with it is what keeps a
|
|
158
|
+
* calendar built on either adapter rendering the same thing.
|
|
159
|
+
*/
|
|
116
160
|
isSameDay(a, b) {
|
|
117
|
-
return a.
|
|
161
|
+
return a.year === b.year && a.month === b.month && a.day === b.day;
|
|
118
162
|
}
|
|
119
163
|
isSameMonth(a, b) {
|
|
120
|
-
return a.
|
|
164
|
+
return a.year === b.year && a.month === b.month;
|
|
121
165
|
}
|
|
122
166
|
compareDate(a, b) {
|
|
123
|
-
|
|
167
|
+
if (a.year !== b.year)
|
|
168
|
+
return a.year - b.year;
|
|
169
|
+
if (a.month !== b.month)
|
|
170
|
+
return a.month - b.month;
|
|
171
|
+
return a.day - b.day;
|
|
124
172
|
}
|
|
125
173
|
// Formatting / parsing
|
|
126
174
|
format(date, formatKeyOrString) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-date-adapter-luxon.mjs","sources":["../../../projects/lib/date-adapter-luxon/wr-luxon-adapter.ts","../../../projects/lib/date-adapter-luxon/provide-wr-luxon-adapter.ts","../../../projects/lib/date-adapter-luxon/ngwr-date-adapter-luxon.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 { Service, inject } from '@angular/core';\n\nimport { DateTime, Info } from 'luxon';\nimport { WrDateAdapter, WR_DATE_LOCALE, type WrDateFormat, isNamedFormat } from 'ngwr/date-adapter';\n\nconst NAMED_PATTERNS: Readonly<Record<WrDateFormat, string>> = {\n shortDate: 'D',\n mediumDate: 'DD',\n longDate: 'DDD',\n time: 't',\n shortDateTime: 'f',\n mediumDateTime: 'ff',\n};\n\n/**\n * Token translation table — our token grammar (matches the native adapter)\n * mapped to luxon's. Notably `MMMM`/`MMM` (month names) become luxon's\n * standalone-month tokens `LLLL`/`LLL`.\n */\nconst TOKEN_MAP: Readonly<Record<string, string>> = {\n yyyy: 'yyyy',\n yy: 'yy',\n MMMM: 'LLLL',\n MMM: 'LLL',\n MM: 'MM',\n M: 'M',\n dd: 'dd',\n d: 'd',\n HH: 'HH',\n H: 'H',\n hh: 'hh',\n h: 'h',\n mm: 'mm',\n ss: 'ss',\n a: 'a',\n};\n\nconst TOKEN_RE = /yyyy|yy|MMMM|MMM|MM|M|dd|d|HH|H|hh|h|mm|ss|a/g;\n\nfunction translatePattern(pattern: string): string {\n return pattern.replace(TOKEN_RE, t => TOKEN_MAP[t] ?? t);\n}\n\n/**\n * {@link WrDateAdapter} backed by Luxon `DateTime`. Use this when you need\n * proper timezone-aware math or IANA zone handling (the native + date-fns\n * adapters both work on plain `Date` and inherit JS quirks).\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrLuxonAdapter()],\n * });\n * ```\n *\n * Peer dep: `luxon@^3`.\n */\n@Service()\nexport class WrLuxonAdapter extends WrDateAdapter<DateTime> {\n private readonly locale = inject(WR_DATE_LOCALE);\n\n // Construction & identity\n\n today(): DateTime {\n return DateTime.now().setLocale(this.locale);\n }\n\n clone(date: DateTime): DateTime {\n return DateTime.fromMillis(date.toMillis(), { zone: date.zone, locale: this.locale });\n }\n\n createDate(year: number, month: number, day: number): DateTime {\n // `month` is 0-based on our API; luxon's months are 1-based.\n return DateTime.fromObject({ year, month: month + 1, day }, { locale: this.locale });\n }\n\n isValid(date: DateTime): boolean {\n return date.isValid;\n }\n\n // Accessors\n\n getYear(date: DateTime): number {\n return date.year;\n }\n getMonth(date: DateTime): number {\n return date.month - 1;\n }\n getDate(date: DateTime): number {\n return date.day;\n }\n getDayOfWeek(date: DateTime): number {\n // Luxon weekday: 1 (Mon) – 7 (Sun). Our API: 0 (Sun) – 6 (Sat).\n return date.weekday % 7;\n }\n getDaysInMonth(date: DateTime): number {\n return date.daysInMonth ?? 30;\n }\n getHours(date: DateTime): number {\n return date.hour;\n }\n getMinutes(date: DateTime): number {\n return date.minute;\n }\n getSeconds(date: DateTime): number {\n return date.second;\n }\n\n // Immutable math\n\n addYears(date: DateTime, amount: number): DateTime {\n return date.plus({ years: amount });\n }\n addMonths(date: DateTime, amount: number): DateTime {\n return date.plus({ months: amount });\n }\n addDays(date: DateTime, amount: number): DateTime {\n return date.plus({ days: amount });\n }\n setTime(date: DateTime, hours: number, minutes: number, seconds: number): DateTime {\n return date.set({ hour: hours, minute: minutes, second: seconds, millisecond: 0 });\n }\n\n // Comparison\n\n isSameDay(a: DateTime, b: DateTime): boolean {\n return a.hasSame(b, 'day');\n }\n isSameMonth(a: DateTime, b: DateTime): boolean {\n return a.hasSame(b, 'month');\n }\n compareDate(a: DateTime, b: DateTime): number {\n return a.startOf('day').toMillis() - b.startOf('day').toMillis();\n }\n\n // Formatting / parsing\n\n format(date: DateTime, formatKeyOrString: WrDateFormat | (string & {})): string {\n if (isNamedFormat(formatKeyOrString)) {\n return date.setLocale(this.locale).toFormat(NAMED_PATTERNS[formatKeyOrString]);\n }\n return date.setLocale(this.locale).toFormat(translatePattern(formatKeyOrString));\n }\n\n parse(value: string, formatKeyOrString: WrDateFormat | (string & {})): DateTime | null {\n const raw = value?.trim();\n if (!raw) return null;\n const pattern = isNamedFormat(formatKeyOrString)\n ? NAMED_PATTERNS[formatKeyOrString]\n : translatePattern(formatKeyOrString);\n const parsed = DateTime.fromFormat(raw, pattern, { locale: this.locale });\n return parsed.isValid ? parsed : null;\n }\n\n // Locale info\n\n getFirstDayOfWeek(): number {\n try {\n const locale = new Intl.Locale(this.locale) as unknown as { getWeekInfo?: () => { firstDay: number } };\n const info = locale.getWeekInfo?.();\n if (info && typeof info.firstDay === 'number') return info.firstDay % 7;\n } catch {\n // Intl.Locale unsupported — fall through.\n }\n return this.locale.toLowerCase().startsWith('en-us') ? 0 : 1;\n }\n\n getDayOfWeekNames(style: 'narrow' | 'short' | 'long'): readonly string[] {\n // Luxon returns Mon-first; reorder according to our locale's first day.\n const names = Info.weekdays(style, { locale: this.locale });\n const first = this.getFirstDayOfWeek();\n // Convert Mon-first (index 0 = Mon) to our Sun-first then rotate.\n // Easier: pad to Sun-first using known offset (luxon Mon=0, Sun=6).\n const sunFirst = [names[6], ...names.slice(0, 6)];\n return [...sunFirst.slice(first), ...sunFirst.slice(0, first)];\n }\n\n getMonthNames(style: 'narrow' | 'short' | 'long'): readonly string[] {\n return Info.months(style, { locale: this.locale });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { EnvironmentProviders } from '@angular/core';\n\nimport { provideWrDateAdapter } from 'ngwr/date-adapter';\n\nimport { WrLuxonAdapter } from './wr-luxon-adapter';\n\n/**\n * Register the {@link WrLuxonAdapter} so date-pickers / calendars in this\n * app use Luxon `DateTime` for all math and formatting. Pass `locale` to\n * override the BCP 47 tag.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrLuxonAdapter()],\n * });\n * ```\n */\nexport function provideWrLuxonAdapter(options: { readonly locale?: string } = {}): EnvironmentProviders {\n return provideWrDateAdapter({ adapter: WrLuxonAdapter, locale: options.locale });\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-date-adapter-luxon.mjs","sources":["../../../projects/lib/date-adapter-luxon/wr-luxon-adapter.ts","../../../projects/lib/date-adapter-luxon/provide-wr-luxon-adapter.ts","../../../projects/lib/date-adapter-luxon/ngwr-date-adapter-luxon.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 { Service, inject } from '@angular/core';\n\nimport { DateTime, Info } from 'luxon';\nimport { WrDateAdapter, WR_DATE_LOCALE, type WrDateFormat, isNamedFormat } from 'ngwr/date-adapter';\n\nconst NAMED_PATTERNS: Readonly<Record<WrDateFormat, string>> = {\n shortDate: 'D',\n mediumDate: 'DD',\n longDate: 'DDD',\n time: 't',\n shortDateTime: 'f',\n mediumDateTime: 'ff',\n};\n\n/**\n * Token translation table — our token grammar (matches the native adapter)\n * mapped to luxon's. Notably `MMMM`/`MMM` (month names) become luxon's\n * standalone-month tokens `LLLL`/`LLL`.\n */\nconst TOKEN_MAP: Readonly<Record<string, string>> = {\n yyyy: 'yyyy',\n yy: 'yy',\n MMMM: 'LLLL',\n MMM: 'LLL',\n MM: 'MM',\n M: 'M',\n dd: 'dd',\n d: 'd',\n HH: 'HH',\n H: 'H',\n hh: 'hh',\n h: 'h',\n mm: 'mm',\n ss: 'ss',\n a: 'a',\n};\n\nconst TOKEN_RE = /yyyy|yy|MMMM|MMM|MM|M|dd|d|HH|H|hh|h|mm|ss|a/g;\n\n/**\n * A quoted literal, in Luxon's own syntax: text between single quotes, where\n * `''` is an escaped quote. Split on this and the odd-numbered pieces are the\n * literals — which must reach Luxon untouched.\n */\nconst QUOTED_RE = /('(?:[^']|'')*')/;\n\n/**\n * Rewrite the library's tokens into Luxon's, LEAVING QUOTED TEXT ALONE.\n *\n * The tokens are mostly shared, but a few are not — `MMMM` is Luxon's standalone\n * `LLLL`, for one — so the pattern is translated on the way in. Doing that over\n * the whole string also rewrote the caller's own literals: `\"MMMM 'MMMM'\"`, a\n * month name followed by the word, printed \"August LLLL\". Splitting on quotes\n * first keeps the substitution where it belongs.\n */\nfunction translatePattern(pattern: string): string {\n return pattern\n .split(QUOTED_RE)\n .map((part, index) => (index % 2 === 1 ? part : part.replace(TOKEN_RE, t => TOKEN_MAP[t] ?? t)))\n .join('');\n}\n\n/**\n * {@link WrDateAdapter} backed by Luxon `DateTime`. Use this when you need\n * proper timezone-aware math or IANA zone handling (the native + date-fns\n * adapters both work on plain `Date` and inherit JS quirks).\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrLuxonAdapter()],\n * });\n * ```\n *\n * Peer dep: `luxon@^3`.\n */\n@Service()\nexport class WrLuxonAdapter extends WrDateAdapter<DateTime> {\n private readonly locale = inject(WR_DATE_LOCALE);\n\n // Construction & identity\n\n today(): DateTime {\n return DateTime.now().setLocale(this.locale);\n }\n\n clone(date: DateTime): DateTime {\n return DateTime.fromMillis(date.toMillis(), { zone: date.zone, locale: this.locale });\n }\n\n createDate(year: number, month: number, day: number): DateTime {\n // `month` is 0-based on our API; luxon's months are 1-based.\n return DateTime.fromObject({ year, month: month + 1, day }, { locale: this.locale });\n }\n\n isValid(date: DateTime): boolean {\n return date.isValid;\n }\n\n // Accessors\n\n getYear(date: DateTime): number {\n return date.year;\n }\n getMonth(date: DateTime): number {\n return date.month - 1;\n }\n getDate(date: DateTime): number {\n return date.day;\n }\n getDayOfWeek(date: DateTime): number {\n // Luxon weekday: 1 (Mon) – 7 (Sun). Our API: 0 (Sun) – 6 (Sat).\n return date.weekday % 7;\n }\n getDaysInMonth(date: DateTime): number {\n return date.daysInMonth ?? 30;\n }\n getHours(date: DateTime): number {\n return date.hour;\n }\n getMinutes(date: DateTime): number {\n return date.minute;\n }\n getSeconds(date: DateTime): number {\n return date.second;\n }\n\n // Immutable math\n\n addYears(date: DateTime, amount: number): DateTime {\n return date.plus({ years: amount });\n }\n addMonths(date: DateTime, amount: number): DateTime {\n return date.plus({ months: amount });\n }\n addDays(date: DateTime, amount: number): DateTime {\n return date.plus({ days: amount });\n }\n setTime(date: DateTime, hours: number, minutes: number, seconds: number): DateTime {\n return date.set({ hour: hours, minute: minutes, second: seconds, millisecond: 0 });\n }\n\n // Comparison\n\n /**\n * The comparison trio, all three answering the same question: what CALENDAR DAY\n * does each value display?\n *\n * Field comparison rather than Luxon's own helpers, and deliberately. This\n * adapter exists for zone-aware apps, so its values do not all share a zone —\n * the grid is built with `createDate` in the app's zone while the selected value\n * may arrive as `DateTime.utc()`. Two things went wrong when the zone was left\n * in the answer:\n *\n * `compareDate` subtracted `startOf('day')` millis, and `startOf` respects each\n * value's OWN zone, so two values both reading \"1 August\" came out three hours\n * apart. Non-zero means \"different day\" to every caller — including\n * `isWithinRange`, which the base class documents as inclusive and which\n * therefore dropped its own endpoint.\n *\n * `hasSame` is the other tempting one-liner, and it asks a third question: it\n * re-expresses one side in the other's zone and tests that instant against the\n * day's bounds. That mostly agrees with a field comparison — but only mostly,\n * and only in this version of luxon, whose `hasSame` keeps the local time\n * while an earlier one kept the instant. Where a date's midnight is ambiguous\n * or missing (Cuba rewinds 01:00 to 00:00 on 2 November 2025) the bounds stop\n * lining up and it answers false for two values a user reads as the same date.\n * The native adapter compares fields; agreeing with it is what keeps a\n * calendar built on either adapter rendering the same thing.\n */\n isSameDay(a: DateTime, b: DateTime): boolean {\n return a.year === b.year && a.month === b.month && a.day === b.day;\n }\n isSameMonth(a: DateTime, b: DateTime): boolean {\n return a.year === b.year && a.month === b.month;\n }\n compareDate(a: DateTime, b: DateTime): number {\n if (a.year !== b.year) return a.year - b.year;\n if (a.month !== b.month) return a.month - b.month;\n return a.day - b.day;\n }\n\n // Formatting / parsing\n\n format(date: DateTime, formatKeyOrString: WrDateFormat | (string & {})): string {\n if (isNamedFormat(formatKeyOrString)) {\n return date.setLocale(this.locale).toFormat(NAMED_PATTERNS[formatKeyOrString]);\n }\n return date.setLocale(this.locale).toFormat(translatePattern(formatKeyOrString));\n }\n\n parse(value: string, formatKeyOrString: WrDateFormat | (string & {})): DateTime | null {\n const raw = value?.trim();\n if (!raw) return null;\n const pattern = isNamedFormat(formatKeyOrString)\n ? NAMED_PATTERNS[formatKeyOrString]\n : translatePattern(formatKeyOrString);\n const parsed = DateTime.fromFormat(raw, pattern, { locale: this.locale });\n return parsed.isValid ? parsed : null;\n }\n\n // Locale info\n\n getFirstDayOfWeek(): number {\n try {\n const locale = new Intl.Locale(this.locale) as unknown as { getWeekInfo?: () => { firstDay: number } };\n const info = locale.getWeekInfo?.();\n if (info && typeof info.firstDay === 'number') return info.firstDay % 7;\n } catch {\n // Intl.Locale unsupported — fall through.\n }\n return this.locale.toLowerCase().startsWith('en-us') ? 0 : 1;\n }\n\n getDayOfWeekNames(style: 'narrow' | 'short' | 'long'): readonly string[] {\n // Luxon returns Mon-first; reorder according to our locale's first day.\n const names = Info.weekdays(style, { locale: this.locale });\n const first = this.getFirstDayOfWeek();\n // Convert Mon-first (index 0 = Mon) to our Sun-first then rotate.\n // Easier: pad to Sun-first using known offset (luxon Mon=0, Sun=6).\n const sunFirst = [names[6], ...names.slice(0, 6)];\n return [...sunFirst.slice(first), ...sunFirst.slice(0, first)];\n }\n\n getMonthNames(style: 'narrow' | 'short' | 'long'): readonly string[] {\n return Info.months(style, { locale: this.locale });\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport type { EnvironmentProviders } from '@angular/core';\n\nimport { provideWrDateAdapter } from 'ngwr/date-adapter';\n\nimport { WrLuxonAdapter } from './wr-luxon-adapter';\n\n/**\n * Register the {@link WrLuxonAdapter} so date-pickers / calendars in this\n * app use Luxon `DateTime` for all math and formatting. Pass `locale` to\n * override the BCP 47 tag.\n *\n * @example\n * ```ts\n * bootstrapApplication(AppComponent, {\n * providers: [provideWrLuxonAdapter()],\n * });\n * ```\n */\nexport function provideWrLuxonAdapter(options: { readonly locale?: string } = {}): EnvironmentProviders {\n return provideWrDateAdapter({ adapter: WrLuxonAdapter, locale: options.locale });\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -85,8 +85,14 @@ const INTL_OPTIONS = {
|
|
|
85
85
|
mediumDateTime: { year: 'numeric', month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' },
|
|
86
86
|
};
|
|
87
87
|
/** Recognised tokens, longest first so `MMMM` matches before `MMM`. */
|
|
88
|
-
|
|
89
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Every token, with single-quoted runs taken FIRST so they win.
|
|
90
|
+
*
|
|
91
|
+
* Without that, the one-letter tokens match letters inside literal text: `'yyyy [year]'`
|
|
92
|
+
* came out as `2025 [yeamr]`, because the `a` in "year" was read as the meridiem token.
|
|
93
|
+
* Quote literals the way `DatePipe` and LDML do — `'at'` — and `''` for a real quote.
|
|
94
|
+
*/
|
|
95
|
+
const PART_RE = /'([^']*)'|yyyy|yy|MMMM|MMM|MM|M|dd|d|HH|H|hh|h|mm|ss|a/g;
|
|
90
96
|
function pad(n, width = 2) {
|
|
91
97
|
return String(Math.abs(n)).padStart(width, '0');
|
|
92
98
|
}
|
|
@@ -184,7 +190,14 @@ class WrNativeDateAdapter extends WrDateAdapter {
|
|
|
184
190
|
return d;
|
|
185
191
|
}
|
|
186
192
|
addDays(date, amount) {
|
|
187
|
-
|
|
193
|
+
// A calendar day, not 86 400 000 ms. Where daylight saving applies a day can be 23 or
|
|
194
|
+
// 25 hours long, so millisecond arithmetic drifts the wall clock and — across an
|
|
195
|
+
// autumn change — lands back on the same calendar date, which makes a month grid
|
|
196
|
+
// repeat a day and lose one. Not observable in a fixed-offset timezone, which is why
|
|
197
|
+
// the reason lives here rather than only in a test.
|
|
198
|
+
const d = this.clone(date);
|
|
199
|
+
d.setDate(d.getDate() + amount);
|
|
200
|
+
return d;
|
|
188
201
|
}
|
|
189
202
|
setTime(date, hours, minutes, seconds) {
|
|
190
203
|
const d = this.clone(date);
|
|
@@ -278,7 +291,11 @@ class WrNativeDateAdapter extends WrDateAdapter {
|
|
|
278
291
|
const seconds = date.getSeconds();
|
|
279
292
|
const monthNames = this.getMonthNames('long');
|
|
280
293
|
const monthShort = this.getMonthNames('short');
|
|
281
|
-
return pattern.replace(
|
|
294
|
+
return pattern.replace(PART_RE, (part, quoted) => {
|
|
295
|
+
// A quoted run is emitted as-is; `''` is how a single quote is written.
|
|
296
|
+
if (quoted !== undefined)
|
|
297
|
+
return quoted === '' ? "'" : quoted;
|
|
298
|
+
const token = part;
|
|
282
299
|
switch (token) {
|
|
283
300
|
case 'yyyy':
|
|
284
301
|
return pad(year, 4);
|
|
@@ -316,10 +333,17 @@ class WrNativeDateAdapter extends WrDateAdapter {
|
|
|
316
333
|
}
|
|
317
334
|
parseWithTokens(value, pattern) {
|
|
318
335
|
const tokens = [];
|
|
336
|
+
const monthLong = this.getMonthNames('long');
|
|
337
|
+
const monthShort = this.getMonthNames('short');
|
|
319
338
|
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
320
|
-
const regex = escaped.replace(
|
|
321
|
-
|
|
322
|
-
|
|
339
|
+
const regex = escaped.replace(PART_RE, (part, quoted) => {
|
|
340
|
+
if (quoted !== undefined) {
|
|
341
|
+
// Literal text matches itself and captures nothing, so the token indices stay
|
|
342
|
+
// aligned with the groups below.
|
|
343
|
+
return quoted === '' ? "'" : quoted;
|
|
344
|
+
}
|
|
345
|
+
tokens.push(part);
|
|
346
|
+
return tokenToRegex(part);
|
|
323
347
|
});
|
|
324
348
|
const match = new RegExp(`^${regex}$`).exec(value);
|
|
325
349
|
if (!match)
|
|
@@ -348,6 +372,15 @@ class WrNativeDateAdapter extends WrDateAdapter {
|
|
|
348
372
|
case 'M':
|
|
349
373
|
month = n - 1;
|
|
350
374
|
break;
|
|
375
|
+
case 'MMM':
|
|
376
|
+
case 'MMMM': {
|
|
377
|
+
const names = token === 'MMM' ? monthShort : monthLong;
|
|
378
|
+
const found = names.findIndex(name => name.toLowerCase() === raw.toLowerCase());
|
|
379
|
+
if (found < 0)
|
|
380
|
+
return null;
|
|
381
|
+
month = found;
|
|
382
|
+
break;
|
|
383
|
+
}
|
|
351
384
|
case 'dd':
|
|
352
385
|
case 'd':
|
|
353
386
|
day = n;
|
|
@@ -375,8 +408,21 @@ class WrNativeDateAdapter extends WrDateAdapter {
|
|
|
375
408
|
if (hadHour12) {
|
|
376
409
|
hours = (hour12 % 12) + (isPm ? 12 : 0);
|
|
377
410
|
}
|
|
411
|
+
// `new Date(2025, 12, 45)` does not fail — it rolls forward into the next year — and
|
|
412
|
+
// `isValid` is happy with the result, so a text field turned nonsense into a confident
|
|
413
|
+
// wrong answer. The clock parts are range-checked directly; the month and the day are
|
|
414
|
+
// checked by comparing what came back, which catches every rollover including a month
|
|
415
|
+
// of 12 or -1.
|
|
416
|
+
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59 || seconds < 0 || seconds > 59)
|
|
417
|
+
return null;
|
|
378
418
|
const out = new Date(year, month, day, hours, minutes, seconds);
|
|
379
|
-
|
|
419
|
+
if (!this.isValid(out))
|
|
420
|
+
return null;
|
|
421
|
+
// The day is range-checked by construction: anything the calendar rolled over comes
|
|
422
|
+
// back as a different month or a different day.
|
|
423
|
+
if (out.getMonth() !== month || out.getDate() !== day)
|
|
424
|
+
return null;
|
|
425
|
+
return out;
|
|
380
426
|
}
|
|
381
427
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.1", ngImport: i0, type: WrNativeDateAdapter, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
382
428
|
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.1.1", ngImport: i0, type: WrNativeDateAdapter });
|