ngwr 6.0.0 → 7.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/LICENSE +1 -3
- package/README.md +179 -32
- package/affix/styles/_index.scss +12 -0
- package/alert/styles/_index.scss +75 -32
- package/anchor/styles/_index.scss +59 -0
- package/aurora/aurora.scss +1 -0
- package/aurora/styles/_index.scss +30 -0
- package/avatar/styles/_index.scss +30 -14
- package/back-top/styles/_index.scss +42 -0
- package/badge/styles/_index.scss +80 -0
- package/badge/styles/_tag.scss +81 -0
- package/bar-chart/styles/_index.scss +56 -0
- package/blur-text/blur-text.scss +1 -0
- package/blur-text/styles/_index.scss +14 -0
- package/border-glow/border-glow.scss +4 -0
- package/border-glow/styles/_index.scss +228 -0
- package/breadcrumbs/breadcrumbs.scss +1 -0
- package/breadcrumbs/styles/_index.scss +76 -0
- package/button/styles/_index.scss +148 -125
- package/calendar/styles/_index.scss +252 -0
- package/calendar-heatmap/styles/_index.scss +69 -0
- package/card/card.scss +1 -0
- package/card/styles/_index.scss +96 -0
- package/carousel/styles/_index.scss +102 -0
- package/cascader/cascader.scss +1 -0
- package/cascader/styles/_index.scss +174 -0
- package/checkbox/styles/_index.scss +76 -60
- package/circular-text/circular-text.scss +1 -0
- package/circular-text/styles/_index.scss +45 -0
- package/click-spark/click-spark.scss +1 -0
- package/click-spark/styles/_index.scss +16 -0
- package/collapse/styles/_index.scss +92 -0
- package/color-picker/styles/_index.scss +247 -0
- package/command-palette/styles/_index.scss +188 -0
- package/compare/styles/_index.scss +100 -0
- package/context-menu/styles/_index.scss +112 -0
- package/counter/styles/_index.scss +44 -0
- package/date-picker/styles/_index.scss +204 -0
- package/decrypt-text/decrypt-text.scss +1 -0
- package/decrypt-text/styles/_index.scss +26 -0
- package/density/styles/_index.scss +37 -0
- package/descriptions/styles/_index.scss +104 -0
- package/dialog/styles/_index.scss +101 -27
- package/divider/styles/_index.scss +43 -24
- package/donut-chart/styles/_index.scss +76 -0
- package/drag-drop/sortable-list.scss +1 -0
- package/drag-drop/styles/_index.scss +99 -0
- package/drawer/styles/_index.scss +164 -0
- package/dropdown/styles/_index.scss +76 -56
- package/empty/styles/_index.scss +49 -0
- package/falling-text/falling-text.scss +1 -0
- package/falling-text/styles/_index.scss +30 -0
- package/fesm2022/ngwr-affix.mjs +102 -0
- package/fesm2022/ngwr-affix.mjs.map +1 -0
- package/fesm2022/ngwr-alert.mjs +70 -52
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +103 -0
- package/fesm2022/ngwr-anchor.mjs.map +1 -0
- package/fesm2022/ngwr-aurora.mjs +309 -0
- package/fesm2022/ngwr-aurora.mjs.map +1 -0
- package/fesm2022/ngwr-avatar.mjs +81 -71
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +81 -0
- package/fesm2022/ngwr-back-top.mjs.map +1 -0
- package/fesm2022/ngwr-badge.mjs +192 -0
- package/fesm2022/ngwr-badge.mjs.map +1 -0
- package/fesm2022/ngwr-bar-chart.mjs +69 -0
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -0
- package/fesm2022/ngwr-blur-text.mjs +181 -0
- package/fesm2022/ngwr-blur-text.mjs.map +1 -0
- package/fesm2022/ngwr-border-glow.mjs +278 -0
- package/fesm2022/ngwr-border-glow.mjs.map +1 -0
- package/fesm2022/ngwr-breadcrumbs.mjs +101 -0
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -0
- package/fesm2022/ngwr-button.mjs +179 -104
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +145 -0
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -0
- package/fesm2022/ngwr-calendar.mjs +402 -0
- package/fesm2022/ngwr-calendar.mjs.map +1 -0
- package/fesm2022/ngwr-card.mjs +100 -0
- package/fesm2022/ngwr-card.mjs.map +1 -0
- package/fesm2022/ngwr-carousel.mjs +128 -0
- package/fesm2022/ngwr-carousel.mjs.map +1 -0
- package/fesm2022/ngwr-cascader.mjs +280 -0
- package/fesm2022/ngwr-cascader.mjs.map +1 -0
- package/fesm2022/ngwr-checkbox.mjs +214 -54
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +168 -0
- package/fesm2022/ngwr-circular-text.mjs.map +1 -0
- package/fesm2022/ngwr-click-spark.mjs +163 -0
- package/fesm2022/ngwr-click-spark.mjs.map +1 -0
- package/fesm2022/ngwr-clipboard.mjs +130 -0
- package/fesm2022/ngwr-clipboard.mjs.map +1 -0
- package/fesm2022/ngwr-collapse.mjs +232 -0
- package/fesm2022/ngwr-collapse.mjs.map +1 -0
- package/fesm2022/ngwr-color-picker.mjs +646 -0
- package/fesm2022/ngwr-color-picker.mjs.map +1 -0
- package/fesm2022/ngwr-command-palette.mjs +259 -0
- package/fesm2022/ngwr-command-palette.mjs.map +1 -0
- package/fesm2022/ngwr-compare.mjs +137 -0
- package/fesm2022/ngwr-compare.mjs.map +1 -0
- package/fesm2022/ngwr-confetti.mjs +160 -0
- package/fesm2022/ngwr-confetti.mjs.map +1 -0
- package/fesm2022/ngwr-context-menu.mjs +653 -0
- package/fesm2022/ngwr-context-menu.mjs.map +1 -0
- package/fesm2022/ngwr-cookie.mjs +127 -0
- package/fesm2022/ngwr-cookie.mjs.map +1 -0
- package/fesm2022/ngwr-counter.mjs +415 -0
- package/fesm2022/ngwr-counter.mjs.map +1 -0
- package/fesm2022/ngwr-date-adapter-fns.mjs +180 -0
- package/fesm2022/ngwr-date-adapter-fns.mjs.map +1 -0
- package/fesm2022/ngwr-date-adapter-luxon.mjs +201 -0
- package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -0
- package/fesm2022/ngwr-date-adapter.mjs +419 -0
- package/fesm2022/ngwr-date-adapter.mjs.map +1 -0
- package/fesm2022/ngwr-date-picker.mjs +624 -0
- package/fesm2022/ngwr-date-picker.mjs.map +1 -0
- package/fesm2022/ngwr-decrypt-text.mjs +396 -0
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -0
- package/fesm2022/ngwr-density.mjs +157 -0
- package/fesm2022/ngwr-density.mjs.map +1 -0
- package/fesm2022/ngwr-descriptions.mjs +83 -0
- package/fesm2022/ngwr-descriptions.mjs.map +1 -0
- package/fesm2022/ngwr-dialog.mjs +249 -383
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-directives.mjs +315 -0
- package/fesm2022/ngwr-directives.mjs.map +1 -0
- package/fesm2022/ngwr-divider.mjs +74 -59
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +131 -0
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -0
- package/fesm2022/ngwr-drag-drop.mjs +117 -0
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -0
- package/fesm2022/ngwr-drawer.mjs +315 -0
- package/fesm2022/ngwr-drawer.mjs.map +1 -0
- package/fesm2022/ngwr-dropdown.mjs +276 -229
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +57 -0
- package/fesm2022/ngwr-empty.mjs.map +1 -0
- package/fesm2022/ngwr-falling-text.mjs +316 -0
- package/fesm2022/ngwr-falling-text.mjs.map +1 -0
- package/fesm2022/ngwr-file-upload.mjs +260 -0
- package/fesm2022/ngwr-file-upload.mjs.map +1 -0
- package/fesm2022/ngwr-form.mjs +133 -48
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +373 -0
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -0
- package/fesm2022/ngwr-gauge.mjs +83 -0
- package/fesm2022/ngwr-gauge.mjs.map +1 -0
- package/fesm2022/ngwr-glitch-text.mjs +67 -0
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -0
- package/fesm2022/ngwr-gradient-text.mjs +109 -0
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -0
- package/fesm2022/ngwr-hotkey.mjs +263 -0
- package/fesm2022/ngwr-hotkey.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-en.mjs +168 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -0
- package/fesm2022/ngwr-i18n-ru.mjs +156 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -0
- package/fesm2022/ngwr-i18n.mjs +478 -0
- package/fesm2022/ngwr-i18n.mjs.map +1 -0
- package/fesm2022/ngwr-icon-adapters-feather.mjs +74 -0
- package/fesm2022/ngwr-icon-adapters-feather.mjs.map +1 -0
- package/fesm2022/ngwr-icon-adapters-lucide.mjs +88 -0
- package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -0
- package/fesm2022/ngwr-icon.mjs +189 -650
- package/fesm2022/ngwr-icon.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +299 -0
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -0
- package/fesm2022/ngwr-input-number.mjs +239 -0
- package/fesm2022/ngwr-input-number.mjs.map +1 -0
- package/fesm2022/ngwr-input-otp.mjs +216 -0
- package/fesm2022/ngwr-input-otp.mjs.map +1 -0
- package/fesm2022/ngwr-input.mjs +183 -104
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-keyboard.mjs +47 -0
- package/fesm2022/ngwr-keyboard.mjs.map +1 -0
- package/fesm2022/ngwr-knob.mjs +227 -0
- package/fesm2022/ngwr-knob.mjs.map +1 -0
- package/fesm2022/ngwr-layout.mjs +197 -0
- package/fesm2022/ngwr-layout.mjs.map +1 -0
- package/fesm2022/ngwr-lightbox.mjs +131 -0
- package/fesm2022/ngwr-lightbox.mjs.map +1 -0
- package/fesm2022/ngwr-line-chart.mjs +176 -0
- package/fesm2022/ngwr-line-chart.mjs.map +1 -0
- package/fesm2022/ngwr-list.mjs +132 -0
- package/fesm2022/ngwr-list.mjs.map +1 -0
- package/fesm2022/ngwr-loading-bar.mjs +160 -0
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -0
- package/fesm2022/ngwr-marquee.mjs +224 -0
- package/fesm2022/ngwr-marquee.mjs.map +1 -0
- package/fesm2022/ngwr-media.mjs +132 -0
- package/fesm2022/ngwr-media.mjs.map +1 -0
- package/fesm2022/ngwr-mention.mjs +374 -0
- package/fesm2022/ngwr-mention.mjs.map +1 -0
- package/fesm2022/ngwr-meta.mjs +266 -0
- package/fesm2022/ngwr-meta.mjs.map +1 -0
- package/fesm2022/ngwr-meter-group.mjs +73 -0
- package/fesm2022/ngwr-meter-group.mjs.map +1 -0
- package/fesm2022/ngwr-overlay.mjs +145 -0
- package/fesm2022/ngwr-overlay.mjs.map +1 -0
- package/fesm2022/ngwr-page-header.mjs +53 -0
- package/fesm2022/ngwr-page-header.mjs.map +1 -0
- package/fesm2022/ngwr-pagination.mjs +152 -96
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +290 -11
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-platform.mjs +63 -0
- package/fesm2022/ngwr-platform.mjs.map +1 -0
- package/fesm2022/ngwr-popconfirm.mjs +188 -0
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -0
- package/fesm2022/ngwr-popover.mjs +361 -0
- package/fesm2022/ngwr-popover.mjs.map +1 -0
- package/fesm2022/ngwr-progress.mjs +47 -39
- package/fesm2022/ngwr-progress.mjs.map +1 -1
- package/fesm2022/ngwr-qr.mjs +168 -190
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +204 -0
- package/fesm2022/ngwr-radio.mjs.map +1 -0
- package/fesm2022/ngwr-rating.mjs +180 -0
- package/fesm2022/ngwr-rating.mjs.map +1 -0
- package/fesm2022/ngwr-result.mjs +119 -0
- package/fesm2022/ngwr-result.mjs.map +1 -0
- package/fesm2022/ngwr-rotating-text.mjs +256 -0
- package/fesm2022/ngwr-rotating-text.mjs.map +1 -0
- package/fesm2022/ngwr-scramble-text.mjs +165 -0
- package/fesm2022/ngwr-scramble-text.mjs.map +1 -0
- package/fesm2022/ngwr-scroll.mjs +107 -0
- package/fesm2022/ngwr-scroll.mjs.map +1 -0
- package/fesm2022/ngwr-segmented.mjs +96 -0
- package/fesm2022/ngwr-segmented.mjs.map +1 -0
- package/fesm2022/ngwr-select.mjs +842 -307
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +127 -0
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -0
- package/fesm2022/ngwr-sidebar.mjs +134 -0
- package/fesm2022/ngwr-sidebar.mjs.map +1 -0
- package/fesm2022/ngwr-skeleton.mjs +59 -34
- package/fesm2022/ngwr-skeleton.mjs.map +1 -1
- package/fesm2022/ngwr-slider.mjs +234 -0
- package/fesm2022/ngwr-slider.mjs.map +1 -0
- package/fesm2022/ngwr-sparkline.mjs +104 -0
- package/fesm2022/ngwr-sparkline.mjs.map +1 -0
- package/fesm2022/ngwr-speed-dial.mjs +79 -0
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -0
- package/fesm2022/ngwr-spinner.mjs +34 -28
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor.mjs +970 -0
- package/fesm2022/ngwr-splash-cursor.mjs.map +1 -0
- package/fesm2022/ngwr-split-text.mjs +200 -0
- package/fesm2022/ngwr-split-text.mjs.map +1 -0
- package/fesm2022/ngwr-splitter.mjs +125 -0
- package/fesm2022/ngwr-splitter.mjs.map +1 -0
- package/fesm2022/ngwr-spotlight-card.mjs +138 -0
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -0
- package/fesm2022/ngwr-squircle.mjs +320 -0
- package/fesm2022/ngwr-squircle.mjs.map +1 -0
- package/fesm2022/ngwr-star-border.mjs +72 -0
- package/fesm2022/ngwr-star-border.mjs.map +1 -0
- package/fesm2022/ngwr-statistic.mjs +220 -0
- package/fesm2022/ngwr-statistic.mjs.map +1 -0
- package/fesm2022/ngwr-stepper.mjs +186 -0
- package/fesm2022/ngwr-stepper.mjs.map +1 -0
- package/fesm2022/ngwr-storage.mjs +317 -0
- package/fesm2022/ngwr-storage.mjs.map +1 -0
- package/fesm2022/ngwr-switch.mjs +99 -0
- package/fesm2022/ngwr-switch.mjs.map +1 -0
- package/fesm2022/ngwr-table.mjs +218 -207
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +217 -0
- package/fesm2022/ngwr-tabs.mjs.map +1 -0
- package/fesm2022/ngwr-textarea.mjs +106 -120
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-theme.mjs +152 -0
- package/fesm2022/ngwr-theme.mjs.map +1 -0
- package/fesm2022/ngwr-tilt-card.mjs +137 -0
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -0
- package/fesm2022/ngwr-timeline.mjs +73 -0
- package/fesm2022/ngwr-timeline.mjs.map +1 -0
- package/fesm2022/ngwr-toast.mjs +446 -0
- package/fesm2022/ngwr-toast.mjs.map +1 -0
- package/fesm2022/ngwr-toolbar.mjs +46 -0
- package/fesm2022/ngwr-toolbar.mjs.map +1 -0
- package/fesm2022/ngwr-tree.mjs +483 -0
- package/fesm2022/ngwr-tree.mjs.map +1 -0
- package/fesm2022/ngwr-typewriter.mjs +229 -0
- package/fesm2022/ngwr-typewriter.mjs.map +1 -0
- package/fesm2022/ngwr-typography.mjs +79 -0
- package/fesm2022/ngwr-typography.mjs.map +1 -0
- package/fesm2022/ngwr-utils.mjs +535 -0
- package/fesm2022/ngwr-utils.mjs.map +1 -0
- package/fesm2022/ngwr-validators.mjs +214 -0
- package/fesm2022/ngwr-validators.mjs.map +1 -0
- package/fesm2022/ngwr-version.mjs +51 -0
- package/fesm2022/ngwr-version.mjs.map +1 -0
- package/fesm2022/ngwr-virtual-scroll.mjs +99 -0
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -0
- package/fesm2022/ngwr-waves.mjs +356 -0
- package/fesm2022/ngwr-waves.mjs.map +1 -0
- package/fesm2022/ngwr-window.mjs +1141 -0
- package/fesm2022/ngwr-window.mjs.map +1 -0
- package/fesm2022/ngwr.mjs +0 -3
- package/fesm2022/ngwr.mjs.map +1 -1
- package/file-upload/styles/_index.scss +152 -0
- package/form/styles/_index.scss +85 -42
- package/gauge/styles/_index.scss +37 -0
- package/glitch-text/glitch-text.scss +1 -0
- package/glitch-text/styles/_index.scss +144 -0
- package/gradient-text/gradient-text.scss +1 -0
- package/gradient-text/styles/_index.scss +113 -0
- package/icon/styles/_index.scss +21 -15
- package/image-cropper/styles/_index.scss +114 -0
- package/input/styles/_index.scss +133 -93
- package/input-number/styles/_index.scss +75 -0
- package/input-otp/styles/_index.scss +53 -0
- package/keyboard/styles/_index.scss +55 -0
- package/knob/styles/_index.scss +54 -0
- package/layout/styles/_index.scss +65 -0
- package/lightbox/lightbox.scss +1 -0
- package/lightbox/styles/_index.scss +144 -0
- package/line-chart/styles/_index.scss +93 -0
- package/list/list.scss +1 -0
- package/list/styles/_index.scss +101 -0
- package/loading-bar/loading-bar.scss +1 -0
- package/loading-bar/styles/_index.scss +29 -0
- package/marquee/marquee.scss +1 -0
- package/marquee/styles/_index.scss +138 -0
- package/mention/styles/_index.scss +47 -0
- package/meter-group/styles/_index.scss +61 -0
- package/package.json +576 -99
- package/page-header/styles/_index.scss +78 -0
- package/pagination/styles/_index.scss +89 -34
- package/popconfirm/styles/_index.scss +32 -0
- package/popover/styles/_index.scss +83 -0
- package/progress/styles/_index.scss +29 -14
- package/qr/styles/_index.scss +6 -3
- package/radio/styles/_index.scss +111 -0
- package/rating/styles/_index.scss +63 -0
- package/result/styles/_index.scss +69 -0
- package/rotating-text/rotating-text.scss +1 -0
- package/rotating-text/styles/_index.scss +39 -0
- package/schematics/collection.json +37 -0
- package/schematics/component-style/index.js +49 -0
- package/{alert/alert-type.d.ts → schematics/component-style/schema.js} +2 -1
- package/schematics/component-style/schema.json +20 -0
- package/schematics/icon-set/index.js +96 -0
- package/{avatar/public-api.d.ts → schematics/icon-set/schema.js} +2 -1
- package/schematics/icon-set/schema.json +39 -0
- package/schematics/migrations/v7/index.js +187 -0
- package/schematics/migrations.json +10 -0
- package/schematics/ng-add/index.js +180 -0
- package/{cdk/public-api.d.ts → schematics/ng-add/schema.js} +2 -1
- package/schematics/ng-add/schema.json +80 -0
- package/schematics/page/index.js +63 -0
- package/{alert/public-api.d.ts → schematics/page/schema.js} +2 -2
- package/schematics/page/schema.json +39 -0
- package/schematics/page/templates.js +198 -0
- package/schematics/provider/index.js +126 -0
- package/schematics/provider/schema.js +8 -0
- package/schematics/provider/schema.json +52 -0
- package/schematics/use/index.js +143 -0
- package/schematics/use/schema.js +8 -0
- package/schematics/use/schema.json +25 -0
- package/schematics/use/symbol-map.json +356 -0
- package/scramble-text/scramble-text.scss +1 -0
- package/scramble-text/styles/_index.scss +8 -0
- package/segmented/styles/_index.scss +92 -0
- package/select/styles/_index.scss +245 -159
- package/shiny-text/shiny-text.scss +1 -0
- package/shiny-text/styles/_index.scss +101 -0
- package/sidebar/styles/_index.scss +208 -0
- package/skeleton/styles/_index.scss +33 -33
- package/slider/styles/_index.scss +77 -0
- package/sparkline/styles/_index.scss +9 -0
- package/speed-dial/styles/_index.scss +158 -0
- package/spinner/styles/_index.scss +38 -22
- package/splash-cursor/splash-cursor.scss +1 -0
- package/splash-cursor/styles/_index.scss +27 -0
- package/split-text/split-text.scss +1 -0
- package/split-text/styles/_index.scss +22 -0
- package/splitter/styles/_index.scss +85 -0
- package/spotlight-card/spotlight-card.scss +1 -0
- package/spotlight-card/styles/_index.scss +43 -0
- package/squircle/styles/_index.scss +34 -0
- package/star-border/star-border.scss +1 -0
- package/star-border/styles/_index.scss +118 -0
- package/statistic/styles/_index.scss +54 -0
- package/stepper/styles/_index.scss +162 -0
- package/styles/_animations.scss +198 -0
- package/styles/_breakpoints.scss +75 -0
- package/styles/_grid.scss +71 -0
- package/styles/_reset.scss +123 -0
- package/styles/_typography.scss +122 -0
- package/styles.scss +102 -13
- package/switch/styles/_index.scss +82 -0
- package/table/styles/_index.scss +255 -4
- package/tabs/styles/_index.scss +71 -0
- package/textarea/styles/_index.scss +47 -56
- package/theme/styles/_colors.scss +83 -0
- package/theme/styles/_dark.scss +85 -0
- package/theme/styles/_focus.scss +93 -0
- package/theme/styles/_index.scss +5 -0
- package/theme/styles/_mixins.scss +57 -0
- package/theme/styles/_variables.scss +118 -0
- package/tilt-card/styles/_index.scss +40 -0
- package/tilt-card/tilt-card.scss +1 -0
- package/timeline/styles/_index.scss +127 -0
- package/toast/styles/_index.scss +263 -0
- package/toolbar/styles/_index.scss +65 -0
- package/tree/styles/_index.scss +271 -0
- package/types/ngwr-affix.d.ts +43 -0
- package/types/ngwr-alert.d.ts +68 -0
- package/types/ngwr-anchor.d.ts +53 -0
- package/types/ngwr-aurora.d.ts +52 -0
- package/types/ngwr-avatar.d.ts +90 -0
- package/types/ngwr-back-top.d.ts +37 -0
- package/types/ngwr-badge.d.ts +158 -0
- package/types/ngwr-bar-chart.d.ts +47 -0
- package/types/ngwr-blur-text.d.ts +62 -0
- package/types/ngwr-border-glow.d.ts +66 -0
- package/types/ngwr-breadcrumbs.d.ts +61 -0
- package/types/ngwr-button.d.ts +176 -0
- package/types/ngwr-calendar-heatmap.d.ts +58 -0
- package/types/ngwr-calendar.d.ts +116 -0
- package/types/ngwr-card.d.ts +50 -0
- package/types/ngwr-carousel.d.ts +57 -0
- package/types/ngwr-cascader.d.ts +107 -0
- package/types/ngwr-checkbox.d.ts +139 -0
- package/types/ngwr-circular-text.d.ts +49 -0
- package/types/ngwr-click-spark.d.ts +52 -0
- package/types/ngwr-clipboard.d.ts +53 -0
- package/types/ngwr-collapse.d.ts +139 -0
- package/types/ngwr-color-picker.d.ts +302 -0
- package/types/ngwr-command-palette.d.ts +113 -0
- package/types/ngwr-compare.d.ts +55 -0
- package/types/ngwr-confetti.d.ts +70 -0
- package/types/ngwr-context-menu.d.ts +207 -0
- package/types/ngwr-cookie.d.ts +60 -0
- package/types/ngwr-counter.d.ts +182 -0
- package/types/ngwr-date-adapter-fns.d.ts +73 -0
- package/types/ngwr-date-adapter-luxon.d.ts +73 -0
- package/types/ngwr-date-adapter.d.ts +198 -0
- package/types/ngwr-date-picker.d.ts +117 -0
- package/types/ngwr-decrypt-text.d.ts +85 -0
- package/types/ngwr-density.d.ts +97 -0
- package/types/ngwr-descriptions.d.ts +41 -0
- package/types/ngwr-dialog.d.ts +210 -0
- package/types/ngwr-directives.d.ts +125 -0
- package/types/ngwr-divider.d.ts +73 -0
- package/types/ngwr-donut-chart.d.ts +53 -0
- package/types/ngwr-drag-drop.d.ts +83 -0
- package/types/ngwr-drawer.d.ts +155 -0
- package/types/ngwr-dropdown.d.ts +124 -0
- package/types/ngwr-empty.d.ts +38 -0
- package/types/ngwr-falling-text.d.ts +63 -0
- package/types/ngwr-file-upload.d.ts +94 -0
- package/types/ngwr-form.d.ts +95 -0
- package/types/ngwr-fuzzy-text.d.ts +74 -0
- package/types/ngwr-gauge.d.ts +39 -0
- package/types/ngwr-glitch-text.d.ts +31 -0
- package/types/ngwr-gradient-text.d.ts +46 -0
- package/types/ngwr-hotkey.d.ts +142 -0
- package/types/ngwr-i18n-en.d.ts +18 -0
- package/types/ngwr-i18n-ru.d.ts +6 -0
- package/types/ngwr-i18n.d.ts +336 -0
- package/types/ngwr-icon-adapters-feather.d.ts +44 -0
- package/types/ngwr-icon-adapters-lucide.d.ts +54 -0
- package/types/ngwr-icon.d.ts +180 -0
- package/types/ngwr-image-cropper.d.ts +110 -0
- package/types/ngwr-input-number.d.ts +77 -0
- package/types/ngwr-input-otp.d.ts +78 -0
- package/types/ngwr-input.d.ts +131 -0
- package/types/ngwr-keyboard.d.ts +34 -0
- package/types/ngwr-knob.d.ts +77 -0
- package/types/ngwr-layout.d.ts +89 -0
- package/types/ngwr-lightbox.d.ts +50 -0
- package/types/ngwr-line-chart.d.ts +90 -0
- package/types/ngwr-list.d.ts +71 -0
- package/types/ngwr-loading-bar.d.ts +79 -0
- package/types/ngwr-marquee.d.ts +95 -0
- package/types/ngwr-media.d.ts +74 -0
- package/types/ngwr-mention.d.ts +110 -0
- package/types/ngwr-meta.d.ts +164 -0
- package/types/ngwr-meter-group.d.ts +57 -0
- package/types/ngwr-overlay.d.ts +110 -0
- package/types/ngwr-page-header.d.ts +35 -0
- package/types/ngwr-pagination.d.ts +119 -0
- package/types/ngwr-pipes.d.ts +177 -0
- package/types/ngwr-platform.d.ts +38 -0
- package/types/ngwr-popconfirm.d.ts +79 -0
- package/types/ngwr-popover.d.ts +90 -0
- package/types/ngwr-progress.d.ts +33 -0
- package/types/ngwr-qr.d.ts +56 -0
- package/types/ngwr-radio.d.ts +120 -0
- package/types/ngwr-rating.d.ts +62 -0
- package/types/ngwr-result.d.ts +64 -0
- package/types/ngwr-rotating-text.d.ts +72 -0
- package/types/ngwr-scramble-text.d.ts +49 -0
- package/types/ngwr-scroll.d.ts +65 -0
- package/types/ngwr-segmented.d.ts +65 -0
- package/types/ngwr-select.d.ts +413 -0
- package/types/ngwr-shiny-text.d.ts +70 -0
- package/types/ngwr-sidebar.d.ts +83 -0
- package/types/ngwr-skeleton.d.ts +41 -0
- package/types/ngwr-slider.d.ts +86 -0
- package/types/ngwr-sparkline.d.ts +48 -0
- package/types/ngwr-speed-dial.d.ts +51 -0
- package/types/ngwr-spinner.d.ts +41 -0
- package/types/ngwr-splash-cursor.d.ts +94 -0
- package/types/ngwr-split-text.d.ts +83 -0
- package/types/ngwr-splitter.d.ts +52 -0
- package/types/ngwr-spotlight-card.d.ts +71 -0
- package/types/ngwr-squircle.d.ts +132 -0
- package/types/ngwr-star-border.d.ts +40 -0
- package/types/ngwr-statistic.d.ts +88 -0
- package/types/ngwr-stepper.d.ts +99 -0
- package/types/ngwr-storage.d.ts +178 -0
- package/types/ngwr-switch.d.ts +39 -0
- package/types/ngwr-table.d.ts +237 -0
- package/types/ngwr-tabs.d.ts +125 -0
- package/types/ngwr-textarea.d.ts +60 -0
- package/types/ngwr-theme.d.ts +124 -0
- package/types/ngwr-tilt-card.d.ts +63 -0
- package/types/ngwr-timeline.d.ts +40 -0
- package/types/ngwr-toast.d.ts +230 -0
- package/types/ngwr-toolbar.d.ts +30 -0
- package/types/ngwr-tree.d.ts +150 -0
- package/types/ngwr-typewriter.d.ts +84 -0
- package/types/ngwr-typography.d.ts +56 -0
- package/types/ngwr-utils.d.ts +447 -0
- package/types/ngwr-validators.d.ts +70 -0
- package/types/ngwr-version.d.ts +44 -0
- package/types/ngwr-virtual-scroll.d.ts +64 -0
- package/types/ngwr-waves.d.ts +71 -0
- package/types/ngwr-window.d.ts +437 -0
- package/types/ngwr.d.ts +2 -0
- package/typewriter/styles/_index.scss +33 -0
- package/typewriter/typewriter.scss +1 -0
- package/typography/styles/_index.scss +211 -0
- package/virtual-scroll/styles/_index.scss +27 -0
- package/virtual-scroll/virtual-scroll.scss +1 -0
- package/waves/styles/_index.scss +24 -0
- package/waves/waves.scss +1 -0
- package/window/styles/_index.scss +430 -0
- package/alert/alert.component.d.ts +0 -21
- package/alert/index.d.ts +0 -5
- package/alert/styles/theming.scss +0 -26
- package/alert/styles/vars.scss +0 -11
- package/avatar/avatar.component.d.ts +0 -27
- package/avatar/index.d.ts +0 -5
- package/button/button-group.component.d.ts +0 -12
- package/button/button.component.d.ts +0 -31
- package/button/index.d.ts +0 -5
- package/button/public-api.d.ts +0 -8
- package/button/styles/vars.scss +0 -13
- package/cdk/base.directive.d.ts +0 -20
- package/cdk/index.d.ts +0 -5
- package/cdk/rxjs/index.d.ts +0 -5
- package/cdk/rxjs/is-array.d.ts +0 -8
- package/cdk/rxjs/is-defined.d.ts +0 -8
- package/cdk/rxjs/is-not-empty-array.d.ts +0 -8
- package/cdk/rxjs/is-observable.d.ts +0 -9
- package/cdk/rxjs/public-api.d.ts +0 -10
- package/cdk/types/index.d.ts +0 -5
- package/cdk/types/maybe.d.ts +0 -7
- package/cdk/types/public-api.d.ts +0 -9
- package/cdk/types/safe-any.d.ts +0 -7
- package/cdk/types/theme-color.d.ts +0 -8
- package/cdk/utils/generate-random-id.d.ts +0 -12
- package/cdk/utils/index.d.ts +0 -5
- package/cdk/utils/public-api.d.ts +0 -7
- package/checkbox/checkbox.component.d.ts +0 -28
- package/checkbox/index.d.ts +0 -5
- package/checkbox/public-api.d.ts +0 -7
- package/checkbox/styles/vars.scss +0 -16
- package/dialog/dialog-animations.d.ts +0 -22
- package/dialog/dialog-base.directive.d.ts +0 -40
- package/dialog/dialog-close.directive.d.ts +0 -9
- package/dialog/dialog-content.directive.d.ts +0 -6
- package/dialog/dialog-data.token.d.ts +0 -8
- package/dialog/dialog-footer.directive.d.ts +0 -8
- package/dialog/dialog-options.d.ts +0 -19
- package/dialog/dialog-ref.d.ts +0 -26
- package/dialog/dialog-title.directive.d.ts +0 -6
- package/dialog/dialog.component.d.ts +0 -28
- package/dialog/dialog.module.d.ts +0 -6
- package/dialog/dialog.service.d.ts +0 -28
- package/dialog/index.d.ts +0 -5
- package/dialog/public-api.d.ts +0 -18
- package/dialog/styles/vars.scss +0 -7
- package/divider/divider.component.d.ts +0 -13
- package/divider/index.d.ts +0 -5
- package/divider/public-api.d.ts +0 -7
- package/dropdown/dropdown-menu-item.component.d.ts +0 -12
- package/dropdown/dropdown-menu.component.d.ts +0 -14
- package/dropdown/dropdown.directive.d.ts +0 -29
- package/dropdown/dropdown.types.d.ts +0 -9
- package/dropdown/index.d.ts +0 -5
- package/dropdown/public-api.d.ts +0 -10
- package/dropdown/styles/vars.scss +0 -18
- package/fesm2022/ngwr-cdk-rxjs.mjs +0 -53
- package/fesm2022/ngwr-cdk-rxjs.mjs.map +0 -1
- package/fesm2022/ngwr-cdk-types.mjs +0 -44
- package/fesm2022/ngwr-cdk-types.mjs.map +0 -1
- package/fesm2022/ngwr-cdk-utils.mjs +0 -30
- package/fesm2022/ngwr-cdk-utils.mjs.map +0 -1
- package/fesm2022/ngwr-cdk.mjs +0 -46
- package/fesm2022/ngwr-cdk.mjs.map +0 -1
- package/fesm2022/ngwr-tag.mjs +0 -87
- package/fesm2022/ngwr-tag.mjs.map +0 -1
- package/form/form-error.component.d.ts +0 -11
- package/form/form-item.component.d.ts +0 -14
- package/form/index.d.ts +0 -5
- package/form/public-api.d.ts +0 -8
- package/icon/icon.component.d.ts +0 -24
- package/icon/icon.service.d.ts +0 -23
- package/icon/icons.d.ts +0 -770
- package/icon/index.d.ts +0 -5
- package/icon/provide-wr-icons.d.ts +0 -9
- package/icon/public-api.d.ts +0 -10
- package/icon/styles/vars.scss +0 -3
- package/index.d.ts +0 -5
- package/input/index.d.ts +0 -5
- package/input/input-types.d.ts +0 -1
- package/input/input.component.d.ts +0 -38
- package/input/public-api.d.ts +0 -8
- package/input/styles/vars.scss +0 -17
- package/pagination/index.d.ts +0 -5
- package/pagination/pagination.component.d.ts +0 -23
- package/pagination/pagination.types.d.ts +0 -7
- package/pagination/public-api.d.ts +0 -8
- package/pagination/styles/vars.scss +0 -14
- package/pipes/index.d.ts +0 -5
- package/pipes/new-array.pipe.d.ts +0 -13
- package/pipes/public-api.d.ts +0 -7
- package/progress/index.d.ts +0 -5
- package/progress/progress.component.d.ts +0 -10
- package/progress/public-api.d.ts +0 -7
- package/progress/styles/theming.scss +0 -8
- package/progress/styles/vars.scss +0 -6
- package/public-api.d.ts +0 -2
- package/qr/generator.d.ts +0 -7
- package/qr/index.d.ts +0 -5
- package/qr/public-api.d.ts +0 -7
- package/qr/qr.component.d.ts +0 -31
- package/qr/qrcodegen.d.ts +0 -94
- package/select/index.d.ts +0 -5
- package/select/public-api.d.ts +0 -10
- package/select/select-option-group.component.d.ts +0 -19
- package/select/select-option.component.d.ts +0 -22
- package/select/select.component.d.ts +0 -63
- package/select/select.types.d.ts +0 -17
- package/select/styles/vars.scss +0 -32
- package/skeleton/index.d.ts +0 -1
- package/skeleton/skeleton.component.d.ts +0 -10
- package/spinner/index.d.ts +0 -1
- package/spinner/spinner.component.d.ts +0 -13
- package/spinner/spinner.types.d.ts +0 -7
- package/styles/animations.scss +0 -92
- package/styles/cdk.scss +0 -5
- package/styles/colors.scss +0 -72
- package/styles/grid.scss +0 -99
- package/styles/maps.scss +0 -31
- package/styles/reset.scss +0 -112
- package/styles/variables.scss +0 -72
- package/table/index.d.ts +0 -5
- package/table/public-api.d.ts +0 -11
- package/table/styles/table-filter.scss +0 -202
- package/table/styles/table-sort.scss +0 -47
- package/table/styles/table.scss +0 -232
- package/table/styles/vars.scss +0 -21
- package/table/table-cell/index.d.ts +0 -7
- package/table/table-cell/table-cell.directive.d.ts +0 -8
- package/table/table-filter/index.d.ts +0 -7
- package/table/table-filter/table-filter.component.d.ts +0 -18
- package/table/table-sort/index.d.ts +0 -7
- package/table/table-sort/table-sort.component.d.ts +0 -8
- package/table/table.component.d.ts +0 -33
- package/table/types/index.d.ts +0 -6
- package/table/types/table-cell-context.d.ts +0 -6
- package/table/types/table-columns.d.ts +0 -7
- package/table/types/table-filter-emit.d.ts +0 -5
- package/table/types/table-filter-item.d.ts +0 -6
- package/table/types/table-order-item.d.ts +0 -5
- package/table/types/table-order.enum.d.ts +0 -5
- package/tag/index.d.ts +0 -5
- package/tag/public-api.d.ts +0 -7
- package/tag/styles/_index.scss +0 -32
- package/tag/styles/theming.scss +0 -21
- package/tag/styles/vars.scss +0 -12
- package/tag/tag.component.d.ts +0 -21
- package/textarea/index.d.ts +0 -7
- package/textarea/public-api.d.ts +0 -7
- package/textarea/styles/vars.scss +0 -17
- package/textarea/textarea.component.d.ts +0 -44
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
2
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
3
|
+
import * as i0 from '@angular/core';
|
|
4
|
+
import { input, output, signal, computed, inject, ElementRef, DestroyRef, PLATFORM_ID, afterNextRender, effect, ViewEncapsulation, Component } from '@angular/core';
|
|
5
|
+
import { WrPlatform } from 'ngwr/platform';
|
|
6
|
+
import { numAttr } from 'ngwr/utils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @license
|
|
10
|
+
*
|
|
11
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
12
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
13
|
+
*
|
|
14
|
+
* Angular adaptation of the RotatingText effect by David Haz / reactbits.dev.
|
|
15
|
+
* Original: https://www.reactbits.dev/text-animations/rotating-text
|
|
16
|
+
*
|
|
17
|
+
* The reactbits version uses `motion/react` + `AnimatePresence`. This
|
|
18
|
+
* port is dependency-free — vanilla DOM split + Web Animations API for
|
|
19
|
+
* the enter/exit transitions.
|
|
20
|
+
*/
|
|
21
|
+
const DEFAULT_EASING = 'cubic-bezier(0.16, 1, 0.3, 1)';
|
|
22
|
+
function graphemes(text) {
|
|
23
|
+
if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {
|
|
24
|
+
const seg = new Intl.Segmenter('en', { granularity: 'grapheme' });
|
|
25
|
+
return Array.from(seg.segment(text), s => s.segment);
|
|
26
|
+
}
|
|
27
|
+
return Array.from(text);
|
|
28
|
+
}
|
|
29
|
+
function splitWords(text, by) {
|
|
30
|
+
if (!text)
|
|
31
|
+
return [];
|
|
32
|
+
if (by === 'lines') {
|
|
33
|
+
const lines = text.split('\n');
|
|
34
|
+
return lines.map((line, i) => ({ characters: [line], needsSpace: i !== lines.length - 1 }));
|
|
35
|
+
}
|
|
36
|
+
if (by === 'words') {
|
|
37
|
+
const words = text.split(' ');
|
|
38
|
+
return words.map((w, i) => ({ characters: [w], needsSpace: i !== words.length - 1 }));
|
|
39
|
+
}
|
|
40
|
+
// characters: split each word into graphemes, keep word boundaries for spacing.
|
|
41
|
+
const words = text.split(' ');
|
|
42
|
+
return words.map((w, i) => ({ characters: graphemes(w), needsSpace: i !== words.length - 1 }));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Cycles through a list of strings, animating each transition
|
|
46
|
+
* character-by-character (or word/line). Auto-advances on a timer by
|
|
47
|
+
* default; can also be controlled imperatively via `next()` /
|
|
48
|
+
* `previous()` / `jumpTo()` / `reset()`.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```html
|
|
52
|
+
* <wr-rotating-text [texts]="['design', 'ship', 'iterate']" />
|
|
53
|
+
*
|
|
54
|
+
* // Manual control:
|
|
55
|
+
* @ViewChild(WrRotatingText) rotator!: WrRotatingText;
|
|
56
|
+
* onClick(): void { this.rotator.next(); }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @see https://www.reactbits.dev/text-animations/rotating-text
|
|
60
|
+
*/
|
|
61
|
+
class WrRotatingText {
|
|
62
|
+
/** Strings to cycle. Required. */
|
|
63
|
+
texts = input.required(/* @ts-ignore */
|
|
64
|
+
...(ngDevMode ? [{ debugName: "texts" }] : /* istanbul ignore next */ []));
|
|
65
|
+
/** Auto-advance interval in ms. @default 2000 */
|
|
66
|
+
rotationInterval = input(2000, { ...(ngDevMode ? { debugName: "rotationInterval" } : /* istanbul ignore next */ {}), transform: numAttr(2000) });
|
|
67
|
+
/** Granularity of the split. @default 'characters' */
|
|
68
|
+
splitBy = input('characters', /* @ts-ignore */
|
|
69
|
+
...(ngDevMode ? [{ debugName: "splitBy" }] : /* istanbul ignore next */ []));
|
|
70
|
+
/** Auto-advance on a timer. @default true */
|
|
71
|
+
auto = input(true, { ...(ngDevMode ? { debugName: "auto" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
72
|
+
/** Loop back to the first string after the last. @default true */
|
|
73
|
+
loop = input(true, { ...(ngDevMode ? { debugName: "loop" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
74
|
+
/** Per-swap tween duration in seconds. @default 0.6 */
|
|
75
|
+
duration = input(0.6, { ...(ngDevMode ? { debugName: "duration" } : /* istanbul ignore next */ {}), transform: numAttr(0.6) });
|
|
76
|
+
/** CSS easing of the per-piece tween. @default 'cubic-bezier(0.16, 1, 0.3, 1)' (~power3.out) */
|
|
77
|
+
easing = input(DEFAULT_EASING, /* @ts-ignore */
|
|
78
|
+
...(ngDevMode ? [{ debugName: "easing" }] : /* istanbul ignore next */ []));
|
|
79
|
+
/** Per-piece stagger in seconds. @default 0 */
|
|
80
|
+
staggerDuration = input(0, { ...(ngDevMode ? { debugName: "staggerDuration" } : /* istanbul ignore next */ {}), transform: numAttr(0) });
|
|
81
|
+
/** Stagger origin. @default 'first' */
|
|
82
|
+
staggerFrom = input('first', /* @ts-ignore */
|
|
83
|
+
...(ngDevMode ? [{ debugName: "staggerFrom" }] : /* istanbul ignore next */ []));
|
|
84
|
+
/** Emitted with the new index on every rotation. */
|
|
85
|
+
nextChange = output();
|
|
86
|
+
index = signal(0, /* @ts-ignore */
|
|
87
|
+
...(ngDevMode ? [{ debugName: "index" }] : /* istanbul ignore next */ []));
|
|
88
|
+
current = computed(() => {
|
|
89
|
+
const arr = this.texts();
|
|
90
|
+
return arr.length === 0 ? '' : arr[Math.min(this.index(), arr.length - 1)];
|
|
91
|
+
}, /* @ts-ignore */
|
|
92
|
+
...(ngDevMode ? [{ debugName: "current" }] : /* istanbul ignore next */ []));
|
|
93
|
+
words = computed(() => splitWords(this.current(), this.splitBy()), /* @ts-ignore */
|
|
94
|
+
...(ngDevMode ? [{ debugName: "words" }] : /* istanbul ignore next */ []));
|
|
95
|
+
host = inject(ElementRef);
|
|
96
|
+
destroyRef = inject(DestroyRef);
|
|
97
|
+
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
98
|
+
platform = inject(WrPlatform);
|
|
99
|
+
timerId;
|
|
100
|
+
isAnimating = false;
|
|
101
|
+
constructor() {
|
|
102
|
+
if (!this.isBrowser)
|
|
103
|
+
return;
|
|
104
|
+
afterNextRender(() => this.animateIn());
|
|
105
|
+
// Restart the timer when interval / auto change.
|
|
106
|
+
effect(() => {
|
|
107
|
+
this.rotationInterval();
|
|
108
|
+
this.auto();
|
|
109
|
+
this.restartTimer();
|
|
110
|
+
});
|
|
111
|
+
this.destroyRef.onDestroy(() => clearInterval(this.timerId));
|
|
112
|
+
}
|
|
113
|
+
// Public imperative API
|
|
114
|
+
next() {
|
|
115
|
+
const arr = this.texts();
|
|
116
|
+
if (arr.length === 0)
|
|
117
|
+
return;
|
|
118
|
+
const cur = this.index();
|
|
119
|
+
const last = arr.length - 1;
|
|
120
|
+
const target = cur === last ? (this.loop() ? 0 : cur) : cur + 1;
|
|
121
|
+
if (target !== cur)
|
|
122
|
+
void this.transitionTo(target);
|
|
123
|
+
}
|
|
124
|
+
previous() {
|
|
125
|
+
const arr = this.texts();
|
|
126
|
+
if (arr.length === 0)
|
|
127
|
+
return;
|
|
128
|
+
const cur = this.index();
|
|
129
|
+
const last = arr.length - 1;
|
|
130
|
+
const target = cur === 0 ? (this.loop() ? last : cur) : cur - 1;
|
|
131
|
+
if (target !== cur)
|
|
132
|
+
void this.transitionTo(target);
|
|
133
|
+
}
|
|
134
|
+
jumpTo(target) {
|
|
135
|
+
const arr = this.texts();
|
|
136
|
+
if (arr.length === 0)
|
|
137
|
+
return;
|
|
138
|
+
const clamped = Math.max(0, Math.min(target, arr.length - 1));
|
|
139
|
+
if (clamped !== this.index())
|
|
140
|
+
void this.transitionTo(clamped);
|
|
141
|
+
}
|
|
142
|
+
reset() {
|
|
143
|
+
if (this.index() !== 0)
|
|
144
|
+
void this.transitionTo(0);
|
|
145
|
+
}
|
|
146
|
+
// Internals
|
|
147
|
+
restartTimer() {
|
|
148
|
+
clearInterval(this.timerId);
|
|
149
|
+
if (!this.auto())
|
|
150
|
+
return;
|
|
151
|
+
this.timerId = setInterval(() => this.next(), this.rotationInterval());
|
|
152
|
+
}
|
|
153
|
+
async transitionTo(target) {
|
|
154
|
+
if (this.isAnimating)
|
|
155
|
+
return;
|
|
156
|
+
this.isAnimating = true;
|
|
157
|
+
await this.animateOut();
|
|
158
|
+
this.index.set(target);
|
|
159
|
+
this.nextChange.emit(target);
|
|
160
|
+
// Wait one microtask so the new spans are rendered, then animate in.
|
|
161
|
+
queueMicrotask(() => {
|
|
162
|
+
this.animateIn();
|
|
163
|
+
this.isAnimating = false;
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
animateIn() {
|
|
167
|
+
const targets = this.host.nativeElement.querySelectorAll('.wr-rotating-text__char');
|
|
168
|
+
if (targets.length === 0)
|
|
169
|
+
return;
|
|
170
|
+
// Reduced motion: the word swap itself is content and keeps cycling,
|
|
171
|
+
// but each swap is instant — no per-char rise/fall tween.
|
|
172
|
+
if (this.platform.prefersReducedMotion()) {
|
|
173
|
+
targets.forEach(el => {
|
|
174
|
+
el.style.opacity = '1';
|
|
175
|
+
el.style.transform = 'translate3d(0, 0, 0)';
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
const stagger = this.staggerDuration() * 1000;
|
|
180
|
+
targets.forEach((el, i) => {
|
|
181
|
+
const delay = this.delayFor(i, targets.length, stagger);
|
|
182
|
+
el.style.opacity = '0';
|
|
183
|
+
el.style.transform = 'translate3d(0, 100%, 0)';
|
|
184
|
+
const anim = el.animate([
|
|
185
|
+
{ opacity: 0, transform: 'translate3d(0, 100%, 0)' },
|
|
186
|
+
{ opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
|
187
|
+
], { duration: this.duration() * 1000, delay, easing: this.easing(), fill: 'forwards' });
|
|
188
|
+
anim.onfinish = () => {
|
|
189
|
+
el.style.opacity = '1';
|
|
190
|
+
el.style.transform = 'translate3d(0, 0, 0)';
|
|
191
|
+
try {
|
|
192
|
+
anim.cancel();
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
/* noop */
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
animateOut() {
|
|
201
|
+
const targets = this.host.nativeElement.querySelectorAll('.wr-rotating-text__char');
|
|
202
|
+
if (targets.length === 0)
|
|
203
|
+
return Promise.resolve();
|
|
204
|
+
if (this.platform.prefersReducedMotion())
|
|
205
|
+
return Promise.resolve();
|
|
206
|
+
const stagger = this.staggerDuration() * 1000;
|
|
207
|
+
const promises = [];
|
|
208
|
+
targets.forEach((el, i) => {
|
|
209
|
+
const delay = this.delayFor(i, targets.length, stagger);
|
|
210
|
+
const anim = el.animate([
|
|
211
|
+
{ opacity: 1, transform: 'translate3d(0, 0, 0)' },
|
|
212
|
+
{ opacity: 0, transform: 'translate3d(0, -120%, 0)' },
|
|
213
|
+
], { duration: this.duration() * 1000, delay, easing: this.easing(), fill: 'forwards' });
|
|
214
|
+
promises.push(new Promise(resolve => {
|
|
215
|
+
anim.onfinish = () => {
|
|
216
|
+
try {
|
|
217
|
+
anim.cancel();
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
/* noop */
|
|
221
|
+
}
|
|
222
|
+
resolve();
|
|
223
|
+
};
|
|
224
|
+
}));
|
|
225
|
+
});
|
|
226
|
+
return Promise.all(promises).then(() => undefined);
|
|
227
|
+
}
|
|
228
|
+
delayFor(i, total, stagger) {
|
|
229
|
+
if (stagger === 0)
|
|
230
|
+
return 0;
|
|
231
|
+
switch (this.staggerFrom()) {
|
|
232
|
+
case 'last':
|
|
233
|
+
return (total - 1 - i) * stagger;
|
|
234
|
+
case 'center': {
|
|
235
|
+
const center = Math.floor(total / 2);
|
|
236
|
+
return Math.abs(center - i) * stagger;
|
|
237
|
+
}
|
|
238
|
+
case 'first':
|
|
239
|
+
default:
|
|
240
|
+
return i * stagger;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrRotatingText, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
244
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.1", type: WrRotatingText, isStandalone: true, selector: "wr-rotating-text", inputs: { texts: { classPropertyName: "texts", publicName: "texts", isSignal: true, isRequired: true, transformFunction: null }, rotationInterval: { classPropertyName: "rotationInterval", publicName: "rotationInterval", isSignal: true, isRequired: false, transformFunction: null }, splitBy: { classPropertyName: "splitBy", publicName: "splitBy", isSignal: true, isRequired: false, transformFunction: null }, auto: { classPropertyName: "auto", publicName: "auto", isSignal: true, isRequired: false, transformFunction: null }, loop: { classPropertyName: "loop", publicName: "loop", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, easing: { classPropertyName: "easing", publicName: "easing", isSignal: true, isRequired: false, transformFunction: null }, staggerDuration: { classPropertyName: "staggerDuration", publicName: "staggerDuration", isSignal: true, isRequired: false, transformFunction: null }, staggerFrom: { classPropertyName: "staggerFrom", publicName: "staggerFrom", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { nextChange: "nextChange" }, host: { classAttribute: "wr-rotating-text" }, ngImport: i0, template: "<!-- Screen-reader-only live region with the canonical text. -->\n<span class=\"wr-rotating-text__sr-only\">{{ current() }}</span>\n\n<!-- Animated visual content. -->\n<span class=\"wr-rotating-text__inner\" aria-hidden=\"true\">\n @for (word of words(); track $index) {\n <span class=\"wr-rotating-text__word\">\n @for (char of word.characters; track $index) {\n <span class=\"wr-rotating-text__char\">{{ char }}</span>\n }\n @if (word.needsSpace) {\n <span class=\"wr-rotating-text__space\"> </span>\n }\n </span>\n }\n</span>\n", styles: [".wr-rotating-text{display:inline-flex;align-items:center;overflow:hidden;vertical-align:bottom}.wr-rotating-text__sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.wr-rotating-text__inner{display:inline-flex;flex-wrap:wrap}.wr-rotating-text__word{display:inline-flex;align-items:center}.wr-rotating-text__char{display:inline-block;will-change:transform,opacity}.wr-rotating-text__space{display:inline;white-space:pre}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
245
|
+
}
|
|
246
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrRotatingText, decorators: [{
|
|
247
|
+
type: Component,
|
|
248
|
+
args: [{ selector: 'wr-rotating-text', encapsulation: ViewEncapsulation.None, host: { class: 'wr-rotating-text' }, template: "<!-- Screen-reader-only live region with the canonical text. -->\n<span class=\"wr-rotating-text__sr-only\">{{ current() }}</span>\n\n<!-- Animated visual content. -->\n<span class=\"wr-rotating-text__inner\" aria-hidden=\"true\">\n @for (word of words(); track $index) {\n <span class=\"wr-rotating-text__word\">\n @for (char of word.characters; track $index) {\n <span class=\"wr-rotating-text__char\">{{ char }}</span>\n }\n @if (word.needsSpace) {\n <span class=\"wr-rotating-text__space\"> </span>\n }\n </span>\n }\n</span>\n", styles: [".wr-rotating-text{display:inline-flex;align-items:center;overflow:hidden;vertical-align:bottom}.wr-rotating-text__sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}.wr-rotating-text__inner{display:inline-flex;flex-wrap:wrap}.wr-rotating-text__word{display:inline-flex;align-items:center}.wr-rotating-text__char{display:inline-block;will-change:transform,opacity}.wr-rotating-text__space{display:inline;white-space:pre}\n"] }]
|
|
249
|
+
}], ctorParameters: () => [], propDecorators: { texts: [{ type: i0.Input, args: [{ isSignal: true, alias: "texts", required: true }] }], rotationInterval: [{ type: i0.Input, args: [{ isSignal: true, alias: "rotationInterval", required: false }] }], splitBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "splitBy", required: false }] }], auto: [{ type: i0.Input, args: [{ isSignal: true, alias: "auto", required: false }] }], loop: [{ type: i0.Input, args: [{ isSignal: true, alias: "loop", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], easing: [{ type: i0.Input, args: [{ isSignal: true, alias: "easing", required: false }] }], staggerDuration: [{ type: i0.Input, args: [{ isSignal: true, alias: "staggerDuration", required: false }] }], staggerFrom: [{ type: i0.Input, args: [{ isSignal: true, alias: "staggerFrom", required: false }] }], nextChange: [{ type: i0.Output, args: ["nextChange"] }] } });
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Generated bundle index. Do not edit.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
export { WrRotatingText };
|
|
256
|
+
//# sourceMappingURL=ngwr-rotating-text.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngwr-rotating-text.mjs","sources":["../../../projects/lib/rotating-text/rotating-text.ts","../../../projects/lib/rotating-text/rotating-text.html","../../../projects/lib/rotating-text/ngwr-rotating-text.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 * Angular adaptation of the RotatingText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/rotating-text\n *\n * The reactbits version uses `motion/react` + `AnimatePresence`. This\n * port is dependency-free — vanilla DOM split + Web Animations API for\n * the enter/exit transitions.\n */\n\nimport { coerceBooleanProperty } from '@angular/cdk/coercion';\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\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 { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrRotatingTextSplit, WrRotatingTextStaggerFrom } from './interfaces';\n\nconst DEFAULT_EASING = 'cubic-bezier(0.16, 1, 0.3, 1)';\n\ninterface Word {\n readonly characters: readonly string[];\n readonly needsSpace: boolean;\n}\n\nfunction graphemes(text: string): readonly string[] {\n if (typeof Intl !== 'undefined' && 'Segmenter' in Intl) {\n const seg = new Intl.Segmenter('en', { granularity: 'grapheme' });\n return Array.from(seg.segment(text), s => s.segment);\n }\n return Array.from(text);\n}\n\nfunction splitWords(text: string, by: WrRotatingTextSplit): readonly Word[] {\n if (!text) return [];\n if (by === 'lines') {\n const lines = text.split('\\n');\n return lines.map((line, i) => ({ characters: [line], needsSpace: i !== lines.length - 1 }));\n }\n if (by === 'words') {\n const words = text.split(' ');\n return words.map((w, i) => ({ characters: [w], needsSpace: i !== words.length - 1 }));\n }\n // characters: split each word into graphemes, keep word boundaries for spacing.\n const words = text.split(' ');\n return words.map((w, i) => ({ characters: graphemes(w), needsSpace: i !== words.length - 1 }));\n}\n\n/**\n * Cycles through a list of strings, animating each transition\n * character-by-character (or word/line). Auto-advances on a timer by\n * default; can also be controlled imperatively via `next()` /\n * `previous()` / `jumpTo()` / `reset()`.\n *\n * @example\n * ```html\n * <wr-rotating-text [texts]=\"['design', 'ship', 'iterate']\" />\n *\n * // Manual control:\n * @ViewChild(WrRotatingText) rotator!: WrRotatingText;\n * onClick(): void { this.rotator.next(); }\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/rotating-text\n */\n@Component({\n selector: 'wr-rotating-text',\n templateUrl: './rotating-text.html',\n styleUrl: './rotating-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-rotating-text' },\n})\nexport class WrRotatingText {\n /** Strings to cycle. Required. */\n readonly texts = input.required<readonly string[]>();\n\n /** Auto-advance interval in ms. @default 2000 */\n readonly rotationInterval = input(2000, { transform: numAttr(2000) });\n\n /** Granularity of the split. @default 'characters' */\n readonly splitBy = input<WrRotatingTextSplit>('characters');\n\n /** Auto-advance on a timer. @default true */\n readonly auto = input(true, { transform: coerceBooleanProperty });\n\n /** Loop back to the first string after the last. @default true */\n readonly loop = input(true, { transform: coerceBooleanProperty });\n\n /** Per-swap tween duration in seconds. @default 0.6 */\n readonly duration = input(0.6, { transform: numAttr(0.6) });\n\n /** CSS easing of the per-piece tween. @default 'cubic-bezier(0.16, 1, 0.3, 1)' (~power3.out) */\n readonly easing = input(DEFAULT_EASING);\n\n /** Per-piece stagger in seconds. @default 0 */\n readonly staggerDuration = input(0, { transform: numAttr(0) });\n\n /** Stagger origin. @default 'first' */\n readonly staggerFrom = input<WrRotatingTextStaggerFrom>('first');\n\n /** Emitted with the new index on every rotation. */\n readonly nextChange = output<number>();\n\n protected readonly index = signal(0);\n\n protected readonly current = computed(() => {\n const arr = this.texts();\n return arr.length === 0 ? '' : arr[Math.min(this.index(), arr.length - 1)];\n });\n\n protected readonly words = computed<readonly Word[]>(() => splitWords(this.current(), this.splitBy()));\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n\n private timerId: ReturnType<typeof setInterval> | undefined;\n private isAnimating = false;\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => this.animateIn());\n\n // Restart the timer when interval / auto change.\n effect(() => {\n this.rotationInterval();\n this.auto();\n this.restartTimer();\n });\n\n this.destroyRef.onDestroy(() => clearInterval(this.timerId));\n }\n\n // Public imperative API\n\n next(): void {\n const arr = this.texts();\n if (arr.length === 0) return;\n const cur = this.index();\n const last = arr.length - 1;\n const target = cur === last ? (this.loop() ? 0 : cur) : cur + 1;\n if (target !== cur) void this.transitionTo(target);\n }\n\n previous(): void {\n const arr = this.texts();\n if (arr.length === 0) return;\n const cur = this.index();\n const last = arr.length - 1;\n const target = cur === 0 ? (this.loop() ? last : cur) : cur - 1;\n if (target !== cur) void this.transitionTo(target);\n }\n\n jumpTo(target: number): void {\n const arr = this.texts();\n if (arr.length === 0) return;\n const clamped = Math.max(0, Math.min(target, arr.length - 1));\n if (clamped !== this.index()) void this.transitionTo(clamped);\n }\n\n reset(): void {\n if (this.index() !== 0) void this.transitionTo(0);\n }\n\n // Internals\n\n private restartTimer(): void {\n clearInterval(this.timerId);\n if (!this.auto()) return;\n this.timerId = setInterval(() => this.next(), this.rotationInterval());\n }\n\n private async transitionTo(target: number): Promise<void> {\n if (this.isAnimating) return;\n this.isAnimating = true;\n\n await this.animateOut();\n this.index.set(target);\n this.nextChange.emit(target);\n // Wait one microtask so the new spans are rendered, then animate in.\n queueMicrotask(() => {\n this.animateIn();\n this.isAnimating = false;\n });\n }\n\n private animateIn(): void {\n const targets = this.host.nativeElement.querySelectorAll<HTMLElement>('.wr-rotating-text__char');\n if (targets.length === 0) return;\n\n // Reduced motion: the word swap itself is content and keeps cycling,\n // but each swap is instant — no per-char rise/fall tween.\n if (this.platform.prefersReducedMotion()) {\n targets.forEach(el => {\n el.style.opacity = '1';\n el.style.transform = 'translate3d(0, 0, 0)';\n });\n return;\n }\n\n const stagger = this.staggerDuration() * 1000;\n targets.forEach((el, i) => {\n const delay = this.delayFor(i, targets.length, stagger);\n el.style.opacity = '0';\n el.style.transform = 'translate3d(0, 100%, 0)';\n const anim = el.animate(\n [\n { opacity: 0, transform: 'translate3d(0, 100%, 0)' },\n { opacity: 1, transform: 'translate3d(0, 0, 0)' },\n ],\n { duration: this.duration() * 1000, delay, easing: this.easing(), fill: 'forwards' }\n );\n anim.onfinish = (): void => {\n el.style.opacity = '1';\n el.style.transform = 'translate3d(0, 0, 0)';\n try {\n anim.cancel();\n } catch {\n /* noop */\n }\n };\n });\n }\n\n private animateOut(): Promise<void> {\n const targets = this.host.nativeElement.querySelectorAll<HTMLElement>('.wr-rotating-text__char');\n if (targets.length === 0) return Promise.resolve();\n if (this.platform.prefersReducedMotion()) return Promise.resolve();\n const stagger = this.staggerDuration() * 1000;\n const promises: Promise<void>[] = [];\n targets.forEach((el, i) => {\n const delay = this.delayFor(i, targets.length, stagger);\n const anim = el.animate(\n [\n { opacity: 1, transform: 'translate3d(0, 0, 0)' },\n { opacity: 0, transform: 'translate3d(0, -120%, 0)' },\n ],\n { duration: this.duration() * 1000, delay, easing: this.easing(), fill: 'forwards' }\n );\n promises.push(\n new Promise<void>(resolve => {\n anim.onfinish = (): void => {\n try {\n anim.cancel();\n } catch {\n /* noop */\n }\n resolve();\n };\n })\n );\n });\n return Promise.all(promises).then(() => undefined);\n }\n\n private delayFor(i: number, total: number, stagger: number): number {\n if (stagger === 0) return 0;\n switch (this.staggerFrom()) {\n case 'last':\n return (total - 1 - i) * stagger;\n case 'center': {\n const center = Math.floor(total / 2);\n return Math.abs(center - i) * stagger;\n }\n case 'first':\n default:\n return i * stagger;\n }\n }\n}\n\nexport type { WrRotatingTextSplit, WrRotatingTextStaggerFrom } from './interfaces';\n","<!-- Screen-reader-only live region with the canonical text. -->\n<span class=\"wr-rotating-text__sr-only\">{{ current() }}</span>\n\n<!-- Animated visual content. -->\n<span class=\"wr-rotating-text__inner\" aria-hidden=\"true\">\n @for (word of words(); track $index) {\n <span class=\"wr-rotating-text__word\">\n @for (char of word.characters; track $index) {\n <span class=\"wr-rotating-text__char\">{{ char }}</span>\n }\n @if (word.needsSpace) {\n <span class=\"wr-rotating-text__space\"> </span>\n }\n </span>\n }\n</span>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { isPlatformBrowser } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { input, inject, ElementRef, DestroyRef, PLATFORM_ID, afterNextRender, ViewEncapsulation, Component } from '@angular/core';
|
|
4
|
+
import { WrPlatform } from 'ngwr/platform';
|
|
5
|
+
import { numAttr } from 'ngwr/utils';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @license
|
|
9
|
+
*
|
|
10
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
11
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
12
|
+
*
|
|
13
|
+
* Angular adaptation of the ScrambledText effect by David Haz / reactbits.dev.
|
|
14
|
+
* Original: https://www.reactbits.dev/text-animations/scrambled-text
|
|
15
|
+
*
|
|
16
|
+
* The reactbits version uses GSAP's paid SplitText + ScrambleTextPlugin.
|
|
17
|
+
* This port is dependency-free — splits via vanilla DOM, scrambles via a
|
|
18
|
+
* per-char `setInterval` loop, restores on settle.
|
|
19
|
+
*/
|
|
20
|
+
function pickRandom(pool, exclude) {
|
|
21
|
+
if (pool.length === 0)
|
|
22
|
+
return exclude;
|
|
23
|
+
if (pool.length === 1)
|
|
24
|
+
return pool;
|
|
25
|
+
// Avoid landing on the original mid-scramble — looks like nothing happened.
|
|
26
|
+
let pick = pool.charAt(Math.floor(Math.random() * pool.length));
|
|
27
|
+
for (let tries = 0; tries < 3 && pick === exclude; tries++) {
|
|
28
|
+
pick = pool.charAt(Math.floor(Math.random() * pool.length));
|
|
29
|
+
}
|
|
30
|
+
return pick;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Cursor-proximity scrambler. Each character inside the projected text
|
|
34
|
+
* scrambles through `scrambleChars` whenever the pointer moves within
|
|
35
|
+
* `radius` px of it, then settles back to the original. Closer pointer →
|
|
36
|
+
* longer scramble.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```html
|
|
40
|
+
* <wr-scramble-text
|
|
41
|
+
* [radius]="120"
|
|
42
|
+
* [duration]="1.4"
|
|
43
|
+
* scrambleChars="!&%*"
|
|
44
|
+
* >
|
|
45
|
+
* Hover this paragraph to scramble characters near the cursor.
|
|
46
|
+
* </wr-scramble-text>
|
|
47
|
+
* ```
|
|
48
|
+
*
|
|
49
|
+
* @see https://www.reactbits.dev/text-animations/scrambled-text
|
|
50
|
+
*/
|
|
51
|
+
class WrScrambleText {
|
|
52
|
+
/** Proximity radius in pixels. @default 100 */
|
|
53
|
+
radius = input(100, { ...(ngDevMode ? { debugName: "radius" } : /* istanbul ignore next */ {}), transform: numAttr(100) });
|
|
54
|
+
/** Max scramble duration in seconds (scaled by proximity — closer = longer). @default 1.2 */
|
|
55
|
+
duration = input(1.2, { ...(ngDevMode ? { debugName: "duration" } : /* istanbul ignore next */ {}), transform: numAttr(1.2) });
|
|
56
|
+
/** Approximate seconds between random-char swaps. Lower = faster scramble. @default 0.05 */
|
|
57
|
+
speed = input(0.05, { ...(ngDevMode ? { debugName: "speed" } : /* istanbul ignore next */ {}), transform: numAttr(0.05) });
|
|
58
|
+
/** Pool of glyphs to scramble through. @default '.:' */
|
|
59
|
+
scrambleChars = input('.:', /* @ts-ignore */
|
|
60
|
+
...(ngDevMode ? [{ debugName: "scrambleChars" }] : /* istanbul ignore next */ []));
|
|
61
|
+
host = inject(ElementRef);
|
|
62
|
+
destroyRef = inject(DestroyRef);
|
|
63
|
+
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
64
|
+
platform = inject(WrPlatform);
|
|
65
|
+
/** One entry per active scramble, keyed by char span. */
|
|
66
|
+
active = new Map();
|
|
67
|
+
/** Cached list of char spans. Re-computed after each render. */
|
|
68
|
+
chars = [];
|
|
69
|
+
constructor() {
|
|
70
|
+
if (!this.isBrowser)
|
|
71
|
+
return;
|
|
72
|
+
afterNextRender(() => this.split());
|
|
73
|
+
this.destroyRef.onDestroy(() => this.clearAll());
|
|
74
|
+
}
|
|
75
|
+
onPointerMove(event) {
|
|
76
|
+
if (this.chars.length === 0)
|
|
77
|
+
return;
|
|
78
|
+
// Reduced motion: pointer proximity stops scrambling — text stays put.
|
|
79
|
+
if (this.platform.prefersReducedMotion())
|
|
80
|
+
return;
|
|
81
|
+
const radius = this.radius();
|
|
82
|
+
const duration = this.duration() * 1000;
|
|
83
|
+
const swapInterval = Math.max(16, this.speed() * 1000);
|
|
84
|
+
const pool = this.scrambleChars();
|
|
85
|
+
for (const charEl of this.chars) {
|
|
86
|
+
const rect = charEl.getBoundingClientRect();
|
|
87
|
+
const dx = event.clientX - (rect.left + rect.width / 2);
|
|
88
|
+
const dy = event.clientY - (rect.top + rect.height / 2);
|
|
89
|
+
const dist = Math.hypot(dx, dy);
|
|
90
|
+
if (dist > radius)
|
|
91
|
+
continue;
|
|
92
|
+
// Cancel any in-flight scramble for this char — we're restarting.
|
|
93
|
+
this.cancelOne(charEl);
|
|
94
|
+
// Proximity factor: 0 at the edge, 1 at the centre.
|
|
95
|
+
const proximity = 1 - dist / radius;
|
|
96
|
+
const scrambleMs = duration * proximity;
|
|
97
|
+
const original = charEl.dataset['scrambleOriginal'] ?? '';
|
|
98
|
+
const swapId = setInterval(() => {
|
|
99
|
+
charEl.textContent = pickRandom(pool, original);
|
|
100
|
+
}, swapInterval);
|
|
101
|
+
const settleId = setTimeout(() => {
|
|
102
|
+
clearInterval(swapId);
|
|
103
|
+
charEl.textContent = original;
|
|
104
|
+
this.active.delete(charEl);
|
|
105
|
+
}, scrambleMs);
|
|
106
|
+
this.active.set(charEl, { swapId, settleId });
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Walk the projected text and wrap each non-whitespace character in a span. */
|
|
110
|
+
split() {
|
|
111
|
+
const inner = this.host.nativeElement.querySelector('.wr-scramble-text__inner');
|
|
112
|
+
if (!inner)
|
|
113
|
+
return;
|
|
114
|
+
const raw = inner.textContent ?? '';
|
|
115
|
+
if (!raw)
|
|
116
|
+
return;
|
|
117
|
+
const frag = document.createDocumentFragment();
|
|
118
|
+
for (const ch of [...raw]) {
|
|
119
|
+
if (/\s/.test(ch)) {
|
|
120
|
+
frag.appendChild(document.createTextNode(ch));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
const span = document.createElement('span');
|
|
124
|
+
span.className = 'wr-scramble-text__char';
|
|
125
|
+
span.textContent = ch;
|
|
126
|
+
span.dataset['scrambleOriginal'] = ch;
|
|
127
|
+
frag.appendChild(span);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
inner.replaceChildren(frag);
|
|
131
|
+
this.chars = Array.from(inner.querySelectorAll('.wr-scramble-text__char'));
|
|
132
|
+
}
|
|
133
|
+
cancelOne(el) {
|
|
134
|
+
const entry = this.active.get(el);
|
|
135
|
+
if (!entry)
|
|
136
|
+
return;
|
|
137
|
+
clearInterval(entry.swapId);
|
|
138
|
+
clearTimeout(entry.settleId);
|
|
139
|
+
this.active.delete(el);
|
|
140
|
+
}
|
|
141
|
+
clearAll() {
|
|
142
|
+
for (const [el, entry] of this.active) {
|
|
143
|
+
clearInterval(entry.swapId);
|
|
144
|
+
clearTimeout(entry.settleId);
|
|
145
|
+
el.textContent = el.dataset['scrambleOriginal'] ?? '';
|
|
146
|
+
}
|
|
147
|
+
this.active.clear();
|
|
148
|
+
}
|
|
149
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrScrambleText, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
150
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0.1", type: WrScrambleText, isStandalone: true, selector: "wr-scramble-text", inputs: { radius: { classPropertyName: "radius", publicName: "radius", isSignal: true, isRequired: false, transformFunction: null }, duration: { classPropertyName: "duration", publicName: "duration", isSignal: true, isRequired: false, transformFunction: null }, speed: { classPropertyName: "speed", publicName: "speed", isSignal: true, isRequired: false, transformFunction: null }, scrambleChars: { classPropertyName: "scrambleChars", publicName: "scrambleChars", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "pointermove": "onPointerMove($event)" }, classAttribute: "wr-scramble-text" }, ngImport: i0, template: '<span class="wr-scramble-text__inner" #inner><ng-content /></span>', isInline: true, styles: [".wr-scramble-text{display:block}.wr-scramble-text__char{display:inline-block;will-change:contents}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
151
|
+
}
|
|
152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrScrambleText, decorators: [{
|
|
153
|
+
type: Component,
|
|
154
|
+
args: [{ selector: 'wr-scramble-text', template: '<span class="wr-scramble-text__inner" #inner><ng-content /></span>', encapsulation: ViewEncapsulation.None, host: {
|
|
155
|
+
class: 'wr-scramble-text',
|
|
156
|
+
'(pointermove)': 'onPointerMove($event)',
|
|
157
|
+
}, styles: [".wr-scramble-text{display:block}.wr-scramble-text__char{display:inline-block;will-change:contents}\n"] }]
|
|
158
|
+
}], ctorParameters: () => [], propDecorators: { radius: [{ type: i0.Input, args: [{ isSignal: true, alias: "radius", required: false }] }], duration: [{ type: i0.Input, args: [{ isSignal: true, alias: "duration", required: false }] }], speed: [{ type: i0.Input, args: [{ isSignal: true, alias: "speed", required: false }] }], scrambleChars: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrambleChars", required: false }] }] } });
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Generated bundle index. Do not edit.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
export { WrScrambleText };
|
|
165
|
+
//# sourceMappingURL=ngwr-scramble-text.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngwr-scramble-text.mjs","sources":["../../../projects/lib/scramble-text/scramble-text.ts","../../../projects/lib/scramble-text/ngwr-scramble-text.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 * Angular adaptation of the ScrambledText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/scrambled-text\n *\n * The reactbits version uses GSAP's paid SplitText + ScrambleTextPlugin.\n * This port is dependency-free — splits via vanilla DOM, scrambles via a\n * per-char `setInterval` loop, restores on settle.\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n inject,\n input,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\ninterface ActiveScramble {\n swapId: ReturnType<typeof setInterval>;\n settleId: ReturnType<typeof setTimeout>;\n}\n\nfunction pickRandom(pool: string, exclude: string): string {\n if (pool.length === 0) return exclude;\n if (pool.length === 1) return pool;\n // Avoid landing on the original mid-scramble — looks like nothing happened.\n let pick = pool.charAt(Math.floor(Math.random() * pool.length));\n for (let tries = 0; tries < 3 && pick === exclude; tries++) {\n pick = pool.charAt(Math.floor(Math.random() * pool.length));\n }\n return pick;\n}\n\n/**\n * Cursor-proximity scrambler. Each character inside the projected text\n * scrambles through `scrambleChars` whenever the pointer moves within\n * `radius` px of it, then settles back to the original. Closer pointer →\n * longer scramble.\n *\n * @example\n * ```html\n * <wr-scramble-text\n * [radius]=\"120\"\n * [duration]=\"1.4\"\n * scrambleChars=\"!&%*\"\n * >\n * Hover this paragraph to scramble characters near the cursor.\n * </wr-scramble-text>\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/scrambled-text\n */\n@Component({\n selector: 'wr-scramble-text',\n template: '<span class=\"wr-scramble-text__inner\" #inner><ng-content /></span>',\n styleUrl: './scramble-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: {\n class: 'wr-scramble-text',\n '(pointermove)': 'onPointerMove($event)',\n },\n})\nexport class WrScrambleText {\n /** Proximity radius in pixels. @default 100 */\n readonly radius = input(100, { transform: numAttr(100) });\n\n /** Max scramble duration in seconds (scaled by proximity — closer = longer). @default 1.2 */\n readonly duration = input(1.2, { transform: numAttr(1.2) });\n\n /** Approximate seconds between random-char swaps. Lower = faster scramble. @default 0.05 */\n readonly speed = input(0.05, { transform: numAttr(0.05) });\n\n /** Pool of glyphs to scramble through. @default '.:' */\n readonly scrambleChars = input('.:');\n\n private readonly host = inject<ElementRef<HTMLElement>>(ElementRef);\n private readonly destroyRef = inject(DestroyRef);\n private readonly isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n private readonly platform = inject(WrPlatform);\n\n /** One entry per active scramble, keyed by char span. */\n private readonly active = new Map<HTMLElement, ActiveScramble>();\n\n /** Cached list of char spans. Re-computed after each render. */\n private chars: readonly HTMLElement[] = [];\n\n constructor() {\n if (!this.isBrowser) return;\n afterNextRender(() => this.split());\n this.destroyRef.onDestroy(() => this.clearAll());\n }\n\n protected onPointerMove(event: PointerEvent): void {\n if (this.chars.length === 0) return;\n // Reduced motion: pointer proximity stops scrambling — text stays put.\n if (this.platform.prefersReducedMotion()) return;\n const radius = this.radius();\n const duration = this.duration() * 1000;\n const swapInterval = Math.max(16, this.speed() * 1000);\n const pool = this.scrambleChars();\n\n for (const charEl of this.chars) {\n const rect = charEl.getBoundingClientRect();\n const dx = event.clientX - (rect.left + rect.width / 2);\n const dy = event.clientY - (rect.top + rect.height / 2);\n const dist = Math.hypot(dx, dy);\n if (dist > radius) continue;\n\n // Cancel any in-flight scramble for this char — we're restarting.\n this.cancelOne(charEl);\n\n // Proximity factor: 0 at the edge, 1 at the centre.\n const proximity = 1 - dist / radius;\n const scrambleMs = duration * proximity;\n const original = charEl.dataset['scrambleOriginal'] ?? '';\n\n const swapId = setInterval(() => {\n charEl.textContent = pickRandom(pool, original);\n }, swapInterval);\n\n const settleId = setTimeout(() => {\n clearInterval(swapId);\n charEl.textContent = original;\n this.active.delete(charEl);\n }, scrambleMs);\n\n this.active.set(charEl, { swapId, settleId });\n }\n }\n\n /** Walk the projected text and wrap each non-whitespace character in a span. */\n private split(): void {\n const inner = this.host.nativeElement.querySelector<HTMLElement>('.wr-scramble-text__inner');\n if (!inner) return;\n const raw = inner.textContent ?? '';\n if (!raw) return;\n\n const frag = document.createDocumentFragment();\n for (const ch of [...raw]) {\n if (/\\s/.test(ch)) {\n frag.appendChild(document.createTextNode(ch));\n } else {\n const span = document.createElement('span');\n span.className = 'wr-scramble-text__char';\n span.textContent = ch;\n span.dataset['scrambleOriginal'] = ch;\n frag.appendChild(span);\n }\n }\n inner.replaceChildren(frag);\n this.chars = Array.from(inner.querySelectorAll<HTMLElement>('.wr-scramble-text__char'));\n }\n\n private cancelOne(el: HTMLElement): void {\n const entry = this.active.get(el);\n if (!entry) return;\n clearInterval(entry.swapId);\n clearTimeout(entry.settleId);\n this.active.delete(el);\n }\n\n private clearAll(): void {\n for (const [el, entry] of this.active) {\n clearInterval(entry.swapId);\n clearTimeout(entry.settleId);\n el.textContent = el.dataset['scrambleOriginal'] ?? '';\n }\n this.active.clear();\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { DOCUMENT } from '@angular/common';
|
|
2
|
+
import * as i0 from '@angular/core';
|
|
3
|
+
import { inject, Service } from '@angular/core';
|
|
4
|
+
import { WrPlatform } from 'ngwr/platform';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @license
|
|
8
|
+
*
|
|
9
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
10
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Smooth-scroll utility. Resolves `id` / selector / element / coords
|
|
14
|
+
* targets; subtracts an `offset` (for sticky headers); respects
|
|
15
|
+
* `prefers-reduced-motion` — automatically falls back to instant
|
|
16
|
+
* scrolling when the user has opted out.
|
|
17
|
+
*
|
|
18
|
+
* SSR-safe — all methods no-op on the server.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const scroll = inject(WrScroll);
|
|
23
|
+
* scroll.to('#section-three', { offset: 80 });
|
|
24
|
+
* scroll.toTop({ smooth: false });
|
|
25
|
+
* scroll.intoView(myEl, { offset: 64 });
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* @see https://ngwr.dev/services/scroll
|
|
29
|
+
*/
|
|
30
|
+
class WrScroll {
|
|
31
|
+
doc = inject(DOCUMENT);
|
|
32
|
+
platform = inject(WrPlatform);
|
|
33
|
+
/** Scroll to an arbitrary target. */
|
|
34
|
+
to(target, options = {}) {
|
|
35
|
+
if (!this.platform.isBrowser)
|
|
36
|
+
return;
|
|
37
|
+
const win = this.doc.defaultView;
|
|
38
|
+
if (!win)
|
|
39
|
+
return;
|
|
40
|
+
const offset = options.offset ?? 0;
|
|
41
|
+
const behavior = this.behavior(options.smooth);
|
|
42
|
+
const container = options.container ?? win;
|
|
43
|
+
if (typeof target === 'object' && 'top' in target) {
|
|
44
|
+
this.scroll(container, { top: target.top - offset, left: target.left ?? 0, behavior });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const el = typeof target === 'string' ? this.resolveSelector(target) : target;
|
|
48
|
+
if (!el)
|
|
49
|
+
return;
|
|
50
|
+
const rect = el.getBoundingClientRect();
|
|
51
|
+
if (container === win) {
|
|
52
|
+
const top = rect.top + win.scrollY - offset;
|
|
53
|
+
this.scroll(container, { top, left: 0, behavior });
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const ctx = container;
|
|
57
|
+
const ctxRect = ctx.getBoundingClientRect();
|
|
58
|
+
const top = rect.top - ctxRect.top + ctx.scrollTop - offset;
|
|
59
|
+
this.scroll(container, { top, left: 0, behavior });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Convenience for an element — accepts the same options. */
|
|
63
|
+
intoView(el, options = {}) {
|
|
64
|
+
this.to(el, options);
|
|
65
|
+
}
|
|
66
|
+
/** Scroll the page (or container) to the top. */
|
|
67
|
+
toTop(options = {}) {
|
|
68
|
+
this.to({ top: 0 }, options);
|
|
69
|
+
}
|
|
70
|
+
// Internals
|
|
71
|
+
resolveSelector(value) {
|
|
72
|
+
if (value.startsWith('#')) {
|
|
73
|
+
return this.doc.getElementById(value.slice(1));
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
return this.doc.querySelector(value);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
behavior(requested) {
|
|
83
|
+
if (requested === false)
|
|
84
|
+
return 'auto';
|
|
85
|
+
if (this.platform.prefersReducedMotion())
|
|
86
|
+
return 'auto';
|
|
87
|
+
return 'smooth';
|
|
88
|
+
}
|
|
89
|
+
scroll(container, options) {
|
|
90
|
+
if (container instanceof Window)
|
|
91
|
+
container.scrollTo(options);
|
|
92
|
+
else
|
|
93
|
+
container.scrollTo(options);
|
|
94
|
+
}
|
|
95
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrScroll, deps: [], target: i0.ɵɵFactoryTarget.Service });
|
|
96
|
+
static ɵprov = i0.ɵɵngDeclareService({ minVersion: "22.0.0", version: "22.0.1", ngImport: i0, type: WrScroll });
|
|
97
|
+
}
|
|
98
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.1", ngImport: i0, type: WrScroll, decorators: [{
|
|
99
|
+
type: Service
|
|
100
|
+
}] });
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Generated bundle index. Do not edit.
|
|
104
|
+
*/
|
|
105
|
+
|
|
106
|
+
export { WrScroll };
|
|
107
|
+
//# sourceMappingURL=ngwr-scroll.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngwr-scroll.mjs","sources":["../../../projects/lib/scroll/wr-scroll.ts","../../../projects/lib/scroll/ngwr-scroll.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 { WrPlatform } from 'ngwr/platform';\n\nimport type { WrScrollOptions, WrScrollTarget } from './interfaces';\n\n/**\n * Smooth-scroll utility. Resolves `id` / selector / element / coords\n * targets; subtracts an `offset` (for sticky headers); respects\n * `prefers-reduced-motion` — automatically falls back to instant\n * scrolling when the user has opted out.\n *\n * SSR-safe — all methods no-op on the server.\n *\n * @example\n * ```ts\n * const scroll = inject(WrScroll);\n * scroll.to('#section-three', { offset: 80 });\n * scroll.toTop({ smooth: false });\n * scroll.intoView(myEl, { offset: 64 });\n * ```\n *\n * @see https://ngwr.dev/services/scroll\n */\n@Service()\nexport class WrScroll {\n private readonly doc = inject(DOCUMENT);\n private readonly platform = inject(WrPlatform);\n\n /** Scroll to an arbitrary target. */\n to(target: WrScrollTarget, options: WrScrollOptions = {}): void {\n if (!this.platform.isBrowser) return;\n const win = this.doc.defaultView;\n if (!win) return;\n\n const offset = options.offset ?? 0;\n const behavior = this.behavior(options.smooth);\n const container = options.container ?? win;\n\n if (typeof target === 'object' && 'top' in target) {\n this.scroll(container, { top: target.top - offset, left: target.left ?? 0, behavior });\n return;\n }\n\n const el = typeof target === 'string' ? this.resolveSelector(target) : target;\n if (!el) return;\n\n const rect = el.getBoundingClientRect();\n if (container === win) {\n const top = rect.top + win.scrollY - offset;\n this.scroll(container, { top, left: 0, behavior });\n } else {\n const ctx = container as Element;\n const ctxRect = ctx.getBoundingClientRect();\n const top = rect.top - ctxRect.top + ctx.scrollTop - offset;\n this.scroll(container, { top, left: 0, behavior });\n }\n }\n\n /** Convenience for an element — accepts the same options. */\n intoView(el: Element, options: WrScrollOptions = {}): void {\n this.to(el, options);\n }\n\n /** Scroll the page (or container) to the top. */\n toTop(options: WrScrollOptions = {}): void {\n this.to({ top: 0 }, options);\n }\n\n // Internals\n\n private resolveSelector(value: string): Element | null {\n if (value.startsWith('#')) {\n return this.doc.getElementById(value.slice(1));\n }\n try {\n return this.doc.querySelector(value);\n } catch {\n return null;\n }\n }\n\n private behavior(requested: boolean | undefined): ScrollBehavior {\n if (requested === false) return 'auto';\n if (this.platform.prefersReducedMotion()) return 'auto';\n return 'smooth';\n }\n\n private scroll(container: Window | Element, options: ScrollToOptions): void {\n if (container instanceof Window) container.scrollTo(options);\n else container.scrollTo(options);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|