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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-color-picker-testing.mjs","sources":["../../../projects/lib/color-picker/testing/wr-color-picker-harness.ts","../../../projects/lib/color-picker/testing/wr-color-picker-trigger-harness.ts","../../../projects/lib/color-picker/testing/ngwr-color-picker-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, type TestElement } from '@angular/cdk/testing';\n\nimport { WrSegmentedHarness } from 'ngwr/segmented/testing';\n\nimport type { WrColorPickerHarnessFilters, WrColorPickerTab, WrColorPickerThumbs } from './interfaces';\n\n/**\n * One labelled numeric field — internal. A `TestElement` cannot be queried into, so\n * pairing an input with the label printed under it means a harness anchored on the\n * `<label>` that holds both.\n */\nclass FieldHarness extends ComponentHarness {\n static hostSelector = '.wr-color-picker__field';\n\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-color-picker__field-label')()).text();\n }\n\n async getInput(): Promise<TestElement> {\n return this.locatorFor('input')();\n }\n\n async getValue(): Promise<string> {\n return (await this.getInput()).getProperty<string>('value');\n }\n}\n\n/** An inline `left` / `top` percentage as a number. */\nasync function percent(thumb: TestElement, side: 'left' | 'top'): Promise<number> {\n return Number.parseFloat(await thumb.getCssValue(side));\n}\n\n/**\n * Test harness for `<wr-color-picker>` — the inline picker, and the one the\n * `[wrColorPickerTrigger]` directive mounts in an overlay.\n *\n * **What this harness will not do: drag.** The SV canvas and the hue / alpha\n * sliders are pointer surfaces that read `getBoundingClientRect()` and divide by\n * its width. A unit test has no layout, so every box is 0×0 and the division is\n * `NaN` — a `setHue()` built on a synthetic pointer event would report success and\n * write nothing, or write garbage. The numeric fields reach the same state and are\n * also the only keyboard path the component has, so they are the whole write API\n * here. {@link getThumbs} reads where the thumbs ARE, from the percentages the\n * component writes inline, which is how a spec checks a surface followed a value.\n *\n * **And it will not read the preview swatch.** The preview paints the current\n * colour as a CSS background, and jsdom normalises that to `rgb(…)` — dropping the\n * alpha channel entirely, so `#ff880080` and `#ff8800ff` come back identical. A\n * `getColor()` reading it would answer one thing in a unit test and another in a\n * browser. {@link getHex} is the colour: the field holds the canonical 8-digit\n * string, alpha included, whatever `format` writes into `value`.\n *\n * @example\n * ```ts\n * const picker = await loader.getHarness(WrColorPickerHarness);\n *\n * await picker.setHex('#3969e2');\n * expect(await picker.getHex()).toBe('#3969e2ff');\n *\n * await picker.setTab('rgb');\n * expect(await picker.getRgb()).toEqual({ r: 57, g: 105, b: 226 });\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrColorPickerHarness extends ComponentHarness {\n static hostSelector = 'wr-color-picker';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrColorPickerHarnessFilters = {}): HarnessPredicate<WrColorPickerHarness> {\n return new HarnessPredicate(WrColorPickerHarness, options)\n .addOption('color', options.color, (harness, color) => HarnessPredicate.stringMatches(harness.readHex(), color))\n .addOption('tab', options.tab, async (harness, tab) => (await harness.getTab()) === tab)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly hexField = this.locatorForOptional('.wr-color-picker__inputs--hex input');\n private readonly tabs = this.locatorFor(WrSegmentedHarness.with({ selector: '.wr-color-picker__tabs' }));\n\n /**\n * The tab switcher, as a {@link WrSegmentedHarness}.\n *\n * Handed back rather than re-queried: the switcher IS a `<wr-segmented>`, which\n * already knows that the roving tab stop is not the selection and how the sliding\n * thumb reports itself. Re-reading its buttons here would be a second, worse copy.\n */\n async getTabs(): Promise<WrSegmentedHarness> {\n return this.tabs();\n }\n\n /** Which set of numeric fields is showing. */\n async getTab(): Promise<WrColorPickerTab> {\n const label = await (await this.tabs()).getSelectedLabel();\n return (label ?? 'HEX').toLowerCase() as WrColorPickerTab;\n }\n\n /** Show a different set of numeric fields. An already-active tab is left alone. */\n async setTab(tab: WrColorPickerTab): Promise<void> {\n if ((await this.getTab()) === tab) return;\n await (await this.tabs()).select({ label: tab.toUpperCase() });\n }\n\n /**\n * The canonical hex string, as the HEX field shows it — 8 digits while `alpha` is\n * on, 6 while it is off.\n *\n * This is the picker's colour, and deliberately not the same thing as its `value`:\n * `format` decides whether `value` is written as hex, `rgb()` or `hsl()`, while the\n * field always shows hex. A spec that cares about the emitted string should read\n * the bound signal; one that cares about the COLOUR should read this.\n *\n * Throws off the HEX tab, where the field does not exist — see {@link setTab}.\n */\n async getHex(): Promise<string> {\n const field = await this.hexField();\n if (!field) {\n throw new Error(\n `WrColorPickerHarness.getHex(): the HEX field is not rendered — the picker is showing the ` +\n `${(await this.getTab()).toUpperCase()} tab. Call setTab('hex') first.`\n );\n }\n return field.getProperty<string>('value');\n }\n\n /**\n * Type a colour into the HEX field.\n *\n * Typed rather than assigned, because that is the path the component is built\n * around: it re-parses on every keystroke and applies the first spelling that\n * parses, so a partial `#ff8` commits a colour on its way to `#ff8800`. An\n * unparseable string leaves the committed colour ALONE and lives in the field\n * until {@link blurHex} snaps it back — assert that rather than expecting a throw.\n */\n async setHex(value: string): Promise<void> {\n const field = await this.requireHexField('setHex');\n await field.clear();\n await field.sendKeys(value);\n }\n\n /**\n * Blur the HEX field — re-syncing it with the committed colour and emitting\n * `touch`.\n *\n * The re-sync is the visible half: a field left holding text that never parsed\n * goes back to the canonical hex here, and nowhere else.\n */\n async blurHex(): Promise<void> {\n await (await this.requireHexField('blurHex')).blur();\n }\n\n /** Whether the HEX field currently holds focus. */\n async isHexFocused(): Promise<boolean> {\n return (await this.requireHexField('isHexFocused')).isFocused();\n }\n\n /** The three RGB channels as the RGB tab shows them. Throws off that tab. */\n async getRgb(): Promise<{ r: number; g: number; b: number }> {\n const [r, g, b] = await this.channelValues('rgb', ['R', 'G', 'B']);\n return { r, g, b };\n }\n\n /** Write one RGB channel, 0–255. Out-of-range numbers are clamped by the component. */\n async setRgbChannel(channel: 'r' | 'g' | 'b', value: number): Promise<void> {\n await this.writeChannel('rgb', channel.toUpperCase(), value);\n }\n\n /**\n * Hue, saturation and lightness as the HSL tab shows them — degrees and whole\n * percents, already rounded for display. Throws off that tab.\n */\n async getHsl(): Promise<{ h: number; s: number; l: number }> {\n const [h, s, l] = await this.channelValues('hsl', ['H', 'S%', 'L%']);\n return { h, s, l };\n }\n\n /** Write one HSL channel — `h` in degrees, `s` / `l` in percent. */\n async setHslChannel(channel: 'h' | 's' | 'l', value: number): Promise<void> {\n await this.writeChannel('hsl', channel === 'h' ? 'H' : `${channel.toUpperCase()}%`, value);\n }\n\n /**\n * Alpha as the whole percent the numeric tabs show, or `null` when the picker was\n * built without alpha.\n *\n * Only the RGB and HSL tabs carry the field — the HEX tab spells alpha into the\n * hex string instead — so this throws on the HEX tab rather than answering `null`,\n * which would read as \"this picker has no alpha\".\n */\n async getAlphaPercent(): Promise<number | null> {\n const tab = await this.getTab();\n if (tab === 'hex') {\n throw new Error(\n 'WrColorPickerHarness.getAlphaPercent(): the HEX tab has no alpha field — the alpha is the last two ' +\n \"digits of getHex(). Call setTab('rgb') or setTab('hsl') to read it as a percent.\"\n );\n }\n if (!(await this.hasAlpha())) return null;\n const [alpha] = await this.channelValues(tab, ['A%']);\n return alpha;\n }\n\n /** Write alpha as a whole percent, 0–100. */\n async setAlphaPercent(value: number): Promise<void> {\n const tab = await this.getTab();\n if (tab === 'hex') {\n throw new Error(\n \"WrColorPickerHarness.setAlphaPercent(): the HEX tab has no alpha field. Call setTab('rgb') first, \" +\n 'or write the two alpha digits through setHex().'\n );\n }\n await this.writeChannel(tab, 'A%', value);\n }\n\n /**\n * Whether the picker offers alpha at all.\n *\n * From the host modifier, which is the one answer that holds on every tab: the\n * alpha SLIDER is always rendered when it is on, while the `A%` field only exists\n * on the two numeric tabs.\n */\n async hasAlpha(): Promise<boolean> {\n return (await this.host()).hasClass('wr-color-picker--alpha');\n }\n\n /**\n * Whether the picker refuses interaction.\n *\n * Read from the modifier the host paints rather than from a field's `disabled`\n * property, because the fields come and go with the tab while the state does not —\n * and the drag surfaces, which have no `disabled` of their own, are gated by the\n * same signal.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-color-picker--disabled');\n }\n\n /** The preset colours offered under the fields, as the strings the consumer passed. */\n async getSwatches(): Promise<string[]> {\n const swatches = await this.locatorForAll('.wr-color-picker__swatch')();\n return Promise.all(swatches.map(async swatch => (await swatch.getAttribute('aria-label')) ?? ''));\n }\n\n /**\n * Click a preset.\n *\n * Matched on the string the consumer passed, which is what the button publishes as\n * its accessible name — the rendered background is a CSS colour and would come back\n * normalised and alpha-stripped. Throws when nothing matches, naming what is offered.\n */\n async pickSwatch(color: string): Promise<void> {\n const swatches = await this.locatorForAll('.wr-color-picker__swatch')();\n for (const swatch of swatches) {\n if ((await swatch.getAttribute('aria-label')) === color) {\n await swatch.click();\n return;\n }\n }\n throw new Error(\n `WrColorPickerHarness.pickSwatch(): no swatch for \"${color}\". The picker offers: ` +\n `${(await this.getSwatches()).join(', ')}.`\n );\n }\n\n /**\n * Where the three thumbs sit, in percent along their surfaces.\n *\n * The component writes these as inline `left` / `top` percentages, so they are\n * readable with no layout at all — which makes them the only evidence a spec has\n * that the surfaces followed a colour set through the fields. A measured position\n * would be zero for all three.\n */\n async getThumbs(): Promise<WrColorPickerThumbs> {\n const sv = await this.locatorFor('.wr-color-picker__sv .wr-color-picker__thumb')();\n const hue = await this.locatorFor('.wr-color-picker__slider--hue .wr-color-picker__thumb')();\n const alpha = await this.locatorForOptional('.wr-color-picker__slider--alpha .wr-color-picker__thumb')();\n\n return {\n sv: { x: await percent(sv, 'left'), y: await percent(sv, 'top') },\n hue: await percent(hue, 'left'),\n alpha: alpha ? await percent(alpha, 'left') : null,\n };\n }\n\n /** The HEX field's value without the tab check — for filters, which must not throw. */\n private async readHex(): Promise<string> {\n const field = await this.hexField();\n return field ? field.getProperty<string>('value') : '';\n }\n\n private async requireHexField(method: string): Promise<TestElement> {\n const field = await this.hexField();\n if (!field) {\n throw new Error(\n `WrColorPickerHarness.${method}(): the HEX field is not rendered — the picker is showing the ` +\n `${(await this.getTab()).toUpperCase()} tab. Call setTab('hex') first.`\n );\n }\n return field;\n }\n\n private async channelValues(tab: WrColorPickerTab, labels: readonly string[]): Promise<number[]> {\n await this.requireTab(tab, 'read');\n const inputs = await this.inputsByLabel();\n\n return labels.map(label => {\n const input = inputs.get(label);\n if (!input) throw new Error(`WrColorPickerHarness: the ${tab.toUpperCase()} tab has no \"${label}\" field.`);\n return Number(input.value);\n });\n }\n\n private async writeChannel(tab: WrColorPickerTab, label: string, value: number): Promise<void> {\n await this.requireTab(tab, 'write');\n const inputs = await this.inputsByLabel();\n const found = inputs.get(label);\n if (!found) {\n throw new Error(\n `WrColorPickerHarness: the ${tab.toUpperCase()} tab has no \"${label}\" field. ${\n label === 'A%' ? 'This picker was built with `[alpha]=\"false\"`.' : ''\n }`\n );\n }\n\n // Set and dispatch once, rather than clearing and typing. Each of these inputs\n // is bound to `[value]`, and the component commits on every `input` event — so\n // typing 128 would land 1, then 12, then 128, and CLEARING would land 0 first,\n // because `Number('')` is 0 rather than NaN. A spec that asked for one colour\n // would get four, the first of them black.\n await found.element.setInputValue(String(value));\n await found.element.dispatchEvent('input');\n }\n\n private async requireTab(tab: WrColorPickerTab, verb: string): Promise<void> {\n const current = await this.getTab();\n if (current !== tab) {\n throw new Error(\n `WrColorPickerHarness: cannot ${verb} the ${tab.toUpperCase()} channels while the picker is showing ` +\n `the ${current.toUpperCase()} tab — those fields are not rendered. Call setTab('${tab}') first.`\n );\n }\n }\n\n /** Every numeric input of the current tab, keyed by the label printed under it. */\n private async inputsByLabel(): Promise<Map<string, { element: TestElement; value: string }>> {\n const found = new Map<string, { element: TestElement; value: string }>();\n\n for (const field of await this.locatorForAll(FieldHarness)()) {\n const label = await field.getLabel();\n found.set(label, { element: await field.getInput(), value: await field.getValue() });\n }\n return found;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrColorPickerTriggerHarnessFilters } from './interfaces';\nimport { WrColorPickerHarness } from './wr-color-picker-harness';\n\n/**\n * Test harness for `[wrColorPickerTrigger]` — the element that opens a\n * `<wr-color-picker>` in an overlay.\n *\n * The trigger stays in your fixture; the picker it opens does not. So this harness\n * is loaded from the fixture loader like any element, and {@link getPicker} reaches\n * ACROSS into the overlay container for you — scoped by the panel id the trigger\n * publishes through `aria-controls`, never by `.wr-color-picker-overlay`, which\n * answers with whichever trigger opened first.\n *\n * @example\n * ```ts\n * const trigger = await loader.getHarness(WrColorPickerTriggerHarness);\n * const picker = await trigger.open();\n *\n * await picker.setHex('#3969e2');\n * await trigger.sendEscape();\n * expect(await trigger.isOpen()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrColorPickerTriggerHarness extends ComponentHarness {\n static hostSelector = '[wrColorPickerTrigger]';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrColorPickerTriggerHarnessFilters = {}): HarnessPredicate<WrColorPickerTriggerHarness> {\n return new HarnessPredicate(WrColorPickerTriggerHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);\n }\n\n /** The trigger's own text, trimmed. */\n async getText(): Promise<string> {\n return (await this.host()).text();\n }\n\n /** Whether the picker is showing, from the trigger's `aria-expanded`. */\n async isOpen(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-expanded')) === 'true';\n }\n\n /**\n * Whether the trigger refuses to open.\n *\n * From `aria-disabled`, which the directive writes for its own `disabled` input.\n * The host is usually a `<button>`, but the directive does not touch its `disabled`\n * PROPERTY — a consumer who binds that as well turns the element off at the DOM\n * level, which is a stronger thing and reads here too.\n */\n async isDisabled(): Promise<boolean> {\n const host = await this.host();\n return (await host.getAttribute('aria-disabled')) === 'true' || (await host.getProperty<boolean>('disabled'));\n }\n\n /**\n * The picker this trigger opened, or `null` while it is closed.\n *\n * Scoped by the id in `aria-controls`, so two triggers open at once — which\n * nothing in the component prevents, since only an outside click closes one —\n * answer with their own panels rather than with whichever came first.\n */\n async getPicker(): Promise<WrColorPickerHarness | null> {\n const id = await (await this.host()).getAttribute('aria-controls');\n if (!id) return null;\n\n return this.documentRootLocatorFactory().locatorForOptional(WrColorPickerHarness.with({ ancestor: `#${id}` }))();\n }\n\n /**\n * Open the picker and hand it back. An already-open trigger is left alone.\n *\n * Throws on a disabled trigger rather than answering `null` three lines later:\n * `toggle()` returns early while `disabled` is set, so the click lands and nothing\n * happens at all.\n */\n async open(): Promise<WrColorPickerHarness> {\n if (!(await this.isOpen())) {\n if (await this.isDisabled()) {\n throw new Error(\n `WrColorPickerTriggerHarness.open(): \"${await this.getText()}\" is disabled — the directive turns its ` +\n 'own toggle away, so the click would land and change nothing.'\n );\n }\n await (await this.host()).click();\n }\n\n const picker = await this.getPicker();\n if (!picker) {\n throw new Error(\n 'WrColorPickerTriggerHarness.open(): the trigger reports itself open but published no panel to find. ' +\n 'That is a broken `aria-controls` pairing, not a timing problem.'\n );\n }\n return picker;\n }\n\n /** Close the picker. An already-closed trigger is left alone. */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n await (await this.host()).click();\n }\n\n /** Click the trigger once, whichever way that takes it. */\n async toggle(): Promise<void> {\n await (await this.host()).click();\n }\n\n /**\n * Press Escape.\n *\n * Sent to the TRIGGER, and it still reaches the picker: the overlay listens through\n * the CDK's keyboard dispatcher, which keeps one document listener and routes to\n * the top-most overlay — so this does not depend on where focus happens to be.\n */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n\n /** The role the trigger claims to open — `dialog`. */\n async getHasPopup(): Promise<string | null> {\n return (await this.host()).getAttribute('aria-haspopup');\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":";;;AAAA;;;;;AAKG;AAQH;;;;AAIG;AACH,MAAM,YAAa,SAAQ,gBAAgB,CAAA;AACzC,IAAA,OAAO,YAAY,GAAG,yBAAyB;AAE/C,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,+BAA+B,CAAC,EAAE,EAAE,IAAI,EAAE;IAC1E;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE;IACnC;AAEA,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,EAAE,EAAE,WAAW,CAAS,OAAO,CAAC;IAC7D;;AAGF;AACA,eAAe,OAAO,CAAC,KAAkB,EAAE,IAAoB,EAAA;AAC7D,IAAA,OAAO,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACzD;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACG,MAAO,oBAAqB,SAAQ,gBAAgB,CAAA;AACxD,IAAA,OAAO,YAAY,GAAG,iBAAiB;;AAGvC,IAAA,OAAO,IAAI,CAAC,OAAA,GAAuC,EAAE,EAAA;AACnD,QAAA,OAAO,IAAI,gBAAgB,CAAC,oBAAoB,EAAE,OAAO;aACtD,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,KAAK,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC;aAC9G,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,EAAE,OAAO,OAAO,EAAE,GAAG,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG;aACtF,SAAS,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,OAAO,EAAE,QAAQ,KAAK,CAAC,MAAM,OAAO,CAAC,UAAU,EAAE,MAAM,QAAQ,CAAC;IACpH;AAEiB,IAAA,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,qCAAqC,CAAC;AACzE,IAAA,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,wBAAwB,EAAE,CAAC,CAAC;AAExG;;;;;;AAMG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,OAAO,IAAI,CAAC,IAAI,EAAE;IACpB;;AAGA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,gBAAgB,EAAE;QAC1D,OAAO,CAAC,KAAK,IAAI,KAAK,EAAE,WAAW,EAAsB;IAC3D;;IAGA,MAAM,MAAM,CAAC,GAAqB,EAAA;QAChC,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG;YAAE;AACnC,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;IAChE;AAEA;;;;;;;;;;AAUG;AACH,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;QACnC,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,KAAK,CACb,CAAA,yFAAA,CAA2F;AACzF,gBAAA,CAAA,EAAG,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAA,+BAAA,CAAiC,CAC1E;QACH;AACA,QAAA,OAAO,KAAK,CAAC,WAAW,CAAS,OAAO,CAAC;IAC3C;AAEA;;;;;;;;AAQG;IACH,MAAM,MAAM,CAAC,KAAa,EAAA;QACxB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC;AAClD,QAAA,MAAM,KAAK,CAAC,KAAK,EAAE;AACnB,QAAA,MAAM,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;IAC7B;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,OAAO,GAAA;AACX,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE;IACtD;;AAGA,IAAA,MAAM,YAAY,GAAA;AAChB,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE;IACjE;;AAGA,IAAA,MAAM,MAAM,GAAA;QACV,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;AAClE,QAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;IACpB;;AAGA,IAAA,MAAM,aAAa,CAAC,OAAwB,EAAE,KAAa,EAAA;AACzD,QAAA,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,KAAK,CAAC;IAC9D;AAEA;;;AAGG;AACH,IAAA,MAAM,MAAM,GAAA;QACV,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACpE,QAAA,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;IACpB;;AAGA,IAAA,MAAM,aAAa,CAAC,OAAwB,EAAE,KAAa,EAAA;QACzD,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,KAAK,GAAG,GAAG,GAAG,GAAG,CAAA,EAAG,OAAO,CAAC,WAAW,EAAE,CAAA,CAAA,CAAG,EAAE,KAAK,CAAC;IAC5F;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,eAAe,GAAA;AACnB,QAAA,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;AAC/B,QAAA,IAAI,GAAG,KAAK,KAAK,EAAE;YACjB,MAAM,IAAI,KAAK,CACb,qGAAqG;AACnG,gBAAA,kFAAkF,CACrF;QACH;AACA,QAAA,IAAI,EAAE,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;AAAE,YAAA,OAAO,IAAI;AACzC,QAAA,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;AACrD,QAAA,OAAO,KAAK;IACd;;IAGA,MAAM,eAAe,CAAC,KAAa,EAAA;AACjC,QAAA,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;AAC/B,QAAA,IAAI,GAAG,KAAK,KAAK,EAAE;YACjB,MAAM,IAAI,KAAK,CACb,oGAAoG;AAClG,gBAAA,iDAAiD,CACpD;QACH;QACA,MAAM,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC;IAC3C;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,QAAQ,GAAA;AACZ,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,wBAAwB,CAAC;IAC/D;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,2BAA2B,CAAC;IAClE;;AAGA,IAAA,MAAM,WAAW,GAAA;QACf,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,0BAA0B,CAAC,EAAE;QACvE,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAM,MAAM,KAAI,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,CAAC;IACnG;AAEA;;;;;;AAMG;IACH,MAAM,UAAU,CAAC,KAAa,EAAA;QAC5B,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,0BAA0B,CAAC,EAAE;AACvE,QAAA,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE;AAC7B,YAAA,IAAI,CAAC,MAAM,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,KAAK,EAAE;AACvD,gBAAA,MAAM,MAAM,CAAC,KAAK,EAAE;gBACpB;YACF;QACF;AACA,QAAA,MAAM,IAAI,KAAK,CACb,CAAA,kDAAA,EAAqD,KAAK,CAAA,sBAAA,CAAwB;AAChF,YAAA,CAAA,EAAG,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA,CAAA,CAAG,CAC9C;IACH;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,SAAS,GAAA;QACb,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,8CAA8C,CAAC,EAAE;QAClF,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,uDAAuD,CAAC,EAAE;QAC5F,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,yDAAyD,CAAC,EAAE;QAExG,OAAO;YACL,EAAE,EAAE,EAAE,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,EAAE,MAAM,OAAO,CAAC,EAAE,EAAE,KAAK,CAAC,EAAE;AACjE,YAAA,GAAG,EAAE,MAAM,OAAO,CAAC,GAAG,EAAE,MAAM,CAAC;AAC/B,YAAA,KAAK,EAAE,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,IAAI;SACnD;IACH;;AAGQ,IAAA,MAAM,OAAO,GAAA;AACnB,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;AACnC,QAAA,OAAO,KAAK,GAAG,KAAK,CAAC,WAAW,CAAS,OAAO,CAAC,GAAG,EAAE;IACxD;IAEQ,MAAM,eAAe,CAAC,MAAc,EAAA;AAC1C,QAAA,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE;QACnC,IAAI,CAAC,KAAK,EAAE;AACV,YAAA,MAAM,IAAI,KAAK,CACb,CAAA,qBAAA,EAAwB,MAAM,CAAA,8DAAA,CAAgE;AAC5F,gBAAA,CAAA,EAAG,CAAC,MAAM,IAAI,CAAC,MAAM,EAAE,EAAE,WAAW,EAAE,CAAA,+BAAA,CAAiC,CAC1E;QACH;AACA,QAAA,OAAO,KAAK;IACd;AAEQ,IAAA,MAAM,aAAa,CAAC,GAAqB,EAAE,MAAyB,EAAA;QAC1E,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;AAClC,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;AAEzC,QAAA,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,IAAG;YACxB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,YAAA,IAAI,CAAC,KAAK;AAAE,gBAAA,MAAM,IAAI,KAAK,CAAC,CAAA,0BAAA,EAA6B,GAAG,CAAC,WAAW,EAAE,CAAA,aAAA,EAAgB,KAAK,CAAA,QAAA,CAAU,CAAC;AAC1G,YAAA,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;AAC5B,QAAA,CAAC,CAAC;IACJ;AAEQ,IAAA,MAAM,YAAY,CAAC,GAAqB,EAAE,KAAa,EAAE,KAAa,EAAA;QAC5E,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;AACnC,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;QAC/B,IAAI,CAAC,KAAK,EAAE;YACV,MAAM,IAAI,KAAK,CACb,CAAA,0BAAA,EAA6B,GAAG,CAAC,WAAW,EAAE,CAAA,aAAA,EAAgB,KAAK,CAAA,SAAA,EACjE,KAAK,KAAK,IAAI,GAAG,+CAA+C,GAAG,EACrE,CAAA,CAAE,CACH;QACH;;;;;;QAOA,MAAM,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,OAAO,CAAC;IAC5C;AAEQ,IAAA,MAAM,UAAU,CAAC,GAAqB,EAAE,IAAY,EAAA;AAC1D,QAAA,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE;AACnC,QAAA,IAAI,OAAO,KAAK,GAAG,EAAE;YACnB,MAAM,IAAI,KAAK,CACb,CAAA,6BAAA,EAAgC,IAAI,QAAQ,GAAG,CAAC,WAAW,EAAE,CAAA,sCAAA,CAAwC;gBACnG,CAAA,IAAA,EAAO,OAAO,CAAC,WAAW,EAAE,sDAAsD,GAAG,CAAA,SAAA,CAAW,CACnG;QACH;IACF;;AAGQ,IAAA,MAAM,aAAa,GAAA;AACzB,QAAA,MAAM,KAAK,GAAG,IAAI,GAAG,EAAmD;AAExE,QAAA,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,EAAE,EAAE;AAC5D,YAAA,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,QAAQ,EAAE;YACpC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,KAAK,CAAC,QAAQ,EAAE,EAAE,CAAC;QACtF;AACA,QAAA,OAAO,KAAK;IACd;;;ACtWF;;;;;AAKG;AAOH;;;;;;;;;;;;;;;;;;;;;AAqBG;AACG,MAAO,2BAA4B,SAAQ,gBAAgB,CAAA;AAC/D,IAAA,OAAO,YAAY,GAAG,wBAAwB;;AAG9C,IAAA,OAAO,IAAI,CAAC,OAAA,GAA8C,EAAE,EAAA;AAC1D,QAAA,OAAO,IAAI,gBAAgB,CAAC,2BAA2B,EAAE,OAAO;aAC7D,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,gBAAgB,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,CAAC;aAC1G,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,OAAO,EAAE,IAAI,KAAK,CAAC,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,CAAC;IAChG;;AAGA,IAAA,MAAM,OAAO,GAAA;QACX,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE;IACnC;;AAGA,IAAA,MAAM,MAAM,GAAA;AACV,QAAA,OAAO,CAAC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC,MAAM,MAAM;IAC7E;AAEA;;;;;;;AAOG;AACH,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;QAC9B,OAAO,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,eAAe,CAAC,MAAM,MAAM,KAAK,MAAM,IAAI,CAAC,WAAW,CAAU,UAAU,CAAC,CAAC;IAC/G;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,SAAS,GAAA;AACb,QAAA,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC;AAClE,QAAA,IAAI,CAAC,EAAE;AAAE,YAAA,OAAO,IAAI;QAEpB,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA,CAAA,EAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE;IAClH;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,IAAI,GAAA;QACR,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;AAC1B,YAAA,IAAI,MAAM,IAAI,CAAC,UAAU,EAAE,EAAE;gBAC3B,MAAM,IAAI,KAAK,CACb,CAAA,qCAAA,EAAwC,MAAM,IAAI,CAAC,OAAO,EAAE,CAAA,wCAAA,CAA0C;AACpG,oBAAA,8DAA8D,CACjE;YACH;YACA,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;QACnC;AAEA,QAAA,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE;QACrC,IAAI,CAAC,MAAM,EAAE;YACX,MAAM,IAAI,KAAK,CACb,sGAAsG;AACpG,gBAAA,iEAAiE,CACpE;QACH;AACA,QAAA,OAAO,MAAM;IACf;;AAGA,IAAA,MAAM,KAAK,GAAA;AACT,QAAA,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;YAAE;QAC5B,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;IACnC;;AAGA,IAAA,MAAM,MAAM,GAAA;QACV,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE;IACnC;AAEA;;;;;;AAMG;AACH,IAAA,MAAM,UAAU,GAAA;AACd,QAAA,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC;IACpD;;AAGA,IAAA,MAAM,WAAW,GAAA;AACf,QAAA,OAAO,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,EAAE,YAAY,CAAC,eAAe,CAAC;IAC1D;;;ACtIF;;AAEG;;;;"}
|
|
1
|
+
{"version":3,"file":"ngwr-color-picker-testing.mjs","sources":["../../../projects/lib/color-picker/testing/wr-color-picker-harness.ts","../../../projects/lib/color-picker/testing/wr-color-picker-trigger-harness.ts","../../../projects/lib/color-picker/testing/ngwr-color-picker-testing.ts"],"sourcesContent":["/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, type TestElement } from '@angular/cdk/testing';\n\nimport { WrSegmentedHarness } from 'ngwr/segmented/testing';\n\nimport type { WrColorPickerHarnessFilters, WrColorPickerTab, WrColorPickerThumbs } from './interfaces';\n\n/**\n * One labelled numeric field — internal. A `TestElement` cannot be queried into, so\n * pairing an input with the label printed under it means a harness anchored on the\n * `<label>` that holds both.\n */\nclass FieldHarness extends ComponentHarness {\n static hostSelector = '.wr-color-picker__field';\n\n async getLabel(): Promise<string> {\n return (await this.locatorFor('.wr-color-picker__field-label')()).text();\n }\n\n async getInput(): Promise<TestElement> {\n return this.locatorFor('input')();\n }\n\n async getValue(): Promise<string> {\n return (await this.getInput()).getProperty<string>('value');\n }\n}\n\n/** The `left: <n>%` / `top: <n>%` a thumb carries, out of its inline `style`. */\nconst THUMB_POS = {\n left: /(?:^|;)\\s*left\\s*:\\s*([\\d.]+)%/,\n top: /(?:^|;)\\s*top\\s*:\\s*([\\d.]+)%/,\n} as const;\n\n/** One thumb's declared offset. See {@link WrColorPickerHarness.getThumbs} for why this is not `getCssValue()`. */\nasync function percent(thumb: TestElement, side: 'left' | 'top', surface: string): Promise<number> {\n const style = await thumb.getAttribute('style');\n const match = THUMB_POS[side].exec(style ?? '');\n\n if (!match) {\n throw new Error(\n `WrColorPickerHarness.getThumbs(): the ${surface} thumb carries no inline ${side} percentage ` +\n `(style: \"${style ?? ''}\"). The component writes one on every render, so its absence is the bug — ` +\n `and the stylesheet declares \\`${side}: 0\\`, so reporting 0 would read as a thumb parked at the origin.`\n );\n }\n return Number.parseFloat(match[1]);\n}\n\n/**\n * Test harness for `<wr-color-picker>` — the inline picker, and the one the\n * `[wrColorPickerTrigger]` directive mounts in an overlay.\n *\n * **What this harness will not do: drag.** The SV canvas and the hue / alpha\n * sliders are pointer surfaces that read `getBoundingClientRect()` and divide by\n * its width. A unit test has no layout, so every box is 0×0 and the division is\n * `NaN` — a `setHue()` built on a synthetic pointer event would report success and\n * write nothing, or write garbage. The numeric fields reach the same state and are\n * also the only keyboard path the component has, so they are the whole write API\n * here. {@link getThumbs} reads where the thumbs ARE, from the percentages the\n * component writes inline, which is how a spec checks a surface followed a value.\n *\n * **And it will not read the preview swatch.** The preview paints the current\n * colour as a CSS background, and jsdom normalises that to `rgb(…)` — dropping the\n * alpha channel entirely, so `#ff880080` and `#ff8800ff` come back identical. A\n * `getColor()` reading it would answer one thing in a unit test and another in a\n * browser. {@link getHex} is the colour: the field holds the canonical 8-digit\n * string, alpha included, whatever `format` writes into `value`.\n *\n * @example\n * ```ts\n * const picker = await loader.getHarness(WrColorPickerHarness);\n *\n * await picker.setHex('#3969e2');\n * expect(await picker.getHex()).toBe('#3969e2ff');\n *\n * await picker.setTab('rgb');\n * expect(await picker.getRgb()).toEqual({ r: 57, g: 105, b: 226 });\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrColorPickerHarness extends ComponentHarness {\n static hostSelector = 'wr-color-picker';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrColorPickerHarnessFilters = {}): HarnessPredicate<WrColorPickerHarness> {\n return new HarnessPredicate(WrColorPickerHarness, options)\n .addOption('color', options.color, (harness, color) => HarnessPredicate.stringMatches(harness.readHex(), color))\n .addOption('tab', options.tab, async (harness, tab) => (await harness.getTab()) === tab)\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled);\n }\n\n private readonly hexField = this.locatorForOptional('.wr-color-picker__inputs--hex input');\n private readonly tabs = this.locatorFor(WrSegmentedHarness.with({ selector: '.wr-color-picker__tabs' }));\n\n /**\n * The tab switcher, as a {@link WrSegmentedHarness}.\n *\n * Handed back rather than re-queried: the switcher IS a `<wr-segmented>`, which\n * already knows that the roving tab stop is not the selection and how the sliding\n * thumb reports itself. Re-reading its buttons here would be a second, worse copy.\n */\n async getTabs(): Promise<WrSegmentedHarness> {\n return this.tabs();\n }\n\n /** Which set of numeric fields is showing. */\n async getTab(): Promise<WrColorPickerTab> {\n const label = await (await this.tabs()).getSelectedLabel();\n return (label ?? 'HEX').toLowerCase() as WrColorPickerTab;\n }\n\n /** Show a different set of numeric fields. An already-active tab is left alone. */\n async setTab(tab: WrColorPickerTab): Promise<void> {\n if ((await this.getTab()) === tab) return;\n await (await this.tabs()).select({ label: tab.toUpperCase() });\n }\n\n /**\n * The canonical hex string, as the HEX field shows it — 8 digits while `alpha` is\n * on, 6 while it is off.\n *\n * This is the picker's colour, and deliberately not the same thing as its `value`:\n * `format` decides whether `value` is written as hex, `rgb()` or `hsl()`, while the\n * field always shows hex. A spec that cares about the emitted string should read\n * the bound signal; one that cares about the COLOUR should read this.\n *\n * Throws off the HEX tab, where the field does not exist — see {@link setTab}.\n */\n async getHex(): Promise<string> {\n const field = await this.hexField();\n if (!field) {\n throw new Error(\n `WrColorPickerHarness.getHex(): the HEX field is not rendered — the picker is showing the ` +\n `${(await this.getTab()).toUpperCase()} tab. Call setTab('hex') first.`\n );\n }\n return field.getProperty<string>('value');\n }\n\n /**\n * Type a colour into the HEX field.\n *\n * Typed rather than assigned, because that is the path the component is built\n * around: it re-parses on every keystroke and applies the first spelling that\n * parses, so a partial `#ff8` commits a colour on its way to `#ff8800`. An\n * unparseable string leaves the committed colour ALONE and lives in the field\n * until {@link blurHex} snaps it back — assert that rather than expecting a throw.\n */\n async setHex(value: string): Promise<void> {\n const field = await this.requireHexField('setHex');\n await field.clear();\n await field.sendKeys(value);\n }\n\n /**\n * Blur the HEX field — re-syncing it with the committed colour and emitting\n * `touch`.\n *\n * The re-sync is the visible half: a field left holding text that never parsed\n * goes back to the canonical hex here, and nowhere else.\n */\n async blurHex(): Promise<void> {\n await (await this.requireHexField('blurHex')).blur();\n }\n\n /** Whether the HEX field currently holds focus. */\n async isHexFocused(): Promise<boolean> {\n return (await this.requireHexField('isHexFocused')).isFocused();\n }\n\n /** The three RGB channels as the RGB tab shows them. Throws off that tab. */\n async getRgb(): Promise<{ r: number; g: number; b: number }> {\n const [r, g, b] = await this.channelValues('rgb', ['R', 'G', 'B']);\n return { r, g, b };\n }\n\n /** Write one RGB channel, 0–255. Out-of-range numbers are clamped by the component. */\n async setRgbChannel(channel: 'r' | 'g' | 'b', value: number): Promise<void> {\n await this.writeChannel('rgb', channel.toUpperCase(), value);\n }\n\n /**\n * Hue, saturation and lightness as the HSL tab shows them — degrees and whole\n * percents, already rounded for display. Throws off that tab.\n */\n async getHsl(): Promise<{ h: number; s: number; l: number }> {\n const [h, s, l] = await this.channelValues('hsl', ['H', 'S%', 'L%']);\n return { h, s, l };\n }\n\n /** Write one HSL channel — `h` in degrees, `s` / `l` in percent. */\n async setHslChannel(channel: 'h' | 's' | 'l', value: number): Promise<void> {\n await this.writeChannel('hsl', channel === 'h' ? 'H' : `${channel.toUpperCase()}%`, value);\n }\n\n /**\n * Alpha as the whole percent the numeric tabs show, or `null` when the picker was\n * built without alpha.\n *\n * Only the RGB and HSL tabs carry the field — the HEX tab spells alpha into the\n * hex string instead — so this throws on the HEX tab rather than answering `null`,\n * which would read as \"this picker has no alpha\".\n */\n async getAlphaPercent(): Promise<number | null> {\n const tab = await this.getTab();\n if (tab === 'hex') {\n throw new Error(\n 'WrColorPickerHarness.getAlphaPercent(): the HEX tab has no alpha field — the alpha is the last two ' +\n \"digits of getHex(). Call setTab('rgb') or setTab('hsl') to read it as a percent.\"\n );\n }\n if (!(await this.hasAlpha())) return null;\n const [alpha] = await this.channelValues(tab, ['A%']);\n return alpha;\n }\n\n /** Write alpha as a whole percent, 0–100. */\n async setAlphaPercent(value: number): Promise<void> {\n const tab = await this.getTab();\n if (tab === 'hex') {\n throw new Error(\n \"WrColorPickerHarness.setAlphaPercent(): the HEX tab has no alpha field. Call setTab('rgb') first, \" +\n 'or write the two alpha digits through setHex().'\n );\n }\n await this.writeChannel(tab, 'A%', value);\n }\n\n /**\n * Whether the picker offers alpha at all.\n *\n * From the host modifier, which is the one answer that holds on every tab: the\n * alpha SLIDER is always rendered when it is on, while the `A%` field only exists\n * on the two numeric tabs.\n */\n async hasAlpha(): Promise<boolean> {\n return (await this.host()).hasClass('wr-color-picker--alpha');\n }\n\n /**\n * Whether the picker refuses interaction.\n *\n * Read from the modifier the host paints rather than from a field's `disabled`\n * property, because the fields come and go with the tab while the state does not —\n * and the drag surfaces, which have no `disabled` of their own, are gated by the\n * same signal.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.host()).hasClass('wr-color-picker--disabled');\n }\n\n /** The preset colours offered under the fields, as the strings the consumer passed. */\n async getSwatches(): Promise<string[]> {\n const swatches = await this.locatorForAll('.wr-color-picker__swatch')();\n return Promise.all(swatches.map(async swatch => (await swatch.getAttribute('aria-label')) ?? ''));\n }\n\n /**\n * Click a preset.\n *\n * Matched on the string the consumer passed, which is what the button publishes as\n * its accessible name — the rendered background is a CSS colour and would come back\n * normalised and alpha-stripped. Throws when nothing matches, naming what is offered.\n */\n async pickSwatch(color: string): Promise<void> {\n const swatches = await this.locatorForAll('.wr-color-picker__swatch')();\n for (const swatch of swatches) {\n if ((await swatch.getAttribute('aria-label')) === color) {\n await swatch.click();\n return;\n }\n }\n throw new Error(\n `WrColorPickerHarness.pickSwatch(): no swatch for \"${color}\". The picker offers: ` +\n `${(await this.getSwatches()).join(', ')}.`\n );\n }\n\n /**\n * Where the three thumbs sit, in percent along their surfaces.\n *\n * The component writes these as inline `left` / `top` percentages, so they are\n * readable with no layout at all — which makes them the only evidence a spec has\n * that the surfaces followed a colour set through the fields. A measured position\n * would be zero for all three.\n *\n * Read off the `style` ATTRIBUTE rather than through `getCssValue()`, and the\n * difference is not cosmetic: `getCssValue()` is `getComputedStyle()`, and `left` /\n * `top` on a positioned element resolve to the USED value — so the declared `40%`\n * comes straight back in jsdom and arrives as pixels in a real browser, and the same\n * harness answered 40 here and 96 under a browser runner with nothing to say which\n * one you got. The stylesheet's own `top: 0; left: 0` is a second way that read lies,\n * turning a thumb whose binding is gone into one parked at the origin.\n */\n async getThumbs(): Promise<WrColorPickerThumbs> {\n const sv = await this.locatorFor('.wr-color-picker__sv .wr-color-picker__thumb')();\n const hue = await this.locatorFor('.wr-color-picker__slider--hue .wr-color-picker__thumb')();\n const alpha = await this.locatorForOptional('.wr-color-picker__slider--alpha .wr-color-picker__thumb')();\n\n return {\n sv: { x: await percent(sv, 'left', 'SV'), y: await percent(sv, 'top', 'SV') },\n hue: await percent(hue, 'left', 'hue'),\n alpha: alpha ? await percent(alpha, 'left', 'alpha') : null,\n };\n }\n\n /** The HEX field's value without the tab check — for filters, which must not throw. */\n private async readHex(): Promise<string> {\n const field = await this.hexField();\n return field ? field.getProperty<string>('value') : '';\n }\n\n private async requireHexField(method: string): Promise<TestElement> {\n const field = await this.hexField();\n if (!field) {\n throw new Error(\n `WrColorPickerHarness.${method}(): the HEX field is not rendered — the picker is showing the ` +\n `${(await this.getTab()).toUpperCase()} tab. Call setTab('hex') first.`\n );\n }\n return field;\n }\n\n private async channelValues(tab: WrColorPickerTab, labels: readonly string[]): Promise<number[]> {\n await this.requireTab(tab, 'read');\n const inputs = await this.inputsByLabel();\n\n return labels.map(label => {\n const input = inputs.get(label);\n if (!input) throw new Error(`WrColorPickerHarness: the ${tab.toUpperCase()} tab has no \"${label}\" field.`);\n return Number(input.value);\n });\n }\n\n private async writeChannel(tab: WrColorPickerTab, label: string, value: number): Promise<void> {\n await this.requireTab(tab, 'write');\n const inputs = await this.inputsByLabel();\n const found = inputs.get(label);\n if (!found) {\n throw new Error(\n `WrColorPickerHarness: the ${tab.toUpperCase()} tab has no \"${label}\" field. ${\n label === 'A%' ? 'This picker was built with `[alpha]=\"false\"`.' : ''\n }`\n );\n }\n\n // Set and dispatch once, rather than clearing and typing. Each of these inputs\n // is bound to `[value]`, and the component commits on every `input` event — so\n // typing 128 would land 1, then 12, then 128, and CLEARING would land 0 first,\n // because `Number('')` is 0 rather than NaN. A spec that asked for one colour\n // would get four, the first of them black.\n await found.element.setInputValue(String(value));\n await found.element.dispatchEvent('input');\n }\n\n private async requireTab(tab: WrColorPickerTab, verb: string): Promise<void> {\n const current = await this.getTab();\n if (current !== tab) {\n throw new Error(\n `WrColorPickerHarness: cannot ${verb} the ${tab.toUpperCase()} channels while the picker is showing ` +\n `the ${current.toUpperCase()} tab — those fields are not rendered. Call setTab('${tab}') first.`\n );\n }\n }\n\n /** Every numeric input of the current tab, keyed by the label printed under it. */\n private async inputsByLabel(): Promise<Map<string, { element: TestElement; value: string }>> {\n const found = new Map<string, { element: TestElement; value: string }>();\n\n for (const field of await this.locatorForAll(FieldHarness)()) {\n const label = await field.getLabel();\n found.set(label, { element: await field.getInput(), value: await field.getValue() });\n }\n return found;\n }\n}\n","/**\n * @license\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE\n */\n\nimport { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testing';\n\nimport type { WrColorPickerTriggerHarnessFilters } from './interfaces';\nimport { WrColorPickerHarness } from './wr-color-picker-harness';\n\n/**\n * Test harness for `[wrColorPickerTrigger]` — the element that opens a\n * `<wr-color-picker>` in an overlay.\n *\n * The trigger stays in your fixture; the picker it opens does not. So this harness\n * is loaded from the fixture loader like any element, and {@link getPicker} reaches\n * ACROSS into the overlay container for you — scoped by the panel id the trigger\n * publishes through `aria-controls`, never by `.wr-color-picker-overlay`, which\n * answers with whichever trigger opened first.\n *\n * @example\n * ```ts\n * const trigger = await loader.getHarness(WrColorPickerTriggerHarness);\n * const picker = await trigger.open();\n *\n * await picker.setHex('#3969e2');\n * await trigger.sendEscape();\n * expect(await trigger.isOpen()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrColorPickerTriggerHarness extends ComponentHarness {\n static hostSelector = '[wrColorPickerTrigger]';\n\n /** Build a predicate that narrows the query — pass to `getHarness` / `getAllHarnesses`. */\n static with(options: WrColorPickerTriggerHarnessFilters = {}): HarnessPredicate<WrColorPickerTriggerHarness> {\n return new HarnessPredicate(WrColorPickerTriggerHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);\n }\n\n /** The trigger's own text, trimmed. */\n async getText(): Promise<string> {\n return (await this.host()).text();\n }\n\n /** Whether the picker is showing, from the trigger's `aria-expanded`. */\n async isOpen(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-expanded')) === 'true';\n }\n\n /**\n * Whether the trigger refuses to open.\n *\n * From `aria-disabled`, which the directive writes for its own `disabled` input.\n * The host is usually a `<button>`, but the directive does not touch its `disabled`\n * PROPERTY — a consumer who binds that as well turns the element off at the DOM\n * level, which is a stronger thing and reads here too.\n */\n async isDisabled(): Promise<boolean> {\n const host = await this.host();\n return (await host.getAttribute('aria-disabled')) === 'true' || (await host.getProperty<boolean>('disabled'));\n }\n\n /**\n * The picker this trigger opened, or `null` while it is closed.\n *\n * Scoped by the id in `aria-controls`, so two triggers open at once — which\n * nothing in the component prevents, since only an outside click closes one —\n * answer with their own panels rather than with whichever came first.\n */\n async getPicker(): Promise<WrColorPickerHarness | null> {\n const id = await (await this.host()).getAttribute('aria-controls');\n if (!id) return null;\n\n return this.documentRootLocatorFactory().locatorForOptional(WrColorPickerHarness.with({ ancestor: `#${id}` }))();\n }\n\n /**\n * Open the picker and hand it back. An already-open trigger is left alone.\n *\n * Throws on a disabled trigger rather than answering `null` three lines later:\n * `toggle()` returns early while `disabled` is set, so the click lands and nothing\n * happens at all.\n */\n async open(): Promise<WrColorPickerHarness> {\n if (!(await this.isOpen())) {\n if (await this.isDisabled()) {\n throw new Error(\n `WrColorPickerTriggerHarness.open(): \"${await this.getText()}\" is disabled — the directive turns its ` +\n 'own toggle away, so the click would land and change nothing.'\n );\n }\n await (await this.host()).click();\n }\n\n const picker = await this.getPicker();\n if (!picker) {\n throw new Error(\n 'WrColorPickerTriggerHarness.open(): the trigger reports itself open but published no panel to find. ' +\n 'That is a broken `aria-controls` pairing, not a timing problem.'\n );\n }\n return picker;\n }\n\n /** Close the picker. An already-closed trigger is left alone. */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n await (await this.host()).click();\n }\n\n /** Click the trigger once, whichever way that takes it. */\n async toggle(): Promise<void> {\n await (await this.host()).click();\n }\n\n /**\n * Press Escape.\n *\n * Sent to the TRIGGER, and it still reaches the picker: the overlay listens through\n * the CDK's keyboard dispatcher, which keeps one document listener and routes to\n * the top-most overlay — so this does not depend on where focus happens to be.\n */\n async sendEscape(): Promise<void> {\n await (await this.host()).sendKeys(TestKey.ESCAPE);\n }\n\n /** The role the trigger claims to open — `dialog`. */\n async getHasPopup(): Promise<string | null> {\n return (await this.host()).getAttribute('aria-haspopup');\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@ import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
|
|
2
2
|
import { DecimalPipe } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
4
|
import { input, model, output, signal, computed, effect, ViewEncapsulation, Component, inject, ElementRef, ViewContainerRef, DestroyRef, Directive } from '@angular/core';
|
|
5
|
+
import { useI18nFormatter, readI18nText } from 'ngwr/i18n';
|
|
5
6
|
import { WrSegmented } from 'ngwr/segmented';
|
|
6
7
|
import { clamp } from 'ngwr/utils';
|
|
7
8
|
import { ScrollStrategyOptions } from '@angular/cdk/overlay';
|
|
@@ -342,6 +343,9 @@ function formatColor(rgb, format, withAlpha) {
|
|
|
342
343
|
* Use of this source code is governed by an MIT-style license that can be
|
|
343
344
|
* found in the LICENSE file at https://github.com/thekhegay/ngwr/blob/main/LICENSE
|
|
344
345
|
*/
|
|
346
|
+
/** Arrow step, in each surface's own unit: degrees of hue, percent everywhere else. */
|
|
347
|
+
const KEY_STEP = 1;
|
|
348
|
+
const KEY_STEP_COARSE = 10;
|
|
345
349
|
/** Whether a hex string carries its own alpha (`#rgba` or `#rrggbbaa`). */
|
|
346
350
|
function hasAlphaDigits(hex) {
|
|
347
351
|
const digits = hex.trim().replace(/^#/, '').length;
|
|
@@ -432,9 +436,18 @@ class WrColorPicker {
|
|
|
432
436
|
/** HSL view of the current colour, computed lazily. */
|
|
433
437
|
hslView = computed(() => rgbToHsl(this.rgb()), /* @ts-ignore */
|
|
434
438
|
...(ngDevMode ? [{ debugName: "hslView" }] : /* istanbul ignore next */ []));
|
|
435
|
-
/** Alpha as integer percent
|
|
439
|
+
/** Alpha as integer percent — the numeric tabs and the alpha slider's `aria-valuenow`. */
|
|
436
440
|
alphaPercent = computed(() => Math.round(this.a() * 100), /* @ts-ignore */
|
|
437
441
|
...(ngDevMode ? [{ debugName: "alphaPercent" }] : /* istanbul ignore next */ []));
|
|
442
|
+
/** Hue in whole degrees, for the hue slider's `aria-valuenow`. */
|
|
443
|
+
hueValue = computed(() => Math.round(this.h()), /* @ts-ignore */
|
|
444
|
+
...(ngDevMode ? [{ debugName: "hueValue" }] : /* istanbul ignore next */ []));
|
|
445
|
+
areaLabel = useI18nFormatter('colorPicker.area', 'Saturation and brightness, {{saturation}}% and {{brightness}}%');
|
|
446
|
+
/** Name of the SV surface, carrying the two values a `role="group"` cannot. */
|
|
447
|
+
resolvedAreaLabel = computed(() => this.areaLabel({ saturation: Math.round(this.s() * 100), brightness: Math.round(this.v() * 100) }), /* @ts-ignore */
|
|
448
|
+
...(ngDevMode ? [{ debugName: "resolvedAreaLabel" }] : /* istanbul ignore next */ []));
|
|
449
|
+
resolvedHueLabel = readI18nText('colorPicker.hue', 'Hue');
|
|
450
|
+
resolvedAlphaLabel = readI18nText('colorPicker.alpha', 'Opacity');
|
|
438
451
|
tabOptions = [
|
|
439
452
|
{ value: 'hex', label: 'HEX' },
|
|
440
453
|
{ value: 'rgb', label: 'RGB' },
|
|
@@ -509,6 +522,83 @@ class WrColorPicker {
|
|
|
509
522
|
target.addEventListener('pointercancel', cleanup);
|
|
510
523
|
this.updateFromEvent(event, target, surface);
|
|
511
524
|
}
|
|
525
|
+
// Keyboard handlers
|
|
526
|
+
//
|
|
527
|
+
// The three surfaces used to be bare `<div>`s carrying nothing but
|
|
528
|
+
// `(pointerdown)` — no role, no name, no tab stop, no key handler — so the
|
|
529
|
+
// control the component is built around was operable by pointer only. The
|
|
530
|
+
// numeric HEX / RGB / HSL fields could always reach the same values, which is
|
|
531
|
+
// why this is 4.1.2 rather than a total loss of keyboard access, but a
|
|
532
|
+
// roleless div driving a colour is WCAG F59 either way.
|
|
533
|
+
/**
|
|
534
|
+
* Hue and alpha are real one-value sliders, so they take the APG slider keys —
|
|
535
|
+
* the same set `wr-knob` and `wr-slider` implement, including Home / End.
|
|
536
|
+
*/
|
|
537
|
+
onSliderKeydown(event, surface) {
|
|
538
|
+
if (this.disabled())
|
|
539
|
+
return;
|
|
540
|
+
const step = event.shiftKey ? KEY_STEP_COARSE : KEY_STEP;
|
|
541
|
+
const max = surface === 'hue' ? 360 : 100;
|
|
542
|
+
const current = surface === 'hue' ? this.h() : this.a() * 100;
|
|
543
|
+
let next;
|
|
544
|
+
switch (event.key) {
|
|
545
|
+
case 'ArrowRight':
|
|
546
|
+
case 'ArrowUp':
|
|
547
|
+
next = current + step;
|
|
548
|
+
break;
|
|
549
|
+
case 'ArrowLeft':
|
|
550
|
+
case 'ArrowDown':
|
|
551
|
+
next = current - step;
|
|
552
|
+
break;
|
|
553
|
+
case 'Home':
|
|
554
|
+
next = 0;
|
|
555
|
+
break;
|
|
556
|
+
case 'End':
|
|
557
|
+
next = max;
|
|
558
|
+
break;
|
|
559
|
+
default:
|
|
560
|
+
return;
|
|
561
|
+
}
|
|
562
|
+
event.preventDefault();
|
|
563
|
+
const value = clamp(next, 0, max);
|
|
564
|
+
if (surface === 'hue')
|
|
565
|
+
this.h.set(value);
|
|
566
|
+
else
|
|
567
|
+
this.a.set(value / 100);
|
|
568
|
+
this.emit();
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* The SV canvas is two axes at once, so the keys follow the picture: left and
|
|
572
|
+
* right run along saturation, up and down along brightness — the directions
|
|
573
|
+
* the thumb visibly moves. Shift takes ten percent at a time.
|
|
574
|
+
*/
|
|
575
|
+
onAreaKeydown(event) {
|
|
576
|
+
if (this.disabled())
|
|
577
|
+
return;
|
|
578
|
+
const step = (event.shiftKey ? KEY_STEP_COARSE : KEY_STEP) / 100;
|
|
579
|
+
switch (event.key) {
|
|
580
|
+
case 'ArrowRight':
|
|
581
|
+
this.s.set(clamp(this.s() + step, 0, 1));
|
|
582
|
+
break;
|
|
583
|
+
case 'ArrowLeft':
|
|
584
|
+
this.s.set(clamp(this.s() - step, 0, 1));
|
|
585
|
+
break;
|
|
586
|
+
case 'ArrowUp':
|
|
587
|
+
this.v.set(clamp(this.v() + step, 0, 1));
|
|
588
|
+
break;
|
|
589
|
+
case 'ArrowDown':
|
|
590
|
+
this.v.set(clamp(this.v() - step, 0, 1));
|
|
591
|
+
break;
|
|
592
|
+
default:
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
event.preventDefault();
|
|
596
|
+
this.emit();
|
|
597
|
+
}
|
|
598
|
+
/** Leaving a surface is what "touched" means, the same as leaving the hex field. */
|
|
599
|
+
onSurfaceBlur() {
|
|
600
|
+
this.touch.emit();
|
|
601
|
+
}
|
|
512
602
|
updateFromEvent(event, target, surface) {
|
|
513
603
|
const rect = target.getBoundingClientRect();
|
|
514
604
|
const x = clamp((event.clientX - rect.left) / rect.width, 0, 1);
|
|
@@ -602,16 +692,16 @@ class WrColorPicker {
|
|
|
602
692
|
this.a.set(hsv.a);
|
|
603
693
|
this.emit();
|
|
604
694
|
}
|
|
605
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
606
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.
|
|
695
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrColorPicker, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
696
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.2", type: WrColorPicker, isStandalone: true, selector: "wr-color-picker", inputs: { alpha: { classPropertyName: "alpha", publicName: "alpha", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, swatches: { classPropertyName: "swatches", publicName: "swatches", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touch: "touch" }, host: { properties: { "class": "classes()", "style.--wr-color-picker-hue": "hueCss()", "style.--wr-color-picker-rgb": "rgbCss()" } }, ngImport: i0, template: "<!--\n `role=\"group\"` rather than `role=\"slider\"`, because this surface holds TWO\n values and a slider has one `aria-valuenow`; and rather than\n `role=\"application\"`, which would switch the reader out of its own browse mode\n for the whole subtree \u2014 the call `wr-image-cropper` already made. A group has\n no value of its own, so the two percentages ride in its accessible name, which\n is where a reader querying the focused element finds them.\n-->\n<div\n class=\"wr-color-picker__sv\"\n role=\"group\"\n [attr.aria-label]=\"resolvedAreaLabel()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'sv')\"\n (keydown)=\"onAreaKeydown($event)\"\n (blur)=\"onSurfaceBlur()\"\n>\n <span class=\"wr-color-picker__thumb\" [style.left.%]=\"svThumbX()\" [style.top.%]=\"svThumbY()\"></span>\n</div>\n\n<div\n class=\"wr-color-picker__slider wr-color-picker__slider--hue\"\n role=\"slider\"\n aria-valuemin=\"0\"\n aria-valuemax=\"360\"\n [attr.aria-label]=\"resolvedHueLabel()\"\n [attr.aria-valuenow]=\"hueValue()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'hue')\"\n (keydown)=\"onSliderKeydown($event, 'hue')\"\n (blur)=\"onSurfaceBlur()\"\n>\n <span class=\"wr-color-picker__thumb wr-color-picker__thumb--slider\" [style.left.%]=\"hueThumbX()\"></span>\n</div>\n\n@if (alpha()) {\n <div\n class=\"wr-color-picker__slider wr-color-picker__slider--alpha\"\n role=\"slider\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"resolvedAlphaLabel()\"\n [attr.aria-valuenow]=\"alphaPercent()\"\n [attr.aria-valuetext]=\"`${alphaPercent()}%`\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'alpha')\"\n (keydown)=\"onSliderKeydown($event, 'alpha')\"\n (blur)=\"onSurfaceBlur()\"\n >\n <span class=\"wr-color-picker__thumb wr-color-picker__thumb--slider\" [style.left.%]=\"alphaThumbX()\"></span>\n </div>\n}\n\n<div class=\"wr-color-picker__chrome\">\n <span class=\"wr-color-picker__preview\" [style.background]=\"hex()\"></span>\n <wr-segmented\n class=\"wr-color-picker__tabs\"\n [options]=\"tabOptions\"\n [value]=\"activeTab()\"\n (valueChange)=\"onTabChange($event)\"\n />\n</div>\n\n@switch (activeTab()) {\n @case ('hex') {\n <div class=\"wr-color-picker__inputs wr-color-picker__inputs--hex\">\n <label class=\"wr-color-picker__field wr-color-picker__field--wide\">\n <input\n type=\"text\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n [value]=\"hexInput()\"\n [disabled]=\"disabled()\"\n (input)=\"onHexInput($event)\"\n (blur)=\"onHexBlur()\"\n />\n <span class=\"wr-color-picker__field-label\">HEX</span>\n </label>\n </div>\n }\n @case ('rgb') {\n <div class=\"wr-color-picker__inputs\">\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().r\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('r', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">R</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().g\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('g', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">G</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().b\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('b', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">B</span>\n </label>\n @if (alpha()) {\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"alphaPercent()\"\n [disabled]=\"disabled()\"\n (input)=\"onAlphaPercent($event)\"\n />\n <span class=\"wr-color-picker__field-label\">A%</span>\n </label>\n }\n </div>\n }\n @case ('hsl') {\n <div class=\"wr-color-picker__inputs\">\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"360\"\n [value]=\"hslView().h | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('h', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">H</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"hslView().s * 100 | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('s', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">S%</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"hslView().l * 100 | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('l', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">L%</span>\n </label>\n @if (alpha()) {\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"alphaPercent()\"\n [disabled]=\"disabled()\"\n (input)=\"onAlphaPercent($event)\"\n />\n <span class=\"wr-color-picker__field-label\">A%</span>\n </label>\n }\n </div>\n }\n}\n\n@if (swatches().length > 0) {\n <div class=\"wr-color-picker__swatches\">\n @for (color of swatches(); track color) {\n <button\n type=\"button\"\n class=\"wr-color-picker__swatch\"\n [style.background]=\"color\"\n [attr.aria-label]=\"color\"\n [disabled]=\"disabled()\"\n (click)=\"onSwatchClick(color)\"\n ></button>\n }\n </div>\n}\n", dependencies: [{ kind: "component", type: WrSegmented, selector: "wr-segmented", inputs: ["options", "value", "disabled", "size"], outputs: ["valueChange"] }, { kind: "pipe", type: DecimalPipe, name: "number" }], encapsulation: i0.ViewEncapsulation.None });
|
|
607
697
|
}
|
|
608
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
698
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrColorPicker, decorators: [{
|
|
609
699
|
type: Component,
|
|
610
700
|
args: [{ selector: 'wr-color-picker', encapsulation: ViewEncapsulation.None, host: {
|
|
611
701
|
'[class]': 'classes()',
|
|
612
702
|
'[style.--wr-color-picker-hue]': 'hueCss()',
|
|
613
703
|
'[style.--wr-color-picker-rgb]': 'rgbCss()',
|
|
614
|
-
}, imports: [DecimalPipe, WrSegmented], template: "<div
|
|
704
|
+
}, imports: [DecimalPipe, WrSegmented], template: "<!--\n `role=\"group\"` rather than `role=\"slider\"`, because this surface holds TWO\n values and a slider has one `aria-valuenow`; and rather than\n `role=\"application\"`, which would switch the reader out of its own browse mode\n for the whole subtree \u2014 the call `wr-image-cropper` already made. A group has\n no value of its own, so the two percentages ride in its accessible name, which\n is where a reader querying the focused element finds them.\n-->\n<div\n class=\"wr-color-picker__sv\"\n role=\"group\"\n [attr.aria-label]=\"resolvedAreaLabel()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'sv')\"\n (keydown)=\"onAreaKeydown($event)\"\n (blur)=\"onSurfaceBlur()\"\n>\n <span class=\"wr-color-picker__thumb\" [style.left.%]=\"svThumbX()\" [style.top.%]=\"svThumbY()\"></span>\n</div>\n\n<div\n class=\"wr-color-picker__slider wr-color-picker__slider--hue\"\n role=\"slider\"\n aria-valuemin=\"0\"\n aria-valuemax=\"360\"\n [attr.aria-label]=\"resolvedHueLabel()\"\n [attr.aria-valuenow]=\"hueValue()\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'hue')\"\n (keydown)=\"onSliderKeydown($event, 'hue')\"\n (blur)=\"onSurfaceBlur()\"\n>\n <span class=\"wr-color-picker__thumb wr-color-picker__thumb--slider\" [style.left.%]=\"hueThumbX()\"></span>\n</div>\n\n@if (alpha()) {\n <div\n class=\"wr-color-picker__slider wr-color-picker__slider--alpha\"\n role=\"slider\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n [attr.aria-label]=\"resolvedAlphaLabel()\"\n [attr.aria-valuenow]=\"alphaPercent()\"\n [attr.aria-valuetext]=\"`${alphaPercent()}%`\"\n [attr.aria-disabled]=\"disabled() || null\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (pointerdown)=\"onPointerDown($event, 'alpha')\"\n (keydown)=\"onSliderKeydown($event, 'alpha')\"\n (blur)=\"onSurfaceBlur()\"\n >\n <span class=\"wr-color-picker__thumb wr-color-picker__thumb--slider\" [style.left.%]=\"alphaThumbX()\"></span>\n </div>\n}\n\n<div class=\"wr-color-picker__chrome\">\n <span class=\"wr-color-picker__preview\" [style.background]=\"hex()\"></span>\n <wr-segmented\n class=\"wr-color-picker__tabs\"\n [options]=\"tabOptions\"\n [value]=\"activeTab()\"\n (valueChange)=\"onTabChange($event)\"\n />\n</div>\n\n@switch (activeTab()) {\n @case ('hex') {\n <div class=\"wr-color-picker__inputs wr-color-picker__inputs--hex\">\n <label class=\"wr-color-picker__field wr-color-picker__field--wide\">\n <input\n type=\"text\"\n spellcheck=\"false\"\n autocomplete=\"off\"\n [value]=\"hexInput()\"\n [disabled]=\"disabled()\"\n (input)=\"onHexInput($event)\"\n (blur)=\"onHexBlur()\"\n />\n <span class=\"wr-color-picker__field-label\">HEX</span>\n </label>\n </div>\n }\n @case ('rgb') {\n <div class=\"wr-color-picker__inputs\">\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().r\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('r', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">R</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().g\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('g', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">G</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"255\"\n [value]=\"rgb().b\"\n [disabled]=\"disabled()\"\n (input)=\"onRgbChannel('b', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">B</span>\n </label>\n @if (alpha()) {\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"alphaPercent()\"\n [disabled]=\"disabled()\"\n (input)=\"onAlphaPercent($event)\"\n />\n <span class=\"wr-color-picker__field-label\">A%</span>\n </label>\n }\n </div>\n }\n @case ('hsl') {\n <div class=\"wr-color-picker__inputs\">\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"360\"\n [value]=\"hslView().h | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('h', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">H</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"hslView().s * 100 | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('s', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">S%</span>\n </label>\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"hslView().l * 100 | number: '1.0-0'\"\n [disabled]=\"disabled()\"\n (input)=\"onHslChannel('l', $event)\"\n />\n <span class=\"wr-color-picker__field-label\">L%</span>\n </label>\n @if (alpha()) {\n <label class=\"wr-color-picker__field\">\n <input\n type=\"number\"\n min=\"0\"\n max=\"100\"\n [value]=\"alphaPercent()\"\n [disabled]=\"disabled()\"\n (input)=\"onAlphaPercent($event)\"\n />\n <span class=\"wr-color-picker__field-label\">A%</span>\n </label>\n }\n </div>\n }\n}\n\n@if (swatches().length > 0) {\n <div class=\"wr-color-picker__swatches\">\n @for (color of swatches(); track color) {\n <button\n type=\"button\"\n class=\"wr-color-picker__swatch\"\n [style.background]=\"color\"\n [attr.aria-label]=\"color\"\n [disabled]=\"disabled()\"\n (click)=\"onSwatchClick(color)\"\n ></button>\n }\n </div>\n}\n" }]
|
|
615
705
|
}], ctorParameters: () => [], propDecorators: { alpha: [{ type: i0.Input, args: [{ isSignal: true, alias: "alpha", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], format: [{ type: i0.Input, args: [{ isSignal: true, alias: "format", required: false }] }], swatches: [{ type: i0.Input, args: [{ isSignal: true, alias: "swatches", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }] } });
|
|
616
706
|
|
|
617
707
|
/**
|
|
@@ -752,10 +842,10 @@ class WrColorPickerTrigger {
|
|
|
752
842
|
this.overlayRef = null;
|
|
753
843
|
}
|
|
754
844
|
}
|
|
755
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
756
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.
|
|
845
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrColorPickerTrigger, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
846
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.1.2", type: WrColorPickerTrigger, isStandalone: true, selector: "[wrColorPickerTrigger]", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, alpha: { classPropertyName: "alpha", publicName: "alpha", isSignal: true, isRequired: false, transformFunction: null }, format: { classPropertyName: "format", publicName: "format", isSignal: true, isRequired: false, transformFunction: null }, swatches: { classPropertyName: "swatches", publicName: "swatches", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed" }, host: { listeners: { "click": "toggle()" }, properties: { "attr.aria-haspopup": "\"dialog\"", "attr.aria-expanded": "isOpen()", "attr.aria-controls": "isOpen() ? panelId : null", "attr.aria-disabled": "disabled() ? true : null" } }, ngImport: i0 });
|
|
757
847
|
}
|
|
758
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
848
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.2", ngImport: i0, type: WrColorPickerTrigger, decorators: [{
|
|
759
849
|
type: Directive,
|
|
760
850
|
args: [{
|
|
761
851
|
selector: '[wrColorPickerTrigger]',
|