ngwr 8.0.0 → 9.0.1
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 +76 -29
- package/action-sheet/styles/_index.scss +93 -0
- package/alert/styles/_index.scss +10 -10
- package/anchor/styles/_index.scss +3 -3
- package/back-top/styles/_index.scss +1 -1
- package/badge/styles/_tag.scss +3 -3
- package/bar-chart/styles/_index.scss +4 -4
- package/border-glow/styles/_index.scss +3 -3
- package/breadcrumbs/styles/_index.scss +3 -3
- package/burger/styles/_index.scss +1 -1
- package/button/styles/_index.scss +4 -4
- package/calendar/styles/_index.scss +4 -4
- package/calendar-heatmap/styles/_index.scss +3 -3
- package/card/styles/_index.scss +5 -5
- package/carousel/styles/_index.scss +5 -5
- package/cascader/styles/_index.scss +15 -15
- package/checkbox/styles/_index.scss +20 -5
- package/collapse/styles/_index.scss +6 -6
- package/color-picker/styles/_index.scss +15 -9
- package/command-palette/styles/_index.scss +19 -16
- package/compare/styles/_index.scss +3 -3
- package/context-menu/styles/_index.scss +16 -6
- package/counter/styles/_index.scss +12 -1
- package/date-picker/styles/_index.scss +8 -8
- package/descriptions/styles/_index.scss +9 -9
- package/dialog/styles/_index.scss +7 -6
- package/divider/styles/_index.scss +2 -2
- package/donut-chart/styles/_index.scss +3 -3
- package/drag-drop/styles/_index.scss +11 -6
- package/drawer/styles/_index.scss +15 -6
- package/dropdown/styles/_index.scss +5 -5
- package/empty/styles/_index.scss +4 -4
- package/fesm2022/ngwr-action-sheet.mjs +81 -0
- package/fesm2022/ngwr-action-sheet.mjs.map +1 -0
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +4 -4
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +4 -4
- package/fesm2022/ngwr-anchor.mjs.map +1 -1
- package/fesm2022/ngwr-aurora.mjs +5 -4
- package/fesm2022/ngwr-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-avatar.mjs +4 -4
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +4 -4
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-badge.mjs +8 -8
- package/fesm2022/ngwr-badge.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart.mjs +4 -4
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text.mjs +3 -3
- package/fesm2022/ngwr-border-glow.mjs +4 -4
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +8 -8
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +4 -4
- package/fesm2022/ngwr-burger.mjs.map +1 -1
- package/fesm2022/ngwr-button.mjs +8 -8
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +4 -4
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +4 -4
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +11 -11
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +7 -7
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +52 -60
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +74 -106
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +5 -4
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +5 -4
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-clipboard.mjs +4 -4
- package/fesm2022/ngwr-clipboard.mjs.map +1 -1
- package/fesm2022/ngwr-collapse.mjs +12 -12
- package/fesm2022/ngwr-collapse.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker.mjs +58 -66
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +4 -4
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +4 -4
- package/fesm2022/ngwr-compare.mjs.map +1 -1
- package/fesm2022/ngwr-confetti.mjs +3 -3
- package/fesm2022/ngwr-context-menu.mjs +86 -15
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +19 -6
- package/fesm2022/ngwr-cookie.mjs.map +1 -1
- package/fesm2022/ngwr-counter.mjs +26 -12
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter-fns.mjs +3 -3
- package/fesm2022/ngwr-date-adapter-luxon.mjs +3 -3
- package/fesm2022/ngwr-date-adapter.mjs +10 -5
- package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +128 -123
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-density.mjs +7 -7
- package/fesm2022/ngwr-density.mjs.map +1 -1
- package/fesm2022/ngwr-descriptions.mjs +7 -7
- package/fesm2022/ngwr-descriptions.mjs.map +1 -1
- package/fesm2022/ngwr-dialog.mjs +16 -16
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-directives.mjs +21 -15
- package/fesm2022/ngwr-directives.mjs.map +1 -1
- package/fesm2022/ngwr-divider.mjs +4 -4
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +4 -4
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +10 -9
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer.mjs +19 -18
- package/fesm2022/ngwr-drawer.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +13 -12
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +4 -4
- package/fesm2022/ngwr-empty.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +5 -4
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +58 -60
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +11 -11
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +5 -4
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +4 -4
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +4 -4
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +4 -4
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-hotkey.mjs +7 -7
- package/fesm2022/ngwr-hotkey.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +10 -10
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon-adapters-lucide.mjs +6 -7
- package/fesm2022/ngwr-icon-adapters-lucide.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +4 -4
- package/fesm2022/ngwr-icon.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +6 -5
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +56 -73
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +46 -52
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +17 -17
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-keyboard.mjs +4 -4
- package/fesm2022/ngwr-keyboard.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +47 -58
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +16 -16
- package/fesm2022/ngwr-layout.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +7 -6
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +4 -4
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +8 -8
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +7 -7
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-marquee.mjs +6 -5
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-media.mjs +4 -4
- package/fesm2022/ngwr-media.mjs.map +1 -1
- package/fesm2022/ngwr-mention.mjs +15 -9
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +7 -7
- package/fesm2022/ngwr-meta.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +4 -4
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-overlay.mjs +9 -4
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-page-header.mjs +4 -4
- package/fesm2022/ngwr-page-header.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +4 -4
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-platform.mjs +169 -5
- package/fesm2022/ngwr-platform.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm.mjs +7 -7
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +7 -7
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +4 -4
- package/fesm2022/ngwr-progress.mjs.map +1 -1
- package/fesm2022/ngwr-pull-to-refresh.mjs +172 -0
- package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -0
- package/fesm2022/ngwr-qr.mjs +5 -5
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +27 -52
- package/fesm2022/ngwr-radio.mjs.map +1 -1
- package/fesm2022/ngwr-rating.mjs +35 -48
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-result.mjs +13 -13
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text.mjs +15 -4
- package/fesm2022/ngwr-rotating-text.mjs.map +1 -1
- package/fesm2022/ngwr-scroll.mjs +4 -4
- package/fesm2022/ngwr-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-segmented.mjs +3 -3
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +289 -85
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +7 -7
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +4 -4
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-skeleton.mjs +4 -4
- package/fesm2022/ngwr-skeleton.mjs.map +1 -1
- package/fesm2022/ngwr-slider.mjs +79 -73
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +4 -4
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +13 -5
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +4 -4
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor.mjs +4 -4
- package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
- package/fesm2022/ngwr-split-text.mjs +3 -3
- package/fesm2022/ngwr-splitter.mjs +4 -4
- package/fesm2022/ngwr-splitter.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card.mjs +7 -7
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +7 -7
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +4 -4
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +65 -10
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +8 -8
- package/fesm2022/ngwr-stepper.mjs.map +1 -1
- package/fesm2022/ngwr-storage.mjs +4 -4
- package/fesm2022/ngwr-storage.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +16 -48
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table.mjs +824 -20
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +9 -8
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +18 -50
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-theme.mjs +20 -5
- package/fesm2022/ngwr-theme.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +27 -11
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-timeline.mjs +7 -7
- package/fesm2022/ngwr-timeline.mjs.map +1 -1
- package/fesm2022/ngwr-toast.mjs +10 -10
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +4 -4
- package/fesm2022/ngwr-toolbar.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +280 -84
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +10 -5
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-typography.mjs +4 -4
- package/fesm2022/ngwr-typography.mjs.map +1 -1
- package/fesm2022/ngwr-validators.mjs +1 -1
- package/fesm2022/ngwr-validators.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +9 -7
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +6 -5
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +16 -15
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/file-upload/styles/_index.scss +11 -11
- package/form/styles/_index.scss +4 -4
- package/gauge/styles/_index.scss +2 -2
- package/glitch-text/styles/_index.scss +1 -1
- package/gradient-text/styles/_index.scss +1 -1
- package/image-cropper/styles/_index.scss +5 -4
- package/input/styles/_index.scss +9 -9
- package/input-number/styles/_index.scss +1 -1
- package/input-otp/styles/_index.scss +5 -5
- package/keyboard/styles/_index.scss +5 -5
- package/knob/styles/_index.scss +6 -2
- package/layout/styles/_index.scss +12 -12
- package/lightbox/styles/_index.scss +10 -8
- package/line-chart/styles/_index.scss +5 -5
- package/list/styles/_index.scss +3 -3
- package/llms-full.txt +31 -5
- package/llms.txt +48 -32
- package/marquee/styles/_index.scss +1 -1
- package/mention/styles/_index.scss +4 -4
- package/meter-group/styles/_index.scss +4 -4
- package/overlay/styles/_index.scss +8 -0
- package/package.json +21 -9
- package/page-header/styles/_index.scss +4 -4
- package/pagination/styles/_index.scss +3 -3
- package/popconfirm/styles/_index.scss +3 -3
- package/popover/styles/_index.scss +5 -5
- package/progress/styles/_index.scss +1 -1
- package/pull-to-refresh/styles/_index.scss +38 -0
- package/radio/styles/_index.scss +4 -4
- package/rating/styles/_index.scss +1 -1
- package/result/styles/_index.scss +3 -3
- package/schematics/migrations/v9/index.js +71 -0
- package/schematics/migrations.json +5 -0
- package/schematics/ng-add/schema.json +1 -1
- package/schematics/use/symbol-map.json +13 -0
- package/segmented/styles/_index.scss +4 -4
- package/select/styles/_index.scss +53 -18
- package/shiny-text/styles/_index.scss +4 -4
- package/sidebar/styles/_index.scss +12 -12
- package/slider/styles/_index.scss +5 -5
- package/speed-dial/styles/_index.scss +22 -6
- package/splash-cursor/styles/_index.scss +1 -0
- package/splitter/styles/_index.scss +7 -4
- package/spotlight-card/styles/_index.scss +7 -7
- package/star-border/styles/_index.scss +3 -3
- package/statistic/styles/_index.scss +51 -4
- package/stepper/styles/_index.scss +6 -6
- package/styles/_typography.scss +4 -1
- package/styles.scss +2 -0
- package/switch/styles/_index.scss +4 -4
- package/table/styles/_index.scss +447 -17
- package/tabs/styles/_index.scss +3 -3
- package/textarea/styles/_index.scss +7 -7
- package/theme/styles/_colors.scss +27 -3
- package/tilt-card/styles/_index.scss +4 -4
- package/timeline/styles/_index.scss +7 -6
- package/toast/styles/_index.scss +11 -11
- package/toolbar/styles/_index.scss +4 -4
- package/tree/styles/_index.scss +45 -15
- package/types/ngwr-action-sheet.d.ts +75 -0
- package/types/ngwr-alert.d.ts +1 -1
- package/types/ngwr-anchor.d.ts +1 -1
- package/types/ngwr-avatar.d.ts +1 -1
- package/types/ngwr-back-top.d.ts +1 -1
- package/types/ngwr-badge.d.ts +4 -4
- package/types/ngwr-bar-chart.d.ts +1 -1
- package/types/ngwr-breadcrumbs.d.ts +1 -1
- package/types/ngwr-burger.d.ts +1 -1
- package/types/ngwr-button.d.ts +3 -3
- package/types/ngwr-calendar-heatmap.d.ts +1 -1
- package/types/ngwr-calendar.d.ts +1 -1
- package/types/ngwr-card.d.ts +1 -1
- package/types/ngwr-carousel.d.ts +1 -1
- package/types/ngwr-cascader.d.ts +27 -16
- package/types/ngwr-checkbox.d.ts +63 -43
- package/types/ngwr-clipboard.d.ts +1 -1
- package/types/ngwr-collapse.d.ts +3 -3
- package/types/ngwr-color-picker.d.ts +24 -19
- package/types/ngwr-command-palette.d.ts +1 -1
- package/types/ngwr-compare.d.ts +1 -1
- package/types/ngwr-context-menu.d.ts +25 -1
- package/types/ngwr-cookie.d.ts +7 -1
- package/types/ngwr-counter.d.ts +9 -2
- package/types/ngwr-date-picker.d.ts +36 -23
- package/types/ngwr-density.d.ts +1 -1
- package/types/ngwr-descriptions.d.ts +1 -1
- package/types/ngwr-dialog.d.ts +1 -1
- package/types/ngwr-directives.d.ts +1 -0
- package/types/ngwr-divider.d.ts +2 -2
- package/types/ngwr-donut-chart.d.ts +1 -1
- package/types/ngwr-drag-drop.d.ts +1 -1
- package/types/ngwr-drawer.d.ts +1 -1
- package/types/ngwr-dropdown.d.ts +1 -1
- package/types/ngwr-empty.d.ts +1 -1
- package/types/ngwr-file-upload.d.ts +28 -17
- package/types/ngwr-form.d.ts +2 -2
- package/types/ngwr-gauge.d.ts +1 -1
- package/types/ngwr-hotkey.d.ts +1 -1
- package/types/ngwr-i18n.d.ts +1 -1
- package/types/ngwr-icon-adapters-lucide.d.ts +5 -3
- package/types/ngwr-icon.d.ts +1 -1
- package/types/ngwr-image-cropper.d.ts +1 -1
- package/types/ngwr-input-number.d.ts +25 -19
- package/types/ngwr-input-otp.d.ts +23 -17
- package/types/ngwr-input.d.ts +2 -2
- package/types/ngwr-keyboard.d.ts +1 -1
- package/types/ngwr-knob.d.ts +24 -19
- package/types/ngwr-layout.d.ts +1 -1
- package/types/ngwr-lightbox.d.ts +1 -1
- package/types/ngwr-line-chart.d.ts +1 -1
- package/types/ngwr-list.d.ts +1 -1
- package/types/ngwr-loading-bar.d.ts +1 -1
- package/types/ngwr-marquee.d.ts +1 -1
- package/types/ngwr-media.d.ts +1 -1
- package/types/ngwr-mention.d.ts +1 -1
- package/types/ngwr-meta.d.ts +1 -1
- package/types/ngwr-meter-group.d.ts +1 -1
- package/types/ngwr-page-header.d.ts +1 -1
- package/types/ngwr-pagination.d.ts +1 -1
- package/types/ngwr-platform.d.ts +93 -2
- package/types/ngwr-popconfirm.d.ts +3 -3
- package/types/ngwr-progress.d.ts +2 -2
- package/types/ngwr-pull-to-refresh.d.ts +69 -0
- package/types/ngwr-qr.d.ts +1 -1
- package/types/ngwr-radio.d.ts +25 -22
- package/types/ngwr-rating.d.ts +28 -20
- package/types/ngwr-result.d.ts +1 -1
- package/types/ngwr-rotating-text.d.ts +1 -0
- package/types/ngwr-scroll.d.ts +1 -1
- package/types/ngwr-segmented.d.ts +1 -1
- package/types/ngwr-select.d.ts +93 -26
- package/types/ngwr-sidebar.d.ts +1 -1
- package/types/ngwr-skeleton.d.ts +2 -2
- package/types/ngwr-slider.d.ts +35 -21
- package/types/ngwr-sparkline.d.ts +1 -1
- package/types/ngwr-speed-dial.d.ts +8 -2
- package/types/ngwr-spinner.d.ts +1 -1
- package/types/ngwr-splitter.d.ts +1 -1
- package/types/ngwr-squircle.d.ts +1 -1
- package/types/ngwr-statistic.d.ts +40 -5
- package/types/ngwr-stepper.d.ts +2 -2
- package/types/ngwr-storage.d.ts +1 -1
- package/types/ngwr-switch.d.ts +20 -16
- package/types/ngwr-table.d.ts +417 -6
- package/types/ngwr-tabs.d.ts +1 -1
- package/types/ngwr-textarea.d.ts +21 -18
- package/types/ngwr-theme.d.ts +7 -2
- package/types/ngwr-tilt-card.d.ts +3 -0
- package/types/ngwr-timeline.d.ts +1 -1
- package/types/ngwr-toast.d.ts +1 -1
- package/types/ngwr-toolbar.d.ts +1 -1
- package/types/ngwr-tree.d.ts +100 -19
- package/types/ngwr-typography.d.ts +1 -1
- package/types/ngwr-validators.d.ts +1 -1
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-virtual-scroll.d.ts +1 -1
- package/types/ngwr-window.d.ts +1 -1
- package/typography/styles/_index.scss +11 -11
- package/virtual-scroll/styles/_index.scss +1 -1
- package/waves/styles/_index.scss +1 -1
- package/window/styles/_index.scss +18 -18
|
@@ -104,7 +104,8 @@ class WrFallingText {
|
|
|
104
104
|
/** Font size as a CSS length. @default '1rem' */
|
|
105
105
|
fontSize = input('1rem', /* @ts-ignore */
|
|
106
106
|
...(ngDevMode ? [{ debugName: "fontSize" }] : /* istanbul ignore next */ []));
|
|
107
|
-
wordsRef = viewChild.required('wordsContainer'
|
|
107
|
+
wordsRef = viewChild.required('wordsContainer', /* @ts-ignore */
|
|
108
|
+
...(ngDevMode ? [{ debugName: "wordsRef" }] : /* istanbul ignore next */ []));
|
|
108
109
|
host = inject(ElementRef);
|
|
109
110
|
destroyRef = inject(DestroyRef);
|
|
110
111
|
isBrowser = isPlatformBrowser(inject(PLATFORM_ID));
|
|
@@ -300,10 +301,10 @@ class WrFallingText {
|
|
|
300
301
|
const rect = host.getBoundingClientRect();
|
|
301
302
|
return { x: e.clientX - rect.left, y: e.clientY - rect.top };
|
|
302
303
|
}
|
|
303
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0
|
|
304
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0
|
|
304
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFallingText, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
305
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrFallingText, isStandalone: true, selector: "wr-falling-text", inputs: { text: { classPropertyName: "text", publicName: "text", isSignal: true, isRequired: true, transformFunction: null }, highlightWords: { classPropertyName: "highlightWords", publicName: "highlightWords", isSignal: true, isRequired: false, transformFunction: null }, trigger: { classPropertyName: "trigger", publicName: "trigger", isSignal: true, isRequired: false, transformFunction: null }, gravity: { classPropertyName: "gravity", publicName: "gravity", isSignal: true, isRequired: false, transformFunction: null }, fontSize: { classPropertyName: "fontSize", publicName: "fontSize", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "wr-falling-text" }, viewQueries: [{ propertyName: "wordsRef", first: true, predicate: ["wordsContainer"], descendants: true, isSignal: true }], ngImport: i0, template: "<div #wordsContainer class=\"wr-falling-text__words\" [style.font-size]=\"fontSize()\">\n @for (w of words(); track $index) {\n <span class=\"wr-falling-text__word\" [class.wr-falling-text__word--hl]=\"w.highlighted\">{{ w.text }}</span>\n @if (!$last) {\n <span class=\"wr-falling-text__space\"> </span>\n }\n }\n</div>\n", styles: [".wr-falling-text{position:relative;display:block;overflow:hidden;touch-action:none}.wr-falling-text__words{line-height:1.4}.wr-falling-text__word{display:inline-block;will-change:transform;-webkit-user-select:none;user-select:none;cursor:grab}.wr-falling-text__word:active{cursor:grabbing}.wr-falling-text__word--hl{color:var(--wr-color-primary)}.wr-falling-text__space{display:inline;white-space:pre}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
305
306
|
}
|
|
306
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0
|
|
307
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFallingText, decorators: [{
|
|
307
308
|
type: Component,
|
|
308
309
|
args: [{ selector: 'wr-falling-text', encapsulation: ViewEncapsulation.None, host: { class: 'wr-falling-text' }, template: "<div #wordsContainer class=\"wr-falling-text__words\" [style.font-size]=\"fontSize()\">\n @for (w of words(); track $index) {\n <span class=\"wr-falling-text__word\" [class.wr-falling-text__word--hl]=\"w.highlighted\">{{ w.text }}</span>\n @if (!$last) {\n <span class=\"wr-falling-text__space\"> </span>\n }\n }\n</div>\n", styles: [".wr-falling-text{position:relative;display:block;overflow:hidden;touch-action:none}.wr-falling-text__words{line-height:1.4}.wr-falling-text__word{display:inline-block;will-change:transform;-webkit-user-select:none;user-select:none;cursor:grab}.wr-falling-text__word:active{cursor:grabbing}.wr-falling-text__word--hl{color:var(--wr-color-primary)}.wr-falling-text__space{display:inline;white-space:pre}\n"] }]
|
|
309
310
|
}], ctorParameters: () => [], propDecorators: { text: [{ type: i0.Input, args: [{ isSignal: true, alias: "text", required: true }] }], highlightWords: [{ type: i0.Input, args: [{ isSignal: true, alias: "highlightWords", required: false }] }], trigger: [{ type: i0.Input, args: [{ isSignal: true, alias: "trigger", required: false }] }], gravity: [{ type: i0.Input, args: [{ isSignal: true, alias: "gravity", required: false }] }], fontSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "fontSize", required: false }] }], wordsRef: [{ type: i0.ViewChild, args: ['wordsContainer', { isSignal: true }] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-falling-text.mjs","sources":["../../../projects/lib/falling-text/falling-text.ts","../../../projects/lib/falling-text/falling-text.html","../../../projects/lib/falling-text/ngwr-falling-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 FallingText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/falling-text\n *\n * The reactbits version uses matter-js (~140 KB) for the physics. This\n * port ships a minimal AABB physics simulator (gravity + air drag + wall\n * / floor collision + body-vs-body resolution + cursor drag) so there's\n * no runtime dependency.\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n inject,\n input,\n viewChild,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrFallingTextTrigger } from './interfaces';\n\ninterface Body {\n el: HTMLElement;\n x: number; // centre x\n y: number; // centre y\n vx: number;\n vy: number;\n angle: number;\n angVel: number;\n w: number;\n h: number;\n}\n\nconst RESTITUTION = 0.55;\nconst AIR_DRAG = 0.005;\nconst FRICTION = 0.4; // tangential damping on wall/floor hits\nconst DRAG_STIFFNESS = 0.6;\n\n/** Resolve AABB-vs-AABB collision between two bodies via min-overlap axis. */\nfunction resolveCollision(a: Body, b: Body): void {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const overlapX = a.w / 2 + b.w / 2 - Math.abs(dx);\n const overlapY = a.h / 2 + b.h / 2 - Math.abs(dy);\n if (overlapX <= 0 || overlapY <= 0) return;\n\n if (overlapX < overlapY) {\n // Resolve along x.\n const push = overlapX / 2;\n if (dx > 0) {\n a.x -= push;\n b.x += push;\n } else {\n a.x += push;\n b.x -= push;\n }\n const avg = (a.vx + b.vx) / 2;\n a.vx = avg * RESTITUTION - (a.vx - avg) * RESTITUTION;\n b.vx = avg * RESTITUTION - (b.vx - avg) * RESTITUTION;\n } else {\n const push = overlapY / 2;\n if (dy > 0) {\n a.y -= push;\n b.y += push;\n } else {\n a.y += push;\n b.y -= push;\n }\n const avg = (a.vy + b.vy) / 2;\n a.vy = avg * RESTITUTION - (a.vy - avg) * RESTITUTION;\n b.vy = avg * RESTITUTION - (b.vy - avg) * RESTITUTION;\n }\n\n // Tiny torque so stacked bodies wiggle naturally.\n a.angVel += (Math.random() - 0.5) * 0.2;\n b.angVel += (Math.random() - 0.5) * 0.2;\n}\n\n/**\n * Words fall like physical bodies — gravity, wall/floor collision, and\n * cursor drag-to-pick-up. Words start at their typeset position then\n * release into the simulator on trigger.\n *\n * Triggers:\n * - `'auto'` release immediately on mount\n * - `'scroll'` release on viewport entry\n * - `'hover'` release on first hover\n * - `'click'` release on first click\n *\n * Highlight specific words by passing prefix-matched keywords via\n * `[highlightWords]` — matched spans get `wr-falling-text__word--hl`.\n *\n * @example\n * ```html\n * <wr-falling-text\n * text=\"React-Bits is a library of animated and interactive React components.\"\n * [highlightWords]=\"['React', 'animated', 'components']\"\n * trigger=\"hover\"\n * [gravity]=\"0.6\"\n * />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/falling-text\n */\n@Component({\n selector: 'wr-falling-text',\n templateUrl: './falling-text.html',\n styleUrl: './falling-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-falling-text' },\n})\nexport class WrFallingText {\n /** Text to render. Words are separated by spaces. */\n readonly text = input.required<string>();\n\n /** Prefix-match keywords; any word starting with one of these gets the highlight class. */\n readonly highlightWords = input<readonly string[]>([]);\n\n /** When to release the words into the simulator. @default 'auto' */\n readonly trigger = input<WrFallingTextTrigger>('auto');\n\n /** Gravity in pixels/sec². @default 980 */\n readonly gravity = input(980, { transform: numAttr(980) });\n\n /** Font size as a CSS length. @default '1rem' */\n readonly fontSize = input('1rem');\n\n private readonly wordsRef = viewChild.required<ElementRef<HTMLDivElement>>('wordsContainer');\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 started = false;\n private teardownLoop: (() => void) | undefined;\n\n protected readonly words = computed<readonly { text: string; highlighted: boolean }[]>(() => {\n const hl = this.highlightWords();\n return this.text()\n .split(' ')\n .filter(w => w.length > 0)\n .map(text => ({ text, highlighted: hl.some(h => text.startsWith(h)) }));\n });\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const trigger = this.trigger();\n if (trigger === 'auto') {\n this.start();\n return;\n }\n if (trigger === 'scroll') {\n const io = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting) {\n obs.disconnect();\n this.start();\n break;\n }\n }\n },\n { threshold: 0.1 }\n );\n io.observe(this.host.nativeElement);\n this.destroyRef.onDestroy(() => io.disconnect());\n return;\n }\n // hover / click — wait for host event\n const startOnce = (): void => {\n if (this.started) return;\n this.start();\n };\n const handler = trigger === 'hover' ? 'mouseenter' : 'click';\n this.host.nativeElement.addEventListener(handler, startOnce, { once: true });\n this.destroyRef.onDestroy(() => this.host.nativeElement.removeEventListener(handler, startOnce));\n });\n\n this.destroyRef.onDestroy(() => this.teardownLoop?.());\n }\n\n // Physics\n\n private start(): void {\n if (this.started) return;\n // Reduced motion: tumbling words are pure decoration — leave the\n // text standing in its normal layout no matter the trigger.\n if (this.platform.prefersReducedMotion()) return;\n this.started = true;\n\n const hostEl = this.host.nativeElement;\n const wordsContainer = this.wordsRef().nativeElement;\n const containerRect = hostEl.getBoundingClientRect();\n const width = containerRect.width;\n const height = containerRect.height;\n if (width <= 0 || height <= 0) return;\n\n // Snapshot each word's position relative to the container, then absolutise.\n const wordEls = Array.from(wordsContainer.querySelectorAll<HTMLElement>('.wr-falling-text__word'));\n if (wordEls.length === 0) return;\n\n const bodies: Body[] = wordEls.map(el => {\n const r = el.getBoundingClientRect();\n const cx = r.left - containerRect.left + r.width / 2;\n const cy = r.top - containerRect.top + r.height / 2;\n return {\n el,\n x: cx,\n y: cy,\n vx: (Math.random() - 0.5) * 5 * 60, // px/s\n vy: 0,\n angle: 0,\n angVel: (Math.random() - 0.5) * 2,\n w: r.width,\n h: r.height,\n };\n });\n\n // Absolutely position all word spans so we can move them freely.\n bodies.forEach(b => {\n b.el.style.position = 'absolute';\n b.el.style.left = '0';\n b.el.style.top = '0';\n b.el.style.willChange = 'transform';\n this.commit(b);\n });\n\n // Drag state.\n let drag: { body: Body; offX: number; offY: number } | null = null;\n\n const onPointerDown = (e: PointerEvent): void => {\n const local = this.toLocal(e, hostEl);\n // Pick the topmost (last) body whose AABB contains the pointer.\n for (let i = bodies.length - 1; i >= 0; i--) {\n const b = bodies[i];\n if (\n local.x >= b.x - b.w / 2 &&\n local.x <= b.x + b.w / 2 &&\n local.y >= b.y - b.h / 2 &&\n local.y <= b.y + b.h / 2\n ) {\n drag = { body: b, offX: local.x - b.x, offY: local.y - b.y };\n hostEl.setPointerCapture(e.pointerId);\n break;\n }\n }\n };\n const onPointerMove = (e: PointerEvent): void => {\n if (!drag) return;\n const local = this.toLocal(e, hostEl);\n const targetX = local.x - drag.offX;\n const targetY = local.y - drag.offY;\n // Spring toward the target — produces a satisfying tug rather than a snap.\n drag.body.vx += (targetX - drag.body.x) * DRAG_STIFFNESS;\n drag.body.vy += (targetY - drag.body.y) * DRAG_STIFFNESS;\n };\n const onPointerUp = (e: PointerEvent): void => {\n if (!drag) return;\n hostEl.releasePointerCapture(e.pointerId);\n drag = null;\n };\n hostEl.addEventListener('pointerdown', onPointerDown);\n hostEl.addEventListener('pointermove', onPointerMove);\n hostEl.addEventListener('pointerup', onPointerUp);\n hostEl.addEventListener('pointercancel', onPointerUp);\n\n let raf = 0;\n let lastTs = 0;\n const tick = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const g = this.gravity();\n for (const b of bodies) {\n // Integrate.\n b.vy += g * dt;\n b.vx *= 1 - AIR_DRAG;\n b.vy *= 1 - AIR_DRAG;\n b.x += b.vx * dt;\n b.y += b.vy * dt;\n b.angle += b.angVel * dt;\n b.angVel *= 1 - AIR_DRAG;\n\n // Walls + floor + ceiling.\n if (b.x - b.w / 2 < 0) {\n b.x = b.w / 2;\n b.vx = Math.abs(b.vx) * RESTITUTION;\n b.angVel *= FRICTION;\n }\n if (b.x + b.w / 2 > width) {\n b.x = width - b.w / 2;\n b.vx = -Math.abs(b.vx) * RESTITUTION;\n b.angVel *= FRICTION;\n }\n if (b.y + b.h / 2 > height) {\n b.y = height - b.h / 2;\n b.vy = -Math.abs(b.vy) * RESTITUTION;\n b.vx *= FRICTION;\n b.angVel *= FRICTION;\n }\n if (b.y - b.h / 2 < 0) {\n b.y = b.h / 2;\n b.vy = Math.abs(b.vy) * RESTITUTION;\n }\n }\n\n // Body-vs-body collisions — O(n²), fine for ~30 words.\n for (let i = 0; i < bodies.length; i++) {\n for (let j = i + 1; j < bodies.length; j++) {\n resolveCollision(bodies[i], bodies[j]);\n }\n }\n\n for (const b of bodies) this.commit(b);\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n\n this.teardownLoop = (): void => {\n cancelAnimationFrame(raf);\n hostEl.removeEventListener('pointerdown', onPointerDown);\n hostEl.removeEventListener('pointermove', onPointerMove);\n hostEl.removeEventListener('pointerup', onPointerUp);\n hostEl.removeEventListener('pointercancel', onPointerUp);\n };\n }\n\n /** Apply the body's position + angle to the DOM. */\n private commit(b: Body): void {\n b.el.style.transform = `translate(${b.x - b.w / 2}px, ${b.y - b.h / 2}px) rotate(${b.angle}rad)`;\n b.el.style.transformOrigin = `${b.w / 2}px ${b.h / 2}px`;\n }\n\n private toLocal(e: PointerEvent | MouseEvent, host: HTMLElement): { x: number; y: number } {\n const rect = host.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n}\n\nexport type { WrFallingTextTrigger } from './interfaces';\n","<div #wordsContainer class=\"wr-falling-text__words\" [style.font-size]=\"fontSize()\">\n @for (w of words(); track $index) {\n <span class=\"wr-falling-text__word\" [class.wr-falling-text__word--hl]=\"w.highlighted\">{{ w.text }}</span>\n @if (!$last) {\n <span class=\"wr-falling-text__space\"> </span>\n }\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-falling-text.mjs","sources":["../../../projects/lib/falling-text/falling-text.ts","../../../projects/lib/falling-text/falling-text.html","../../../projects/lib/falling-text/ngwr-falling-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 FallingText effect by David Haz / reactbits.dev.\n * Original: https://www.reactbits.dev/text-animations/falling-text\n *\n * The reactbits version uses matter-js (~140 KB) for the physics. This\n * port ships a minimal AABB physics simulator (gravity + air drag + wall\n * / floor collision + body-vs-body resolution + cursor drag) so there's\n * no runtime dependency.\n */\n\nimport { isPlatformBrowser } from '@angular/common';\nimport {\n Component,\n DestroyRef,\n ElementRef,\n PLATFORM_ID,\n ViewEncapsulation,\n afterNextRender,\n computed,\n inject,\n input,\n viewChild,\n} from '@angular/core';\n\nimport { WrPlatform } from 'ngwr/platform';\nimport { numAttr } from 'ngwr/utils';\n\nimport type { WrFallingTextTrigger } from './interfaces';\n\ninterface Body {\n el: HTMLElement;\n x: number; // centre x\n y: number; // centre y\n vx: number;\n vy: number;\n angle: number;\n angVel: number;\n w: number;\n h: number;\n}\n\nconst RESTITUTION = 0.55;\nconst AIR_DRAG = 0.005;\nconst FRICTION = 0.4; // tangential damping on wall/floor hits\nconst DRAG_STIFFNESS = 0.6;\n\n/** Resolve AABB-vs-AABB collision between two bodies via min-overlap axis. */\nfunction resolveCollision(a: Body, b: Body): void {\n const dx = b.x - a.x;\n const dy = b.y - a.y;\n const overlapX = a.w / 2 + b.w / 2 - Math.abs(dx);\n const overlapY = a.h / 2 + b.h / 2 - Math.abs(dy);\n if (overlapX <= 0 || overlapY <= 0) return;\n\n if (overlapX < overlapY) {\n // Resolve along x.\n const push = overlapX / 2;\n if (dx > 0) {\n a.x -= push;\n b.x += push;\n } else {\n a.x += push;\n b.x -= push;\n }\n const avg = (a.vx + b.vx) / 2;\n a.vx = avg * RESTITUTION - (a.vx - avg) * RESTITUTION;\n b.vx = avg * RESTITUTION - (b.vx - avg) * RESTITUTION;\n } else {\n const push = overlapY / 2;\n if (dy > 0) {\n a.y -= push;\n b.y += push;\n } else {\n a.y += push;\n b.y -= push;\n }\n const avg = (a.vy + b.vy) / 2;\n a.vy = avg * RESTITUTION - (a.vy - avg) * RESTITUTION;\n b.vy = avg * RESTITUTION - (b.vy - avg) * RESTITUTION;\n }\n\n // Tiny torque so stacked bodies wiggle naturally.\n a.angVel += (Math.random() - 0.5) * 0.2;\n b.angVel += (Math.random() - 0.5) * 0.2;\n}\n\n/**\n * Words fall like physical bodies — gravity, wall/floor collision, and\n * cursor drag-to-pick-up. Words start at their typeset position then\n * release into the simulator on trigger.\n *\n * Triggers:\n * - `'auto'` release immediately on mount\n * - `'scroll'` release on viewport entry\n * - `'hover'` release on first hover\n * - `'click'` release on first click\n *\n * Highlight specific words by passing prefix-matched keywords via\n * `[highlightWords]` — matched spans get `wr-falling-text__word--hl`.\n *\n * @example\n * ```html\n * <wr-falling-text\n * text=\"React-Bits is a library of animated and interactive React components.\"\n * [highlightWords]=\"['React', 'animated', 'components']\"\n * trigger=\"hover\"\n * [gravity]=\"0.6\"\n * />\n * ```\n *\n * @see https://www.reactbits.dev/text-animations/falling-text\n */\n@Component({\n selector: 'wr-falling-text',\n templateUrl: './falling-text.html',\n styleUrl: './falling-text.scss',\n encapsulation: ViewEncapsulation.None,\n host: { class: 'wr-falling-text' },\n})\nexport class WrFallingText {\n /** Text to render. Words are separated by spaces. */\n readonly text = input.required<string>();\n\n /** Prefix-match keywords; any word starting with one of these gets the highlight class. */\n readonly highlightWords = input<readonly string[]>([]);\n\n /** When to release the words into the simulator. @default 'auto' */\n readonly trigger = input<WrFallingTextTrigger>('auto');\n\n /** Gravity in pixels/sec². @default 980 */\n readonly gravity = input(980, { transform: numAttr(980) });\n\n /** Font size as a CSS length. @default '1rem' */\n readonly fontSize = input('1rem');\n\n private readonly wordsRef = viewChild.required<ElementRef<HTMLDivElement>>('wordsContainer');\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 started = false;\n private teardownLoop: (() => void) | undefined;\n\n protected readonly words = computed<readonly { text: string; highlighted: boolean }[]>(() => {\n const hl = this.highlightWords();\n return this.text()\n .split(' ')\n .filter(w => w.length > 0)\n .map(text => ({ text, highlighted: hl.some(h => text.startsWith(h)) }));\n });\n\n constructor() {\n if (!this.isBrowser) return;\n\n afterNextRender(() => {\n const trigger = this.trigger();\n if (trigger === 'auto') {\n this.start();\n return;\n }\n if (trigger === 'scroll') {\n const io = new IntersectionObserver(\n (entries, obs) => {\n for (const e of entries) {\n if (e.isIntersecting) {\n obs.disconnect();\n this.start();\n break;\n }\n }\n },\n { threshold: 0.1 }\n );\n io.observe(this.host.nativeElement);\n this.destroyRef.onDestroy(() => io.disconnect());\n return;\n }\n // hover / click — wait for host event\n const startOnce = (): void => {\n if (this.started) return;\n this.start();\n };\n const handler = trigger === 'hover' ? 'mouseenter' : 'click';\n this.host.nativeElement.addEventListener(handler, startOnce, { once: true });\n this.destroyRef.onDestroy(() => this.host.nativeElement.removeEventListener(handler, startOnce));\n });\n\n this.destroyRef.onDestroy(() => this.teardownLoop?.());\n }\n\n // Physics\n\n private start(): void {\n if (this.started) return;\n // Reduced motion: tumbling words are pure decoration — leave the\n // text standing in its normal layout no matter the trigger.\n if (this.platform.prefersReducedMotion()) return;\n this.started = true;\n\n const hostEl = this.host.nativeElement;\n const wordsContainer = this.wordsRef().nativeElement;\n const containerRect = hostEl.getBoundingClientRect();\n const width = containerRect.width;\n const height = containerRect.height;\n if (width <= 0 || height <= 0) return;\n\n // Snapshot each word's position relative to the container, then absolutise.\n const wordEls = Array.from(wordsContainer.querySelectorAll<HTMLElement>('.wr-falling-text__word'));\n if (wordEls.length === 0) return;\n\n const bodies: Body[] = wordEls.map(el => {\n const r = el.getBoundingClientRect();\n const cx = r.left - containerRect.left + r.width / 2;\n const cy = r.top - containerRect.top + r.height / 2;\n return {\n el,\n x: cx,\n y: cy,\n vx: (Math.random() - 0.5) * 5 * 60, // px/s\n vy: 0,\n angle: 0,\n angVel: (Math.random() - 0.5) * 2,\n w: r.width,\n h: r.height,\n };\n });\n\n // Absolutely position all word spans so we can move them freely.\n bodies.forEach(b => {\n b.el.style.position = 'absolute';\n b.el.style.left = '0';\n b.el.style.top = '0';\n b.el.style.willChange = 'transform';\n this.commit(b);\n });\n\n // Drag state.\n let drag: { body: Body; offX: number; offY: number } | null = null;\n\n const onPointerDown = (e: PointerEvent): void => {\n const local = this.toLocal(e, hostEl);\n // Pick the topmost (last) body whose AABB contains the pointer.\n for (let i = bodies.length - 1; i >= 0; i--) {\n const b = bodies[i];\n if (\n local.x >= b.x - b.w / 2 &&\n local.x <= b.x + b.w / 2 &&\n local.y >= b.y - b.h / 2 &&\n local.y <= b.y + b.h / 2\n ) {\n drag = { body: b, offX: local.x - b.x, offY: local.y - b.y };\n hostEl.setPointerCapture(e.pointerId);\n break;\n }\n }\n };\n const onPointerMove = (e: PointerEvent): void => {\n if (!drag) return;\n const local = this.toLocal(e, hostEl);\n const targetX = local.x - drag.offX;\n const targetY = local.y - drag.offY;\n // Spring toward the target — produces a satisfying tug rather than a snap.\n drag.body.vx += (targetX - drag.body.x) * DRAG_STIFFNESS;\n drag.body.vy += (targetY - drag.body.y) * DRAG_STIFFNESS;\n };\n const onPointerUp = (e: PointerEvent): void => {\n if (!drag) return;\n hostEl.releasePointerCapture(e.pointerId);\n drag = null;\n };\n hostEl.addEventListener('pointerdown', onPointerDown);\n hostEl.addEventListener('pointermove', onPointerMove);\n hostEl.addEventListener('pointerup', onPointerUp);\n hostEl.addEventListener('pointercancel', onPointerUp);\n\n let raf = 0;\n let lastTs = 0;\n const tick = (ts: number): void => {\n const dt = lastTs === 0 ? 1 / 60 : Math.min(0.05, (ts - lastTs) / 1000);\n lastTs = ts;\n\n const g = this.gravity();\n for (const b of bodies) {\n // Integrate.\n b.vy += g * dt;\n b.vx *= 1 - AIR_DRAG;\n b.vy *= 1 - AIR_DRAG;\n b.x += b.vx * dt;\n b.y += b.vy * dt;\n b.angle += b.angVel * dt;\n b.angVel *= 1 - AIR_DRAG;\n\n // Walls + floor + ceiling.\n if (b.x - b.w / 2 < 0) {\n b.x = b.w / 2;\n b.vx = Math.abs(b.vx) * RESTITUTION;\n b.angVel *= FRICTION;\n }\n if (b.x + b.w / 2 > width) {\n b.x = width - b.w / 2;\n b.vx = -Math.abs(b.vx) * RESTITUTION;\n b.angVel *= FRICTION;\n }\n if (b.y + b.h / 2 > height) {\n b.y = height - b.h / 2;\n b.vy = -Math.abs(b.vy) * RESTITUTION;\n b.vx *= FRICTION;\n b.angVel *= FRICTION;\n }\n if (b.y - b.h / 2 < 0) {\n b.y = b.h / 2;\n b.vy = Math.abs(b.vy) * RESTITUTION;\n }\n }\n\n // Body-vs-body collisions — O(n²), fine for ~30 words.\n for (let i = 0; i < bodies.length; i++) {\n for (let j = i + 1; j < bodies.length; j++) {\n resolveCollision(bodies[i], bodies[j]);\n }\n }\n\n for (const b of bodies) this.commit(b);\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n\n this.teardownLoop = (): void => {\n cancelAnimationFrame(raf);\n hostEl.removeEventListener('pointerdown', onPointerDown);\n hostEl.removeEventListener('pointermove', onPointerMove);\n hostEl.removeEventListener('pointerup', onPointerUp);\n hostEl.removeEventListener('pointercancel', onPointerUp);\n };\n }\n\n /** Apply the body's position + angle to the DOM. */\n private commit(b: Body): void {\n b.el.style.transform = `translate(${b.x - b.w / 2}px, ${b.y - b.h / 2}px) rotate(${b.angle}rad)`;\n b.el.style.transformOrigin = `${b.w / 2}px ${b.h / 2}px`;\n }\n\n private toLocal(e: PointerEvent | MouseEvent, host: HTMLElement): { x: number; y: number } {\n const rect = host.getBoundingClientRect();\n return { x: e.clientX - rect.left, y: e.clientY - rect.top };\n }\n}\n\nexport type { WrFallingTextTrigger } from './interfaces';\n","<div #wordsContainer class=\"wr-falling-text__words\" [style.font-size]=\"fontSize()\">\n @for (w of words(); track $index) {\n <span class=\"wr-falling-text__word\" [class.wr-falling-text__word--hl]=\"w.highlighted\">{{ w.text }}</span>\n @if (!$last) {\n <span class=\"wr-falling-text__space\"> </span>\n }\n }\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { input, output, viewChild, signal, computed,
|
|
4
|
-
import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
3
|
+
import { input, model, output, viewChild, signal, computed, effect, untracked, ViewEncapsulation, Component } from '@angular/core';
|
|
5
4
|
import { useI18nText } from 'ngwr/i18n';
|
|
6
|
-
import { noop } from 'ngwr/utils';
|
|
7
5
|
|
|
8
6
|
/**
|
|
9
7
|
* @license
|
|
@@ -44,16 +42,22 @@ function matchesAccept(file, accept) {
|
|
|
44
42
|
* Drag-and-drop file upload zone. Click to browse, drag-and-drop to add,
|
|
45
43
|
* with an optional file list + remove buttons.
|
|
46
44
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
45
|
+
* A signal-forms native control: it implements
|
|
46
|
+
* `FormValueControl<File | readonly File[] | null>`, so `[formField]` binds
|
|
47
|
+
* straight to its `value` model — no `ControlValueAccessor` in between.
|
|
48
|
+
* `[(value)]` works standalone. The value shape follows `multiple`: a single
|
|
49
|
+
* `File` (or `null`), or a `File[]` array.
|
|
49
50
|
*
|
|
50
51
|
* @example
|
|
51
52
|
* ```html
|
|
52
|
-
*
|
|
53
|
-
* <wr-file-upload [
|
|
53
|
+
* <!-- signal forms -->
|
|
54
|
+
* <wr-file-upload [formField]="form.files" [multiple]="true" accept="image/*" />
|
|
55
|
+
*
|
|
56
|
+
* <!-- standalone two-way binding -->
|
|
57
|
+
* <wr-file-upload [(value)]="avatar" accept=".png,.jpg" [maxSize]="2 * 1024 * 1024" />
|
|
54
58
|
* ```
|
|
55
59
|
*
|
|
56
|
-
* @see https://ngwr.dev/components/file-upload
|
|
60
|
+
* @see https://ngwr.dev/reference/components/file-upload
|
|
57
61
|
*/
|
|
58
62
|
class WrFileUpload {
|
|
59
63
|
/** Allow multiple files. Single mode replaces on each add. @default false */
|
|
@@ -67,7 +71,12 @@ class WrFileUpload {
|
|
|
67
71
|
maxFiles = input(0, { ...(ngDevMode ? { debugName: "maxFiles" } : /* istanbul ignore next */ {}), transform: (v) => Math.max(0, coerceNumberProperty(v, 0)) });
|
|
68
72
|
/** Render the picked-files list below the zone. @default true */
|
|
69
73
|
showList = input(true, { ...(ngDevMode ? { debugName: "showList" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
70
|
-
/**
|
|
74
|
+
/**
|
|
75
|
+
* Disable interaction. Bound automatically from the field's disabled state
|
|
76
|
+
* when used with `[formField]`.
|
|
77
|
+
*
|
|
78
|
+
* @default false
|
|
79
|
+
*/
|
|
71
80
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: coerceBooleanProperty });
|
|
72
81
|
/** Primary call-to-action label. Falls back to `fileUpload.browse`. */
|
|
73
82
|
pickLabel = input(null, /* @ts-ignore */
|
|
@@ -88,49 +97,52 @@ class WrFileUpload {
|
|
|
88
97
|
/** Optional helper text shown below the labels (e.g. accepted formats). */
|
|
89
98
|
helperText = input('', /* @ts-ignore */
|
|
90
99
|
...(ngDevMode ? [{ debugName: "helperText" }] : /* istanbul ignore next */ []));
|
|
100
|
+
/**
|
|
101
|
+
* Selected file(s). Bound by `[formField]`, or two-way via `[(value)]`. Shape
|
|
102
|
+
* follows `multiple`: a single `File` (or `null`), or a `File[]` array.
|
|
103
|
+
*/
|
|
104
|
+
value = model(null, /* @ts-ignore */
|
|
105
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
91
106
|
/** Emitted when files are rejected for type / size / count reasons. */
|
|
92
107
|
rejected = output();
|
|
93
|
-
|
|
108
|
+
/** Emitted on commit so a bound field can mark itself touched. */
|
|
109
|
+
touch = output();
|
|
110
|
+
picker = viewChild.required('picker', /* @ts-ignore */
|
|
111
|
+
...(ngDevMode ? [{ debugName: "picker" }] : /* istanbul ignore next */ []));
|
|
94
112
|
files = signal([], /* @ts-ignore */
|
|
95
113
|
...(ngDevMode ? [{ debugName: "files" }] : /* istanbul ignore next */ []));
|
|
96
114
|
dragging = signal(false, /* @ts-ignore */
|
|
97
115
|
...(ngDevMode ? [{ debugName: "dragging" }] : /* istanbul ignore next */ []));
|
|
98
|
-
disabledFromCva = signal(false, /* @ts-ignore */
|
|
99
|
-
...(ngDevMode ? [{ debugName: "disabledFromCva" }] : /* istanbul ignore next */ []));
|
|
100
|
-
effectiveDisabled = computed(() => this.disabled() || this.disabledFromCva(), /* @ts-ignore */
|
|
101
|
-
...(ngDevMode ? [{ debugName: "effectiveDisabled" }] : /* istanbul ignore next */ []));
|
|
102
116
|
classes = computed(() => {
|
|
103
117
|
const parts = ['wr-file-upload'];
|
|
104
118
|
if (this.dragging())
|
|
105
119
|
parts.push('wr-file-upload--dragging');
|
|
106
|
-
if (this.
|
|
120
|
+
if (this.disabled())
|
|
107
121
|
parts.push('wr-file-upload--disabled');
|
|
108
122
|
return parts.join(' ');
|
|
109
123
|
}, /* @ts-ignore */
|
|
110
124
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
111
125
|
formatBytes = formatBytes;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
setDisabledState(isDisabled) {
|
|
129
|
-
this.disabledFromCva.set(coerceBooleanProperty(isDisabled));
|
|
126
|
+
constructor() {
|
|
127
|
+
// Rebuild the internal file list from an external `value` write (mirrors the
|
|
128
|
+
// old `writeValue`). Skipped when the value is merely the echo of an
|
|
129
|
+
// in-component edit, so re-syncing can never clobber a live selection.
|
|
130
|
+
effect(() => {
|
|
131
|
+
const v = this.value();
|
|
132
|
+
untracked(() => {
|
|
133
|
+
// Coerce null/undefined to `[]` — a classic-forms binding can write
|
|
134
|
+
// null, which the old `writeValue(v: … | null)` accepted too.
|
|
135
|
+
const next = v === null || v === undefined ? [] : Array.isArray(v) ? v : [v];
|
|
136
|
+
const current = this.files();
|
|
137
|
+
if (current.length === next.length && current.every((file, i) => file === next[i]))
|
|
138
|
+
return;
|
|
139
|
+
this.files.set(next);
|
|
140
|
+
});
|
|
141
|
+
});
|
|
130
142
|
}
|
|
131
143
|
// Template handlers
|
|
132
144
|
openPicker() {
|
|
133
|
-
if (this.
|
|
145
|
+
if (this.disabled())
|
|
134
146
|
return;
|
|
135
147
|
this.picker().nativeElement.click();
|
|
136
148
|
}
|
|
@@ -148,13 +160,13 @@ class WrFileUpload {
|
|
|
148
160
|
target.value = '';
|
|
149
161
|
}
|
|
150
162
|
onDragEnter(event) {
|
|
151
|
-
if (this.
|
|
163
|
+
if (this.disabled())
|
|
152
164
|
return;
|
|
153
165
|
event.preventDefault();
|
|
154
166
|
this.dragging.set(true);
|
|
155
167
|
}
|
|
156
168
|
onDragOver(event) {
|
|
157
|
-
if (this.
|
|
169
|
+
if (this.disabled())
|
|
158
170
|
return;
|
|
159
171
|
event.preventDefault();
|
|
160
172
|
if (event.dataTransfer)
|
|
@@ -168,14 +180,14 @@ class WrFileUpload {
|
|
|
168
180
|
onDrop(event) {
|
|
169
181
|
event.preventDefault();
|
|
170
182
|
this.dragging.set(false);
|
|
171
|
-
if (this.
|
|
183
|
+
if (this.disabled())
|
|
172
184
|
return;
|
|
173
185
|
const dropped = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];
|
|
174
186
|
if (dropped.length > 0)
|
|
175
187
|
this.acceptFiles(dropped);
|
|
176
188
|
}
|
|
177
189
|
removeAt(index) {
|
|
178
|
-
if (this.
|
|
190
|
+
if (this.disabled())
|
|
179
191
|
return;
|
|
180
192
|
const next = this.files().filter((_, i) => i !== index);
|
|
181
193
|
this.files.set(next);
|
|
@@ -209,7 +221,7 @@ class WrFileUpload {
|
|
|
209
221
|
next = accepted.length > 0 ? [accepted[accepted.length - 1]] : [...this.files()];
|
|
210
222
|
}
|
|
211
223
|
this.files.set(next);
|
|
212
|
-
this.
|
|
224
|
+
this.touch.emit();
|
|
213
225
|
this.emit();
|
|
214
226
|
if (rejections.length > 0)
|
|
215
227
|
this.rejected.emit(rejections);
|
|
@@ -224,33 +236,19 @@ class WrFileUpload {
|
|
|
224
236
|
emit() {
|
|
225
237
|
const list = this.files();
|
|
226
238
|
if (this.multiple()) {
|
|
227
|
-
this.
|
|
239
|
+
this.value.set(list);
|
|
228
240
|
}
|
|
229
241
|
else {
|
|
230
|
-
this.
|
|
242
|
+
this.value.set(list.length > 0 ? list[0] : null);
|
|
231
243
|
}
|
|
232
244
|
}
|
|
233
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0
|
|
234
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0
|
|
235
|
-
{
|
|
236
|
-
provide: NG_VALUE_ACCESSOR,
|
|
237
|
-
// eslint-disable-next-line @angular-eslint/no-forward-ref
|
|
238
|
-
useExisting: forwardRef(() => WrFileUpload),
|
|
239
|
-
multi: true,
|
|
240
|
-
},
|
|
241
|
-
], viewQueries: [{ propertyName: "picker", first: true, predicate: ["picker"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"effectiveDisabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"effectiveDisabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"effectiveDisabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
245
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFileUpload, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
246
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrFileUpload, isStandalone: true, selector: "wr-file-upload", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, accept: { classPropertyName: "accept", publicName: "accept", isSignal: true, isRequired: false, transformFunction: null }, maxSize: { classPropertyName: "maxSize", publicName: "maxSize", isSignal: true, isRequired: false, transformFunction: null }, maxFiles: { classPropertyName: "maxFiles", publicName: "maxFiles", isSignal: true, isRequired: false, transformFunction: null }, showList: { classPropertyName: "showList", publicName: "showList", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, pickLabel: { classPropertyName: "pickLabel", publicName: "pickLabel", isSignal: true, isRequired: false, transformFunction: null }, dropLabel: { classPropertyName: "dropLabel", publicName: "dropLabel", isSignal: true, isRequired: false, transformFunction: null }, dropZoneLabel: { classPropertyName: "dropZoneLabel", publicName: "dropZoneLabel", isSignal: true, isRequired: false, transformFunction: null }, removeFileLabel: { classPropertyName: "removeFileLabel", publicName: "removeFileLabel", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", rejected: "rejected", touch: "touch" }, host: { properties: { "class": "classes()" } }, viewQueries: [{ propertyName: "picker", first: true, predicate: ["picker"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"disabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"disabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"disabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
242
247
|
}
|
|
243
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0
|
|
248
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFileUpload, decorators: [{
|
|
244
249
|
type: Component,
|
|
245
|
-
args: [{ selector: 'wr-file-upload', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [],
|
|
246
|
-
|
|
247
|
-
provide: NG_VALUE_ACCESSOR,
|
|
248
|
-
// eslint-disable-next-line @angular-eslint/no-forward-ref
|
|
249
|
-
useExisting: forwardRef(() => WrFileUpload),
|
|
250
|
-
multi: true,
|
|
251
|
-
},
|
|
252
|
-
], template: "<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"effectiveDisabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"effectiveDisabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"effectiveDisabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n}\n" }]
|
|
253
|
-
}], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], showList: [{ type: i0.Input, args: [{ isSignal: true, alias: "showList", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], pickLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickLabel", required: false }] }], dropLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropLabel", required: false }] }], dropZoneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropZoneLabel", required: false }] }], removeFileLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeFileLabel", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], rejected: [{ type: i0.Output, args: ["rejected"] }], picker: [{ type: i0.ViewChild, args: ['picker', { isSignal: true }] }] } });
|
|
250
|
+
args: [{ selector: 'wr-file-upload', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, imports: [], template: "<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"disabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"disabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"disabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n}\n" }]
|
|
251
|
+
}], ctorParameters: () => [], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], accept: [{ type: i0.Input, args: [{ isSignal: true, alias: "accept", required: false }] }], maxSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxSize", required: false }] }], maxFiles: [{ type: i0.Input, args: [{ isSignal: true, alias: "maxFiles", required: false }] }], showList: [{ type: i0.Input, args: [{ isSignal: true, alias: "showList", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], pickLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "pickLabel", required: false }] }], dropLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropLabel", required: false }] }], dropZoneLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "dropZoneLabel", required: false }] }], removeFileLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "removeFileLabel", required: false }] }], helperText: [{ type: i0.Input, args: [{ isSignal: true, alias: "helperText", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], rejected: [{ type: i0.Output, args: ["rejected"] }], touch: [{ type: i0.Output, args: ["touch"] }], picker: [{ type: i0.ViewChild, args: ['picker', { isSignal: true }] }] } });
|
|
254
252
|
|
|
255
253
|
/**
|
|
256
254
|
* Generated bundle index. Do not edit.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-file-upload.mjs","sources":["../../../projects/lib/file-upload/file-upload.ts","../../../projects/lib/file-upload/file-upload.html","../../../projects/lib/file-upload/ngwr-file-upload.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n type ElementRef,\n ViewEncapsulation,\n computed,\n forwardRef,\n input,\n output,\n signal,\n viewChild,\n} from '@angular/core';\nimport { type ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\nimport { useI18nText } from 'ngwr/i18n';\nimport { noop } from 'ngwr/utils';\n\nimport type { WrFileUploadRejection, WrFileUploadRejectionReason } from './interfaces';\n\n/** Human-readable byte size (e.g. `1.2 MB`). */\nfunction formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);\n const v = bytes / 1024 ** i;\n return `${v.toFixed(v >= 100 || i === 0 ? 0 : 1)} ${units[i]}`;\n}\n\n/** Does `file` match the `accept` attribute (extensions or MIME globs)? */\nfunction matchesAccept(file: File, accept: string): boolean {\n if (!accept) return true;\n const tokens = accept\n .split(',')\n .map(t => t.trim().toLowerCase())\n .filter(Boolean);\n if (tokens.length === 0) return true;\n const name = file.name.toLowerCase();\n const mime = file.type.toLowerCase();\n return tokens.some(token => {\n if (token.startsWith('.')) return name.endsWith(token);\n if (token.endsWith('/*')) return mime.startsWith(token.slice(0, -1));\n return mime === token;\n });\n}\n\n/**\n * Drag-and-drop file upload zone. Click to browse, drag-and-drop to add,\n * with an optional file list + remove buttons.\n *\n * Implements `ControlValueAccessor` — value is `File | File[] | null`\n * (single or array, governed by `multiple`).\n *\n * @example\n * ```html\n * <wr-file-upload [(ngModel)]=\"files\" [multiple]=\"true\" accept=\"image/*\" />\n * <wr-file-upload [(ngModel)]=\"avatar\" accept=\".png,.jpg\" [maxSize]=\"2 * 1024 * 1024\" />\n * ```\n *\n * @see https://ngwr.dev/components/file-upload\n */\n@Component({\n selector: 'wr-file-upload',\n templateUrl: './file-upload.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [],\n providers: [\n {\n provide: NG_VALUE_ACCESSOR,\n // eslint-disable-next-line @angular-eslint/no-forward-ref\n useExisting: forwardRef(() => WrFileUpload),\n multi: true,\n },\n ],\n})\nexport class WrFileUpload implements ControlValueAccessor {\n /** Allow multiple files. Single mode replaces on each add. @default false */\n readonly multiple = input(false, { transform: coerceBooleanProperty });\n\n /** `accept` attribute — comma-separated MIME types or extensions. @default '' */\n readonly accept = input<string>('');\n\n /** Max bytes per file. `0` disables the check. @default 0 */\n readonly maxSize = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Max files (multi mode only). `0` disables the check. @default 0 */\n readonly maxFiles = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Render the picked-files list below the zone. @default true */\n readonly showList = input(true, { transform: coerceBooleanProperty });\n\n /** Disable interaction. @default false */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Primary call-to-action label. Falls back to `fileUpload.browse`. */\n readonly pickLabel = input<string | null>(null);\n\n /** Secondary instruction below the CTA. Falls back to `fileUpload.dropZone`. */\n readonly dropLabel = input<string | null>(null);\n\n /** Drop-zone host aria-label. Falls back to `fileUpload.dropZoneLabel`. */\n readonly dropZoneLabel = input<string | null>(null);\n\n /** Remove-file button aria-label. Falls back to `fileUpload.removeFile`. */\n readonly removeFileLabel = input<string | null>(null);\n\n protected readonly resolvedPick = useI18nText(this.pickLabel, 'fileUpload.browse', 'Click to browse');\n protected readonly resolvedDrop = useI18nText(this.dropLabel, 'fileUpload.dropZone', 'or drop files here');\n protected readonly resolvedDropZone = useI18nText(\n this.dropZoneLabel,\n 'fileUpload.dropZoneLabel',\n 'File upload drop zone — click or drop files'\n );\n protected readonly resolvedRemove = useI18nText(this.removeFileLabel, 'fileUpload.removeFile', 'Remove file');\n\n /** Optional helper text shown below the labels (e.g. accepted formats). */\n readonly helperText = input<string>('');\n\n /** Emitted when files are rejected for type / size / count reasons. */\n readonly rejected = output<readonly WrFileUploadRejection[]>();\n\n protected readonly picker = viewChild.required<ElementRef<HTMLInputElement>>('picker');\n\n protected readonly files = signal<readonly File[]>([]);\n protected readonly dragging = signal(false);\n\n private readonly disabledFromCva = signal(false);\n\n protected readonly effectiveDisabled = computed(() => this.disabled() || this.disabledFromCva());\n\n protected readonly classes = computed(() => {\n const parts = ['wr-file-upload'];\n if (this.dragging()) parts.push('wr-file-upload--dragging');\n if (this.effectiveDisabled()) parts.push('wr-file-upload--disabled');\n return parts.join(' ');\n });\n\n protected readonly formatBytes = formatBytes;\n\n // ControlValueAccessor\n\n private onChange: (value: File | readonly File[] | null) => void = noop;\n private onTouched: () => void = noop;\n\n writeValue(value: File | readonly File[] | null): void {\n if (value === null || value === undefined) {\n this.files.set([]);\n return;\n }\n this.files.set(Array.isArray(value) ? value : [value as File]);\n }\n\n registerOnChange(fn: (value: File | readonly File[] | null) => void): void {\n this.onChange = fn;\n }\n\n registerOnTouched(fn: () => void): void {\n this.onTouched = fn;\n }\n\n setDisabledState(isDisabled: boolean): void {\n this.disabledFromCva.set(coerceBooleanProperty(isDisabled));\n }\n\n // Template handlers\n\n protected openPicker(): void {\n if (this.effectiveDisabled()) return;\n this.picker().nativeElement.click();\n }\n\n protected onZoneKey(event: KeyboardEvent): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.openPicker();\n }\n }\n\n protected onPickerChange(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (target.files) this.acceptFiles(Array.from(target.files));\n // Reset so picking the same file twice re-fires `change`.\n target.value = '';\n }\n\n protected onDragEnter(event: DragEvent): void {\n if (this.effectiveDisabled()) return;\n event.preventDefault();\n this.dragging.set(true);\n }\n\n protected onDragOver(event: DragEvent): void {\n if (this.effectiveDisabled()) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n }\n\n protected onDragLeave(event: DragEvent): void {\n // Only clear when leaving the zone itself, not internal children.\n if (event.currentTarget === event.target) this.dragging.set(false);\n }\n\n protected onDrop(event: DragEvent): void {\n event.preventDefault();\n this.dragging.set(false);\n if (this.effectiveDisabled()) return;\n const dropped = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];\n if (dropped.length > 0) this.acceptFiles(dropped);\n }\n\n protected removeAt(index: number): void {\n if (this.effectiveDisabled()) return;\n const next = this.files().filter((_, i) => i !== index);\n this.files.set(next);\n this.emit();\n }\n\n // Internals\n\n private acceptFiles(incoming: readonly File[]): void {\n const accept = this.accept();\n const maxSize = this.maxSize();\n const rejections: WrFileUploadRejection[] = [];\n const accepted: File[] = [];\n\n for (const file of incoming) {\n const reason = this.reject(file, accept, maxSize);\n if (reason) rejections.push({ file, reason });\n else accepted.push(file);\n }\n\n let next: File[];\n if (this.multiple()) {\n next = [...this.files(), ...accepted];\n const maxFiles = this.maxFiles();\n if (maxFiles > 0 && next.length > maxFiles) {\n const overflow = next.splice(maxFiles);\n for (const file of overflow) rejections.push({ file, reason: 'count' });\n }\n } else {\n // Single mode — last accepted wins, prior selection cleared.\n next = accepted.length > 0 ? [accepted[accepted.length - 1]] : [...this.files()];\n }\n\n this.files.set(next);\n this.onTouched();\n this.emit();\n if (rejections.length > 0) this.rejected.emit(rejections);\n }\n\n private reject(file: File, accept: string, maxSize: number): WrFileUploadRejectionReason | null {\n if (accept && !matchesAccept(file, accept)) return 'type';\n if (maxSize > 0 && file.size > maxSize) return 'size';\n return null;\n }\n\n private emit(): void {\n const list = this.files();\n if (this.multiple()) {\n this.onChange(list);\n } else {\n this.onChange(list.length > 0 ? list[0] : null);\n }\n }\n}\n","<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"effectiveDisabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"effectiveDisabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"effectiveDisabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\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-file-upload.mjs","sources":["../../../projects/lib/file-upload/file-upload.ts","../../../projects/lib/file-upload/file-upload.html","../../../projects/lib/file-upload/ngwr-file-upload.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';\nimport {\n Component,\n type ElementRef,\n ViewEncapsulation,\n computed,\n effect,\n input,\n model,\n output,\n signal,\n untracked,\n viewChild,\n} from '@angular/core';\nimport type { FormValueControl } from '@angular/forms/signals';\n\nimport { useI18nText } from 'ngwr/i18n';\n\nimport type { WrFileUploadRejection, WrFileUploadRejectionReason } from './interfaces';\n\n/** Human-readable byte size (e.g. `1.2 MB`). */\nfunction formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const i = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);\n const v = bytes / 1024 ** i;\n return `${v.toFixed(v >= 100 || i === 0 ? 0 : 1)} ${units[i]}`;\n}\n\n/** Does `file` match the `accept` attribute (extensions or MIME globs)? */\nfunction matchesAccept(file: File, accept: string): boolean {\n if (!accept) return true;\n const tokens = accept\n .split(',')\n .map(t => t.trim().toLowerCase())\n .filter(Boolean);\n if (tokens.length === 0) return true;\n const name = file.name.toLowerCase();\n const mime = file.type.toLowerCase();\n return tokens.some(token => {\n if (token.startsWith('.')) return name.endsWith(token);\n if (token.endsWith('/*')) return mime.startsWith(token.slice(0, -1));\n return mime === token;\n });\n}\n\n/**\n * Drag-and-drop file upload zone. Click to browse, drag-and-drop to add,\n * with an optional file list + remove buttons.\n *\n * A signal-forms native control: it implements\n * `FormValueControl<File | readonly File[] | null>`, so `[formField]` binds\n * straight to its `value` model — no `ControlValueAccessor` in between.\n * `[(value)]` works standalone. The value shape follows `multiple`: a single\n * `File` (or `null`), or a `File[]` array.\n *\n * @example\n * ```html\n * <!-- signal forms -->\n * <wr-file-upload [formField]=\"form.files\" [multiple]=\"true\" accept=\"image/*\" />\n *\n * <!-- standalone two-way binding -->\n * <wr-file-upload [(value)]=\"avatar\" accept=\".png,.jpg\" [maxSize]=\"2 * 1024 * 1024\" />\n * ```\n *\n * @see https://ngwr.dev/reference/components/file-upload\n */\n@Component({\n selector: 'wr-file-upload',\n templateUrl: './file-upload.html',\n encapsulation: ViewEncapsulation.None,\n host: { '[class]': 'classes()' },\n imports: [],\n})\nexport class WrFileUpload implements FormValueControl<File | readonly File[] | null> {\n /** Allow multiple files. Single mode replaces on each add. @default false */\n readonly multiple = input(false, { transform: coerceBooleanProperty });\n\n /** `accept` attribute — comma-separated MIME types or extensions. @default '' */\n readonly accept = input<string>('');\n\n /** Max bytes per file. `0` disables the check. @default 0 */\n readonly maxSize = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Max files (multi mode only). `0` disables the check. @default 0 */\n readonly maxFiles = input(0, { transform: (v: unknown): number => Math.max(0, coerceNumberProperty(v, 0)) });\n\n /** Render the picked-files list below the zone. @default true */\n readonly showList = input(true, { transform: coerceBooleanProperty });\n\n /**\n * Disable interaction. Bound automatically from the field's disabled state\n * when used with `[formField]`.\n *\n * @default false\n */\n readonly disabled = input(false, { transform: coerceBooleanProperty });\n\n /** Primary call-to-action label. Falls back to `fileUpload.browse`. */\n readonly pickLabel = input<string | null>(null);\n\n /** Secondary instruction below the CTA. Falls back to `fileUpload.dropZone`. */\n readonly dropLabel = input<string | null>(null);\n\n /** Drop-zone host aria-label. Falls back to `fileUpload.dropZoneLabel`. */\n readonly dropZoneLabel = input<string | null>(null);\n\n /** Remove-file button aria-label. Falls back to `fileUpload.removeFile`. */\n readonly removeFileLabel = input<string | null>(null);\n\n protected readonly resolvedPick = useI18nText(this.pickLabel, 'fileUpload.browse', 'Click to browse');\n protected readonly resolvedDrop = useI18nText(this.dropLabel, 'fileUpload.dropZone', 'or drop files here');\n protected readonly resolvedDropZone = useI18nText(\n this.dropZoneLabel,\n 'fileUpload.dropZoneLabel',\n 'File upload drop zone — click or drop files'\n );\n protected readonly resolvedRemove = useI18nText(this.removeFileLabel, 'fileUpload.removeFile', 'Remove file');\n\n /** Optional helper text shown below the labels (e.g. accepted formats). */\n readonly helperText = input<string>('');\n\n /**\n * Selected file(s). Bound by `[formField]`, or two-way via `[(value)]`. Shape\n * follows `multiple`: a single `File` (or `null`), or a `File[]` array.\n */\n readonly value = model<File | readonly File[] | null>(null);\n\n /** Emitted when files are rejected for type / size / count reasons. */\n readonly rejected = output<readonly WrFileUploadRejection[]>();\n\n /** Emitted on commit so a bound field can mark itself touched. */\n readonly touch = output<void>();\n\n protected readonly picker = viewChild.required<ElementRef<HTMLInputElement>>('picker');\n\n protected readonly files = signal<readonly File[]>([]);\n protected readonly dragging = signal(false);\n\n protected readonly classes = computed(() => {\n const parts = ['wr-file-upload'];\n if (this.dragging()) parts.push('wr-file-upload--dragging');\n if (this.disabled()) parts.push('wr-file-upload--disabled');\n return parts.join(' ');\n });\n\n protected readonly formatBytes = formatBytes;\n\n constructor() {\n // Rebuild the internal file list from an external `value` write (mirrors the\n // old `writeValue`). Skipped when the value is merely the echo of an\n // in-component edit, so re-syncing can never clobber a live selection.\n effect(() => {\n const v = this.value();\n untracked(() => {\n // Coerce null/undefined to `[]` — a classic-forms binding can write\n // null, which the old `writeValue(v: … | null)` accepted too.\n const next: readonly File[] = v === null || v === undefined ? [] : Array.isArray(v) ? v : [v as File];\n const current = this.files();\n if (current.length === next.length && current.every((file, i) => file === next[i])) return;\n this.files.set(next);\n });\n });\n }\n\n // Template handlers\n\n protected openPicker(): void {\n if (this.disabled()) return;\n this.picker().nativeElement.click();\n }\n\n protected onZoneKey(event: KeyboardEvent): void {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n this.openPicker();\n }\n }\n\n protected onPickerChange(event: Event): void {\n const target = event.target as HTMLInputElement;\n if (target.files) this.acceptFiles(Array.from(target.files));\n // Reset so picking the same file twice re-fires `change`.\n target.value = '';\n }\n\n protected onDragEnter(event: DragEvent): void {\n if (this.disabled()) return;\n event.preventDefault();\n this.dragging.set(true);\n }\n\n protected onDragOver(event: DragEvent): void {\n if (this.disabled()) return;\n event.preventDefault();\n if (event.dataTransfer) event.dataTransfer.dropEffect = 'copy';\n }\n\n protected onDragLeave(event: DragEvent): void {\n // Only clear when leaving the zone itself, not internal children.\n if (event.currentTarget === event.target) this.dragging.set(false);\n }\n\n protected onDrop(event: DragEvent): void {\n event.preventDefault();\n this.dragging.set(false);\n if (this.disabled()) return;\n const dropped = event.dataTransfer?.files ? Array.from(event.dataTransfer.files) : [];\n if (dropped.length > 0) this.acceptFiles(dropped);\n }\n\n protected removeAt(index: number): void {\n if (this.disabled()) return;\n const next = this.files().filter((_, i) => i !== index);\n this.files.set(next);\n this.emit();\n }\n\n // Internals\n\n private acceptFiles(incoming: readonly File[]): void {\n const accept = this.accept();\n const maxSize = this.maxSize();\n const rejections: WrFileUploadRejection[] = [];\n const accepted: File[] = [];\n\n for (const file of incoming) {\n const reason = this.reject(file, accept, maxSize);\n if (reason) rejections.push({ file, reason });\n else accepted.push(file);\n }\n\n let next: File[];\n if (this.multiple()) {\n next = [...this.files(), ...accepted];\n const maxFiles = this.maxFiles();\n if (maxFiles > 0 && next.length > maxFiles) {\n const overflow = next.splice(maxFiles);\n for (const file of overflow) rejections.push({ file, reason: 'count' });\n }\n } else {\n // Single mode — last accepted wins, prior selection cleared.\n next = accepted.length > 0 ? [accepted[accepted.length - 1]] : [...this.files()];\n }\n\n this.files.set(next);\n this.touch.emit();\n this.emit();\n if (rejections.length > 0) this.rejected.emit(rejections);\n }\n\n private reject(file: File, accept: string, maxSize: number): WrFileUploadRejectionReason | null {\n if (accept && !matchesAccept(file, accept)) return 'type';\n if (maxSize > 0 && file.size > maxSize) return 'size';\n return null;\n }\n\n private emit(): void {\n const list = this.files();\n if (this.multiple()) {\n this.value.set(list);\n } else {\n this.value.set(list.length > 0 ? list[0] : null);\n }\n }\n}\n","<div\n class=\"wr-file-upload__zone\"\n role=\"button\"\n tabindex=\"0\"\n [attr.aria-label]=\"resolvedDropZone()\"\n [attr.aria-disabled]=\"disabled() || null\"\n (click)=\"openPicker()\"\n (keydown)=\"onZoneKey($event)\"\n (dragenter)=\"onDragEnter($event)\"\n (dragover)=\"onDragOver($event)\"\n (dragleave)=\"onDragLeave($event)\"\n (drop)=\"onDrop($event)\"\n>\n <svg class=\"wr-file-upload__icon\" width=\"32\" height=\"32\" viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path\n d=\"M12 16V4M12 4l-4 4M12 4l4 4M4 16v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-2\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <div class=\"wr-file-upload__hint\">\n <strong>{{ resolvedPick() }}</strong>\n <span>{{ resolvedDrop() }}</span>\n @if (helperText()) {\n <small>{{ helperText() }}</small>\n }\n </div>\n <input\n #picker\n class=\"wr-file-upload__picker\"\n type=\"file\"\n [attr.accept]=\"accept() || null\"\n [attr.multiple]=\"multiple() ? '' : null\"\n [disabled]=\"disabled()\"\n (change)=\"onPickerChange($event)\"\n />\n</div>\n\n@if (showList() && files().length > 0) {\n <ul class=\"wr-file-upload__list\">\n @for (file of files(); track $index) {\n <li class=\"wr-file-upload__item\">\n <span class=\"wr-file-upload__name\" [title]=\"file.name\">{{ file.name }}</span>\n <span class=\"wr-file-upload__size\">{{ formatBytes(file.size) }}</span>\n <button\n type=\"button\"\n class=\"wr-file-upload__remove\"\n [attr.aria-label]=\"resolvedRemove()\"\n [disabled]=\"disabled()\"\n (click)=\"removeAt($index)\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" aria-hidden=\"true\">\n <path\n d=\"M2 2 L10 10 M10 2 L2 10\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </li>\n }\n </ul>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
package/fesm2022/ngwr-form.mjs
CHANGED
|
@@ -24,7 +24,7 @@ import { NgControl } from '@angular/forms';
|
|
|
24
24
|
* </wr-form-item>
|
|
25
25
|
* ```
|
|
26
26
|
*
|
|
27
|
-
* @see https://ngwr.dev/components/form
|
|
27
|
+
* @see https://ngwr.dev/reference/components/form
|
|
28
28
|
*/
|
|
29
29
|
class WrFormItem {
|
|
30
30
|
/**
|
|
@@ -40,10 +40,10 @@ class WrFormItem {
|
|
|
40
40
|
return parts.join(' ');
|
|
41
41
|
}, /* @ts-ignore */
|
|
42
42
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
43
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0
|
|
44
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0
|
|
43
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
44
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: WrFormItem, isStandalone: true, selector: "wr-form-item", inputs: { hasError: { classPropertyName: "hasError", publicName: "hasError", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, ngImport: i0, template: '<ng-content />', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
45
45
|
}
|
|
46
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0
|
|
46
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormItem, decorators: [{
|
|
47
47
|
type: Component,
|
|
48
48
|
args: [{
|
|
49
49
|
selector: 'wr-form-item',
|
|
@@ -79,7 +79,7 @@ let uid = 0;
|
|
|
79
79
|
* </wr-form-field>
|
|
80
80
|
* ```
|
|
81
81
|
*
|
|
82
|
-
* @see https://ngwr.dev/components/form-field
|
|
82
|
+
* @see https://ngwr.dev/reference/components/form-field
|
|
83
83
|
*/
|
|
84
84
|
class WrFormField {
|
|
85
85
|
/** Label text shown above the control. */
|
|
@@ -121,10 +121,10 @@ class WrFormField {
|
|
|
121
121
|
return parts.join(' ');
|
|
122
122
|
}, /* @ts-ignore */
|
|
123
123
|
...(ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []));
|
|
124
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0
|
|
125
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0
|
|
124
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
125
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.0", type: WrFormField, isStandalone: true, selector: "wr-form-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, optional: { classPropertyName: "optional", publicName: "optional", isSignal: true, isRequired: false, transformFunction: null }, controlId: { classPropertyName: "controlId", publicName: "controlId", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class": "classes()" } }, queries: [{ propertyName: "ngControl", first: true, predicate: NgControl, descendants: true, isSignal: true }], ngImport: i0, template: "@if (label()) {\n <label class=\"wr-form-field__label\" [attr.for]=\"controlId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"wr-form-field__required\" aria-hidden=\"true\">*</span>\n } @else if (optional()) {\n <span class=\"wr-form-field__optional\">(optional)</span>\n }\n </label>\n}\n\n<div class=\"wr-form-field__control\"><ng-content /></div>\n\n@if (hasError()) {\n <div class=\"wr-form-field__errors\">\n <ng-content select=\"wr-form-error\" />\n </div>\n} @else if (hint()) {\n <small class=\"wr-form-field__hint\">{{ hint() }}</small>\n}\n", encapsulation: i0.ViewEncapsulation.None });
|
|
126
126
|
}
|
|
127
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0
|
|
127
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormField, decorators: [{
|
|
128
128
|
type: Component,
|
|
129
129
|
args: [{ selector: 'wr-form-field', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "@if (label()) {\n <label class=\"wr-form-field__label\" [attr.for]=\"controlId()\">\n {{ label() }}\n @if (required()) {\n <span class=\"wr-form-field__required\" aria-hidden=\"true\">*</span>\n } @else if (optional()) {\n <span class=\"wr-form-field__optional\">(optional)</span>\n }\n </label>\n}\n\n<div class=\"wr-form-field__control\"><ng-content /></div>\n\n@if (hasError()) {\n <div class=\"wr-form-field__errors\">\n <ng-content select=\"wr-form-error\" />\n </div>\n} @else if (hint()) {\n <small class=\"wr-form-field__hint\">{{ hint() }}</small>\n}\n" }]
|
|
130
130
|
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], required: [{ type: i0.Input, args: [{ isSignal: true, alias: "required", required: false }] }], optional: [{ type: i0.Input, args: [{ isSignal: true, alias: "optional", required: false }] }], controlId: [{ type: i0.Input, args: [{ isSignal: true, alias: "controlId", required: false }] }], ngControl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => NgControl), { isSignal: true }] }] } });
|
|
@@ -146,10 +146,10 @@ class WrFormError {
|
|
|
146
146
|
*/
|
|
147
147
|
key = input(/* @ts-ignore */
|
|
148
148
|
...(ngDevMode ? [undefined, { debugName: "key" }] : /* istanbul ignore next */ []));
|
|
149
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0
|
|
150
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.0
|
|
149
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormError, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
150
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "22.1.0", type: WrFormError, isStandalone: true, selector: "wr-form-error", inputs: { key: { classPropertyName: "key", publicName: "key", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "alert" }, properties: { "attr.data-key": "key() ?? null" }, classAttribute: "wr-form-error wr-form-field__error" }, ngImport: i0, template: `<ng-content />`, isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
151
151
|
}
|
|
152
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0
|
|
152
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.0", ngImport: i0, type: WrFormError, decorators: [{
|
|
153
153
|
type: Component,
|
|
154
154
|
args: [{
|
|
155
155
|
selector: 'wr-form-error',
|