ngwr 10.2.1 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -19
- package/action-sheet/styles/_index.scss +4 -1
- package/anchor/styles/_index.scss +6 -5
- package/back-top/styles/_index.scss +6 -1
- package/blur-text/styles/_index.scss +13 -0
- package/button/styles/_index.scss +11 -6
- package/calendar/styles/_index.scss +11 -2
- package/carousel/styles/_index.scss +13 -2
- package/cascader/styles/_index.scss +5 -3
- package/circular-text/styles/_index.scss +2 -0
- package/collapse/styles/_index.scss +1 -1
- package/color-picker/styles/_index.scss +6 -1
- package/command-palette/styles/_index.scss +2 -1
- package/compare/styles/_index.scss +1 -2
- package/context-menu/styles/_index.scss +8 -2
- package/descriptions/styles/_index.scss +2 -2
- package/dialog/styles/_index.scss +7 -0
- package/drawer/styles/_index.scss +20 -1
- package/dropdown/styles/_index.scss +19 -5
- package/empty/styles/_index.scss +10 -0
- package/falling-text/styles/_index.scss +2 -1
- package/fesm2022/ngwr-action-sheet.mjs +13 -3
- package/fesm2022/ngwr-action-sheet.mjs.map +1 -1
- package/fesm2022/ngwr-affix.mjs +40 -13
- package/fesm2022/ngwr-affix.mjs.map +1 -1
- package/fesm2022/ngwr-anchor.mjs +18 -6
- package/fesm2022/ngwr-anchor.mjs.map +1 -1
- package/fesm2022/ngwr-aurora.mjs +2 -2
- package/fesm2022/ngwr-aurora.mjs.map +1 -1
- package/fesm2022/ngwr-avatar.mjs +31 -7
- package/fesm2022/ngwr-avatar.mjs.map +1 -1
- package/fesm2022/ngwr-back-top.mjs +6 -2
- package/fesm2022/ngwr-back-top.mjs.map +1 -1
- package/fesm2022/ngwr-badge.mjs +1 -1
- package/fesm2022/ngwr-badge.mjs.map +1 -1
- package/fesm2022/ngwr-bar-chart.mjs +30 -9
- package/fesm2022/ngwr-bar-chart.mjs.map +1 -1
- package/fesm2022/ngwr-blur-text.mjs +2 -2
- package/fesm2022/ngwr-blur-text.mjs.map +1 -1
- package/fesm2022/ngwr-border-glow.mjs +2 -2
- package/fesm2022/ngwr-border-glow.mjs.map +1 -1
- package/fesm2022/ngwr-breadcrumbs.mjs +2 -2
- package/fesm2022/ngwr-breadcrumbs.mjs.map +1 -1
- package/fesm2022/ngwr-burger.mjs +9 -4
- package/fesm2022/ngwr-burger.mjs.map +1 -1
- package/fesm2022/ngwr-button-testing.mjs +96 -0
- package/fesm2022/ngwr-button-testing.mjs.map +1 -0
- package/fesm2022/ngwr-button.mjs +31 -14
- package/fesm2022/ngwr-button.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +40 -8
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +20 -1
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +2 -2
- package/fesm2022/ngwr-card.mjs.map +1 -1
- package/fesm2022/ngwr-carousel-testing.mjs +377 -0
- package/fesm2022/ngwr-carousel-testing.mjs.map +1 -0
- package/fesm2022/ngwr-carousel.mjs +67 -13
- package/fesm2022/ngwr-carousel.mjs.map +1 -1
- package/fesm2022/ngwr-cascader-testing.mjs +534 -0
- package/fesm2022/ngwr-cascader-testing.mjs.map +1 -0
- package/fesm2022/ngwr-cascader.mjs +2 -2
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox-testing.mjs +90 -0
- package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -0
- package/fesm2022/ngwr-checkbox.mjs +9 -3
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +2 -2
- package/fesm2022/ngwr-circular-text.mjs.map +1 -1
- package/fesm2022/ngwr-click-spark.mjs +2 -2
- package/fesm2022/ngwr-click-spark.mjs.map +1 -1
- package/fesm2022/ngwr-collapse-testing.mjs +368 -0
- package/fesm2022/ngwr-collapse-testing.mjs.map +1 -0
- package/fesm2022/ngwr-color-picker.mjs +134 -14
- package/fesm2022/ngwr-color-picker.mjs.map +1 -1
- package/fesm2022/ngwr-command-palette-testing.mjs +589 -0
- package/fesm2022/ngwr-command-palette-testing.mjs.map +1 -0
- package/fesm2022/ngwr-command-palette.mjs +58 -8
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +103 -13
- package/fesm2022/ngwr-compare.mjs.map +1 -1
- package/fesm2022/ngwr-config.mjs +106 -0
- package/fesm2022/ngwr-config.mjs.map +1 -0
- package/fesm2022/ngwr-context-menu-testing.mjs +631 -0
- package/fesm2022/ngwr-context-menu-testing.mjs.map +1 -0
- package/fesm2022/ngwr-context-menu.mjs +94 -8
- package/fesm2022/ngwr-context-menu.mjs.map +1 -1
- package/fesm2022/ngwr-cookie.mjs +5 -1
- package/fesm2022/ngwr-cookie.mjs.map +1 -1
- package/fesm2022/ngwr-counter.mjs +11 -3
- package/fesm2022/ngwr-counter.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter-luxon.mjs +52 -4
- package/fesm2022/ngwr-date-adapter-luxon.mjs.map +1 -1
- package/fesm2022/ngwr-date-adapter.mjs +54 -8
- package/fesm2022/ngwr-date-adapter.mjs.map +1 -1
- package/fesm2022/ngwr-date-picker-testing.mjs +766 -0
- package/fesm2022/ngwr-date-picker-testing.mjs.map +1 -0
- package/fesm2022/ngwr-date-picker.mjs +73 -3
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-decrypt-text.mjs +27 -9
- package/fesm2022/ngwr-decrypt-text.mjs.map +1 -1
- package/fesm2022/ngwr-dialog-testing.mjs +89 -0
- package/fesm2022/ngwr-dialog-testing.mjs.map +1 -0
- package/fesm2022/ngwr-directives.mjs +36 -12
- package/fesm2022/ngwr-directives.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +22 -5
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +2 -2
- package/fesm2022/ngwr-drag-drop.mjs.map +1 -1
- package/fesm2022/ngwr-drawer-testing.mjs +250 -0
- package/fesm2022/ngwr-drawer-testing.mjs.map +1 -0
- package/fesm2022/ngwr-dropdown-testing.mjs +291 -0
- package/fesm2022/ngwr-dropdown-testing.mjs.map +1 -0
- package/fesm2022/ngwr-dropdown.mjs +10 -2
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +24 -7
- package/fesm2022/ngwr-empty.mjs.map +1 -1
- package/fesm2022/ngwr-event-calendar.mjs +57 -10
- package/fesm2022/ngwr-event-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-falling-text.mjs +2 -2
- package/fesm2022/ngwr-falling-text.mjs.map +1 -1
- package/fesm2022/ngwr-file-upload-testing.mjs +332 -0
- package/fesm2022/ngwr-file-upload-testing.mjs.map +1 -0
- package/fesm2022/ngwr-form-testing.mjs +451 -0
- package/fesm2022/ngwr-form-testing.mjs.map +1 -0
- package/fesm2022/ngwr-form.mjs +19 -3
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +9 -2
- package/fesm2022/ngwr-fuzzy-text.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +19 -5
- package/fesm2022/ngwr-gauge.mjs.map +1 -1
- package/fesm2022/ngwr-glitch-text.mjs +2 -2
- package/fesm2022/ngwr-glitch-text.mjs.map +1 -1
- package/fesm2022/ngwr-gradient-text.mjs +2 -2
- package/fesm2022/ngwr-gradient-text.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +50 -0
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +48 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-image-cropper.mjs +23 -0
- package/fesm2022/ngwr-image-cropper.mjs.map +1 -1
- package/fesm2022/ngwr-input-number-testing.mjs +306 -0
- package/fesm2022/ngwr-input-number-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input-number.mjs +35 -3
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp-testing.mjs +419 -0
- package/fesm2022/ngwr-input-otp-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input-otp.mjs +36 -5
- package/fesm2022/ngwr-input-otp.mjs.map +1 -1
- package/fesm2022/ngwr-input-testing.mjs +102 -0
- package/fesm2022/ngwr-input-testing.mjs.map +1 -0
- package/fesm2022/ngwr-input.mjs +47 -10
- package/fesm2022/ngwr-input.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +44 -8
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +21 -5
- package/fesm2022/ngwr-layout.mjs.map +1 -1
- package/fesm2022/ngwr-lightbox.mjs +33 -6
- package/fesm2022/ngwr-lightbox.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +17 -4
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +2 -2
- package/fesm2022/ngwr-list.mjs.map +1 -1
- package/fesm2022/ngwr-loading-bar.mjs +2 -2
- package/fesm2022/ngwr-loading-bar.mjs.map +1 -1
- package/fesm2022/ngwr-markdown-testing.mjs +516 -0
- package/fesm2022/ngwr-markdown-testing.mjs.map +1 -0
- package/fesm2022/ngwr-markdown.mjs +1492 -0
- package/fesm2022/ngwr-markdown.mjs.map +1 -0
- package/fesm2022/ngwr-marquee.mjs +17 -6
- package/fesm2022/ngwr-marquee.mjs.map +1 -1
- package/fesm2022/ngwr-mention-testing.mjs +513 -0
- package/fesm2022/ngwr-mention-testing.mjs.map +1 -0
- package/fesm2022/ngwr-mention.mjs +10 -1
- package/fesm2022/ngwr-mention.mjs.map +1 -1
- package/fesm2022/ngwr-meta.mjs +22 -7
- package/fesm2022/ngwr-meta.mjs.map +1 -1
- package/fesm2022/ngwr-meter-group.mjs +19 -5
- package/fesm2022/ngwr-meter-group.mjs.map +1 -1
- package/fesm2022/ngwr-overlay.mjs +41 -1
- package/fesm2022/ngwr-overlay.mjs.map +1 -1
- package/fesm2022/ngwr-pagination-testing.mjs +389 -0
- package/fesm2022/ngwr-pagination-testing.mjs.map +1 -0
- package/fesm2022/ngwr-pagination.mjs +14 -2
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-popconfirm-testing.mjs +309 -0
- package/fesm2022/ngwr-popconfirm-testing.mjs.map +1 -0
- package/fesm2022/ngwr-popconfirm.mjs +95 -17
- package/fesm2022/ngwr-popconfirm.mjs.map +1 -1
- package/fesm2022/ngwr-popover-testing.mjs +316 -0
- package/fesm2022/ngwr-popover-testing.mjs.map +1 -0
- package/fesm2022/ngwr-popover.mjs +21 -3
- package/fesm2022/ngwr-popover.mjs.map +1 -1
- package/fesm2022/ngwr-pull-to-refresh.mjs +17 -2
- package/fesm2022/ngwr-pull-to-refresh.mjs.map +1 -1
- package/fesm2022/ngwr-qr.mjs +13 -3
- package/fesm2022/ngwr-qr.mjs.map +1 -1
- package/fesm2022/ngwr-radio-testing.mjs +392 -0
- package/fesm2022/ngwr-radio-testing.mjs.map +1 -0
- package/fesm2022/ngwr-radio.mjs +10 -3
- package/fesm2022/ngwr-radio.mjs.map +1 -1
- package/fesm2022/ngwr-rating-testing.mjs +384 -0
- package/fesm2022/ngwr-rating-testing.mjs.map +1 -0
- package/fesm2022/ngwr-rating.mjs +37 -2
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-segmented-testing.mjs +512 -0
- package/fesm2022/ngwr-segmented-testing.mjs.map +1 -0
- package/fesm2022/ngwr-select-testing.mjs +268 -0
- package/fesm2022/ngwr-select-testing.mjs.map +1 -0
- package/fesm2022/ngwr-select.mjs +87 -16
- package/fesm2022/ngwr-select.mjs.map +1 -1
- package/fesm2022/ngwr-shiny-text.mjs +2 -2
- package/fesm2022/ngwr-shiny-text.mjs.map +1 -1
- package/fesm2022/ngwr-sidebar.mjs +65 -12
- package/fesm2022/ngwr-sidebar.mjs.map +1 -1
- package/fesm2022/ngwr-slider-testing.mjs +478 -0
- package/fesm2022/ngwr-slider-testing.mjs.map +1 -0
- package/fesm2022/ngwr-slider.mjs +57 -13
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +26 -6
- package/fesm2022/ngwr-sparkline.mjs.map +1 -1
- package/fesm2022/ngwr-speed-dial.mjs +37 -4
- package/fesm2022/ngwr-speed-dial.mjs.map +1 -1
- package/fesm2022/ngwr-spinner.mjs +12 -3
- package/fesm2022/ngwr-spinner.mjs.map +1 -1
- package/fesm2022/ngwr-splash-cursor.mjs +2 -2
- package/fesm2022/ngwr-splash-cursor.mjs.map +1 -1
- package/fesm2022/ngwr-split-text.mjs +2 -2
- package/fesm2022/ngwr-split-text.mjs.map +1 -1
- package/fesm2022/ngwr-splitter.mjs +70 -9
- package/fesm2022/ngwr-splitter.mjs.map +1 -1
- package/fesm2022/ngwr-spotlight-card.mjs +2 -2
- package/fesm2022/ngwr-spotlight-card.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +2 -2
- package/fesm2022/ngwr-star-border.mjs.map +1 -1
- package/fesm2022/ngwr-statistic.mjs +24 -7
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper-testing.mjs +477 -0
- package/fesm2022/ngwr-stepper-testing.mjs.map +1 -0
- package/fesm2022/ngwr-switch-testing.mjs +77 -0
- package/fesm2022/ngwr-switch-testing.mjs.map +1 -0
- package/fesm2022/ngwr-switch.mjs +9 -3
- package/fesm2022/ngwr-switch.mjs.map +1 -1
- package/fesm2022/ngwr-table-testing.mjs +580 -0
- package/fesm2022/ngwr-table-testing.mjs.map +1 -0
- package/fesm2022/ngwr-table.mjs +87 -14
- package/fesm2022/ngwr-table.mjs.map +1 -1
- package/fesm2022/ngwr-tabs-testing.mjs +617 -0
- package/fesm2022/ngwr-tabs-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tabs.mjs +38 -6
- package/fesm2022/ngwr-tabs.mjs.map +1 -1
- package/fesm2022/ngwr-textarea-testing.mjs +238 -0
- package/fesm2022/ngwr-textarea-testing.mjs.map +1 -0
- package/fesm2022/ngwr-textarea.mjs +32 -4
- package/fesm2022/ngwr-textarea.mjs.map +1 -1
- package/fesm2022/ngwr-tilt-card.mjs +2 -2
- package/fesm2022/ngwr-tilt-card.mjs.map +1 -1
- package/fesm2022/ngwr-toast-testing.mjs +101 -0
- package/fesm2022/ngwr-toast-testing.mjs.map +1 -0
- package/fesm2022/ngwr-toast.mjs +2 -2
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-tour.mjs +61 -9
- package/fesm2022/ngwr-tour.mjs.map +1 -1
- package/fesm2022/ngwr-transfer-testing.mjs +538 -0
- package/fesm2022/ngwr-transfer-testing.mjs.map +1 -0
- package/fesm2022/ngwr-transfer.mjs +45 -14
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree-testing.mjs +734 -0
- package/fesm2022/ngwr-tree-testing.mjs.map +1 -0
- package/fesm2022/ngwr-tree.mjs +73 -7
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +5 -3
- package/fesm2022/ngwr-typewriter.mjs.map +1 -1
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +31 -5
- package/fesm2022/ngwr-virtual-scroll.mjs.map +1 -1
- package/fesm2022/ngwr-waves.mjs +3 -3
- package/fesm2022/ngwr-waves.mjs.map +1 -1
- package/fesm2022/ngwr-window.mjs +8 -0
- package/fesm2022/ngwr-window.mjs.map +1 -1
- package/file-upload/styles/_index.scss +7 -2
- package/gauge/styles/_index.scss +1 -1
- package/glitch-text/styles/_index.scss +4 -0
- package/i18n/en.json +48 -0
- package/i18n/ru.json +48 -0
- package/image-cropper/styles/_index.scss +13 -1
- package/input/styles/_index.scss +2 -2
- package/input-number/styles/_index.scss +7 -2
- package/knob/styles/_index.scss +8 -1
- package/layout/styles/_index.scss +3 -3
- package/lightbox/styles/_index.scss +10 -2
- package/line-chart/styles/_index.scss +6 -0
- package/llms-full.txt +151 -4
- package/llms.txt +57 -8
- package/loading-bar/styles/_index.scss +1 -2
- package/markdown/styles/_index.scss +296 -0
- package/marquee/styles/_index.scss +12 -0
- package/mcp/api.js +512 -0
- package/mcp/catalog.js +157 -0
- package/mcp/server.js +273 -0
- package/mcp/tools.js +366 -0
- package/meter-group/styles/_index.scss +1 -1
- package/package.json +186 -35
- package/pagination/styles/_index.scss +6 -6
- package/popover/styles/_index.scss +37 -5
- package/rating/styles/_index.scss +10 -0
- package/result/styles/_index.scss +3 -1
- package/schematics/use/symbol-map.json +2 -0
- package/segmented/styles/_index.scss +12 -1
- package/select/styles/_index.scss +32 -10
- package/sidebar/styles/_index.scss +30 -5
- package/slider/styles/_index.scss +15 -0
- package/speed-dial/styles/_index.scss +20 -0
- package/split-text/styles/_index.scss +13 -0
- package/star-border/styles/_index.scss +2 -0
- package/stepper/styles/_index.scss +19 -3
- package/styles/_grid.scss +4 -4
- package/styles.scss +1 -0
- package/switch/styles/_index.scss +5 -3
- package/table/styles/_index.scss +25 -12
- package/tabs/styles/_index.scss +11 -1
- package/textarea/styles/_index.scss +5 -0
- package/theme/styles/_colors.scss +44 -15
- package/theme/styles/_dark.scss +35 -15
- package/theme/styles/_mixins.scss +3 -0
- package/timeline/styles/_index.scss +2 -2
- package/toast/styles/_index.scss +17 -8
- package/toolbar/styles/_index.scss +3 -3
- package/tour/styles/_index.scss +7 -1
- package/tree/styles/_index.scss +9 -5
- package/types/ngwr-action-sheet.d.ts +9 -1
- package/types/ngwr-affix.d.ts +7 -1
- package/types/ngwr-anchor.d.ts +8 -1
- package/types/ngwr-avatar.d.ts +13 -3
- package/types/ngwr-bar-chart.d.ts +16 -0
- package/types/ngwr-burger.d.ts +6 -2
- package/types/ngwr-button-testing.d.ts +85 -0
- package/types/ngwr-button.d.ts +26 -10
- package/types/ngwr-calendar-heatmap.d.ts +16 -2
- package/types/ngwr-calendar.d.ts +10 -0
- package/types/ngwr-carousel-testing.d.ts +257 -0
- package/types/ngwr-carousel.d.ts +20 -4
- package/types/ngwr-cascader-testing.d.ts +392 -0
- package/types/ngwr-checkbox-testing.d.ts +77 -0
- package/types/ngwr-checkbox.d.ts +7 -2
- package/types/ngwr-collapse-testing.d.ts +290 -0
- package/types/ngwr-color-picker.d.ts +20 -11
- package/types/ngwr-command-palette-testing.d.ts +437 -0
- package/types/ngwr-command-palette.d.ts +25 -2
- package/types/ngwr-compare.d.ts +50 -2
- package/types/ngwr-config.d.ts +176 -0
- package/types/ngwr-context-menu-testing.d.ts +401 -0
- package/types/ngwr-context-menu.d.ts +65 -17
- package/types/ngwr-counter.d.ts +6 -1
- package/types/ngwr-date-adapter-luxon.d.ts +26 -0
- package/types/ngwr-date-picker-testing.d.ts +518 -0
- package/types/ngwr-date-picker.d.ts +4 -0
- package/types/ngwr-dialog-testing.d.ts +79 -0
- package/types/ngwr-directives.d.ts +10 -1
- package/types/ngwr-donut-chart.d.ts +8 -1
- package/types/ngwr-drawer-testing.d.ts +196 -0
- package/types/ngwr-dropdown-testing.d.ts +202 -0
- package/types/ngwr-dropdown.d.ts +7 -1
- package/types/ngwr-empty.d.ts +19 -4
- package/types/ngwr-event-calendar.d.ts +26 -1
- package/types/ngwr-file-upload-testing.d.ts +194 -0
- package/types/ngwr-form-testing.d.ts +379 -0
- package/types/ngwr-form.d.ts +17 -0
- package/types/ngwr-gauge.d.ts +13 -1
- package/types/ngwr-image-cropper.d.ts +10 -0
- package/types/ngwr-input-number-testing.d.ts +226 -0
- package/types/ngwr-input-number.d.ts +29 -1
- package/types/ngwr-input-otp-testing.d.ts +299 -0
- package/types/ngwr-input-otp.d.ts +23 -2
- package/types/ngwr-input-testing.d.ts +84 -0
- package/types/ngwr-input.d.ts +20 -6
- package/types/ngwr-knob.d.ts +18 -0
- package/types/ngwr-layout.d.ts +1 -0
- package/types/ngwr-lightbox.d.ts +17 -3
- package/types/ngwr-line-chart.d.ts +9 -2
- package/types/ngwr-markdown-testing.d.ts +462 -0
- package/types/ngwr-markdown.d.ts +534 -0
- package/types/ngwr-marquee.d.ts +12 -2
- package/types/ngwr-mention-testing.d.ts +359 -0
- package/types/ngwr-meta.d.ts +4 -2
- package/types/ngwr-meter-group.d.ts +11 -1
- package/types/ngwr-overlay.d.ts +33 -2
- package/types/ngwr-pagination-testing.d.ts +291 -0
- package/types/ngwr-pagination.d.ts +1 -0
- package/types/ngwr-popconfirm-testing.d.ts +235 -0
- package/types/ngwr-popconfirm.d.ts +31 -21
- package/types/ngwr-popover-testing.d.ts +221 -0
- package/types/ngwr-popover.d.ts +9 -0
- package/types/ngwr-pull-to-refresh.d.ts +7 -0
- package/types/ngwr-qr.d.ts +9 -1
- package/types/ngwr-radio-testing.d.ts +296 -0
- package/types/ngwr-radio.d.ts +8 -2
- package/types/ngwr-rating-testing.d.ts +291 -0
- package/types/ngwr-rating.d.ts +23 -0
- package/types/ngwr-segmented-testing.d.ts +401 -0
- package/types/ngwr-select-testing.d.ts +175 -0
- package/types/ngwr-select.d.ts +45 -4
- package/types/ngwr-sidebar.d.ts +17 -2
- package/types/ngwr-slider-testing.d.ts +329 -0
- package/types/ngwr-slider.d.ts +35 -1
- package/types/ngwr-sparkline.d.ts +12 -2
- package/types/ngwr-speed-dial.d.ts +17 -18
- package/types/ngwr-spinner.d.ts +8 -1
- package/types/ngwr-splitter.d.ts +24 -1
- package/types/ngwr-statistic.d.ts +12 -2
- package/types/ngwr-stepper-testing.d.ts +346 -0
- package/types/ngwr-switch-testing.d.ts +66 -0
- package/types/ngwr-switch.d.ts +7 -2
- package/types/ngwr-table-testing.d.ts +423 -0
- package/types/ngwr-table.d.ts +42 -0
- package/types/ngwr-tabs-testing.d.ts +470 -0
- package/types/ngwr-tabs.d.ts +9 -0
- package/types/ngwr-textarea-testing.d.ts +184 -0
- package/types/ngwr-textarea.d.ts +7 -2
- package/types/ngwr-toast-testing.d.ts +80 -0
- package/types/ngwr-tour.d.ts +27 -0
- package/types/ngwr-transfer-testing.d.ts +444 -0
- package/types/ngwr-transfer.d.ts +16 -1
- package/types/ngwr-tree-testing.d.ts +501 -0
- package/types/ngwr-tree.d.ts +33 -0
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-virtual-scroll.d.ts +13 -1
- package/typewriter/styles/_index.scss +1 -1
- package/typography/styles/_index.scss +1 -1
- package/window/styles/_index.scss +32 -9
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Narrows which `<wr-file-upload>` a harness query matches. */
|
|
11
|
+
interface WrFileUploadHarnessFilters extends BaseHarnessFilters {
|
|
12
|
+
/**
|
|
13
|
+
* Match the drop zone's accessible name — a string is an exact match, a RegExp
|
|
14
|
+
* is tested. This is `dropZoneLabel`, not the visible CTA: the zone carries an
|
|
15
|
+
* `aria-label`, so the copy inside it is not what identifies the control.
|
|
16
|
+
*/
|
|
17
|
+
readonly label?: string | RegExp;
|
|
18
|
+
/** Match only single-file (`false`) or only multi-file (`true`) uploads. */
|
|
19
|
+
readonly multiple?: boolean;
|
|
20
|
+
/** Match only enabled (`false`) or only disabled (`true`) uploads. */
|
|
21
|
+
readonly disabled?: boolean;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @license
|
|
26
|
+
*
|
|
27
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
28
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Test harness for `<wr-file-upload>`.
|
|
33
|
+
*
|
|
34
|
+
* The control a user operates is the `.wr-file-upload__zone` — a `role="button"`
|
|
35
|
+
* div that is the single tab stop; the `<input type="file">` behind it is
|
|
36
|
+
* `aria-hidden` and `tabindex="-1"`, and exists only so a click can be forwarded
|
|
37
|
+
* to it. So focus, drag and disabled state are all read off the zone, plus the
|
|
38
|
+
* `wr-file-upload--*` host modifiers and the rendered file list. The picker is
|
|
39
|
+
* touched only where it is the one that carries the state — `accept` and
|
|
40
|
+
* `multiple` land on it, and {@link selectFiles} has to hand it the files.
|
|
41
|
+
*
|
|
42
|
+
* What this component does NOT have, so this harness does not either:
|
|
43
|
+
* - **no per-file progress or status.** `<wr-file-upload>` picks files; uploading
|
|
44
|
+
* them is the app's job, and there is no bar or state to read.
|
|
45
|
+
* - **no rendered error.** A file refused for its type, its size or the file count
|
|
46
|
+
* leaves NOTHING in the DOM — no `aria-invalid`, no message, and a list that
|
|
47
|
+
* simply did not grow. The `(rejected)` output is the only channel, so a spec
|
|
48
|
+
* asserts on the host's handler. See {@link selectFiles}.
|
|
49
|
+
* - **no `maxSize` / `maxFiles` readback.** Neither reaches the DOM (unlike
|
|
50
|
+
* `accept` and `multiple`, which land on the picker), so they can only be
|
|
51
|
+
* observed by offering a file that breaks them.
|
|
52
|
+
*
|
|
53
|
+
* Two traps worth knowing before writing assertions. The bound value's SHAPE
|
|
54
|
+
* follows `multiple` — a bare `File` (or `null`) in single mode, a `File[]` in
|
|
55
|
+
* multi — and `[showList]="false"` renders no list at all, so {@link getFileNames}
|
|
56
|
+
* answers `[]` for a component that is holding files. Assert the bound value in
|
|
57
|
+
* that case.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* const upload = await loader.getHarness(WrFileUploadHarness.with({ label: 'Avatar' }));
|
|
62
|
+
* await upload.selectFiles(new File(['…'], 'me.png', { type: 'image/png' }));
|
|
63
|
+
*
|
|
64
|
+
* expect(await upload.getFileNames()).toEqual(['me.png']);
|
|
65
|
+
* await upload.removeFileNamed('me.png');
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @see https://ngwr.dev/guides/testing
|
|
69
|
+
*/
|
|
70
|
+
declare class WrFileUploadHarness extends ComponentHarness {
|
|
71
|
+
static hostSelector: string;
|
|
72
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
73
|
+
static with(options?: WrFileUploadHarnessFilters): HarnessPredicate<WrFileUploadHarness>;
|
|
74
|
+
private readonly zone;
|
|
75
|
+
private readonly picker;
|
|
76
|
+
private readonly items;
|
|
77
|
+
private readonly names;
|
|
78
|
+
private readonly sizes;
|
|
79
|
+
private readonly removeButtons;
|
|
80
|
+
/**
|
|
81
|
+
* The accessible name of the trigger — what a screen-reader user is told this
|
|
82
|
+
* control is.
|
|
83
|
+
*
|
|
84
|
+
* Read from the zone's `aria-label` (the `dropZoneLabel` input) rather than from
|
|
85
|
+
* the copy inside it, because that label OVERRIDES the copy: the visible "Click
|
|
86
|
+
* to browse" is not the accessible name, and a harness that returned it would
|
|
87
|
+
* describe a control nobody is announced.
|
|
88
|
+
*/
|
|
89
|
+
getLabel(): Promise<string>;
|
|
90
|
+
/** The visible call-to-action line — the `pickLabel` input. */
|
|
91
|
+
getPickText(): Promise<string>;
|
|
92
|
+
/** The visible instruction below the CTA — the `dropLabel` input. */
|
|
93
|
+
getDropText(): Promise<string>;
|
|
94
|
+
/** The optional `helperText` line, or `null` when the component was given none. */
|
|
95
|
+
getHelperText(): Promise<string | null>;
|
|
96
|
+
/** The `accept` list the picker advertises, or `null` when it accepts anything. */
|
|
97
|
+
getAccept(): Promise<string | null>;
|
|
98
|
+
/**
|
|
99
|
+
* Whether more than one file can be held.
|
|
100
|
+
*
|
|
101
|
+
* Read as the DOM PROPERTY: the template writes the attribute as an empty string
|
|
102
|
+
* (`[attr.multiple]="multiple() ? '' : null"`), and `''` is falsy — an attribute
|
|
103
|
+
* read would report a multi-file upload as single.
|
|
104
|
+
*/
|
|
105
|
+
isMultiple(): Promise<boolean>;
|
|
106
|
+
/**
|
|
107
|
+
* Whether the control refuses interaction.
|
|
108
|
+
*
|
|
109
|
+
* Read from the zone's `aria-disabled`. The host also carries
|
|
110
|
+
* `wr-file-upload--disabled` and the picker its own `disabled`, but the zone is
|
|
111
|
+
* a `role="button"` div — `aria-disabled` is the only one of the three that
|
|
112
|
+
* tells a screen-reader user the trigger is inert.
|
|
113
|
+
*/
|
|
114
|
+
isDisabled(): Promise<boolean>;
|
|
115
|
+
/**
|
|
116
|
+
* Whether the zone is armed for a drop.
|
|
117
|
+
*
|
|
118
|
+
* The `wr-file-upload--dragging` host modifier is the whole signal — a drop
|
|
119
|
+
* target has no ARIA state, so there is nothing better to read here.
|
|
120
|
+
*/
|
|
121
|
+
isDragging(): Promise<boolean>;
|
|
122
|
+
/** How many files the list is RENDERING. Zero with `[showList]="false"`, always. */
|
|
123
|
+
getFileCount(): Promise<number>;
|
|
124
|
+
/** The file names in the rendered list, in order. */
|
|
125
|
+
getFileNames(): Promise<string[]>;
|
|
126
|
+
/**
|
|
127
|
+
* The file sizes in the rendered list, as SHOWN — `'4.9 KB'`, not `5000`.
|
|
128
|
+
*
|
|
129
|
+
* The component formats bytes for display and the byte count never reaches the
|
|
130
|
+
* DOM, so this is the string a user reads. Assert the `File` itself if the exact
|
|
131
|
+
* size matters.
|
|
132
|
+
*/
|
|
133
|
+
getFileSizes(): Promise<string[]>;
|
|
134
|
+
/**
|
|
135
|
+
* Hand files to the picker, the way choosing them in the browser dialog does.
|
|
136
|
+
*
|
|
137
|
+
* This is the one method that reaches past `TestElement` to the native
|
|
138
|
+
* `<input type="file">`, and it has to: `TestElement` has no file API, and it
|
|
139
|
+
* cannot grow one portably, because a `FileList` is not constructible and a
|
|
140
|
+
* remote WebDriver session cannot be handed a `File` object at all. Everything
|
|
141
|
+
* else on this harness is environment-agnostic; this needs a DOM behind it
|
|
142
|
+
* (`TestbedHarnessEnvironment`), and says so with an error when it does not have
|
|
143
|
+
* one. The input is found through this harness's own locator rather than a
|
|
144
|
+
* `document` query, so it is still THIS component's picker that gets the files.
|
|
145
|
+
*
|
|
146
|
+
* Rejected files are silent: nothing appears in the DOM, so pair this with the
|
|
147
|
+
* host's `(rejected)` handler when a file is meant to be refused. In single mode
|
|
148
|
+
* the LAST accepted file wins, which is also how a drop of several files onto a
|
|
149
|
+
* single-file zone behaves.
|
|
150
|
+
*
|
|
151
|
+
* @throws if called with no files, on a disabled upload, or outside a DOM
|
|
152
|
+
* environment.
|
|
153
|
+
*/
|
|
154
|
+
selectFiles(...files: File[]): Promise<void>;
|
|
155
|
+
/**
|
|
156
|
+
* Drag files over the zone and drop them.
|
|
157
|
+
*
|
|
158
|
+
* Driven by dispatching the drag sequence AT the zone rather than by coordinates:
|
|
159
|
+
* nothing has layout in a unit test — `getBoundingClientRect` is all zeros — so a
|
|
160
|
+
* pointer-driven drag would land nowhere. From the component's side it is the
|
|
161
|
+
* same event either way; it reads `dataTransfer.files` and never a position.
|
|
162
|
+
*
|
|
163
|
+
* A disabled upload refuses the drop itself, so this stays a no-op there rather
|
|
164
|
+
* than throwing the way {@link selectFiles} does — that refusal is the
|
|
165
|
+
* component's own, and worth asserting.
|
|
166
|
+
*/
|
|
167
|
+
dropFiles(...files: File[]): Promise<void>;
|
|
168
|
+
/** Drag over the zone without letting go — arms {@link isDragging}. */
|
|
169
|
+
dragOver(): Promise<void>;
|
|
170
|
+
/**
|
|
171
|
+
* Drag back out of the zone, disarming {@link isDragging}.
|
|
172
|
+
*
|
|
173
|
+
* Dispatched at the zone itself on purpose: the component ignores a `dragleave`
|
|
174
|
+
* whose target is one of the zone's children, because crossing the icon or the
|
|
175
|
+
* hint text is not leaving the zone.
|
|
176
|
+
*/
|
|
177
|
+
dragLeave(): Promise<void>;
|
|
178
|
+
/**
|
|
179
|
+
* Remove the file at `index` from the rendered list.
|
|
180
|
+
*
|
|
181
|
+
* On a disabled upload the remove buttons are disabled too, so this is a no-op
|
|
182
|
+
* there — assert the result rather than assuming it.
|
|
183
|
+
*/
|
|
184
|
+
removeFile(index: number): Promise<void>;
|
|
185
|
+
/** Remove the file with this name. Names come from {@link getFileNames}. */
|
|
186
|
+
removeFileNamed(name: string): Promise<void>;
|
|
187
|
+
/** Move keyboard focus to the zone — the control's only tab stop. */
|
|
188
|
+
focus(): Promise<void>;
|
|
189
|
+
/** Whether the zone has focus. */
|
|
190
|
+
isFocused(): Promise<boolean>;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export { WrFileUploadHarness };
|
|
194
|
+
export type { WrFileUploadHarnessFilters };
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
import { BaseHarnessFilters, ContentContainerComponentHarness, HarnessPredicate, HarnessLoader } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @license
|
|
5
|
+
*
|
|
6
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
7
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Where a visible message came from, as far as the DOM can tell.
|
|
11
|
+
*
|
|
12
|
+
* - `projected` — a `<wr-form-error key="…">` the consumer wrote. It is its own
|
|
13
|
+
* element, so this one IS distinguishable.
|
|
14
|
+
* - `resolved` — the field rendered it from the copy chain
|
|
15
|
+
* (`provideWrFormErrors()` → the `ngwr/i18n` `validation.*` catalog → the
|
|
16
|
+
* built-in English sentence). All three links render the same `<div>`, so the
|
|
17
|
+
* DOM cannot say which of them answered — compare the TEXT if you need to know.
|
|
18
|
+
*/
|
|
19
|
+
type WrFormFieldErrorSource = 'projected' | 'resolved';
|
|
20
|
+
/** One message a `<wr-form-field>` is currently showing. */
|
|
21
|
+
interface WrFormFieldError {
|
|
22
|
+
/**
|
|
23
|
+
* Validator key the message answers, read from `data-key`. `null` for a keyless
|
|
24
|
+
* `<wr-form-error>`, which always renders.
|
|
25
|
+
*/
|
|
26
|
+
readonly key: string | null;
|
|
27
|
+
/** The rendered text. */
|
|
28
|
+
readonly text: string;
|
|
29
|
+
/** Whether the consumer wrote this message or the field resolved it. */
|
|
30
|
+
readonly source: WrFormFieldErrorSource;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @license
|
|
35
|
+
*
|
|
36
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
37
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/** Narrows which `<wr-form-field>` a harness query matches. */
|
|
41
|
+
interface WrFormFieldHarnessFilters extends BaseHarnessFilters {
|
|
42
|
+
/**
|
|
43
|
+
* Match the label text, with the `*` / `(optional)` markers left out of it — a
|
|
44
|
+
* string is an exact match, a RegExp is tested. `null` matches a field that
|
|
45
|
+
* renders no label at all.
|
|
46
|
+
*/
|
|
47
|
+
readonly label?: string | RegExp | null;
|
|
48
|
+
/**
|
|
49
|
+
* Match the hint text. A field showing an error has NO hint in the DOM — the
|
|
50
|
+
* error block takes its place — so this never matches an invalid field.
|
|
51
|
+
*/
|
|
52
|
+
readonly hint?: string | RegExp;
|
|
53
|
+
/** Match only fields marked required (`true`) or not (`false`). */
|
|
54
|
+
readonly required?: boolean;
|
|
55
|
+
/** Match only fields currently showing an error (`true`) or not (`false`). */
|
|
56
|
+
readonly invalid?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Match a field one of whose VISIBLE messages is this text — a string is an
|
|
59
|
+
* exact match, a RegExp is tested. Suppressed messages (a projected
|
|
60
|
+
* `<wr-form-error key>` whose key is not failing) are not considered.
|
|
61
|
+
*/
|
|
62
|
+
readonly errorText?: string | RegExp;
|
|
63
|
+
}
|
|
64
|
+
/** Narrows which `<wr-form-item>` a harness query matches. */
|
|
65
|
+
interface WrFormItemHarnessFilters extends BaseHarnessFilters {
|
|
66
|
+
/**
|
|
67
|
+
* Match the text of the item's own `<label>` child — a string is an exact
|
|
68
|
+
* match, a RegExp is tested. The label is the consumer's, not the item's.
|
|
69
|
+
*/
|
|
70
|
+
readonly label?: string | RegExp;
|
|
71
|
+
/** Match only items the consumer put in the error state (`true`) or not (`false`). */
|
|
72
|
+
readonly invalid?: boolean;
|
|
73
|
+
/** Match an item one of whose `<wr-form-error>` messages is this text. */
|
|
74
|
+
readonly errorText?: string | RegExp;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* @license
|
|
79
|
+
*
|
|
80
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
81
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Test harness for `<wr-form-field>` — the label + control + hint + validation
|
|
86
|
+
* copy block.
|
|
87
|
+
*
|
|
88
|
+
* The field's real job is the COPY CONTRACT, and this harness is built around it.
|
|
89
|
+
* A message reaches the DOM one of two ways, and they are distinguishable there:
|
|
90
|
+
*
|
|
91
|
+
* - a `<wr-form-error key="…">` the consumer wrote, which renders only while that
|
|
92
|
+
* key is failing — the others stay in the DOM carrying
|
|
93
|
+
* `wr-form-field__error--hidden`, which is why {@link getErrors} filters and
|
|
94
|
+
* {@link getSuppressedErrorKeys} exists. A raw `.wr-form-error` query answers
|
|
95
|
+
* with the held-back copy too, and reads green on the wrong sentence.
|
|
96
|
+
* - a message the field RESOLVED for an error no markup claimed:
|
|
97
|
+
* `provideWrFormErrors()`, then the `ngwr/i18n` `validation.*` catalog, then a
|
|
98
|
+
* built-in English sentence. All three render the identical `<div>`, so
|
|
99
|
+
* `source` is `'resolved'` for every one of them — the DOM genuinely cannot say
|
|
100
|
+
* which link answered, and this harness does not pretend otherwise.
|
|
101
|
+
*
|
|
102
|
+
* Nothing renders at all until the projected control is touched or dirty, so a
|
|
103
|
+
* spec has to reach that gate first: {@link blurControl} is the shortest way
|
|
104
|
+
* (blur is what marks a bound control touched), and typing through the control's
|
|
105
|
+
* own harness is the other.
|
|
106
|
+
*
|
|
107
|
+
* The field publishes no `aria-label` anywhere. Its `<label for>` pointing at the
|
|
108
|
+
* projected control IS the naming story, and a control that does not adopt the
|
|
109
|
+
* id leaves the field silently unlabelled — {@link isLabelLinkedToControl} is
|
|
110
|
+
* what catches that. The other half is the reverse wiring: the control reads back
|
|
111
|
+
* `aria-describedby` and `aria-invalid`, which is the only reason a screen reader
|
|
112
|
+
* hears the message ({@link getAnnouncedDescription}).
|
|
113
|
+
*
|
|
114
|
+
* Harnesses loaded through this one resolve INSIDE the control slot, so the
|
|
115
|
+
* control's own harness composes without a selector:
|
|
116
|
+
*
|
|
117
|
+
* @example
|
|
118
|
+
* ```ts
|
|
119
|
+
* const email = await loader.getHarness(WrFormFieldHarness.with({ label: 'Email' }));
|
|
120
|
+
*
|
|
121
|
+
* await (await email.getHarness(WrInputHarness)).setValue('nope');
|
|
122
|
+
* await email.blurControl();
|
|
123
|
+
*
|
|
124
|
+
* expect(await email.getErrorTexts()).toEqual(["That isn't a valid email."]);
|
|
125
|
+
* expect(await email.getAnnouncedDescription()).toBe("That isn't a valid email.");
|
|
126
|
+
* ```
|
|
127
|
+
*
|
|
128
|
+
* @see https://ngwr.dev/guides/testing
|
|
129
|
+
*/
|
|
130
|
+
declare class WrFormFieldHarness extends ContentContainerComponentHarness {
|
|
131
|
+
static hostSelector: string;
|
|
132
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
133
|
+
static with(options?: WrFormFieldHarnessFilters): HarnessPredicate<WrFormFieldHarness>;
|
|
134
|
+
/**
|
|
135
|
+
* The label text, or `null` when the field renders no label.
|
|
136
|
+
*
|
|
137
|
+
* The `*` and `(optional)` markers ride INSIDE the `<label>`, so they are
|
|
138
|
+
* excluded here — otherwise this answers `'Email *'` and every equality
|
|
139
|
+
* assertion has to know which marker the field happens to carry.
|
|
140
|
+
*
|
|
141
|
+
* `null` is not "the consumer forgot": `label=""` renders no `<label>` element
|
|
142
|
+
* at all, which also means there is nothing naming the control.
|
|
143
|
+
*/
|
|
144
|
+
getLabel(): Promise<string | null>;
|
|
145
|
+
/**
|
|
146
|
+
* Whether the field is marked required.
|
|
147
|
+
*
|
|
148
|
+
* Read from the host's `wr-form-field--required` modifier, not from the `*`:
|
|
149
|
+
* that marker is `aria-hidden="true"` decoration, and it is only rendered when
|
|
150
|
+
* there is a label to hang it on — the modifier is set either way. Note what
|
|
151
|
+
* this does NOT mean: the field forwards nothing to the projected control, so
|
|
152
|
+
* `required` here is the field's own visual state. What announces the constraint
|
|
153
|
+
* is the forms layer — a `required` rule writes the native `required` attribute
|
|
154
|
+
* onto the control — and the two are set independently, so a field can carry the
|
|
155
|
+
* `*` with no validator behind it.
|
|
156
|
+
*/
|
|
157
|
+
isRequired(): Promise<boolean>;
|
|
158
|
+
/**
|
|
159
|
+
* Whether the label carries the `(optional)` marker.
|
|
160
|
+
*
|
|
161
|
+
* Read from the marker itself, because — unlike `required` — `optional` sets no
|
|
162
|
+
* host modifier. It is also the marker a screen reader actually reads: this one
|
|
163
|
+
* is not `aria-hidden`. `required` wins when both inputs are set, so a required
|
|
164
|
+
* field is never optional here however it was bound.
|
|
165
|
+
*/
|
|
166
|
+
isOptional(): Promise<boolean>;
|
|
167
|
+
/**
|
|
168
|
+
* The hint text, or `null` when none is showing.
|
|
169
|
+
*
|
|
170
|
+
* `null` does not mean the consumer set no hint: the error block takes the
|
|
171
|
+
* hint's slot outright, so a field with a visible message has no hint in the DOM
|
|
172
|
+
* at all. Note also that the hint carries no id and is NOT referenced by the
|
|
173
|
+
* control's `aria-describedby` — see {@link getAnnouncedDescription}.
|
|
174
|
+
*/
|
|
175
|
+
getHint(): Promise<string | null>;
|
|
176
|
+
/**
|
|
177
|
+
* Whether the field is painting the error state.
|
|
178
|
+
*
|
|
179
|
+
* The host's `wr-form-field--invalid` modifier — what the user sees. The
|
|
180
|
+
* screen-reader half lives on the control as `aria-invalid`, and the two are
|
|
181
|
+
* separate elements rather than two readings of one: {@link isControlInvalid}.
|
|
182
|
+
*/
|
|
183
|
+
isInvalid(): Promise<boolean>;
|
|
184
|
+
/**
|
|
185
|
+
* Every message the field is SHOWING, in DOM order — the consumer's markup
|
|
186
|
+
* first, then whatever the field resolved for the keys that markup left over.
|
|
187
|
+
*
|
|
188
|
+
* Only THIS field's own error block is read — its direct child, holding its
|
|
189
|
+
* direct children — so a `<wr-form-field>` nested in another one's control slot
|
|
190
|
+
* contributes nothing to the outer field's answer. Without that anchoring the
|
|
191
|
+
* outer field reports the inner one's copy as its own, which is the same class
|
|
192
|
+
* of break as reading a sibling field's messages.
|
|
193
|
+
*/
|
|
194
|
+
getErrors(): Promise<WrFormFieldError[]>;
|
|
195
|
+
/** The visible messages as text, in DOM order. */
|
|
196
|
+
getErrorTexts(): Promise<string[]>;
|
|
197
|
+
/**
|
|
198
|
+
* The visible message for one validator key.
|
|
199
|
+
*
|
|
200
|
+
* Throws rather than answering `null` when that key has no visible message: the
|
|
201
|
+
* two reasons are worth failing on and the message names both — the key is not
|
|
202
|
+
* in error at all, or its copy resolved to nothing.
|
|
203
|
+
*/
|
|
204
|
+
getErrorText(key: string): Promise<string>;
|
|
205
|
+
/**
|
|
206
|
+
* The keys of the projected messages the field is holding BACK — copy that is in
|
|
207
|
+
* the DOM but hidden because its key is not among the failing ones.
|
|
208
|
+
*
|
|
209
|
+
* This is the gating contract seen from outside, and the reason a spec must not
|
|
210
|
+
* query `.wr-form-error` itself: the suppressed sentences sit right next to the
|
|
211
|
+
* live one.
|
|
212
|
+
*/
|
|
213
|
+
getSuppressedErrorKeys(): Promise<string[]>;
|
|
214
|
+
/**
|
|
215
|
+
* Whether the field is announcing an error it has no words for: invalid, with an
|
|
216
|
+
* error block that renders nothing.
|
|
217
|
+
*
|
|
218
|
+
* Worth a named check because it is invisible in review — the field still goes
|
|
219
|
+
* red, and `aria-describedby` still points at the block, so a screen reader is
|
|
220
|
+
* sent to an empty element. It happens when no link in the copy chain answers
|
|
221
|
+
* the key (`[autoErrors]="false"` with no markup, or a key nothing has copy for
|
|
222
|
+
* — Signal Forms reports `minLength`, while the chain only knows Angular's
|
|
223
|
+
* lowercase `minlength`).
|
|
224
|
+
*/
|
|
225
|
+
hasEmptyErrorBlock(): Promise<boolean>;
|
|
226
|
+
/** The id the `<label for>` points at, or `null` when there is no label. */
|
|
227
|
+
getLabelFor(): Promise<string | null>;
|
|
228
|
+
/** The `id` the projected control actually answers to, or `null` when it has none. */
|
|
229
|
+
getControlId(): Promise<string | null>;
|
|
230
|
+
/**
|
|
231
|
+
* Whether the `<label for>` resolves to an element inside THIS field's control
|
|
232
|
+
* slot — the only thing that makes the field nameable.
|
|
233
|
+
*
|
|
234
|
+
* Scoped to the slot on purpose: ids are document-global, so a check that went
|
|
235
|
+
* through `getElementById` would also pass for a label pointing at a DIFFERENT
|
|
236
|
+
* field's control, and for a control that has been moved out of the field
|
|
237
|
+
* entirely. The failure this catches is quiet — a projected control that does
|
|
238
|
+
* not adopt the field's `controlId` (a bare `<input>` with no `[wrInput]`, say)
|
|
239
|
+
* leaves a `for` naming nothing, the field renders exactly as it always did, and
|
|
240
|
+
* nothing is labelled.
|
|
241
|
+
*/
|
|
242
|
+
isLabelLinkedToControl(): Promise<boolean>;
|
|
243
|
+
/**
|
|
244
|
+
* The ids the projected control names in `aria-describedby`, in order.
|
|
245
|
+
*
|
|
246
|
+
* The field points this at the error block and nothing else — the hint has no
|
|
247
|
+
* id — so an empty list while a hint is showing is correct rather than a bug.
|
|
248
|
+
* That is not an oversight to fix from a harness either: `[wrInput]` derives
|
|
249
|
+
* `aria-invalid` from the same signal, so describing the hint would announce
|
|
250
|
+
* every hinted field as invalid.
|
|
251
|
+
*/
|
|
252
|
+
getDescribedByIds(): Promise<string[]>;
|
|
253
|
+
/**
|
|
254
|
+
* What a screen reader reads as the control's description: the text of the
|
|
255
|
+
* elements `aria-describedby` names, joined by a space. `null` when the control
|
|
256
|
+
* describes nothing.
|
|
257
|
+
*
|
|
258
|
+
* `''` is a real answer and the interesting one — the reference resolves to an
|
|
259
|
+
* element with no text in it, which is {@link hasEmptyErrorBlock}. Ids naming
|
|
260
|
+
* something outside this field are skipped (a consumer's own description is out
|
|
261
|
+
* of a field harness's reach); an id naming nothing anywhere throws, because a
|
|
262
|
+
* dangling reference is the bug this method exists to surface.
|
|
263
|
+
*
|
|
264
|
+
* Suppressed copy is excluded explicitly rather than left to CSS: a browser drops
|
|
265
|
+
* `display: none` subtrees from the accessibility tree, but a unit test loads no
|
|
266
|
+
* stylesheet at all, so the referenced block's raw `textContent` runs every
|
|
267
|
+
* held-back sentence together with the live one and this would answer with copy
|
|
268
|
+
* nobody can read.
|
|
269
|
+
*/
|
|
270
|
+
getAnnouncedDescription(): Promise<string | null>;
|
|
271
|
+
/**
|
|
272
|
+
* Whether the control announces itself invalid.
|
|
273
|
+
*
|
|
274
|
+
* `aria-invalid` on the projected control, which is what assistive technology
|
|
275
|
+
* is told — the field's own red styling is {@link isInvalid}. Both are here
|
|
276
|
+
* because they live on different elements and travel in opposite directions: the
|
|
277
|
+
* field renders the message, the control reads back that there is one. A field
|
|
278
|
+
* that paints red while the control says nothing is a real (and silent) break.
|
|
279
|
+
*/
|
|
280
|
+
isControlInvalid(): Promise<boolean>;
|
|
281
|
+
/** Move focus to the projected control. */
|
|
282
|
+
focusControl(): Promise<void>;
|
|
283
|
+
/**
|
|
284
|
+
* Blur the projected control, which is usually how a spec gets any message to
|
|
285
|
+
* appear at all: a bound control marks itself touched on blur, and the field
|
|
286
|
+
* renders nothing while the control is untouched AND pristine.
|
|
287
|
+
*/
|
|
288
|
+
blurControl(): Promise<void>;
|
|
289
|
+
/** The rendered `<label>`, or `null` when `label` is empty. */
|
|
290
|
+
private labelElement;
|
|
291
|
+
/**
|
|
292
|
+
* The control this field wraps.
|
|
293
|
+
*
|
|
294
|
+
* The element the label points at, when that resolves inside the slot — which
|
|
295
|
+
* covers a control nested inside a component (`<wr-input-number>`'s own
|
|
296
|
+
* `<input>` adopts the field's id, so the label names it, not the component
|
|
297
|
+
* element). Otherwise the first native control in the slot, so a field with no
|
|
298
|
+
* label still answers.
|
|
299
|
+
*/
|
|
300
|
+
private control;
|
|
301
|
+
/**
|
|
302
|
+
* The content loader every `HarnessLoader` method on this class runs through,
|
|
303
|
+
* scoped to the control slot.
|
|
304
|
+
*
|
|
305
|
+
* So `field.getHarness(WrInputHarness)` finds the control this field wraps and
|
|
306
|
+
* not a sibling field's — the loader is per-instance by construction, which is
|
|
307
|
+
* what a document-wide query for the same selector would lose.
|
|
308
|
+
*/
|
|
309
|
+
protected getRootHarnessLoader(): Promise<HarnessLoader>;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @license
|
|
314
|
+
*
|
|
315
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
316
|
+
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
317
|
+
*/
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Test harness for `<wr-form-item>` — the layout-only field row.
|
|
321
|
+
*
|
|
322
|
+
* Deliberately a much smaller surface than {@link WrFormFieldHarness}, because
|
|
323
|
+
* the component is a much smaller thing: it discovers no control, generates no
|
|
324
|
+
* id, wires no `for` and no `aria-describedby`, and reads no validity. It paints
|
|
325
|
+
* the error state it is TOLD to paint, via `[hasError]`, and everything else in
|
|
326
|
+
* it belongs to the consumer — including the `<label>`, which is named here
|
|
327
|
+
* rather than linked (nothing wires it; the consumer's own `for` is the only
|
|
328
|
+
* thing that can).
|
|
329
|
+
*
|
|
330
|
+
* The one behavioural trap it is worth a harness for: a `<wr-form-error>` inside
|
|
331
|
+
* a form-item renders UNCONDITIONALLY. `key` has no effect at all — the gating
|
|
332
|
+
* lives in the surrounding `<wr-form-field>`, and with no field to ask, every
|
|
333
|
+
* message decides it is the one to show. Markup moved from a field into an item
|
|
334
|
+
* therefore starts printing every sentence at once, and {@link getErrorTexts}
|
|
335
|
+
* is what says so.
|
|
336
|
+
*
|
|
337
|
+
* @example
|
|
338
|
+
* ```ts
|
|
339
|
+
* const item = await loader.getHarness(WrFormItemHarness.with({ label: 'Email' }));
|
|
340
|
+
*
|
|
341
|
+
* expect(await item.isInvalid()).toBe(true);
|
|
342
|
+
* expect(await item.getErrorTexts()).toEqual(['Invalid email']);
|
|
343
|
+
* await (await item.getHarness(WrInputHarness)).setValue('ada@example.test');
|
|
344
|
+
* ```
|
|
345
|
+
*
|
|
346
|
+
* @see https://ngwr.dev/guides/testing
|
|
347
|
+
*/
|
|
348
|
+
declare class WrFormItemHarness extends ContentContainerComponentHarness {
|
|
349
|
+
static hostSelector: string;
|
|
350
|
+
/** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */
|
|
351
|
+
static with(options?: WrFormItemHarnessFilters): HarnessPredicate<WrFormItemHarness>;
|
|
352
|
+
/**
|
|
353
|
+
* The text of the item's own `<label>` child, or `null` when it has none.
|
|
354
|
+
*
|
|
355
|
+
* Direct child only — that is what the item styles (`> label` is what turns red
|
|
356
|
+
* in the error state), so a label nested deeper is the consumer's own business
|
|
357
|
+
* and answering with it would describe something the item never touches.
|
|
358
|
+
*/
|
|
359
|
+
getLabel(): Promise<string | null>;
|
|
360
|
+
/**
|
|
361
|
+
* Whether the item is painting the error state.
|
|
362
|
+
*
|
|
363
|
+
* The `wr-form-item--error` modifier, which is driven entirely by the
|
|
364
|
+
* consumer's `[hasError]` — the item runs no validity check of its own, so this
|
|
365
|
+
* answers what it was told, not what the control thinks.
|
|
366
|
+
*/
|
|
367
|
+
isInvalid(): Promise<boolean>;
|
|
368
|
+
/**
|
|
369
|
+
* Every `<wr-form-error>` in the item, as text, in DOM order.
|
|
370
|
+
*
|
|
371
|
+
* All of them: nothing is gated here, `key` or no `key`. Nothing is ever
|
|
372
|
+
* hidden either, so there is no suppressed-message counterpart to this — see
|
|
373
|
+
* the class docs.
|
|
374
|
+
*/
|
|
375
|
+
getErrorTexts(): Promise<string[]>;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
export { WrFormFieldHarness, WrFormItemHarness };
|
|
379
|
+
export type { WrFormFieldError, WrFormFieldErrorSource, WrFormFieldHarnessFilters, WrFormItemHarnessFilters };
|
package/types/ngwr-form.d.ts
CHANGED
|
@@ -51,6 +51,14 @@ declare class WrFormItem {
|
|
|
51
51
|
interface WrFormFieldContext {
|
|
52
52
|
/** Id the field's `<label for>` points at. */
|
|
53
53
|
readonly controlId: Signal<string>;
|
|
54
|
+
/**
|
|
55
|
+
* The reverse direction, for the one case the paragraph above does not cover: a
|
|
56
|
+
* projected control that already carries its own `id` keeps it, and the label has
|
|
57
|
+
* to follow, or `for` names an element that does not exist and the field ends up
|
|
58
|
+
* with no label at all. Called during the control's construction, so the label's
|
|
59
|
+
* binding still resolves in the same render pass.
|
|
60
|
+
*/
|
|
61
|
+
adoptControlId(id: string): void;
|
|
54
62
|
/**
|
|
55
63
|
* Validator keys currently in error, once the control is touched or dirty.
|
|
56
64
|
* Empty when the field is valid or has not been interacted with.
|
|
@@ -133,6 +141,15 @@ declare class WrFormField implements WrFormFieldContext {
|
|
|
133
141
|
* already carries an `id` of its own.
|
|
134
142
|
*/
|
|
135
143
|
readonly controlId: _angular_core.InputSignal<string>;
|
|
144
|
+
private readonly adoptedId;
|
|
145
|
+
/**
|
|
146
|
+
* Id the `<label for>` renders. A control that came with its own `id` keeps it, so
|
|
147
|
+
* the label follows that instead of the generated one — otherwise `for` points at
|
|
148
|
+
* an element that is not in the document and the field is unlabelled.
|
|
149
|
+
*/
|
|
150
|
+
protected readonly labelFor: _angular_core.Signal<string>;
|
|
151
|
+
/** @internal `WrFormFieldContext` — see the token's docs. */
|
|
152
|
+
adoptControlId(id: string): void;
|
|
136
153
|
/**
|
|
137
154
|
* Projected `NgControl` — used to read touched / dirty / errors.
|
|
138
155
|
*
|
package/types/ngwr-gauge.d.ts
CHANGED
|
@@ -16,7 +16,12 @@ declare class WrGauge {
|
|
|
16
16
|
/** Accessible name — the role needs one. Falls back to `gauge.label`. */
|
|
17
17
|
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
18
18
|
protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The reading. Coerced like every other numeric input here — it was the only one
|
|
21
|
+
* without it, so a NaN reached the arc's `d` as the literal text `NaN`, which is
|
|
22
|
+
* invalid path geometry and drops the arc.
|
|
23
|
+
*/
|
|
24
|
+
readonly value: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
20
25
|
readonly min: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
21
26
|
readonly max: _angular_core.InputSignalWithTransform<number, unknown>;
|
|
22
27
|
/** Diameter in CSS pixels. @default 160 */
|
|
@@ -31,6 +36,13 @@ declare class WrGauge {
|
|
|
31
36
|
protected readonly cx = 50;
|
|
32
37
|
protected readonly cy = 50;
|
|
33
38
|
protected readonly radius: _angular_core.Signal<number>;
|
|
39
|
+
/**
|
|
40
|
+
* The reading as it can actually be shown. Only `ratio` used to be clamped, so an
|
|
41
|
+
* over-range value drew a full bar while `aria-valuenow` announced the raw number
|
|
42
|
+
* against `aria-valuemax` — an invalid state for `role="meter"` — and the printed
|
|
43
|
+
* text disagreed with the bar as well.
|
|
44
|
+
*/
|
|
45
|
+
protected readonly displayValue: _angular_core.Signal<number>;
|
|
34
46
|
protected readonly ratio: _angular_core.Signal<number>;
|
|
35
47
|
protected readonly trackPath: _angular_core.Signal<string>;
|
|
36
48
|
protected readonly valuePath: _angular_core.Signal<string>;
|
|
@@ -85,6 +85,16 @@ declare class WrImageCropper {
|
|
|
85
85
|
/** Resolved crop rect in natural (source) pixel coordinates. */
|
|
86
86
|
readonly cropRect: _angular_core.Signal<WrCropRect>;
|
|
87
87
|
constructor();
|
|
88
|
+
/**
|
|
89
|
+
* Back to "nothing measured yet", which is also what an absent `src` means.
|
|
90
|
+
*
|
|
91
|
+
* `display` is the field that gates everything downstream — the crop UI renders on
|
|
92
|
+
* `display().w > 0` and `cropRect` returns zeros without it — so it is the only one
|
|
93
|
+
* a test can observe. The other two are reset for coherence: anything that learns to
|
|
94
|
+
* set `display` from elsewhere (a resize observer is the obvious candidate for this
|
|
95
|
+
* component) would otherwise resurrect a crop measured against the previous image.
|
|
96
|
+
*/
|
|
97
|
+
private resetGeometry;
|
|
88
98
|
protected onImageLoad(): void;
|
|
89
99
|
/** Compute a sensible initial crop — centered, respecting aspectRatio. */
|
|
90
100
|
private initialCrop;
|