ngwr 11.2.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -7
- package/burger/styles/_index.scss +1 -1
- package/button/styles/_index.scss +2 -2
- package/calendar/styles/_index.scss +32 -12
- package/calendar-heatmap/styles/_index.scss +20 -0
- package/carousel/styles/_index.scss +23 -1
- package/cascader/styles/_index.scss +15 -3
- package/checkbox/styles/_index.scss +2 -2
- package/collapse/styles/_index.scss +2 -2
- package/color-picker/styles/_index.scss +3 -3
- package/compare/styles/_index.scss +18 -2
- package/context-menu/styles/_index.scss +21 -2
- package/date-picker/styles/_index.scss +5 -5
- package/descriptions/styles/_index.scss +1 -1
- package/drag-drop/styles/_index.scss +28 -1
- package/drawer/styles/_index.scss +37 -0
- package/dropdown/styles/_index.scss +2 -2
- package/event-calendar/styles/_index.scss +67 -10
- package/fesm2022/ngwr-action-sheet.mjs +3 -3
- package/fesm2022/ngwr-affix.mjs +3 -3
- package/fesm2022/ngwr-alert.mjs +3 -3
- package/fesm2022/ngwr-anchor.mjs +3 -3
- package/fesm2022/ngwr-aurora.mjs +3 -3
- package/fesm2022/ngwr-avatar.mjs +3 -3
- package/fesm2022/ngwr-back-top.mjs +3 -3
- package/fesm2022/ngwr-badge.mjs +6 -6
- package/fesm2022/ngwr-bar-chart-testing.mjs +20 -2
- package/fesm2022/ngwr-bar-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart.mjs +3 -3
- package/fesm2022/ngwr-blur-text.mjs +3 -3
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +4 -4
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +29 -17
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-button.mjs +6 -6
- package/fesm2022/ngwr-calendar-heatmap.mjs +17 -5
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-testing.mjs +1 -1
- package/fesm2022/ngwr-calendar-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +187 -9
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +10 -10
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel.mjs +124 -24
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +48 -5
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +6 -6
- package/fesm2022/ngwr-circular-text.mjs +4 -4
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +27 -7
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-color-picker-testing.mjs +26 -6
- package/fesm2022/ngwr-color-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-color-picker.mjs +98 -8
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette.mjs +14 -5
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs +31 -6
- package/fesm2022/ngwr-confetti.mjs.map +1 -1
- package/fesm2022/ngwr-config.mjs +9 -0
- package/fesm2022/ngwr-config.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu-testing.mjs +30 -11
- package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -1
- package/fesm2022/ngwr-context-menu.mjs +333 -43
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +25 -9
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/{ngwr-date-adapter-fns.mjs → ngwr-date-adapters-fns.mjs} +37 -10
- package/fesm2022/ngwr-date-adapters-fns.mjs.map +1 -0
- package/fesm2022/{ngwr-date-adapter-luxon.mjs → ngwr-date-adapters-luxon.mjs} +5 -5
- package/fesm2022/ngwr-date-adapters-luxon.mjs.map +1 -0
- package/fesm2022/ngwr-date-picker-testing.mjs +11 -6
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker.mjs +119 -37
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/{ngwr-date-adapter.mjs → ngwr-date.mjs} +36 -10
- package/fesm2022/ngwr-date.mjs.map +1 -0
- package/fesm2022/ngwr-decrypt-text.mjs +3 -3
- package/fesm2022/ngwr-density.mjs +6 -6
- package/fesm2022/ngwr-descriptions.mjs +6 -6
- package/fesm2022/ngwr-dialog.mjs +73 -18
- package/fesm2022/ngwr-dialog.mjs.map +1 -1
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-divider.mjs +52 -5
- package/fesm2022/ngwr-divider.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart-testing.mjs +8 -4
- package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +7 -7
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +160 -11
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer.mjs +121 -58
- package/fesm2022/ngwr-drawer.mjs.map +1 -1
- package/fesm2022/ngwr-dropdown.mjs +26 -10
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-event-calendar.mjs +28 -15
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text-testing.mjs +5 -3
- package/fesm2022/ngwr-falling-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +75 -46
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload.mjs +3 -3
- package/fesm2022/ngwr-form.mjs +32 -15
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +21 -11
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +3 -3
- package/fesm2022/ngwr-glitch-text-testing.mjs +51 -17
- package/fesm2022/ngwr-glitch-text-testing.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +7 -7
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text-testing.mjs +46 -11
- package/fesm2022/ngwr-gradient-text-testing.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 +24 -9
- package/fesm2022/ngwr-hotkey.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +73 -1
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +55 -1
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +26 -15
- package/fesm2022/ngwr-i18n.mjs.map +1 -1
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-image-cropper-testing.mjs +53 -9
- package/fesm2022/ngwr-image-cropper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +150 -12
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number-testing.mjs +15 -10
- package/fesm2022/ngwr-input-number-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-number.mjs +17 -10
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp-testing.mjs +12 -6
- package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +24 -5
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input.mjs +15 -15
- package/fesm2022/ngwr-keyboard.mjs +3 -3
- package/fesm2022/ngwr-knob.mjs +3 -3
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox.mjs +4 -4
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +73 -26
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +7 -7
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +7 -7
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown.mjs +66 -8
- package/fesm2022/ngwr-markdown.mjs.map +1 -1
- package/fesm2022/ngwr-marquee.mjs +4 -4
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-mention.mjs +108 -13
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +6 -6
- package/fesm2022/ngwr-meter-group-testing.mjs +26 -6
- package/fesm2022/ngwr-meter-group-testing.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +3 -3
- package/fesm2022/ngwr-overlay.mjs +6 -6
- package/fesm2022/ngwr-page-header.mjs +3 -3
- package/fesm2022/ngwr-pagination-testing.mjs +6 -6
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -1
- package/fesm2022/ngwr-pagination.mjs +17 -13
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +39 -26
- package/fesm2022/ngwr-pipes.mjs.map +1 -1
- package/fesm2022/ngwr-platform.mjs +9 -9
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popover-testing.mjs +7 -2
- package/fesm2022/ngwr-popover-testing.mjs.map +1 -1
- package/fesm2022/ngwr-popover.mjs +155 -33
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-progress.mjs +3 -3
- package/fesm2022/ngwr-pull-to-refresh.mjs +3 -3
- package/fesm2022/ngwr-qr.mjs +42 -5
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-rating.mjs +3 -3
- package/fesm2022/ngwr-result.mjs +21 -30
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text.mjs +3 -3
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-segmented-testing.mjs +14 -1
- package/fesm2022/ngwr-segmented-testing.mjs.map +1 -1
- package/fesm2022/ngwr-segmented.mjs +29 -6
- package/fesm2022/ngwr-segmented.mjs.map +1 -1
- package/fesm2022/ngwr-select.mjs +159 -34
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +11 -9
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +31 -16
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +100 -9
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +3 -3
- package/fesm2022/ngwr-speed-dial-testing.mjs +15 -13
- package/fesm2022/ngwr-speed-dial-testing.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +27 -12
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-split-text.mjs +17 -5
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-spotlight-card.mjs +7 -7
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-squircle.mjs +6 -6
- package/fesm2022/ngwr-star-border.mjs +4 -4
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +9 -9
- package/fesm2022/ngwr-stepper-testing.mjs +8 -8
- package/fesm2022/ngwr-stepper-testing.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +33 -8
- package/fesm2022/ngwr-stepper.mjs.map +1 -1
- package/fesm2022/ngwr-storage.mjs +17 -5
- package/fesm2022/ngwr-storage.mjs.map +1 -1
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-table.mjs +99 -39
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-testing.mjs +11 -10
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tabs.mjs +36 -10
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea.mjs +3 -3
- package/fesm2022/ngwr-theme.mjs +181 -4
- package/fesm2022/ngwr-theme.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +7 -7
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast.mjs +9 -9
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tour.mjs +34 -10
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer.mjs +3 -3
- package/fesm2022/ngwr-tree.mjs +28 -10
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter-testing.mjs +15 -1
- package/fesm2022/ngwr-typewriter-testing.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +13 -5
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-utils.mjs +5 -2
- package/fesm2022/ngwr-utils.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +4 -4
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +4 -4
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +94 -24
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/file-upload/styles/_index.scss +2 -2
- package/glitch-text/styles/_index.scss +27 -12
- package/i18n/en.json +56 -6
- package/i18n/ru.json +56 -6
- package/image-cropper/styles/_index.scss +19 -0
- package/input/styles/_index.scss +2 -2
- package/input-number/styles/_index.scss +2 -2
- package/input-otp/styles/_index.scss +9 -2
- package/knob/styles/_index.scss +1 -1
- package/lightbox/styles/_index.scss +16 -2
- package/line-chart/styles/_index.scss +28 -14
- package/list/styles/_index.scss +1 -1
- package/llms-full.txt +18 -23
- package/llms.txt +22 -6
- package/markdown/styles/_index.scss +3 -3
- package/mcp/api.js +6 -4
- package/mcp/catalog.js +40 -3
- package/mcp/providers.js +16 -3
- package/mcp/tools.js +21 -1
- package/meter-group/styles/_index.scss +1 -1
- package/overlay/styles/_index.scss +33 -1
- package/package.json +17 -12
- package/pagination/styles/_index.scss +23 -1
- package/popover/styles/_index.scss +16 -7
- package/progress/styles/_index.scss +1 -1
- package/radio/styles/_index.scss +2 -2
- package/rating/styles/_index.scss +1 -1
- package/schematics/collection.json +1 -1
- package/schematics/migrations/v12/index.js +65 -0
- package/schematics/migrations/v7/index.js +12 -1
- package/schematics/migrations/v8/index.js +10 -1
- package/schematics/migrations.json +5 -0
- package/schematics/ng-add/index.js +8 -3
- package/schematics/provider/index.js +80 -13
- package/schematics/use/index.js +9 -129
- package/schematics/use/rule.js +206 -0
- package/schematics/use/symbol-map.json +4 -4
- package/segmented/styles/_index.scss +14 -3
- package/select/styles/_index.scss +14 -2
- package/sidebar/styles/_index.scss +12 -10
- package/skills/ngwr/SKILL.md +7 -5
- package/skills/ngwr/references/catalog.md +9 -9
- package/skills/ngwr/references/setup.md +10 -5
- package/slider/styles/_index.scss +1 -1
- package/speed-dial/styles/_index.scss +1 -1
- package/stepper/styles/_index.scss +12 -3
- package/switch/styles/_index.scss +2 -2
- package/table/styles/_index.scss +61 -12
- package/tabs/styles/_index.scss +1 -1
- package/textarea/styles/_index.scss +1 -1
- package/theme/styles/_colors.scss +142 -56
- package/theme/styles/_dark.scss +46 -3
- package/theme/styles/_focus.scss +28 -5
- package/theme/styles/_mixins.scss +1 -1
- package/theme/styles/_variables.scss +67 -0
- package/transfer/styles/_index.scss +26 -3
- package/tree/styles/_index.scss +29 -6
- package/types/ngwr-bar-chart-testing.d.ts +9 -1
- package/types/ngwr-blur-text.d.ts +8 -4
- package/types/ngwr-breadcrumbs.d.ts +17 -10
- package/types/ngwr-calendar-testing.d.ts +1 -1
- package/types/ngwr-calendar.d.ts +66 -0
- package/types/ngwr-carousel.d.ts +85 -6
- package/types/ngwr-cascader.d.ts +17 -0
- package/types/ngwr-click-spark.d.ts +4 -0
- package/types/ngwr-color-picker-testing.d.ts +8 -0
- package/types/ngwr-color-picker.d.ts +21 -1
- package/types/ngwr-confetti.d.ts +8 -0
- package/types/ngwr-config.d.ts +10 -1
- package/types/ngwr-context-menu-testing.d.ts +24 -11
- package/types/ngwr-context-menu.d.ts +56 -0
- package/types/ngwr-counter.d.ts +1 -0
- package/types/{ngwr-date-adapter-fns.d.ts → ngwr-date-adapters-fns.d.ts} +33 -6
- package/types/{ngwr-date-adapter-luxon.d.ts → ngwr-date-adapters-luxon.d.ts} +1 -1
- package/types/ngwr-date-picker-testing.d.ts +11 -6
- package/types/ngwr-date-picker.d.ts +8 -4
- package/types/{ngwr-date-adapter.d.ts → ngwr-date.d.ts} +24 -5
- package/types/ngwr-dialog.d.ts +38 -1
- package/types/ngwr-divider.d.ts +25 -0
- package/types/ngwr-donut-chart-testing.d.ts +7 -3
- package/types/ngwr-donut-chart.d.ts +3 -3
- package/types/ngwr-drag-drop.d.ts +56 -2
- package/types/ngwr-drawer.d.ts +56 -5
- package/types/ngwr-event-calendar.d.ts +8 -2
- package/types/ngwr-falling-text-testing.d.ts +5 -3
- package/types/ngwr-falling-text.d.ts +1 -1
- package/types/ngwr-form.d.ts +12 -2
- package/types/ngwr-glitch-text-testing.d.ts +37 -8
- package/types/ngwr-gradient-text-testing.d.ts +16 -3
- package/types/ngwr-i18n.d.ts +13 -4
- package/types/ngwr-image-cropper-testing.d.ts +49 -10
- package/types/ngwr-image-cropper.d.ts +70 -5
- package/types/ngwr-input-number-testing.d.ts +15 -10
- package/types/ngwr-input-number.d.ts +11 -4
- package/types/ngwr-input-otp-testing.d.ts +12 -6
- package/types/ngwr-input-otp.d.ts +15 -1
- package/types/ngwr-line-chart.d.ts +20 -3
- package/types/ngwr-markdown.d.ts +11 -0
- package/types/ngwr-mention.d.ts +32 -0
- package/types/ngwr-meter-group-testing.d.ts +12 -2
- package/types/ngwr-overlay.d.ts +1 -0
- package/types/ngwr-pagination-testing.d.ts +4 -4
- package/types/ngwr-pipes.d.ts +1 -1
- package/types/ngwr-popover-testing.d.ts +7 -2
- package/types/ngwr-popover.d.ts +1 -0
- package/types/ngwr-result.d.ts +6 -0
- package/types/ngwr-segmented-testing.d.ts +9 -0
- package/types/ngwr-segmented.d.ts +21 -1
- package/types/ngwr-select.d.ts +68 -6
- package/types/ngwr-shiny-text.d.ts +4 -2
- package/types/ngwr-sidebar.d.ts +14 -5
- package/types/ngwr-slider.d.ts +69 -1
- package/types/ngwr-speed-dial-testing.d.ts +15 -11
- package/types/ngwr-speed-dial.d.ts +22 -3
- package/types/ngwr-split-text.d.ts +9 -0
- package/types/ngwr-stepper-testing.d.ts +5 -5
- package/types/ngwr-stepper.d.ts +8 -0
- package/types/ngwr-storage.d.ts +1 -0
- package/types/ngwr-table.d.ts +104 -11
- package/types/ngwr-tabs-testing.d.ts +11 -10
- package/types/ngwr-tabs.d.ts +2 -0
- package/types/ngwr-theme.d.ts +82 -1
- package/types/ngwr-tour.d.ts +22 -4
- package/types/ngwr-tree.d.ts +5 -4
- package/types/ngwr-typewriter-testing.d.ts +10 -0
- package/types/ngwr-utils.d.ts +5 -2
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-window.d.ts +39 -11
- package/typography/styles/_index.scss +1 -1
- package/window/styles/_index.scss +72 -26
- package/fesm2022/ngwr-date-adapter-fns.mjs.map +0 -1
- package/fesm2022/ngwr-date-adapter-luxon.mjs.map +0 -1
- package/fesm2022/ngwr-date-adapter.mjs.map +0 -1
|
@@ -9,6 +9,71 @@ import { Directionality } from '@angular/cdk/bidi';
|
|
|
9
9
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
10
10
|
import { WrIcon } from 'ngwr/icon';
|
|
11
11
|
|
|
12
|
+
/**
|
|
13
|
+
* @license
|
|
14
|
+
*
|
|
15
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
16
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Roving focus inside ONE context-menu pane.
|
|
20
|
+
*
|
|
21
|
+
* The APG menu pattern makes a menu a single tab stop and moves a focus cursor
|
|
22
|
+
* between its rows with the arrows — which is why every `<wr-context-menu-item>`
|
|
23
|
+
* carries `tabindex="-1"`. Shared by the root directive and by
|
|
24
|
+
* `WrContextMenuItem`'s submenu because a submenu is a SEPARATE overlay pane
|
|
25
|
+
* rather than nested DOM: each pane roves over its own rows, and CDK's keyboard
|
|
26
|
+
* dispatcher hands the key to the topmost one, which is the pane the user is in.
|
|
27
|
+
*
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* The rows of one pane the cursor may land on. Disabled rows are not stops —
|
|
32
|
+
* the same rule `WrDropdown` follows.
|
|
33
|
+
*/
|
|
34
|
+
function wrMenuItems(pane) {
|
|
35
|
+
return Array.from(pane.querySelectorAll('.wr-context-menu-item:not(.wr-context-menu-item--disabled)'));
|
|
36
|
+
}
|
|
37
|
+
/** Focus the row at `index`, wrapping at both ends. A pane with no rows is left alone. */
|
|
38
|
+
function wrFocusMenuItemAt(pane, index) {
|
|
39
|
+
const items = wrMenuItems(pane);
|
|
40
|
+
if (items.length === 0)
|
|
41
|
+
return;
|
|
42
|
+
const clamped = ((index % items.length) + items.length) % items.length;
|
|
43
|
+
items[clamped]?.focus();
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* ArrowDown / ArrowUp / Home / End over one pane's rows. Returns `true` when the
|
|
47
|
+
* key was consumed, so a caller can leave every other key alone.
|
|
48
|
+
*/
|
|
49
|
+
function wrHandleMenuNavigation(pane, event) {
|
|
50
|
+
const items = wrMenuItems(pane);
|
|
51
|
+
if (items.length === 0)
|
|
52
|
+
return false;
|
|
53
|
+
const active = document.activeElement;
|
|
54
|
+
// -1 when the keyboard is not on a row yet, which makes ArrowDown open at the
|
|
55
|
+
// first row and ArrowUp at the last.
|
|
56
|
+
const index = active instanceof HTMLElement ? items.indexOf(active) : -1;
|
|
57
|
+
switch (event.key) {
|
|
58
|
+
case 'ArrowDown':
|
|
59
|
+
wrFocusMenuItemAt(pane, index + 1);
|
|
60
|
+
break;
|
|
61
|
+
case 'ArrowUp':
|
|
62
|
+
wrFocusMenuItemAt(pane, index <= 0 ? items.length - 1 : index - 1);
|
|
63
|
+
break;
|
|
64
|
+
case 'Home':
|
|
65
|
+
wrFocusMenuItemAt(pane, 0);
|
|
66
|
+
break;
|
|
67
|
+
case 'End':
|
|
68
|
+
wrFocusMenuItemAt(pane, items.length - 1);
|
|
69
|
+
break;
|
|
70
|
+
default:
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
event.preventDefault();
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
|
|
12
77
|
/**
|
|
13
78
|
* @license
|
|
14
79
|
*
|
|
@@ -67,9 +132,17 @@ class WrContextMenuItem {
|
|
|
67
132
|
scrollStrategies = inject(ScrollStrategyOptions);
|
|
68
133
|
destroyRef = inject(DestroyRef);
|
|
69
134
|
submenuRef = null;
|
|
135
|
+
submenuKeys = null;
|
|
70
136
|
openTimer = null;
|
|
71
137
|
closeTimer = null;
|
|
72
138
|
submenuOpen = false;
|
|
139
|
+
/**
|
|
140
|
+
* Whether the pending open was asked for by the keyboard (→ / Enter / Space)
|
|
141
|
+
* rather than by hover — only then does the submenu take focus, the same rule
|
|
142
|
+
* `wr-dropdown` applies to its own open. Sweeping the cursor across a row must
|
|
143
|
+
* show its submenu without yanking the caret out of it.
|
|
144
|
+
*/
|
|
145
|
+
openedByKeyboard = false;
|
|
73
146
|
/**
|
|
74
147
|
* Id of the submenu's menu element while it is open, published on the item as
|
|
75
148
|
* `aria-controls` — the same contract the root trigger keeps (see
|
|
@@ -128,6 +201,7 @@ class WrContextMenuItem {
|
|
|
128
201
|
return;
|
|
129
202
|
if (this.submenu()) {
|
|
130
203
|
event.preventDefault();
|
|
204
|
+
this.openedByKeyboard = true;
|
|
131
205
|
this.scheduleOpen(0);
|
|
132
206
|
return;
|
|
133
207
|
}
|
|
@@ -155,6 +229,7 @@ class WrContextMenuItem {
|
|
|
155
229
|
if (this.disabled() || !this.submenu())
|
|
156
230
|
return;
|
|
157
231
|
event.preventDefault();
|
|
232
|
+
this.openedByKeyboard = true;
|
|
158
233
|
this.scheduleOpen(0);
|
|
159
234
|
}
|
|
160
235
|
closeFromKey(event) {
|
|
@@ -168,6 +243,7 @@ class WrContextMenuItem {
|
|
|
168
243
|
if (this.disabled() || !this.submenu())
|
|
169
244
|
return;
|
|
170
245
|
this.cancelClose();
|
|
246
|
+
this.openedByKeyboard = false;
|
|
171
247
|
this.scheduleOpen(SUBMENU_OPEN_DELAY);
|
|
172
248
|
}
|
|
173
249
|
/** @internal Hover-out schedules a close with a grace window. */
|
|
@@ -257,9 +333,60 @@ class WrContextMenuItem {
|
|
|
257
333
|
// when the cursor crosses the gap between item and submenu pane.
|
|
258
334
|
pane.addEventListener('mouseenter', this.onSubmenuEnter);
|
|
259
335
|
pane.addEventListener('mouseleave', this.onSubmenuLeave);
|
|
336
|
+
// While this pane is open it is the newest overlay that listens, so CDK's
|
|
337
|
+
// keyboard dispatcher hands it every keydown and the root menu's own handler
|
|
338
|
+
// stops seeing them. Which pane the keys then act on is decided in
|
|
339
|
+
// `onSubmenuKeydown`, not here: a hover open leaves the caret where it was.
|
|
340
|
+
this.submenuKeys = this.submenuRef.keydownEvents().subscribe(event => this.onSubmenuKeydown(event));
|
|
341
|
+
// A keyboard open walks INTO the submenu; a hover open only shows it.
|
|
342
|
+
if (this.openedByKeyboard)
|
|
343
|
+
wrFocusMenuItemAt(pane, 0);
|
|
260
344
|
this.submenuOpen = true;
|
|
261
345
|
WrContextMenuItem.openSubmenus.set(this.host.nativeElement, this);
|
|
262
346
|
}
|
|
347
|
+
/**
|
|
348
|
+
* @internal Keys routed here while this submenu is the topmost overlay: the
|
|
349
|
+
* arrows walk the rows of the pane the caret is in, and Escape or the arrow
|
|
350
|
+
* pointing BACK the way the menu cascades steps out one level, returning the
|
|
351
|
+
* cursor to the row that owns the pane when the cursor was inside it.
|
|
352
|
+
*
|
|
353
|
+
* Escape closes this level only, not the whole chain — the APG's rule for a
|
|
354
|
+
* submenu. It reaches this handler rather than the root's because the
|
|
355
|
+
* dispatcher stops at the topmost overlay that listens, which is now this one.
|
|
356
|
+
*
|
|
357
|
+
* Which is also why the arrows are aimed at the pane holding the caret rather
|
|
358
|
+
* than at this one. The dispatcher routes by stacking order, not by focus, and
|
|
359
|
+
* a HOVER-opened submenu is topmost while focus is deliberately still on the
|
|
360
|
+
* root row the pointer swept off (see `openedByKeyboard`) — so ArrowDown used
|
|
361
|
+
* to jump into this pane's first row instead of moving down the menu the user
|
|
362
|
+
* is in. Same reason `wr-dropdown`'s menu handler checks ownership.
|
|
363
|
+
*/
|
|
364
|
+
onSubmenuKeydown(event) {
|
|
365
|
+
const pane = this.submenuRef?.overlayElement;
|
|
366
|
+
if (!pane)
|
|
367
|
+
return;
|
|
368
|
+
// A row inside the pane already acted on this key — its own → into a deeper
|
|
369
|
+
// submenu, or Enter on a leaf. Re-handling it here would close the pane out
|
|
370
|
+
// from under the level it just opened.
|
|
371
|
+
if (event.defaultPrevented)
|
|
372
|
+
return;
|
|
373
|
+
const active = document.activeElement;
|
|
374
|
+
const focusedPane = active instanceof Element ? active.closest('.wr-context-menu-overlay') : null;
|
|
375
|
+
const back = this.isRtl() ? 'ArrowRight' : 'ArrowLeft';
|
|
376
|
+
if (event.key === 'Escape' || event.key === back) {
|
|
377
|
+
event.preventDefault();
|
|
378
|
+
this.disposeSubmenu(false);
|
|
379
|
+
// Onto the owning row only when the caret was in the pane just closed:
|
|
380
|
+
// dismissing a submenu the pointer opened must not drag it off the row the
|
|
381
|
+
// keyboard user is on.
|
|
382
|
+
if (focusedPane === pane)
|
|
383
|
+
this.host.nativeElement.focus();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
// Falls back to this pane when the caret is outside every menu — nothing
|
|
387
|
+
// else can answer, and the navigation opens at the first row from there.
|
|
388
|
+
wrHandleMenuNavigation(focusedPane ?? pane, event);
|
|
389
|
+
}
|
|
263
390
|
/** Bound handlers (= preserves identity for removeEventListener). */
|
|
264
391
|
onSubmenuEnter = () => {
|
|
265
392
|
this.cancelClose();
|
|
@@ -336,6 +463,12 @@ class WrContextMenuItem {
|
|
|
336
463
|
this.submenuRef = null;
|
|
337
464
|
this.submenuOpen = false;
|
|
338
465
|
this.submenuId.set(null);
|
|
466
|
+
// Now, not when the ref is finally disposed 220ms later: an overlay with a
|
|
467
|
+
// keydown subscriber is where CDK's dispatcher STOPS looking, so a pane
|
|
468
|
+
// still listening on its way out would swallow the arrows for the whole
|
|
469
|
+
// exit animation and the root menu would go dead for a quarter of a second.
|
|
470
|
+
this.submenuKeys?.unsubscribe();
|
|
471
|
+
this.submenuKeys = null;
|
|
339
472
|
WrContextMenuItem.openSubmenus.delete(this.host.nativeElement);
|
|
340
473
|
const pane = ref.overlayElement;
|
|
341
474
|
pane.removeEventListener('mouseenter', this.onSubmenuEnter);
|
|
@@ -366,10 +499,10 @@ class WrContextMenuItem {
|
|
|
366
499
|
isRtl() {
|
|
367
500
|
return this.dir?.value === 'rtl';
|
|
368
501
|
}
|
|
369
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
370
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
502
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
503
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: WrContextMenuItem, isStandalone: true, selector: "wr-context-menu-item", inputs: { icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, submenu: { classPropertyName: "submenu", publicName: "submenu", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "menuitem" }, listeners: { "mouseenter": "onMouseEnter()", "mouseleave": "onMouseLeave($event)", "click": "onClick()", "keydown.enter": "activate($event)", "keydown.space": "activate($event)", "keydown.arrowRight": "onArrowRight($event)", "keydown.arrowLeft": "onArrowLeft($event)" }, properties: { "class": "classes()", "attr.tabindex": "-1", "attr.aria-disabled": "disabled() ? true : null", "attr.aria-haspopup": "submenu() ? \"menu\" : null", "attr.aria-expanded": "submenu() ? (submenuOpen ? \"true\" : \"false\") : null", "attr.aria-controls": "submenuId()" } }, ngImport: i0, template: "@if (icon(); as name) {\n <wr-icon class=\"wr-context-menu-item__icon\" [name]=\"name\" size=\"14\" />\n}\n<span class=\"wr-context-menu-item__label\"><ng-content /></span>\n@if (submenu()) {\n <svg\n class=\"wr-icon__svg wr-context-menu-item__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n}\n", dependencies: [{ kind: "component", type: WrIcon, selector: "wr-icon", inputs: ["name"] }], encapsulation: i0.ViewEncapsulation.None });
|
|
371
504
|
}
|
|
372
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
505
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuItem, decorators: [{
|
|
373
506
|
type: Component,
|
|
374
507
|
args: [{ selector: 'wr-context-menu-item', encapsulation: ViewEncapsulation.None, host: {
|
|
375
508
|
role: 'menuitem',
|
|
@@ -395,6 +528,45 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
395
528
|
* Use of this source code is governed by an MIT-style license that can be
|
|
396
529
|
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
397
530
|
*/
|
|
531
|
+
/**
|
|
532
|
+
* Where the menu may hang off the pointer, best first: down-and-inline-start of
|
|
533
|
+
* the cursor (what a native context menu does), then flipped up, then across,
|
|
534
|
+
* then both.
|
|
535
|
+
*
|
|
536
|
+
* The origin is a zero-size POINT, so every `originX` / `originY` resolves to
|
|
537
|
+
* the same coordinate and only the overlay's own corner varies. `overlayX:
|
|
538
|
+
* 'start'` is the logical corner: CDK resolves it against the ambient reading
|
|
539
|
+
* direction, so an RTL page opens the menu to the LEFT of the cursor without a
|
|
540
|
+
* second table.
|
|
541
|
+
*/
|
|
542
|
+
const POINTER_POSITIONS = [
|
|
543
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'top' },
|
|
544
|
+
{ originX: 'start', originY: 'top', overlayX: 'start', overlayY: 'bottom' },
|
|
545
|
+
{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'top' },
|
|
546
|
+
{ originX: 'start', originY: 'top', overlayX: 'end', overlayY: 'bottom' },
|
|
547
|
+
];
|
|
548
|
+
/**
|
|
549
|
+
* The pointer as a CDK origin: a zero-size rect at the click, in VIEWPORT
|
|
550
|
+
* coordinates.
|
|
551
|
+
*
|
|
552
|
+
* Live getters rather than a snapshot, and that is the whole trick. The menu is
|
|
553
|
+
* anchored to the DOCUMENT — as the page scrolls it travels with the content it
|
|
554
|
+
* was opened over (native + PrimeNG behaviour) — while CDK positions against
|
|
555
|
+
* the viewport. Reading the scroll offset at `apply()` time is what converts one
|
|
556
|
+
* into the other, so a re-anchor is nothing but a request to re-apply.
|
|
557
|
+
*/
|
|
558
|
+
function pointerOrigin(pageX, pageY) {
|
|
559
|
+
return {
|
|
560
|
+
width: 0,
|
|
561
|
+
height: 0,
|
|
562
|
+
get x() {
|
|
563
|
+
return pageX - window.scrollX;
|
|
564
|
+
},
|
|
565
|
+
get y() {
|
|
566
|
+
return pageY - window.scrollY;
|
|
567
|
+
},
|
|
568
|
+
};
|
|
569
|
+
}
|
|
398
570
|
/**
|
|
399
571
|
* Attach to any element to show a `<wr-context-menu>` at the pointer
|
|
400
572
|
* position when the user right-clicks or otherwise sends a `contextmenu`
|
|
@@ -440,6 +612,18 @@ class WrContextMenu {
|
|
|
440
612
|
openMenuId = signal(null, /* @ts-ignore */
|
|
441
613
|
...(ngDevMode ? [{ debugName: "openMenuId" }] : /* istanbul ignore next */ []));
|
|
442
614
|
overlayRef = null;
|
|
615
|
+
/**
|
|
616
|
+
* The open menu's subscription to CDK's keyboard dispatcher, held so that
|
|
617
|
+
* `closeOverlay()` can drop it — see the unsubscribe there for why the pane's
|
|
618
|
+
* own disposal is 220 ms too late.
|
|
619
|
+
*/
|
|
620
|
+
rootKeys = null;
|
|
621
|
+
/**
|
|
622
|
+
* Where the keyboard was at the moment this menu took it, so a close can put
|
|
623
|
+
* it back there. Null when it was nowhere in particular (`<body>`) or already
|
|
624
|
+
* inside a menu pane, neither of which is a place to return to.
|
|
625
|
+
*/
|
|
626
|
+
restoreFocusTo = null;
|
|
443
627
|
/**
|
|
444
628
|
* Panes waiting out their exit animation, keyed by the timer that disposes
|
|
445
629
|
* them.
|
|
@@ -590,37 +774,47 @@ class WrContextMenu {
|
|
|
590
774
|
}
|
|
591
775
|
// Overlay
|
|
592
776
|
openOverlay(x, y) {
|
|
593
|
-
//
|
|
594
|
-
//
|
|
595
|
-
//
|
|
596
|
-
//
|
|
597
|
-
|
|
777
|
+
// Read before `wrFocusMenuItemAt` below takes the keyboard: this is the
|
|
778
|
+
// element the close hands it back to. A pane row is not a candidate — a
|
|
779
|
+
// previous menu may still be fading out — and neither is `<body>`, which is
|
|
780
|
+
// where focus already is when nobody has it.
|
|
781
|
+
const active = document.activeElement;
|
|
782
|
+
this.restoreFocusTo =
|
|
783
|
+
active instanceof HTMLElement && active !== document.body && !active.closest('.wr-context-menu-overlay')
|
|
784
|
+
? active
|
|
785
|
+
: null;
|
|
786
|
+
// Anchored to the POINTER, which is not an element — CDK takes a virtual
|
|
787
|
+
// origin for exactly that, and a FLEXIBLE strategy is what makes the menu
|
|
788
|
+
// flip up (or across) instead of hanging off the edge of the screen. It used
|
|
789
|
+
// to be a bare `GlobalPositionStrategy` with the raw coordinates written
|
|
790
|
+
// onto the pane, which never measured the menu against the viewport: a
|
|
791
|
+
// right-click 6px above the bottom of the window put two of the three rows
|
|
792
|
+
// below the fold and clipped the third, since the pane is `position: fixed`
|
|
793
|
+
// and cannot be scrolled to. Submenus have used the flexible strategy from
|
|
794
|
+
// the start (`context-menu-item.ts`); only the root skipped it.
|
|
795
|
+
const positionStrategy = this.overlay
|
|
796
|
+
.position()
|
|
797
|
+
.flexibleConnectedTo(pointerOrigin(x, y))
|
|
798
|
+
// The menu sizes itself; the fallbacks below are the whole answer to a
|
|
799
|
+
// cramped viewport, and `withPush` clamps whatever is left over.
|
|
800
|
+
.withFlexibleDimensions(false)
|
|
801
|
+
.withPush(true)
|
|
802
|
+
.withPositions(POINTER_POSITIONS);
|
|
598
803
|
this.overlayRef = this.overlay.create({
|
|
599
|
-
positionStrategy
|
|
600
|
-
// `noop` so scroll doesn't dismiss the menu
|
|
601
|
-
//
|
|
602
|
-
// visually stays put as the page scrolls underneath.
|
|
804
|
+
positionStrategy,
|
|
805
|
+
// `noop` so scroll doesn't dismiss the menu — `sync()` below re-anchors it
|
|
806
|
+
// instead.
|
|
603
807
|
scrollStrategy: this.scrollStrategies.noop(),
|
|
604
808
|
panelClass: ['wr-context-menu-overlay'],
|
|
605
809
|
});
|
|
606
810
|
const portal = new TemplatePortal(this.menu().contentTpl(), this.vcr);
|
|
607
811
|
this.overlayRef.attach(portal);
|
|
608
|
-
//
|
|
609
|
-
//
|
|
610
|
-
//
|
|
611
|
-
//
|
|
612
|
-
|
|
613
|
-
// - Record the page coords (pageX/pageY = document-relative).
|
|
614
|
-
// - Each frame the user scrolls, set top/left to (pageX/Y minus the
|
|
615
|
-
// current scroll offset). At scroll 0 this matches clientX/Y; as
|
|
616
|
-
// scroll grows the menu shifts up/left visually, which is exactly
|
|
617
|
-
// what `position: absolute` inside an un-fixed container would do
|
|
618
|
-
// naturally — we just have to emulate it manually because CDK's
|
|
619
|
-
// overlay container is `position: fixed`.
|
|
812
|
+
// `attach()` defers CDK's first placement into `afterNextRender`. Place it
|
|
813
|
+
// now: until then the pane sits at the container's top-left corner, and the
|
|
814
|
+
// rows are already in the DOM (see `wrFocusMenuItemAt` below), so the
|
|
815
|
+
// measurement the flip depends on is available.
|
|
816
|
+
this.overlayRef.updatePosition();
|
|
620
817
|
const pane = this.overlayRef.overlayElement;
|
|
621
|
-
pane.style.right = 'auto';
|
|
622
|
-
pane.style.bottom = 'auto';
|
|
623
|
-
pane.style.margin = '0';
|
|
624
818
|
// Name the menu we just opened so the host can point at it. The id is
|
|
625
819
|
// minted per OPEN rather than living on the panel: `closeOverlay()` keeps
|
|
626
820
|
// the previous pane in the DOM for its exit animation, so a re-open would
|
|
@@ -631,11 +825,31 @@ class WrContextMenu {
|
|
|
631
825
|
menuEl.id = randomId('wr-context-menu');
|
|
632
826
|
this.openMenuId.set(menuEl.id);
|
|
633
827
|
}
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
828
|
+
// Re-anchor. `pointerOrigin` reads the scroll offset afresh, so this is all
|
|
829
|
+
// it takes for the menu to travel with the content it was opened over.
|
|
830
|
+
//
|
|
831
|
+
// `reapplyLastPosition()` rather than `updatePosition()`: the flip is
|
|
832
|
+
// decided once, when the menu opens. Re-running the fallback list on every
|
|
833
|
+
// scroll event would let the menu hop from above the cursor to below it and
|
|
834
|
+
// back while the page moves under it, which is a worse reading of "the menu
|
|
835
|
+
// stays where you put it" than a menu that simply slides with the page.
|
|
836
|
+
const sync = () => positionStrategy.reapplyLastPosition();
|
|
837
|
+
// Move the keyboard INTO the menu. Without this the pane painted a
|
|
838
|
+
// `role="menu"` that could be seen and never entered: rows are
|
|
839
|
+
// `tabindex="-1"` (the roving-focus contract) and the pane is not a tab
|
|
840
|
+
// stop, so ArrowDown / Enter / ArrowRight all went to whatever still held
|
|
841
|
+
// focus behind the menu and only Escape worked — the dispatcher routes that
|
|
842
|
+
// one regardless of focus.
|
|
843
|
+
//
|
|
844
|
+
// Unconditional, unlike `wr-dropdown`'s `openedByPointer` gate: there is no
|
|
845
|
+
// hover open here. Every path into this method is a deliberate request for
|
|
846
|
+
// the menu (right-click, Shift+F10, the Menu key, a long-press), which is
|
|
847
|
+
// also when a native context menu takes the keyboard.
|
|
848
|
+
//
|
|
849
|
+
// Synchronous, and it can be: `attach()` above runs the embedded view's
|
|
850
|
+
// first change detection itself (CDK's `attachTemplatePortal`), so the rows
|
|
851
|
+
// and their `[class]` host binding are already in the DOM.
|
|
852
|
+
wrFocusMenuItemAt(pane, 0);
|
|
639
853
|
// Trigger the open transition on the next frame — adding the class
|
|
640
854
|
// synchronously with attach would skip the initial 0→1 frame and
|
|
641
855
|
// the menu would just appear without animating.
|
|
@@ -696,20 +910,39 @@ class WrContextMenu {
|
|
|
696
910
|
return;
|
|
697
911
|
this.closeOverlay();
|
|
698
912
|
});
|
|
699
|
-
this.overlayRef
|
|
913
|
+
this.rootKeys = this.overlayRef
|
|
700
914
|
.keydownEvents()
|
|
701
915
|
.pipe(takeUntilDestroyed(this.destroyRef))
|
|
702
916
|
.subscribe(event => {
|
|
703
917
|
if (event.key === 'Escape') {
|
|
704
918
|
event.preventDefault();
|
|
705
919
|
this.closeOverlay();
|
|
706
|
-
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
if (event.key === 'Tab') {
|
|
923
|
+
// Let focus leave naturally — `closeOverlay()` hands it back to the
|
|
924
|
+
// trigger first, so Tab continues from there instead of from a pane
|
|
925
|
+
// that is about to be removed.
|
|
926
|
+
this.closeOverlay();
|
|
927
|
+
return;
|
|
707
928
|
}
|
|
929
|
+
// A row's own handler already acted on this key (ArrowRight into a
|
|
930
|
+
// submenu, Enter on an item): `preventDefault()` is how it says so, and
|
|
931
|
+
// moving the cursor on top of that would undo it.
|
|
932
|
+
if (event.defaultPrevented)
|
|
933
|
+
return;
|
|
934
|
+
wrHandleMenuNavigation(pane, event);
|
|
708
935
|
});
|
|
709
936
|
}
|
|
710
937
|
closeOverlay() {
|
|
711
938
|
if (!this.overlayRef)
|
|
712
939
|
return;
|
|
940
|
+
// Read up front, before the teardown below starts on the panes: the answer
|
|
941
|
+
// wanted is where the keyboard was at the moment of dismissal.
|
|
942
|
+
const active = document.activeElement;
|
|
943
|
+
const focusWasInside = active instanceof Element && active.closest('.wr-context-menu-overlay') !== null;
|
|
944
|
+
const restoreTo = this.restoreFocusTo;
|
|
945
|
+
this.restoreFocusTo = null;
|
|
713
946
|
this.cancelLeaveTimer();
|
|
714
947
|
// Drop the reference immediately: the pane below stays in the DOM until the
|
|
715
948
|
// exit animation has played, and a trigger still pointing at a menu on its
|
|
@@ -728,6 +961,25 @@ class WrContextMenu {
|
|
|
728
961
|
// class first so the SCSS transition runs back to the default
|
|
729
962
|
// (faded + scaled-down) state, then dispose after the transition.
|
|
730
963
|
pane.classList.remove('wr-context-menu-overlay--open');
|
|
964
|
+
// …and stop it hit-testing on the way out. Fading to `opacity: 0` does not
|
|
965
|
+
// stop a pane receiving pointer events — `.cdk-overlay-pane` sets
|
|
966
|
+
// `pointer-events: auto` — so for the whole 220 ms an invisible menu kept
|
|
967
|
+
// swallowing clicks meant for the page underneath, and a second click on
|
|
968
|
+
// the item just picked (a double-click, or Escape then click) re-ran the
|
|
969
|
+
// consumer's action. Written inline rather than in `styles/_index.scss`
|
|
970
|
+
// because the closing state has no class of its own, and inline beats the
|
|
971
|
+
// CDK's own sheet without an `!important`.
|
|
972
|
+
pane.style.pointerEvents = 'none';
|
|
973
|
+
// …and stop it taking the page's KEYS on the way out, for the same reason
|
|
974
|
+
// and with the same timing. An overlay with a keydown subscriber is where
|
|
975
|
+
// CDK's dispatcher stops looking, and it is removed from the dispatcher only
|
|
976
|
+
// by `detach()` / `dispose()` — which is 220 ms away — so a dismissed menu
|
|
977
|
+
// went on swallowing every keydown on the page: ArrowDown pulled real focus
|
|
978
|
+
// back onto a row of the invisible pane, and a second Escape meant for the
|
|
979
|
+
// dialog underneath was `preventDefault`ed and did nothing.
|
|
980
|
+
// `WrContextMenuItem.disposeSubmenu()` does exactly this; the root had not.
|
|
981
|
+
this.rootKeys?.unsubscribe();
|
|
982
|
+
this.rootKeys = null;
|
|
731
983
|
const timer = setTimeout(() => {
|
|
732
984
|
this.closingPanes.delete(timer);
|
|
733
985
|
ref.dispose();
|
|
@@ -736,6 +988,44 @@ class WrContextMenu {
|
|
|
736
988
|
// Mark immediately so a subsequent right-click opens a fresh menu
|
|
737
989
|
// rather than landing on the disposing one.
|
|
738
990
|
this.overlayRef = null;
|
|
991
|
+
// Hand the keyboard back. The menu takes focus on open, so a dismissal that
|
|
992
|
+
// left it in the pane would strand it on `<body>` once the pane is disposed
|
|
993
|
+
// and the next Tab would restart at the top of the document. Only when the
|
|
994
|
+
// caret was actually in the chain: Escape reaches this overlay from anywhere
|
|
995
|
+
// on the page (CDK's dispatcher routes it by stacking order, not by focus),
|
|
996
|
+
// and a menu nobody was in must not steal the caret from a field they are.
|
|
997
|
+
if (focusWasInside)
|
|
998
|
+
this.handBackFocus(restoreTo);
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* Put the keyboard back where it came from.
|
|
1002
|
+
*
|
|
1003
|
+
* The element that had it when the menu opened comes first: a context menu
|
|
1004
|
+
* hangs on a REGION — a card, a table row — and Shift+F10 / the Menu key fires
|
|
1005
|
+
* `contextmenu` at whatever control inside it the user was actually on, which
|
|
1006
|
+
* is their place in the page.
|
|
1007
|
+
*
|
|
1008
|
+
* The trigger is the fallback, and it needs help to be one. `[wrContextMenu]`
|
|
1009
|
+
* adds no `tabindex` and every shape the docs ship is a plain `<div>`, so
|
|
1010
|
+
* `focus()` on it does nothing at all — the handback silently missed, leaving
|
|
1011
|
+
* the caret in the disposing pane and then on `<body>`, which is the outcome
|
|
1012
|
+
* the call is there to prevent. Lending it `tabindex="-1"` for the call and
|
|
1013
|
+
* taking that back on blur keeps the consumer's DOM as they wrote it; a
|
|
1014
|
+
* permanent `tabindex="0"` would make every right-clickable region a tab stop,
|
|
1015
|
+
* which is their decision and not the library's.
|
|
1016
|
+
*/
|
|
1017
|
+
handBackFocus(previous) {
|
|
1018
|
+
const target = previous?.isConnected && !previous.closest('.wr-context-menu-overlay') ? previous : this.host.nativeElement;
|
|
1019
|
+
target.focus();
|
|
1020
|
+
// Asking whether it took, rather than deciding up front whether it can: the
|
|
1021
|
+
// focusability rules are wide (an `<a>` needs an href, a `<div>` needs a
|
|
1022
|
+
// tabindex, `inert`/`disabled` opt out) and `document.activeElement` answers
|
|
1023
|
+
// all of them at once.
|
|
1024
|
+
if (document.activeElement === target)
|
|
1025
|
+
return;
|
|
1026
|
+
target.setAttribute('tabindex', '-1');
|
|
1027
|
+
target.focus();
|
|
1028
|
+
target.addEventListener('blur', () => target.removeAttribute('tabindex'), { once: true });
|
|
739
1029
|
}
|
|
740
1030
|
cancelLeaveTimer() {
|
|
741
1031
|
if (this.leaveTimer !== null) {
|
|
@@ -750,10 +1040,10 @@ class WrContextMenu {
|
|
|
750
1040
|
this.closeOverlay();
|
|
751
1041
|
}, WrContextMenu.LEAVE_DELAY);
|
|
752
1042
|
}
|
|
753
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
754
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.
|
|
1043
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenu, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
1044
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.2", type: WrContextMenu, isStandalone: true, selector: "[wrContextMenu]", inputs: { menu: { classPropertyName: "menu", publicName: "wrContextMenu", isSignal: true, isRequired: true, transformFunction: null } }, host: { listeners: { "contextmenu": "onContextMenu($event)", "pointerdown": "onPointerDown($event)", "pointermove": "onPointerMove($event)", "pointerup": "onPointerUp()", "pointercancel": "onPointerUp()" }, properties: { "attr.aria-controls": "openMenuId()" }, classAttribute: "wr-context-menu-host" }, ngImport: i0 });
|
|
755
1045
|
}
|
|
756
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
1046
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenu, decorators: [{
|
|
757
1047
|
type: Directive,
|
|
758
1048
|
args: [{
|
|
759
1049
|
selector: '[wrContextMenu]',
|
|
@@ -793,10 +1083,10 @@ class WrContextMenuPanel {
|
|
|
793
1083
|
/** The internal template the directive portals into the overlay. @internal */
|
|
794
1084
|
contentTpl = viewChild.required(TemplateRef, /* @ts-ignore */
|
|
795
1085
|
...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
|
|
796
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
797
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.
|
|
1086
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuPanel, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1087
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "22.1.2", type: WrContextMenuPanel, isStandalone: true, selector: "wr-context-menu", host: { styleAttribute: "display:none" }, viewQueries: [{ propertyName: "contentTpl", first: true, predicate: TemplateRef, descendants: true, isSignal: true }], exportAs: ["wrContextMenu"], ngImport: i0, template: '<ng-template><div class="wr-context-menu" role="menu"><ng-content /></div></ng-template>', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
798
1088
|
}
|
|
799
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
1089
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuPanel, decorators: [{
|
|
800
1090
|
type: Component,
|
|
801
1091
|
args: [{
|
|
802
1092
|
selector: 'wr-context-menu',
|
|
@@ -829,10 +1119,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.1", ngImpor
|
|
|
829
1119
|
* ```
|
|
830
1120
|
*/
|
|
831
1121
|
class WrContextMenuDivider {
|
|
832
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
833
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.
|
|
1122
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1123
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "22.1.2", type: WrContextMenuDivider, isStandalone: true, selector: "wr-context-menu-divider", host: { attributes: { "role": "separator", "aria-orientation": "horizontal" }, classAttribute: "wr-context-menu-divider" }, ngImport: i0, template: '', isInline: true, encapsulation: i0.ViewEncapsulation.None });
|
|
834
1124
|
}
|
|
835
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
1125
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrContextMenuDivider, decorators: [{
|
|
836
1126
|
type: Component,
|
|
837
1127
|
args: [{
|
|
838
1128
|
selector: 'wr-context-menu-divider',
|