ngwr 14.3.0 → 14.4.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 +1 -1
- package/avatar/styles/_index.scss +4 -2
- package/badge/styles/_index.scss +4 -1
- package/badge/styles/_tag.scss +3 -0
- package/cascader/styles/_rules.scss +3 -0
- package/command-palette/styles/_index.scss +23 -0
- package/context-menu/styles/_index.scss +13 -1
- package/fesm2022/ngwr-action-sheet.mjs +3 -3
- package/fesm2022/ngwr-affix.mjs +17 -4
- package/fesm2022/ngwr-affix.mjs.map +1 -1
- package/fesm2022/ngwr-alert.mjs +4 -4
- package/fesm2022/ngwr-alert.mjs.map +1 -1
- 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 +18 -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-border-glow.mjs +3 -3
- package/fesm2022/ngwr-breadcrumbs.mjs +6 -6
- package/fesm2022/ngwr-burger.mjs +3 -3
- package/fesm2022/ngwr-button.mjs +6 -6
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs +12 -9
- package/fesm2022/ngwr-calendar-heatmap-testing.mjs.map +1 -1
- package/fesm2022/ngwr-calendar-heatmap.mjs +35 -7
- package/fesm2022/ngwr-calendar-heatmap.mjs.map +1 -1
- package/fesm2022/ngwr-calendar.mjs +32 -4
- package/fesm2022/ngwr-calendar.mjs.map +1 -1
- package/fesm2022/ngwr-card.mjs +9 -9
- package/fesm2022/ngwr-carousel.mjs +6 -6
- package/fesm2022/ngwr-cascader-testing.mjs +87 -17
- package/fesm2022/ngwr-cascader-testing.mjs.map +1 -1
- package/fesm2022/ngwr-cascader.mjs +63 -4
- package/fesm2022/ngwr-cascader.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox-testing.mjs +13 -2
- package/fesm2022/ngwr-checkbox-testing.mjs.map +1 -1
- package/fesm2022/ngwr-checkbox.mjs +42 -7
- package/fesm2022/ngwr-checkbox.mjs.map +1 -1
- package/fesm2022/ngwr-circular-text.mjs +3 -3
- package/fesm2022/ngwr-click-spark.mjs +3 -3
- package/fesm2022/ngwr-clipboard.mjs +3 -3
- package/fesm2022/ngwr-collapse.mjs +9 -9
- package/fesm2022/ngwr-color-picker.mjs +6 -6
- package/fesm2022/ngwr-command-palette.mjs +16 -3
- package/fesm2022/ngwr-command-palette.mjs.map +1 -1
- package/fesm2022/ngwr-compare.mjs +3 -3
- package/fesm2022/ngwr-confetti.mjs +3 -3
- package/fesm2022/ngwr-context-menu.mjs +12 -12
- package/fesm2022/ngwr-cookie.mjs +3 -3
- package/fesm2022/ngwr-counter.mjs +6 -6
- package/fesm2022/ngwr-date-adapters-fns.mjs +3 -3
- package/fesm2022/ngwr-date-adapters-luxon.mjs +3 -3
- package/fesm2022/ngwr-date-picker.mjs +81 -26
- package/fesm2022/ngwr-date-picker.mjs.map +1 -1
- package/fesm2022/ngwr-date.mjs +3 -3
- 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 +15 -15
- package/fesm2022/ngwr-directives.mjs +12 -12
- package/fesm2022/ngwr-divider.mjs +3 -3
- package/fesm2022/ngwr-donut-chart-testing.mjs +18 -2
- package/fesm2022/ngwr-donut-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-donut-chart.mjs +4 -4
- package/fesm2022/ngwr-donut-chart.mjs.map +1 -1
- package/fesm2022/ngwr-drag-drop.mjs +6 -6
- package/fesm2022/ngwr-drawer.mjs +18 -18
- package/fesm2022/ngwr-dropdown.mjs +32 -14
- package/fesm2022/ngwr-dropdown.mjs.map +1 -1
- package/fesm2022/ngwr-empty.mjs +3 -3
- package/fesm2022/ngwr-event-calendar.mjs +6 -6
- package/fesm2022/ngwr-falling-text.mjs +3 -3
- package/fesm2022/ngwr-file-upload.mjs +18 -5
- package/fesm2022/ngwr-file-upload.mjs.map +1 -1
- package/fesm2022/ngwr-form.mjs +66 -14
- package/fesm2022/ngwr-form.mjs.map +1 -1
- package/fesm2022/ngwr-fuzzy-text.mjs +3 -3
- package/fesm2022/ngwr-gauge-testing.mjs +16 -2
- package/fesm2022/ngwr-gauge-testing.mjs.map +1 -1
- package/fesm2022/ngwr-gauge.mjs +3 -3
- package/fesm2022/ngwr-glitch-text.mjs +3 -3
- package/fesm2022/ngwr-gradient-text.mjs +3 -3
- package/fesm2022/ngwr-hotkey.mjs +6 -6
- package/fesm2022/ngwr-i18n-ar.mjs +2 -0
- package/fesm2022/ngwr-i18n-ar.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-cs.mjs +2 -0
- package/fesm2022/ngwr-i18n-cs.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-de.mjs +2 -0
- package/fesm2022/ngwr-i18n-de.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-en.mjs +14 -2
- package/fesm2022/ngwr-i18n-en.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-es.mjs +2 -0
- package/fesm2022/ngwr-i18n-es.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-fr.mjs +2 -0
- package/fesm2022/ngwr-i18n-fr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-he.mjs +2 -0
- package/fesm2022/ngwr-i18n-he.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-hi.mjs +2 -0
- package/fesm2022/ngwr-i18n-hi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-id.mjs +2 -0
- package/fesm2022/ngwr-i18n-id.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-it.mjs +2 -0
- package/fesm2022/ngwr-i18n-it.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ja.mjs +2 -0
- package/fesm2022/ngwr-i18n-ja.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ko.mjs +2 -0
- package/fesm2022/ngwr-i18n-ko.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-nl.mjs +2 -0
- package/fesm2022/ngwr-i18n-nl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pl.mjs +2 -0
- package/fesm2022/ngwr-i18n-pl.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-pt.mjs +2 -0
- package/fesm2022/ngwr-i18n-pt.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-ru.mjs +2 -0
- package/fesm2022/ngwr-i18n-ru.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-sv.mjs +2 -0
- package/fesm2022/ngwr-i18n-sv.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-tr.mjs +2 -0
- package/fesm2022/ngwr-i18n-tr.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-uk.mjs +2 -0
- package/fesm2022/ngwr-i18n-uk.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-vi.mjs +2 -0
- package/fesm2022/ngwr-i18n-vi.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh-TW.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh-TW.mjs.map +1 -1
- package/fesm2022/ngwr-i18n-zh.mjs +2 -0
- package/fesm2022/ngwr-i18n-zh.mjs.map +1 -1
- package/fesm2022/ngwr-i18n.mjs +9 -9
- package/fesm2022/ngwr-icon.mjs +6 -6
- package/fesm2022/ngwr-image-cropper.mjs +3 -3
- package/fesm2022/ngwr-input-number.mjs +15 -6
- package/fesm2022/ngwr-input-number.mjs.map +1 -1
- package/fesm2022/ngwr-input-otp.mjs +38 -6
- 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-testing.mjs +11 -3
- package/fesm2022/ngwr-knob-testing.mjs.map +1 -1
- package/fesm2022/ngwr-knob.mjs +19 -4
- package/fesm2022/ngwr-knob.mjs.map +1 -1
- package/fesm2022/ngwr-layout.mjs +15 -15
- package/fesm2022/ngwr-lightbox.mjs +3 -3
- package/fesm2022/ngwr-line-chart-testing.mjs +18 -2
- package/fesm2022/ngwr-line-chart-testing.mjs.map +1 -1
- package/fesm2022/ngwr-line-chart.mjs +22 -4
- package/fesm2022/ngwr-line-chart.mjs.map +1 -1
- package/fesm2022/ngwr-list.mjs +6 -6
- package/fesm2022/ngwr-loading-bar.mjs +6 -6
- package/fesm2022/ngwr-markdown.mjs +6 -6
- package/fesm2022/ngwr-marquee.mjs +3 -3
- package/fesm2022/ngwr-media.mjs +3 -3
- package/fesm2022/ngwr-mention.mjs +6 -6
- package/fesm2022/ngwr-meta.mjs +6 -6
- 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.mjs +33 -6
- package/fesm2022/ngwr-pagination.mjs.map +1 -1
- package/fesm2022/ngwr-pipes.mjs +21 -21
- package/fesm2022/ngwr-platform.mjs +9 -9
- package/fesm2022/ngwr-popconfirm.mjs +6 -6
- package/fesm2022/ngwr-popover.mjs +29 -11
- 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 +3 -3
- package/fesm2022/ngwr-radio.mjs +6 -6
- package/fesm2022/ngwr-rating-testing.mjs +12 -3
- package/fesm2022/ngwr-rating-testing.mjs.map +1 -1
- package/fesm2022/ngwr-rating.mjs +19 -4
- package/fesm2022/ngwr-rating.mjs.map +1 -1
- package/fesm2022/ngwr-result.mjs +13 -13
- package/fesm2022/ngwr-result.mjs.map +1 -1
- package/fesm2022/ngwr-rotating-text.mjs +3 -3
- package/fesm2022/ngwr-schema-form.mjs +40 -4
- package/fesm2022/ngwr-schema-form.mjs.map +1 -1
- package/fesm2022/ngwr-scroll.mjs +3 -3
- package/fesm2022/ngwr-segmented.mjs +3 -3
- package/fesm2022/ngwr-select.mjs +9 -9
- package/fesm2022/ngwr-shiny-text.mjs +6 -6
- package/fesm2022/ngwr-sidebar.mjs +3 -3
- package/fesm2022/ngwr-skeleton.mjs +3 -3
- package/fesm2022/ngwr-slider.mjs +18 -5
- package/fesm2022/ngwr-slider.mjs.map +1 -1
- package/fesm2022/ngwr-sparkline.mjs +3 -3
- package/fesm2022/ngwr-speed-dial.mjs +3 -3
- package/fesm2022/ngwr-spinner.mjs +3 -3
- package/fesm2022/ngwr-splash-cursor.mjs +3 -3
- package/fesm2022/ngwr-split-text.mjs +3 -3
- package/fesm2022/ngwr-splitter.mjs +3 -3
- package/fesm2022/ngwr-spotlight-card.mjs +6 -6
- package/fesm2022/ngwr-squircle.mjs +28 -9
- package/fesm2022/ngwr-squircle.mjs.map +1 -1
- package/fesm2022/ngwr-star-border.mjs +3 -3
- package/fesm2022/ngwr-statistic.mjs +20 -13
- package/fesm2022/ngwr-statistic.mjs.map +1 -1
- package/fesm2022/ngwr-stepper.mjs +6 -6
- package/fesm2022/ngwr-storage.mjs +3 -3
- package/fesm2022/ngwr-switch.mjs +3 -3
- package/fesm2022/ngwr-table.mjs +18 -18
- package/fesm2022/ngwr-tabs-router.mjs +3 -3
- package/fesm2022/ngwr-tabs.mjs +6 -6
- package/fesm2022/ngwr-textarea.mjs +3 -3
- package/fesm2022/ngwr-theme.mjs +3 -3
- package/fesm2022/ngwr-tilt-card.mjs +6 -6
- package/fesm2022/ngwr-timeline.mjs +6 -6
- package/fesm2022/ngwr-toast.mjs +10 -10
- package/fesm2022/ngwr-toast.mjs.map +1 -1
- package/fesm2022/ngwr-toolbar.mjs +3 -3
- package/fesm2022/ngwr-tour.mjs +6 -6
- package/fesm2022/ngwr-transfer.mjs +88 -11
- package/fesm2022/ngwr-transfer.mjs.map +1 -1
- package/fesm2022/ngwr-tree-testing.mjs +24 -0
- package/fesm2022/ngwr-tree-testing.mjs.map +1 -1
- package/fesm2022/ngwr-tree.mjs +72 -7
- package/fesm2022/ngwr-tree.mjs.map +1 -1
- package/fesm2022/ngwr-typewriter.mjs +3 -3
- package/fesm2022/ngwr-typography.mjs +3 -3
- package/fesm2022/ngwr-version.mjs +1 -1
- package/fesm2022/ngwr-version.mjs.map +1 -1
- package/fesm2022/ngwr-virtual-scroll.mjs +3 -3
- package/fesm2022/ngwr-waves.mjs +3 -3
- package/fesm2022/ngwr-window.mjs +12 -12
- package/form/styles/_index.scss +63 -0
- package/i18n/ar.json +4 -2
- package/i18n/cs.json +4 -2
- package/i18n/de.json +4 -2
- package/i18n/en.json +6 -4
- package/i18n/es.json +4 -2
- package/i18n/fr.json +4 -2
- package/i18n/he.json +4 -2
- package/i18n/hi.json +4 -2
- package/i18n/id.json +4 -2
- package/i18n/it.json +4 -2
- package/i18n/ja.json +4 -2
- package/i18n/ko.json +4 -2
- package/i18n/nl.json +4 -2
- package/i18n/pl.json +4 -2
- package/i18n/pt.json +4 -2
- package/i18n/ru.json +4 -2
- package/i18n/sv.json +4 -2
- package/i18n/tr.json +4 -2
- package/i18n/uk.json +4 -2
- package/i18n/vi.json +4 -2
- package/i18n/zh-TW.json +4 -2
- package/i18n/zh.json +4 -2
- package/input-otp/styles/_index.scss +5 -1
- package/line-chart/styles/_index.scss +5 -3
- package/llms-full.txt +1 -1
- package/markdown/styles/_index.scss +4 -1
- package/mention/styles/_index.scss +22 -1
- package/package.json +1 -1
- package/radio/styles/_index.scss +3 -0
- package/result/styles/_index.scss +12 -0
- package/schematics/migrations/v14/index.js +6 -3
- package/schematics/migrations.json +1 -1
- package/schematics/ng-add/index.js +34 -5
- package/segmented/styles/_index.scss +4 -1
- package/select/styles/_index.scss +20 -1
- package/statistic/styles/_index.scss +4 -0
- package/stepper/styles/_index.scss +36 -0
- package/switch/styles/_index.scss +3 -0
- package/table/styles/_index.scss +12 -0
- package/tabs/styles/_index.scss +4 -1
- package/textarea/styles/_index.scss +6 -1
- package/theme/styles/_colors.scss +11 -0
- package/theme/styles/_contrast.scss +136 -0
- package/theme/styles/_index.scss +1 -0
- package/theme/styles/_mixins.scss +15 -8
- package/timeline/styles/_index.scss +28 -1
- package/toast/styles/_index.scss +11 -0
- package/tree/styles/_index.scss +27 -1
- package/types/ngwr-badge.d.ts +1 -1
- package/types/ngwr-bar-chart-testing.d.ts +11 -1
- package/types/ngwr-button.d.ts +1 -1
- package/types/ngwr-calendar-heatmap-testing.d.ts +10 -5
- package/types/ngwr-calendar-heatmap.d.ts +22 -0
- package/types/ngwr-calendar.d.ts +21 -0
- package/types/ngwr-cascader-testing.d.ts +74 -17
- package/types/ngwr-cascader.d.ts +28 -0
- package/types/ngwr-checkbox-testing.d.ts +12 -1
- package/types/ngwr-checkbox.d.ts +10 -0
- package/types/ngwr-clipboard.d.ts +1 -1
- package/types/ngwr-confetti.d.ts +1 -1
- package/types/ngwr-cookie.d.ts +1 -1
- package/types/ngwr-date-adapters-fns.d.ts +1 -1
- package/types/ngwr-date-adapters-luxon.d.ts +1 -1
- package/types/ngwr-date.d.ts +9 -3
- package/types/ngwr-density.d.ts +1 -1
- package/types/ngwr-dialog.d.ts +1 -1
- package/types/ngwr-donut-chart-testing.d.ts +11 -1
- package/types/ngwr-drawer.d.ts +1 -1
- package/types/ngwr-dropdown.d.ts +16 -0
- package/types/ngwr-file-upload.d.ts +11 -0
- package/types/ngwr-form.d.ts +25 -0
- package/types/ngwr-gauge-testing.d.ts +9 -1
- package/types/ngwr-hotkey.d.ts +1 -1
- package/types/ngwr-i18n.d.ts +1 -1
- package/types/ngwr-input-number.d.ts +12 -2
- package/types/ngwr-input-otp.d.ts +12 -0
- package/types/ngwr-knob-testing.d.ts +11 -3
- package/types/ngwr-knob.d.ts +13 -0
- package/types/ngwr-line-chart-testing.d.ts +11 -1
- package/types/ngwr-line-chart.d.ts +18 -0
- package/types/ngwr-loading-bar.d.ts +1 -1
- package/types/ngwr-markdown.d.ts +1 -1
- package/types/ngwr-media.d.ts +1 -1
- package/types/ngwr-meta.d.ts +1 -1
- package/types/ngwr-overlay.d.ts +2 -2
- package/types/ngwr-pagination.d.ts +16 -0
- package/types/ngwr-platform.d.ts +3 -3
- package/types/ngwr-popover.d.ts +16 -0
- package/types/ngwr-rating-testing.d.ts +12 -3
- package/types/ngwr-rating.d.ts +13 -0
- package/types/ngwr-scroll.d.ts +1 -1
- package/types/ngwr-squircle.d.ts +22 -3
- package/types/ngwr-statistic.d.ts +0 -1
- package/types/ngwr-storage.d.ts +1 -1
- package/types/ngwr-theme.d.ts +1 -1
- package/types/ngwr-toast.d.ts +1 -1
- package/types/ngwr-tour.d.ts +1 -1
- package/types/ngwr-transfer.d.ts +52 -0
- package/types/ngwr-tree-testing.d.ts +20 -0
- package/types/ngwr-tree.d.ts +41 -0
- package/types/ngwr-version.d.ts +1 -1
- package/types/ngwr-window.d.ts +1 -1
- package/typography/styles/_index.scss +26 -4
|
@@ -11,15 +11,19 @@ import { ComponentHarness, HarnessPredicate, TestKey } from '@angular/cdk/testin
|
|
|
11
11
|
*
|
|
12
12
|
* An option is either a BRANCH (it has children, so clicking it opens the next
|
|
13
13
|
* column) or a LEAF (clicking it commits the whole path and closes the panel).
|
|
14
|
-
* {@link hasChildren}
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
14
|
+
* {@link hasChildren} reads the chevron the template draws for branches;
|
|
15
|
+
* {@link isExpanded} reads the state that same branch announces. The two are
|
|
16
|
+
* not one question — a branch always HAS children and is expanded only while
|
|
17
|
+
* the column to its right is showing them.
|
|
18
|
+
*
|
|
19
|
+
* The panel is a `role="tree"` and an option is a `treeitem`. It was a `menu`
|
|
20
|
+
* of `menuitem`s until the roles were corrected, and this class documented that
|
|
21
|
+
* a branch announced nothing at all; both are historical now.
|
|
18
22
|
*
|
|
19
23
|
* @see https://ngwr.dev/guides/testing
|
|
20
24
|
*/
|
|
21
25
|
class WrCascaderOptionHarness extends ComponentHarness {
|
|
22
|
-
/** The `<li role="
|
|
26
|
+
/** The `<li role="treeitem">` a column renders per option. */
|
|
23
27
|
static hostSelector = '.wr-cascader__opt';
|
|
24
28
|
/** Build a predicate that narrows the query. */
|
|
25
29
|
static with(options = {}) {
|
|
@@ -33,7 +37,7 @@ class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
33
37
|
async getText() {
|
|
34
38
|
return (await this.locatorFor('.wr-cascader__opt-label')()).text();
|
|
35
39
|
}
|
|
36
|
-
/** The role the option announces — `
|
|
40
|
+
/** The role the option announces — `treeitem`. */
|
|
37
41
|
async getRole() {
|
|
38
42
|
return (await this.host()).getAttribute('role');
|
|
39
43
|
}
|
|
@@ -46,13 +50,51 @@ class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
46
50
|
* whose children the column to the right is showing, or the committed segment
|
|
47
51
|
* at this level.
|
|
48
52
|
*
|
|
49
|
-
* Read from the `--active` modifier
|
|
50
|
-
*
|
|
51
|
-
*
|
|
53
|
+
* Read from the `--active` modifier, and NOT the same question as
|
|
54
|
+
* {@link isSelected}: this one tracks where the user has navigated, that one
|
|
55
|
+
* tracks what they committed. They agree only once a leaf is picked, and a
|
|
56
|
+
* harness that collapsed them would hide exactly the divergence it exists to
|
|
57
|
+
* catch.
|
|
52
58
|
*/
|
|
53
59
|
async isActive() {
|
|
54
60
|
return (await this.host()).hasClass('wr-cascader__opt--active');
|
|
55
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Whether this option is the committed choice, or `null` when it is not a
|
|
64
|
+
* choice at all.
|
|
65
|
+
*
|
|
66
|
+
* `null` — the attribute absent — for a branch while `changeOnSelect` is off,
|
|
67
|
+
* because such a branch genuinely cannot be chosen. Answering a plausible
|
|
68
|
+
* `false` there would report an unselectable row as merely unselected, which
|
|
69
|
+
* is the distinction the attribute exists to carry.
|
|
70
|
+
*/
|
|
71
|
+
async isSelected() {
|
|
72
|
+
const raw = await (await this.host()).getAttribute('aria-selected');
|
|
73
|
+
return raw === null ? null : raw === 'true';
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Whether this branch's children are the column to its right, or `null` for a
|
|
77
|
+
* leaf.
|
|
78
|
+
*
|
|
79
|
+
* `null` rather than `false`, and the difference is the whole point: a leaf
|
|
80
|
+
* does not have a collapsed subtree, it has none. `aria-expanded="false"` on
|
|
81
|
+
* one would state that a subtree exists and is shut.
|
|
82
|
+
*/
|
|
83
|
+
async isExpanded() {
|
|
84
|
+
const raw = await (await this.host()).getAttribute('aria-expanded');
|
|
85
|
+
return raw === null ? null : raw === 'true';
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The option's depth, 1-based — its `aria-level`.
|
|
89
|
+
*
|
|
90
|
+
* Worth reading in a spec rather than trusting: the columns are DOM SIBLINGS,
|
|
91
|
+
* so nothing about the markup's shape carries depth. Every option would be
|
|
92
|
+
* level 1 if this attribute were dropped, and no gate would say so.
|
|
93
|
+
*/
|
|
94
|
+
async getLevel() {
|
|
95
|
+
const raw = await (await this.host()).getAttribute('aria-level');
|
|
96
|
+
return raw === null ? null : Number.parseInt(raw, 10);
|
|
97
|
+
}
|
|
56
98
|
/** Whether the option opens a deeper level rather than ending the path. */
|
|
57
99
|
async hasChildren() {
|
|
58
100
|
return (await this.locatorForOptional('.wr-cascader__opt-arrow')()) !== null;
|
|
@@ -92,10 +134,10 @@ class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
92
134
|
* This is the component's entire keyboard model — the columns bind
|
|
93
135
|
* `keydown.enter` / `keydown.space` per option and nothing else, so there are
|
|
94
136
|
* no arrow keys to walk levels with. A keyboard user reaches the option they
|
|
95
|
-
* want with Tab and presses Enter
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
137
|
+
* want with Tab and presses Enter. Opening the panel does move focus into it —
|
|
138
|
+
* `focusPanelOption()` lands on the active option, or the first enabled one —
|
|
139
|
+
* so the walk starts there rather than from the trigger; this JSDoc claimed
|
|
140
|
+
* the opposite for a while and was simply wrong.
|
|
99
141
|
*/
|
|
100
142
|
async selectByKeyboard() {
|
|
101
143
|
return (await this.host()).sendKeys(TestKey.ENTER);
|
|
@@ -147,7 +189,7 @@ class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
147
189
|
* @see https://ngwr.dev/guides/testing
|
|
148
190
|
*/
|
|
149
191
|
class WrCascaderColumnHarness extends ComponentHarness {
|
|
150
|
-
/** The `<ul role="
|
|
192
|
+
/** The `<ul role="group">` the panel renders per level, inside the `tree`. */
|
|
151
193
|
static hostSelector = '.wr-cascader__col';
|
|
152
194
|
/** Build a predicate that narrows the query. */
|
|
153
195
|
static with(options = {}) {
|
|
@@ -159,7 +201,7 @@ class WrCascaderColumnHarness extends ComponentHarness {
|
|
|
159
201
|
return false;
|
|
160
202
|
});
|
|
161
203
|
}
|
|
162
|
-
/** The role the column announces — `
|
|
204
|
+
/** The role the column announces — `group`, inside the panel's `tree`. */
|
|
163
205
|
async getRole() {
|
|
164
206
|
return (await this.host()).getAttribute('role');
|
|
165
207
|
}
|
|
@@ -296,11 +338,18 @@ class WrCascaderHarness extends ComponentHarness {
|
|
|
296
338
|
async getAccessibleName() {
|
|
297
339
|
return (await this.trigger()).getAttribute('aria-label');
|
|
298
340
|
}
|
|
299
|
-
/**
|
|
341
|
+
/**
|
|
342
|
+
* The kind of popup the trigger promises via `aria-haspopup` — `tree`.
|
|
343
|
+
*
|
|
344
|
+
* Worth pinning rather than assuming: a combobox's popup may be a listbox, a
|
|
345
|
+
* tree, a grid or a dialog and nothing else, and this one said `menu` for a
|
|
346
|
+
* long time. `menu` is a valid token for the global `aria-haspopup`, so axe
|
|
347
|
+
* reports nothing either way — an assertion here is the only guard there is.
|
|
348
|
+
*/
|
|
300
349
|
async getPopupRole() {
|
|
301
350
|
return (await this.trigger()).getAttribute('aria-haspopup');
|
|
302
351
|
}
|
|
303
|
-
/** The role the panel announces — `
|
|
352
|
+
/** The role the panel announces — `tree`, matching what the trigger promised. */
|
|
304
353
|
async getPanelRole() {
|
|
305
354
|
return (await this.panel()).getAttribute('role');
|
|
306
355
|
}
|
|
@@ -485,6 +534,27 @@ class WrCascaderHarness extends ComponentHarness {
|
|
|
485
534
|
}
|
|
486
535
|
await clear.click();
|
|
487
536
|
}
|
|
537
|
+
/**
|
|
538
|
+
* Clear from the keyboard — Backspace on the closed trigger.
|
|
539
|
+
*
|
|
540
|
+
* The × {@link clear} clicks is a `tabindex="-1"` span inside the trigger, so no
|
|
541
|
+
* key can ever reach it; Backspace on the trigger is its keyboard twin, and the
|
|
542
|
+
* route a keyboard-only user actually has. Prefer this one in a spec that cares
|
|
543
|
+
* about that user — {@link clear} proves the pointer path and nothing more.
|
|
544
|
+
*
|
|
545
|
+
* The component honours the key only on the CLOSED trigger, so an open panel
|
|
546
|
+
* is closed first with Escape — the step a keyboard user takes too. Sending
|
|
547
|
+
* Backspace into an open panel and returning would be a plausible nothing.
|
|
548
|
+
*
|
|
549
|
+
* Does nothing, rather than throwing, when there is nothing to clear, `clearable`
|
|
550
|
+
* is off, or the cascader is disabled or read-only: that silence IS the
|
|
551
|
+
* component's contract, so a spec asserts it on the value.
|
|
552
|
+
*/
|
|
553
|
+
async clearByKeyboard() {
|
|
554
|
+
if (await this.isOpen())
|
|
555
|
+
await this.close();
|
|
556
|
+
await (await this.trigger()).sendKeys(TestKey.BACKSPACE);
|
|
557
|
+
}
|
|
488
558
|
/** Move keyboard focus to the trigger. */
|
|
489
559
|
async focus() {
|
|
490
560
|
return (await this.trigger()).focus();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngwr-cascader-testing.mjs","sources":["../../../projects/lib/cascader/testing/wr-cascader-option-harness.ts","../../../projects/lib/cascader/testing/wr-cascader-column-harness.ts","../../../projects/lib/cascader/testing/wr-cascader-harness.ts","../../../projects/lib/cascader/testing/ngwr-cascader-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, TestKey } from '@angular/cdk/testing';\n\nimport type { WrCascaderOptionHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one option inside a `<wr-cascader>` column.\n *\n * An option is either a BRANCH (it has children, so clicking it opens the next\n * column) or a LEAF (clicking it commits the whole path and closes the panel).\n * {@link hasChildren} is the only way to tell them apart, and it reads the\n * chevron the template draws for branches — the option carries no\n * `aria-haspopup` / `aria-expanded`, so a screen-reader user is told nothing\n * about a branch either. Reported here rather than papered over.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderOptionHarness extends ComponentHarness {\n /** The `<li role=\"menuitem\">` a column renders per option. */\n static hostSelector = '.wr-cascader__opt';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderOptionHarnessFilters = {}): HarnessPredicate<WrCascaderOptionHarness> {\n return new HarnessPredicate(WrCascaderOptionHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('active', options.active, async (harness, active) => (await harness.isActive()) === active)\n .addOption(\n 'hasChildren',\n options.hasChildren,\n async (harness, hasChildren) => (await harness.hasChildren()) === hasChildren\n );\n }\n\n /** The option's label, trimmed. The branch chevron contributes no text. */\n async getText(): Promise<string> {\n return (await this.locatorFor('.wr-cascader__opt-label')()).text();\n }\n\n /** The role the option announces — `menuitem`. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** Whether the option refuses selection, from the state a screen reader is given. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /**\n * Whether this is the option its column is currently drilled into — the one\n * whose children the column to the right is showing, or the committed segment\n * at this level.\n *\n * Read from the `--active` modifier because nothing else says it: the option\n * has no `aria-selected` and no `aria-expanded`, so the class is both the\n * whole visual answer and the only one available.\n */\n async isActive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-cascader__opt--active');\n }\n\n /** Whether the option opens a deeper level rather than ending the path. */\n async hasChildren(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-cascader__opt-arrow')()) !== null;\n }\n\n /**\n * The option's tab index — `0` for every enabled option, `-1` for a disabled\n * one.\n *\n * Worth asking: a cascader column is NOT a roving-cursor listbox. Every\n * enabled option is its own tab stop, in every column, which is the documented\n * reason virtual scrolling is deferred for this component — there is no\n * container-owned arrow-nav model to hang a window off.\n *\n * Read as the element's `tabIndex` PROPERTY rather than the attribute, so an\n * option that carried no `tabindex` at all answers `-1` — what the DOM says of a\n * bare `<li>` — instead of a made-up `0` that would report an unfocusable option\n * as a tab stop if this component ever moved to a roving cursor.\n */\n async getTabIndex(): Promise<number> {\n return (await this.host()).getProperty<number>('tabIndex');\n }\n\n /**\n * Click the option: a branch opens its children to the right, a leaf commits\n * the path and closes the panel.\n *\n * A disabled option is clickable here on purpose — the component refuses it in\n * its own handler rather than through `pointer-events`, so the click a spec\n * dispatches is exactly as ineffective as one in a browser.\n */\n async click(): Promise<void> {\n return (await this.host()).click();\n }\n\n /**\n * Activate the option from the keyboard (Enter; Space is bound to the same\n * handler).\n *\n * This is the component's entire keyboard model — the columns bind\n * `keydown.enter` / `keydown.space` per option and nothing else, so there are\n * no arrow keys to walk levels with. A keyboard user reaches the option they\n * want with Tab and presses Enter — and Tab is a long way round: the panel is a\n * portal in the overlay container at the end of the document, and nothing moves\n * focus into it on open, so the first option is not the next stop after the\n * trigger.\n */\n async selectByKeyboard(): Promise<void> {\n return (await this.host()).sendKeys(TestKey.ENTER);\n }\n\n /**\n * Move the pointer onto the option.\n *\n * Deliberately does NOT expand a branch: this cascader drills down on CLICK\n * only, unlike the hover-to-expand cascaders elsewhere. Kept because a spec\n * may want to pin that, and because the option's hover tint is styled.\n */\n async hover(): Promise<void> {\n return (await this.host()).hover();\n }\n\n /** Move keyboard focus to the option. */\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n /** Whether the option holds keyboard focus. */\n async isFocused(): Promise<boolean> {\n return (await this.host()).isFocused();\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 } from '@angular/cdk/testing';\n\nimport type { WrCascaderColumnHarnessFilters, WrCascaderOptionHarnessFilters } from './interfaces';\nimport { WrCascaderOptionHarness } from './wr-cascader-option-harness';\n\n/**\n * Test harness for one COLUMN of an open `<wr-cascader>` panel.\n *\n * A column is a level of the tree: column 0 holds the root options, and each\n * further column holds the children of the active option in the column before\n * it. Which columns exist is therefore a function of what is expanded — the\n * relationship this harness exists to let a spec assert. Column 0 is always\n * there; a column only appears once there are children to put in it, so a leaf\n * adds none.\n *\n * @example\n * ```ts\n * const [countries, cities] = await cascader.getColumns();\n *\n * expect(await countries.getActiveOptionText()).toBe('Germany');\n * expect(await cities.getOptionLabels()).toEqual(['Berlin']);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderColumnHarness extends ComponentHarness {\n /** The `<ul role=\"menu\">` the panel renders per level. */\n static hostSelector = '.wr-cascader__col';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderColumnHarnessFilters = {}): HarnessPredicate<WrCascaderColumnHarness> {\n return new HarnessPredicate(WrCascaderColumnHarness, options).addOption(\n 'optionText',\n options.optionText,\n async (harness, text) => {\n for (const label of await harness.getOptionLabels()) {\n if (await HarnessPredicate.stringMatches(label, text)) return true;\n }\n return false;\n }\n );\n }\n\n /** The role the column announces — `menu`. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** The options this level offers, in order. */\n async getOptions(filters: WrCascaderOptionHarnessFilters = {}): Promise<WrCascaderOptionHarness[]> {\n return this.locatorForAll(WrCascaderOptionHarness.with(filters))();\n }\n\n /** The labels this level offers, in order. */\n async getOptionLabels(): Promise<string[]> {\n const options = await this.getOptions();\n return Promise.all(options.map(option => option.getText()));\n }\n\n /**\n * The first option matching the filters.\n *\n * Throws rather than answering `null`, and names what the column does offer:\n * a missing option here almost always means the level is not the one the spec\n * thought it was, and that is far easier to see with the alternatives listed.\n */\n async getOption(filters: WrCascaderOptionHarnessFilters): Promise<WrCascaderOptionHarness> {\n const [option] = await this.getOptions(filters);\n if (!option) {\n throw new Error(\n `WrCascaderColumnHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +\n `This column offers: ${(await this.getOptionLabels()).join(', ')}.`\n );\n }\n return option;\n }\n\n /** The option this level is drilled into, or `null` when nothing here is expanded. */\n async getActiveOption(): Promise<WrCascaderOptionHarness | null> {\n const [active] = await this.getOptions({ active: true });\n return active ?? null;\n }\n\n /** The label of the option this level is drilled into, or `null`. */\n async getActiveOptionText(): Promise<string | null> {\n const active = await this.getActiveOption();\n return active ? active.getText() : null;\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 {\n ComponentHarness,\n type HarnessLoader,\n HarnessPredicate,\n TestKey,\n type TestElement,\n} from '@angular/cdk/testing';\n\nimport type {\n WrCascaderColumnHarnessFilters,\n WrCascaderHarnessFilters,\n WrCascaderOptionHarnessFilters,\n} from './interfaces';\nimport { WrCascaderColumnHarness } from './wr-cascader-column-harness';\nimport type { WrCascaderOptionHarness } from './wr-cascader-option-harness';\n\n/**\n * Test harness for `<wr-cascader>` — the trigger, and the panel of COLUMNS it\n * opens. Root of a small family: {@link WrCascaderColumnHarness} for one level,\n * `WrCascaderOptionHarness` for one option in it.\n *\n * A cascader is not a select with extra steps. Its value is the whole PATH from\n * root to leaf (`['eu', 'de', 'ber']`, not `'ber'`), and the panel shows one\n * column per level, so which columns exist depends on what is expanded — column\n * 0 is the roots, and every further column holds the children of the active\n * option in the column to its left. That relationship is the component, so it is\n * what {@link getColumns} and {@link getColumnLabels} are for.\n *\n * The panel is NOT inside the cascader: it is a template portal in the overlay\n * container, a sibling of the whole app. Every read of it goes through the\n * document root scoped by the `aria-controls` id the trigger publishes, so two\n * cascaders on one page can never answer with each other's columns.\n *\n * @example\n * ```ts\n * const cascader = await loader.getHarness(WrCascaderHarness);\n *\n * await cascader.selectPath(['Europe', 'Germany', 'Berlin']);\n *\n * expect(await cascader.getValueText()).toBe('Europe / Germany / Berlin');\n * expect(await cascader.isOpen()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderHarness extends ComponentHarness {\n static hostSelector = 'wr-cascader';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderHarnessFilters = {}): HarnessPredicate<WrCascaderHarness> {\n return new HarnessPredicate(WrCascaderHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getValueText(), text))\n .addOption('placeholder', options.placeholder, (harness, placeholder) =>\n HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder)\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);\n }\n\n private readonly trigger = this.locatorFor('.wr-cascader__trigger');\n\n /**\n * Whether the panel is showing.\n *\n * From the trigger's `aria-expanded` rather than the host's `--open` class:\n * both exist, and the ARIA state is the one a screen-reader user is told.\n */\n async isOpen(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';\n }\n\n /**\n * Whether the cascader refuses interaction.\n *\n * From the trigger's native `disabled`, which is what actually stops a pointer\n * and what assistive tech reports; the host's `--disabled` class only mirrors\n * it for styling.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.trigger()).getProperty<boolean>('disabled');\n }\n\n /**\n * What the trigger displays as the selection: the labels of the whole path\n * joined by the `separator` (`'Europe / Germany / Berlin'` by default), or `''`\n * while nothing is selected and the placeholder is showing.\n *\n * The joined string is all the DOM has — the separator is not published\n * anywhere on its own, so the harness will not pretend it can split the path\n * back apart. Assert against the bound value, or against\n * {@link getActiveTrail} while the panel is open, when the segments matter.\n */\n async getValueText(): Promise<string> {\n const value = await this.locatorForOptional('.wr-cascader__value')();\n return value ? value.text() : '';\n }\n\n /**\n * The placeholder, or `null` when a selection is hiding it.\n *\n * `''` is a real answer, not an absence: a cascader with no `placeholder` still\n * renders the element while unselected.\n */\n async getPlaceholder(): Promise<string | null> {\n const placeholder = await this.locatorForOptional('.wr-cascader__placeholder')();\n return placeholder ? placeholder.text() : null;\n }\n\n /**\n * The trigger's accessible name — the `ariaLabel` input, falling back to the\n * placeholder and then to the i18n catalog, because a `role=\"combobox\"` with\n * nothing selected and no placeholder would otherwise have no name at all.\n */\n async getAccessibleName(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-label');\n }\n\n /** The kind of popup the trigger promises via `aria-haspopup` — `menu`. */\n async getPopupRole(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-haspopup');\n }\n\n /** The role the panel announces — `menu`, matching what the trigger promised. */\n async getPanelRole(): Promise<string | null> {\n return (await this.panel()).getAttribute('role');\n }\n\n /**\n * The id the trigger publishes as `aria-controls`.\n *\n * Published unconditionally, open or closed — so while the panel is closed this\n * id resolves to nothing in the document. Exposed so a spec can pin that\n * (dangling or not) rather than have the harness quietly decide for it; every\n * panel read goes through the same id but refuses to run while closed.\n */\n async getPanelId(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-controls');\n }\n\n /**\n * Whether the panel now in the overlay is the one this trigger claims to\n * control — `aria-controls` resolving to a real element that carries that id.\n *\n * With several cascaders on a page it is also the check that the reference lands\n * on THIS instance's panel rather than a neighbour's: the overlay container is\n * shared, so panels sit side by side in it with nothing but their ids to tell\n * them apart.\n */\n async isPanelWiredToTrigger(): Promise<boolean> {\n const rendered = await (await this.panel()).getAttribute('id');\n return rendered !== null && rendered === (await this.getPanelId());\n }\n\n /**\n * Open the panel.\n *\n * Clicks the trigger, because that is the only gesture the component binds. The\n * trigger is a native `<button>`, so a browser turns Enter / Space on it into\n * the same click — there is no separate keyboard route to model here, and jsdom\n * does not synthesise button activation from a key, so an `openByKeyboard()`\n * would only be able to lie.\n */\n async open(): Promise<void> {\n if (await this.isOpen()) return;\n\n await (await this.trigger()).click();\n if (await this.isOpen()) return;\n\n throw new Error(\n 'WrCascaderHarness.open(): the panel did not open. A disabled cascader refuses the click — ' +\n 'check isDisabled().'\n );\n }\n\n /**\n * Close the panel with Escape. A closed cascader is left alone.\n *\n * Escape reaches the panel through the CDK's keyboard dispatcher rather than\n * through the DOM tree, which is why sending it to the trigger works even\n * though the panel is somewhere else entirely.\n */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n\n await (await this.trigger()).sendKeys(TestKey.ESCAPE);\n if (await this.isOpen()) {\n throw new Error('WrCascaderHarness.close(): Escape did not close the panel.');\n }\n }\n\n /** Click the trigger once, whatever that does — opens a closed panel, closes an open one. */\n async clickTrigger(): Promise<void> {\n return (await this.trigger()).click();\n }\n\n /**\n * The columns of the open panel, left to right: column 0 is the root options,\n * and each further one holds the children of its neighbour's active option.\n *\n * Throws while the panel is closed. The columns do not exist anywhere until the\n * portal is attached, and an empty array reads like a panel that rendered\n * nothing — a confusing failure three lines later instead of here.\n */\n async getColumns(filters: WrCascaderColumnHarnessFilters = {}): Promise<WrCascaderColumnHarness[]> {\n const loader = await this.panelLoader();\n return loader.getAllHarnesses(WrCascaderColumnHarness.with(filters));\n }\n\n /** How many levels the panel is currently showing. */\n async getColumnCount(): Promise<number> {\n return (await this.getColumns()).length;\n }\n\n /**\n * One column by its 0-based level. Throws when the level is not showing, which\n * is the interesting failure: it means the option before it has no children, or\n * has not been expanded yet.\n */\n async getColumn(index: number): Promise<WrCascaderColumnHarness> {\n const columns = await this.getColumns();\n const column = columns[index];\n if (!column) {\n throw new Error(\n `WrCascaderHarness.getColumn(): no column at level ${index} — the panel is showing ` +\n `${columns.length}. A deeper column appears only once a parent with children is expanded.`\n );\n }\n return column;\n }\n\n /** The labels offered by every column, outer array left to right. */\n async getColumnLabels(): Promise<string[][]> {\n const columns = await this.getColumns();\n return Promise.all(columns.map(column => column.getOptionLabels()));\n }\n\n /**\n * The expanded trail — the label of the active option in each column, root\n * first.\n *\n * This is the panel's own idea of where the user is, which is NOT always the\n * committed value: drilling into a branch moves the trail without committing\n * anything unless `changeOnSelect` is on. Once a leaf is picked the two agree,\n * and this is the only place the path's segments exist separately in the DOM.\n */\n async getActiveTrail(): Promise<string[]> {\n const trail: string[] = [];\n for (const column of await this.getColumns()) {\n const active = await column.getActiveOptionText();\n if (active !== null) trail.push(active);\n }\n return trail;\n }\n\n /**\n * The first option matching the filters, anywhere in the panel. Throws when\n * nothing matches, naming what is on offer.\n *\n * Use {@link getColumn} when the level matters — the same label can legitimately\n * appear at more than one level.\n */\n async getOption(filters: WrCascaderOptionHarnessFilters): Promise<WrCascaderOptionHarness> {\n for (const column of await this.getColumns()) {\n const [option] = await column.getOptions(filters);\n if (option) return option;\n }\n\n throw new Error(\n `WrCascaderHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +\n `The panel offers: ${(await this.getColumnLabels()).map(labels => labels.join(', ')).join(' | ')}.`\n );\n }\n\n /**\n * Walk a path by label, opening the panel first if needed: each label is\n * clicked in the column it belongs to, so `['Europe', 'Germany', 'Berlin']`\n * drills two levels and commits the third.\n *\n * Clicking is the only way down — this cascader does not expand on hover, so\n * neither does the harness. A path that ends on a BRANCH just leaves that\n * branch expanded: the component commits nothing on the way down unless\n * `changeOnSelect` is on, and only a leaf closes the panel.\n */\n async selectPath(labels: readonly string[]): Promise<void> {\n if (labels.length === 0) {\n throw new Error(\n 'WrCascaderHarness.selectPath(): the path is empty. Pass at least one label, or call clear() ' +\n 'to unset the selection.'\n );\n }\n\n await this.open();\n\n for (let level = 0; level < labels.length; level++) {\n const label = labels[level];\n const columns = await this.getColumns();\n const column = columns[level];\n if (!column) {\n throw new Error(\n `WrCascaderHarness.selectPath(): \"${label}\" would be at level ${level}, but the panel is ` +\n `showing ${columns.length} column(s) — the step before it opened no deeper level.`\n );\n }\n\n const option = await column.getOption({ text: label });\n if (await option.isDisabled()) {\n throw new Error(`WrCascaderHarness.selectPath(): \"${label}\" is disabled, so no path can pass through it.`);\n }\n\n const isLast = level === labels.length - 1;\n if (!isLast && !(await option.hasChildren())) {\n throw new Error(\n `WrCascaderHarness.selectPath(): \"${label}\" is a leaf, so the path cannot continue to ` +\n `\"${labels[level + 1]}\" — picking it commits and closes the panel.`\n );\n }\n\n await option.click();\n }\n }\n\n /**\n * Click the clear (×) control on the trigger.\n *\n * Throws when there is none, and both reasons are worth failing on: the\n * cascader is not `clearable`, or nothing is selected — the control is not\n * rendered at all in either case (nor while disabled).\n */\n async clear(): Promise<void> {\n const clear = await this.locatorForOptional('.wr-cascader__clear')();\n if (!clear) {\n throw new Error(\n 'WrCascaderHarness.clear(): this cascader shows no clear control — it is rendered only when ' +\n '`clearable` is on, something is selected, and the control is enabled.'\n );\n }\n await clear.click();\n }\n\n /** Move keyboard focus to the trigger. */\n async focus(): Promise<void> {\n return (await this.trigger()).focus();\n }\n\n /** Take focus off the trigger, which is what makes a bound form field touched. */\n async blur(): Promise<void> {\n return (await this.trigger()).blur();\n }\n\n /** Whether the trigger holds keyboard focus. */\n async isFocused(): Promise<boolean> {\n return (await this.trigger()).isFocused();\n }\n\n /** This cascader's panel element in the overlay — the single-element scoped read. */\n private async panel(): Promise<TestElement> {\n return this.documentRootLocatorFactory().locatorFor(`#${await this.panelId()}`)();\n }\n\n /**\n * A loader scoped to THIS cascader's panel — the list scoped read.\n *\n * Scoped by the published id rather than by `.wr-cascader-panel`: the overlay\n * container is shared with every other overlay in the app, so a bare class\n * query would answer with whichever panel happened to be open.\n */\n private async panelLoader(): Promise<HarnessLoader> {\n return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.panelId()}`);\n }\n\n /** The panel id, refusing to hand it out while there is no panel to find. */\n private async panelId(): Promise<string> {\n if (!(await this.isOpen())) {\n throw new Error(\n 'WrCascaderHarness: the panel is closed, so there are no columns to read — call open() or ' +\n 'selectPath() first. The trigger publishes `aria-controls` even while closed, so the id ' +\n 'alone is not proof the panel exists.'\n );\n }\n\n const id = await this.getPanelId();\n if (!id) {\n throw new Error('WrCascaderHarness: the trigger publishes no `aria-controls`, so its panel cannot be found.');\n }\n return id;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngwr-cascader-testing.mjs","sources":["../../../projects/lib/cascader/testing/wr-cascader-option-harness.ts","../../../projects/lib/cascader/testing/wr-cascader-column-harness.ts","../../../projects/lib/cascader/testing/wr-cascader-harness.ts","../../../projects/lib/cascader/testing/ngwr-cascader-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, TestKey } from '@angular/cdk/testing';\n\nimport type { WrCascaderOptionHarnessFilters } from './interfaces';\n\n/**\n * Test harness for one option inside a `<wr-cascader>` column.\n *\n * An option is either a BRANCH (it has children, so clicking it opens the next\n * column) or a LEAF (clicking it commits the whole path and closes the panel).\n * {@link hasChildren} reads the chevron the template draws for branches;\n * {@link isExpanded} reads the state that same branch announces. The two are\n * not one question — a branch always HAS children and is expanded only while\n * the column to its right is showing them.\n *\n * The panel is a `role=\"tree\"` and an option is a `treeitem`. It was a `menu`\n * of `menuitem`s until the roles were corrected, and this class documented that\n * a branch announced nothing at all; both are historical now.\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderOptionHarness extends ComponentHarness {\n /** The `<li role=\"treeitem\">` a column renders per option. */\n static hostSelector = '.wr-cascader__opt';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderOptionHarnessFilters = {}): HarnessPredicate<WrCascaderOptionHarness> {\n return new HarnessPredicate(WrCascaderOptionHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getText(), text))\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('active', options.active, async (harness, active) => (await harness.isActive()) === active)\n .addOption(\n 'hasChildren',\n options.hasChildren,\n async (harness, hasChildren) => (await harness.hasChildren()) === hasChildren\n );\n }\n\n /** The option's label, trimmed. The branch chevron contributes no text. */\n async getText(): Promise<string> {\n return (await this.locatorFor('.wr-cascader__opt-label')()).text();\n }\n\n /** The role the option announces — `treeitem`. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** Whether the option refuses selection, from the state a screen reader is given. */\n async isDisabled(): Promise<boolean> {\n return (await (await this.host()).getAttribute('aria-disabled')) === 'true';\n }\n\n /**\n * Whether this is the option its column is currently drilled into — the one\n * whose children the column to the right is showing, or the committed segment\n * at this level.\n *\n * Read from the `--active` modifier, and NOT the same question as\n * {@link isSelected}: this one tracks where the user has navigated, that one\n * tracks what they committed. They agree only once a leaf is picked, and a\n * harness that collapsed them would hide exactly the divergence it exists to\n * catch.\n */\n async isActive(): Promise<boolean> {\n return (await this.host()).hasClass('wr-cascader__opt--active');\n }\n\n /**\n * Whether this option is the committed choice, or `null` when it is not a\n * choice at all.\n *\n * `null` — the attribute absent — for a branch while `changeOnSelect` is off,\n * because such a branch genuinely cannot be chosen. Answering a plausible\n * `false` there would report an unselectable row as merely unselected, which\n * is the distinction the attribute exists to carry.\n */\n async isSelected(): Promise<boolean | null> {\n const raw = await (await this.host()).getAttribute('aria-selected');\n return raw === null ? null : raw === 'true';\n }\n\n /**\n * Whether this branch's children are the column to its right, or `null` for a\n * leaf.\n *\n * `null` rather than `false`, and the difference is the whole point: a leaf\n * does not have a collapsed subtree, it has none. `aria-expanded=\"false\"` on\n * one would state that a subtree exists and is shut.\n */\n async isExpanded(): Promise<boolean | null> {\n const raw = await (await this.host()).getAttribute('aria-expanded');\n return raw === null ? null : raw === 'true';\n }\n\n /**\n * The option's depth, 1-based — its `aria-level`.\n *\n * Worth reading in a spec rather than trusting: the columns are DOM SIBLINGS,\n * so nothing about the markup's shape carries depth. Every option would be\n * level 1 if this attribute were dropped, and no gate would say so.\n */\n async getLevel(): Promise<number | null> {\n const raw = await (await this.host()).getAttribute('aria-level');\n return raw === null ? null : Number.parseInt(raw, 10);\n }\n\n /** Whether the option opens a deeper level rather than ending the path. */\n async hasChildren(): Promise<boolean> {\n return (await this.locatorForOptional('.wr-cascader__opt-arrow')()) !== null;\n }\n\n /**\n * The option's tab index — `0` for every enabled option, `-1` for a disabled\n * one.\n *\n * Worth asking: a cascader column is NOT a roving-cursor listbox. Every\n * enabled option is its own tab stop, in every column, which is the documented\n * reason virtual scrolling is deferred for this component — there is no\n * container-owned arrow-nav model to hang a window off.\n *\n * Read as the element's `tabIndex` PROPERTY rather than the attribute, so an\n * option that carried no `tabindex` at all answers `-1` — what the DOM says of a\n * bare `<li>` — instead of a made-up `0` that would report an unfocusable option\n * as a tab stop if this component ever moved to a roving cursor.\n */\n async getTabIndex(): Promise<number> {\n return (await this.host()).getProperty<number>('tabIndex');\n }\n\n /**\n * Click the option: a branch opens its children to the right, a leaf commits\n * the path and closes the panel.\n *\n * A disabled option is clickable here on purpose — the component refuses it in\n * its own handler rather than through `pointer-events`, so the click a spec\n * dispatches is exactly as ineffective as one in a browser.\n */\n async click(): Promise<void> {\n return (await this.host()).click();\n }\n\n /**\n * Activate the option from the keyboard (Enter; Space is bound to the same\n * handler).\n *\n * This is the component's entire keyboard model — the columns bind\n * `keydown.enter` / `keydown.space` per option and nothing else, so there are\n * no arrow keys to walk levels with. A keyboard user reaches the option they\n * want with Tab and presses Enter. Opening the panel does move focus into it —\n * `focusPanelOption()` lands on the active option, or the first enabled one —\n * so the walk starts there rather than from the trigger; this JSDoc claimed\n * the opposite for a while and was simply wrong.\n */\n async selectByKeyboard(): Promise<void> {\n return (await this.host()).sendKeys(TestKey.ENTER);\n }\n\n /**\n * Move the pointer onto the option.\n *\n * Deliberately does NOT expand a branch: this cascader drills down on CLICK\n * only, unlike the hover-to-expand cascaders elsewhere. Kept because a spec\n * may want to pin that, and because the option's hover tint is styled.\n */\n async hover(): Promise<void> {\n return (await this.host()).hover();\n }\n\n /** Move keyboard focus to the option. */\n async focus(): Promise<void> {\n return (await this.host()).focus();\n }\n\n /** Whether the option holds keyboard focus. */\n async isFocused(): Promise<boolean> {\n return (await this.host()).isFocused();\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 } from '@angular/cdk/testing';\n\nimport type { WrCascaderColumnHarnessFilters, WrCascaderOptionHarnessFilters } from './interfaces';\nimport { WrCascaderOptionHarness } from './wr-cascader-option-harness';\n\n/**\n * Test harness for one COLUMN of an open `<wr-cascader>` panel.\n *\n * A column is a level of the tree: column 0 holds the root options, and each\n * further column holds the children of the active option in the column before\n * it. Which columns exist is therefore a function of what is expanded — the\n * relationship this harness exists to let a spec assert. Column 0 is always\n * there; a column only appears once there are children to put in it, so a leaf\n * adds none.\n *\n * @example\n * ```ts\n * const [countries, cities] = await cascader.getColumns();\n *\n * expect(await countries.getActiveOptionText()).toBe('Germany');\n * expect(await cities.getOptionLabels()).toEqual(['Berlin']);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderColumnHarness extends ComponentHarness {\n /** The `<ul role=\"group\">` the panel renders per level, inside the `tree`. */\n static hostSelector = '.wr-cascader__col';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderColumnHarnessFilters = {}): HarnessPredicate<WrCascaderColumnHarness> {\n return new HarnessPredicate(WrCascaderColumnHarness, options).addOption(\n 'optionText',\n options.optionText,\n async (harness, text) => {\n for (const label of await harness.getOptionLabels()) {\n if (await HarnessPredicate.stringMatches(label, text)) return true;\n }\n return false;\n }\n );\n }\n\n /** The role the column announces — `group`, inside the panel's `tree`. */\n async getRole(): Promise<string | null> {\n return (await this.host()).getAttribute('role');\n }\n\n /** The options this level offers, in order. */\n async getOptions(filters: WrCascaderOptionHarnessFilters = {}): Promise<WrCascaderOptionHarness[]> {\n return this.locatorForAll(WrCascaderOptionHarness.with(filters))();\n }\n\n /** The labels this level offers, in order. */\n async getOptionLabels(): Promise<string[]> {\n const options = await this.getOptions();\n return Promise.all(options.map(option => option.getText()));\n }\n\n /**\n * The first option matching the filters.\n *\n * Throws rather than answering `null`, and names what the column does offer:\n * a missing option here almost always means the level is not the one the spec\n * thought it was, and that is far easier to see with the alternatives listed.\n */\n async getOption(filters: WrCascaderOptionHarnessFilters): Promise<WrCascaderOptionHarness> {\n const [option] = await this.getOptions(filters);\n if (!option) {\n throw new Error(\n `WrCascaderColumnHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +\n `This column offers: ${(await this.getOptionLabels()).join(', ')}.`\n );\n }\n return option;\n }\n\n /** The option this level is drilled into, or `null` when nothing here is expanded. */\n async getActiveOption(): Promise<WrCascaderOptionHarness | null> {\n const [active] = await this.getOptions({ active: true });\n return active ?? null;\n }\n\n /** The label of the option this level is drilled into, or `null`. */\n async getActiveOptionText(): Promise<string | null> {\n const active = await this.getActiveOption();\n return active ? active.getText() : null;\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 {\n ComponentHarness,\n type HarnessLoader,\n HarnessPredicate,\n TestKey,\n type TestElement,\n} from '@angular/cdk/testing';\n\nimport type {\n WrCascaderColumnHarnessFilters,\n WrCascaderHarnessFilters,\n WrCascaderOptionHarnessFilters,\n} from './interfaces';\nimport { WrCascaderColumnHarness } from './wr-cascader-column-harness';\nimport type { WrCascaderOptionHarness } from './wr-cascader-option-harness';\n\n/**\n * Test harness for `<wr-cascader>` — the trigger, and the panel of COLUMNS it\n * opens. Root of a small family: {@link WrCascaderColumnHarness} for one level,\n * `WrCascaderOptionHarness` for one option in it.\n *\n * A cascader is not a select with extra steps. Its value is the whole PATH from\n * root to leaf (`['eu', 'de', 'ber']`, not `'ber'`), and the panel shows one\n * column per level, so which columns exist depends on what is expanded — column\n * 0 is the roots, and every further column holds the children of the active\n * option in the column to its left. That relationship is the component, so it is\n * what {@link getColumns} and {@link getColumnLabels} are for.\n *\n * The panel is NOT inside the cascader: it is a template portal in the overlay\n * container, a sibling of the whole app. Every read of it goes through the\n * document root scoped by the `aria-controls` id the trigger publishes, so two\n * cascaders on one page can never answer with each other's columns.\n *\n * @example\n * ```ts\n * const cascader = await loader.getHarness(WrCascaderHarness);\n *\n * await cascader.selectPath(['Europe', 'Germany', 'Berlin']);\n *\n * expect(await cascader.getValueText()).toBe('Europe / Germany / Berlin');\n * expect(await cascader.isOpen()).toBe(false);\n * ```\n *\n * @see https://ngwr.dev/guides/testing\n */\nexport class WrCascaderHarness extends ComponentHarness {\n static hostSelector = 'wr-cascader';\n\n /** Build a predicate that narrows the query. */\n static with(options: WrCascaderHarnessFilters = {}): HarnessPredicate<WrCascaderHarness> {\n return new HarnessPredicate(WrCascaderHarness, options)\n .addOption('text', options.text, (harness, text) => HarnessPredicate.stringMatches(harness.getValueText(), text))\n .addOption('placeholder', options.placeholder, (harness, placeholder) =>\n HarnessPredicate.stringMatches(harness.getPlaceholder(), placeholder)\n )\n .addOption('disabled', options.disabled, async (harness, disabled) => (await harness.isDisabled()) === disabled)\n .addOption('open', options.open, async (harness, open) => (await harness.isOpen()) === open);\n }\n\n private readonly trigger = this.locatorFor('.wr-cascader__trigger');\n\n /**\n * Whether the panel is showing.\n *\n * From the trigger's `aria-expanded` rather than the host's `--open` class:\n * both exist, and the ARIA state is the one a screen-reader user is told.\n */\n async isOpen(): Promise<boolean> {\n return (await (await this.trigger()).getAttribute('aria-expanded')) === 'true';\n }\n\n /**\n * Whether the cascader refuses interaction.\n *\n * From the trigger's native `disabled`, which is what actually stops a pointer\n * and what assistive tech reports; the host's `--disabled` class only mirrors\n * it for styling.\n */\n async isDisabled(): Promise<boolean> {\n return (await this.trigger()).getProperty<boolean>('disabled');\n }\n\n /**\n * What the trigger displays as the selection: the labels of the whole path\n * joined by the `separator` (`'Europe / Germany / Berlin'` by default), or `''`\n * while nothing is selected and the placeholder is showing.\n *\n * The joined string is all the DOM has — the separator is not published\n * anywhere on its own, so the harness will not pretend it can split the path\n * back apart. Assert against the bound value, or against\n * {@link getActiveTrail} while the panel is open, when the segments matter.\n */\n async getValueText(): Promise<string> {\n const value = await this.locatorForOptional('.wr-cascader__value')();\n return value ? value.text() : '';\n }\n\n /**\n * The placeholder, or `null` when a selection is hiding it.\n *\n * `''` is a real answer, not an absence: a cascader with no `placeholder` still\n * renders the element while unselected.\n */\n async getPlaceholder(): Promise<string | null> {\n const placeholder = await this.locatorForOptional('.wr-cascader__placeholder')();\n return placeholder ? placeholder.text() : null;\n }\n\n /**\n * The trigger's accessible name — the `ariaLabel` input, falling back to the\n * placeholder and then to the i18n catalog, because a `role=\"combobox\"` with\n * nothing selected and no placeholder would otherwise have no name at all.\n */\n async getAccessibleName(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-label');\n }\n\n /**\n * The kind of popup the trigger promises via `aria-haspopup` — `tree`.\n *\n * Worth pinning rather than assuming: a combobox's popup may be a listbox, a\n * tree, a grid or a dialog and nothing else, and this one said `menu` for a\n * long time. `menu` is a valid token for the global `aria-haspopup`, so axe\n * reports nothing either way — an assertion here is the only guard there is.\n */\n async getPopupRole(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-haspopup');\n }\n\n /** The role the panel announces — `tree`, matching what the trigger promised. */\n async getPanelRole(): Promise<string | null> {\n return (await this.panel()).getAttribute('role');\n }\n\n /**\n * The id the trigger publishes as `aria-controls`.\n *\n * Published unconditionally, open or closed — so while the panel is closed this\n * id resolves to nothing in the document. Exposed so a spec can pin that\n * (dangling or not) rather than have the harness quietly decide for it; every\n * panel read goes through the same id but refuses to run while closed.\n */\n async getPanelId(): Promise<string | null> {\n return (await this.trigger()).getAttribute('aria-controls');\n }\n\n /**\n * Whether the panel now in the overlay is the one this trigger claims to\n * control — `aria-controls` resolving to a real element that carries that id.\n *\n * With several cascaders on a page it is also the check that the reference lands\n * on THIS instance's panel rather than a neighbour's: the overlay container is\n * shared, so panels sit side by side in it with nothing but their ids to tell\n * them apart.\n */\n async isPanelWiredToTrigger(): Promise<boolean> {\n const rendered = await (await this.panel()).getAttribute('id');\n return rendered !== null && rendered === (await this.getPanelId());\n }\n\n /**\n * Open the panel.\n *\n * Clicks the trigger, because that is the only gesture the component binds. The\n * trigger is a native `<button>`, so a browser turns Enter / Space on it into\n * the same click — there is no separate keyboard route to model here, and jsdom\n * does not synthesise button activation from a key, so an `openByKeyboard()`\n * would only be able to lie.\n */\n async open(): Promise<void> {\n if (await this.isOpen()) return;\n\n await (await this.trigger()).click();\n if (await this.isOpen()) return;\n\n throw new Error(\n 'WrCascaderHarness.open(): the panel did not open. A disabled cascader refuses the click — ' +\n 'check isDisabled().'\n );\n }\n\n /**\n * Close the panel with Escape. A closed cascader is left alone.\n *\n * Escape reaches the panel through the CDK's keyboard dispatcher rather than\n * through the DOM tree, which is why sending it to the trigger works even\n * though the panel is somewhere else entirely.\n */\n async close(): Promise<void> {\n if (!(await this.isOpen())) return;\n\n await (await this.trigger()).sendKeys(TestKey.ESCAPE);\n if (await this.isOpen()) {\n throw new Error('WrCascaderHarness.close(): Escape did not close the panel.');\n }\n }\n\n /** Click the trigger once, whatever that does — opens a closed panel, closes an open one. */\n async clickTrigger(): Promise<void> {\n return (await this.trigger()).click();\n }\n\n /**\n * The columns of the open panel, left to right: column 0 is the root options,\n * and each further one holds the children of its neighbour's active option.\n *\n * Throws while the panel is closed. The columns do not exist anywhere until the\n * portal is attached, and an empty array reads like a panel that rendered\n * nothing — a confusing failure three lines later instead of here.\n */\n async getColumns(filters: WrCascaderColumnHarnessFilters = {}): Promise<WrCascaderColumnHarness[]> {\n const loader = await this.panelLoader();\n return loader.getAllHarnesses(WrCascaderColumnHarness.with(filters));\n }\n\n /** How many levels the panel is currently showing. */\n async getColumnCount(): Promise<number> {\n return (await this.getColumns()).length;\n }\n\n /**\n * One column by its 0-based level. Throws when the level is not showing, which\n * is the interesting failure: it means the option before it has no children, or\n * has not been expanded yet.\n */\n async getColumn(index: number): Promise<WrCascaderColumnHarness> {\n const columns = await this.getColumns();\n const column = columns[index];\n if (!column) {\n throw new Error(\n `WrCascaderHarness.getColumn(): no column at level ${index} — the panel is showing ` +\n `${columns.length}. A deeper column appears only once a parent with children is expanded.`\n );\n }\n return column;\n }\n\n /** The labels offered by every column, outer array left to right. */\n async getColumnLabels(): Promise<string[][]> {\n const columns = await this.getColumns();\n return Promise.all(columns.map(column => column.getOptionLabels()));\n }\n\n /**\n * The expanded trail — the label of the active option in each column, root\n * first.\n *\n * This is the panel's own idea of where the user is, which is NOT always the\n * committed value: drilling into a branch moves the trail without committing\n * anything unless `changeOnSelect` is on. Once a leaf is picked the two agree,\n * and this is the only place the path's segments exist separately in the DOM.\n */\n async getActiveTrail(): Promise<string[]> {\n const trail: string[] = [];\n for (const column of await this.getColumns()) {\n const active = await column.getActiveOptionText();\n if (active !== null) trail.push(active);\n }\n return trail;\n }\n\n /**\n * The first option matching the filters, anywhere in the panel. Throws when\n * nothing matches, naming what is on offer.\n *\n * Use {@link getColumn} when the level matters — the same label can legitimately\n * appear at more than one level.\n */\n async getOption(filters: WrCascaderOptionHarnessFilters): Promise<WrCascaderOptionHarness> {\n for (const column of await this.getColumns()) {\n const [option] = await column.getOptions(filters);\n if (option) return option;\n }\n\n throw new Error(\n `WrCascaderHarness.getOption(): no option matched ${JSON.stringify(filters)}. ` +\n `The panel offers: ${(await this.getColumnLabels()).map(labels => labels.join(', ')).join(' | ')}.`\n );\n }\n\n /**\n * Walk a path by label, opening the panel first if needed: each label is\n * clicked in the column it belongs to, so `['Europe', 'Germany', 'Berlin']`\n * drills two levels and commits the third.\n *\n * Clicking is the only way down — this cascader does not expand on hover, so\n * neither does the harness. A path that ends on a BRANCH just leaves that\n * branch expanded: the component commits nothing on the way down unless\n * `changeOnSelect` is on, and only a leaf closes the panel.\n */\n async selectPath(labels: readonly string[]): Promise<void> {\n if (labels.length === 0) {\n throw new Error(\n 'WrCascaderHarness.selectPath(): the path is empty. Pass at least one label, or call clear() ' +\n 'to unset the selection.'\n );\n }\n\n await this.open();\n\n for (let level = 0; level < labels.length; level++) {\n const label = labels[level];\n const columns = await this.getColumns();\n const column = columns[level];\n if (!column) {\n throw new Error(\n `WrCascaderHarness.selectPath(): \"${label}\" would be at level ${level}, but the panel is ` +\n `showing ${columns.length} column(s) — the step before it opened no deeper level.`\n );\n }\n\n const option = await column.getOption({ text: label });\n if (await option.isDisabled()) {\n throw new Error(`WrCascaderHarness.selectPath(): \"${label}\" is disabled, so no path can pass through it.`);\n }\n\n const isLast = level === labels.length - 1;\n if (!isLast && !(await option.hasChildren())) {\n throw new Error(\n `WrCascaderHarness.selectPath(): \"${label}\" is a leaf, so the path cannot continue to ` +\n `\"${labels[level + 1]}\" — picking it commits and closes the panel.`\n );\n }\n\n await option.click();\n }\n }\n\n /**\n * Click the clear (×) control on the trigger.\n *\n * Throws when there is none, and both reasons are worth failing on: the\n * cascader is not `clearable`, or nothing is selected — the control is not\n * rendered at all in either case (nor while disabled).\n */\n async clear(): Promise<void> {\n const clear = await this.locatorForOptional('.wr-cascader__clear')();\n if (!clear) {\n throw new Error(\n 'WrCascaderHarness.clear(): this cascader shows no clear control — it is rendered only when ' +\n '`clearable` is on, something is selected, and the control is enabled.'\n );\n }\n await clear.click();\n }\n\n /**\n * Clear from the keyboard — Backspace on the closed trigger.\n *\n * The × {@link clear} clicks is a `tabindex=\"-1\"` span inside the trigger, so no\n * key can ever reach it; Backspace on the trigger is its keyboard twin, and the\n * route a keyboard-only user actually has. Prefer this one in a spec that cares\n * about that user — {@link clear} proves the pointer path and nothing more.\n *\n * The component honours the key only on the CLOSED trigger, so an open panel\n * is closed first with Escape — the step a keyboard user takes too. Sending\n * Backspace into an open panel and returning would be a plausible nothing.\n *\n * Does nothing, rather than throwing, when there is nothing to clear, `clearable`\n * is off, or the cascader is disabled or read-only: that silence IS the\n * component's contract, so a spec asserts it on the value.\n */\n async clearByKeyboard(): Promise<void> {\n if (await this.isOpen()) await this.close();\n await (await this.trigger()).sendKeys(TestKey.BACKSPACE);\n }\n\n /** Move keyboard focus to the trigger. */\n async focus(): Promise<void> {\n return (await this.trigger()).focus();\n }\n\n /** Take focus off the trigger, which is what makes a bound form field touched. */\n async blur(): Promise<void> {\n return (await this.trigger()).blur();\n }\n\n /** Whether the trigger holds keyboard focus. */\n async isFocused(): Promise<boolean> {\n return (await this.trigger()).isFocused();\n }\n\n /** This cascader's panel element in the overlay — the single-element scoped read. */\n private async panel(): Promise<TestElement> {\n return this.documentRootLocatorFactory().locatorFor(`#${await this.panelId()}`)();\n }\n\n /**\n * A loader scoped to THIS cascader's panel — the list scoped read.\n *\n * Scoped by the published id rather than by `.wr-cascader-panel`: the overlay\n * container is shared with every other overlay in the app, so a bare class\n * query would answer with whichever panel happened to be open.\n */\n private async panelLoader(): Promise<HarnessLoader> {\n return this.documentRootLocatorFactory().harnessLoaderFor(`#${await this.panelId()}`);\n }\n\n /** The panel id, refusing to hand it out while there is no panel to find. */\n private async panelId(): Promise<string> {\n if (!(await this.isOpen())) {\n throw new Error(\n 'WrCascaderHarness: the panel is closed, so there are no columns to read — call open() or ' +\n 'selectPath() first. The trigger publishes `aria-controls` even while closed, so the id ' +\n 'alone is not proof the panel exists.'\n );\n }\n\n const id = await this.getPanelId();\n if (!id) {\n throw new Error('WrCascaderHarness: the trigger publishes no `aria-controls`, so its panel cannot be found.');\n }\n return id;\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
|
|
@@ -214,6 +214,21 @@ class WrCascader {
|
|
|
214
214
|
onTriggerKeydown(event) {
|
|
215
215
|
if (this.disabled() || this.readonly() || this.open())
|
|
216
216
|
return;
|
|
217
|
+
// Backspace is the × from the keyboard, and it has to be: the × is a
|
|
218
|
+
// `tabindex="-1"` span INSIDE this button, and a keydown goes to the focused
|
|
219
|
+
// element, so the `(keydown.enter)` / `(keydown.space)` it used to carry could
|
|
220
|
+
// never fire. Clearing was reachable by pointer alone — a WCAG 2.1.1 failure,
|
|
221
|
+
// not a missing convenience. The span stays unfocusable, because a focusable
|
|
222
|
+
// child of a button is `nested-interactive`. Same key, same gating as
|
|
223
|
+
// `wr-select`: `clearable()` IS the clear control, so a consumer who turned
|
|
224
|
+
// the × off did not ask for a keyboard twin of it.
|
|
225
|
+
if (event.key === 'Backspace') {
|
|
226
|
+
if (!this.clearable() || !this.hasSelection())
|
|
227
|
+
return;
|
|
228
|
+
event.preventDefault();
|
|
229
|
+
this.clearSelection(event);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
217
232
|
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')
|
|
218
233
|
return;
|
|
219
234
|
event.preventDefault();
|
|
@@ -251,6 +266,50 @@ class WrCascader {
|
|
|
251
266
|
isActiveAt(colIndex, value) {
|
|
252
267
|
return this.activePath()[colIndex] === value;
|
|
253
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* Whether this option is the committed choice — `null` when it is not a
|
|
271
|
+
* choice at all.
|
|
272
|
+
*
|
|
273
|
+
* Two questions the panel has to keep apart, and `--active` answers only the
|
|
274
|
+
* first: `activePath()` is where the user has NAVIGATED to, `path()` is what
|
|
275
|
+
* they have COMMITTED. They agree once a leaf is picked and diverge for the
|
|
276
|
+
* whole walk down.
|
|
277
|
+
*
|
|
278
|
+
* `null` — the attribute absent — on a branch while `changeOnSelect` is off,
|
|
279
|
+
* because such a branch genuinely cannot be chosen; ARIA reads a missing
|
|
280
|
+
* `aria-selected` as "not selectable", which is exactly true here. That makes
|
|
281
|
+
* this binding the first expression the `changeOnSelect` contract has ever had
|
|
282
|
+
* in ARIA, in both directions.
|
|
283
|
+
*/
|
|
284
|
+
isSelectedAt(colIndex, opt) {
|
|
285
|
+
const committable = !opt.children?.length || this.changeOnSelect();
|
|
286
|
+
if (!committable)
|
|
287
|
+
return null;
|
|
288
|
+
const path = this.path();
|
|
289
|
+
return colIndex === path.length - 1 && path[colIndex] === opt.value;
|
|
290
|
+
}
|
|
291
|
+
/** Stable id for one option — what a column's `aria-labelledby` points at. */
|
|
292
|
+
optionId(colIndex, optIndex) {
|
|
293
|
+
return `${this.panelId}-opt-${colIndex}-${optIndex}`;
|
|
294
|
+
}
|
|
295
|
+
/** Stable id for one column — what an expanded branch's `aria-controls` points at. */
|
|
296
|
+
columnId(colIndex) {
|
|
297
|
+
return `${this.panelId}-col-${colIndex}`;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* The option whose children a column holds, by id — its accessible name.
|
|
301
|
+
*
|
|
302
|
+
* The columns are DOM SIBLINGS, so nothing in the markup says the second one
|
|
303
|
+
* belongs to "Europe". Column 0 has no parent and stays unnamed; the tree
|
|
304
|
+
* itself already carries the control's name.
|
|
305
|
+
*/
|
|
306
|
+
parentOptionId(colIndex) {
|
|
307
|
+
if (colIndex === 0)
|
|
308
|
+
return null;
|
|
309
|
+
const parent = this.columns()[colIndex - 1] ?? [];
|
|
310
|
+
const index = parent.findIndex(o => this.isActiveAt(colIndex - 1, o.value));
|
|
311
|
+
return index < 0 ? null : this.optionId(colIndex - 1, index);
|
|
312
|
+
}
|
|
254
313
|
pathsEqual(a, b) {
|
|
255
314
|
return a.length === b.length && a.every((v, i) => v === b[i]);
|
|
256
315
|
}
|
|
@@ -334,12 +393,12 @@ class WrCascader {
|
|
|
334
393
|
if (focusWasInside)
|
|
335
394
|
this.host.nativeElement.querySelector('.wr-cascader__trigger')?.focus();
|
|
336
395
|
}
|
|
337
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.
|
|
338
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.5", type: WrCascader, isStandalone: true, selector: "wr-cascader", inputs: { clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, changeOnSelect: { classPropertyName: "changeOnSelect", publicName: "changeOnSelect", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", 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()" } }, viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<button\n type=\"button\"\n class=\"wr-cascader__trigger\"\n role=\"combobox\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKeydown($event)\"\n (blur)=\"touch.emit()\"\n>\n @if (displayLabel(); as label) {\n <span class=\"wr-cascader__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-cascader__placeholder\">{{ placeholder() }}</span>\n }\n\n @if (clearable() && hasSelection() && !disabled() && !readonly()) {\n <span\n class=\"wr-cascader__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClearLabel()\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-cascader__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n</button>\n\n<ng-template #panelTpl>\n <div\n class=\"wr-cascader-panel\"\n [class.wr-cascader-panel--sm]=\"size() === 'sm'\"\n [class.wr-cascader-panel--lg]=\"size() === 'lg'\"\n role=\"menu\"\n [attr.id]=\"panelId\"\n >\n @for (col of columns(); track $index; let colIndex = $index) {\n <ul class=\"wr-cascader__col\" role=\"menu\">\n @for (opt of col; track opt.value) {\n <li\n class=\"wr-cascader__opt\"\n role=\"menuitem\"\n [class.wr-cascader__opt--active]=\"isActiveAt(colIndex, opt.value)\"\n [class.wr-cascader__opt--disabled]=\"opt.disabled\"\n [attr.tabindex]=\"opt.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n (click)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.enter)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.space)=\"onOptionClick(colIndex, opt, $event)\"\n >\n <span class=\"wr-cascader__opt-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <svg\n class=\"wr-icon__svg wr-cascader__opt-arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n</ng-template>\n", styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader{--wr-cascader-color: var(--wr-color-on-surface);--wr-cascader-bg: var(--wr-color-surface);--wr-cascader-border: var(--wr-color-outline);--wr-cascader-radius: var(--wr-control-radius-md);--wr-cascader-padding-y: var(--wr-control-padding-y-md);--wr-cascader-padding-x: var(--wr-control-padding-x-md);--wr-cascader-font-size: var(--wr-control-font-size-md);--wr-cascader-line-height: var(--wr-control-line-height-md);--wr-cascader-col-width: 12rem;--wr-cascader-max-height: 16rem;--wr-cascader-min-width: 12rem;display:inline-flex;vertical-align:middle}.wr-cascader--disabled{--wr-cascader-color: var(--wr-color-on-surface-muted);--wr-cascader-bg: var(--wr-color-fill)}.wr-cascader--sm{--wr-cascader-radius: var(--wr-control-radius-sm);--wr-cascader-padding-y: var(--wr-control-padding-y-sm);--wr-cascader-padding-x: var(--wr-control-padding-x-sm);--wr-cascader-font-size: var(--wr-control-font-size-sm);--wr-cascader-line-height: var(--wr-control-line-height-sm)}.wr-cascader--lg{--wr-cascader-radius: var(--wr-control-radius-lg);--wr-cascader-padding-y: var(--wr-control-padding-y-lg);--wr-cascader-padding-x: var(--wr-control-padding-x-lg);--wr-cascader-font-size: var(--wr-control-font-size-lg);--wr-cascader-line-height: var(--wr-control-line-height-lg)}.wr-cascader__trigger{display:inline-flex;align-items:center;gap:.5rem;width:100%;min-width:var(--wr-cascader-min-width);appearance:none;background:var(--wr-cascader-bg);color:var(--wr-cascader-color);border:1px solid var(--wr-cascader-border);border-radius:var(--wr-cascader-radius);padding:calc(var(--wr-cascader-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-cascader-padding-x) * var(--wr-density-x, 1));font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-font-size);line-height:var(--wr-cascader-line-height);cursor:pointer;text-align:start;transition:border-color var(--wr-transition-base),box-shadow var(--wr-transition-base)}.wr-cascader__trigger:focus-visible{border-color:var(--wr-color-primary);outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader__trigger:disabled{cursor:not-allowed}.wr-cascader--readonly .wr-cascader__trigger{cursor:default}.wr-cascader--open .wr-cascader__trigger{border-color:var(--wr-color-primary);box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.15)}.wr-cascader__value,.wr-cascader__placeholder{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader__placeholder{color:var(--wr-color-text-muted)}.wr-cascader__chevron{--wr-icon-size: 1rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted);transition:transform var(--wr-transition-base)}.wr-cascader--open .wr-cascader__chevron{transform:rotate(180deg)}.wr-cascader__clear{--wr-icon-size: .875rem;display:inline-flex;align-items:center;justify-content:center;width:1.125rem;height:1.125rem;border-radius:999px;color:var(--wr-color-on-surface-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.wr-cascader__clear:hover{background:rgba(var(--wr-color-on-surface-rgb),.06);color:var(--wr-color-on-surface)}.wr-cascader-overlay{padding-top:.25rem}.wr-cascader-panel{--wr-cascader-opt-font: var(--wr-control-font-size-md);--wr-cascader-opt-py: .5rem;display:flex;background:var(--wr-color-surface);border:1px solid var(--wr-color-outline);border-radius:var(--wr-border-radius-base);box-shadow:var(--wr-shadow-overlay);font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-opt-font);overflow:hidden}.wr-cascader-panel--sm{--wr-cascader-opt-font: var(--wr-control-font-size-sm);--wr-cascader-opt-py: .375rem}.wr-cascader-panel--lg{--wr-cascader-opt-font: var(--wr-control-font-size-lg);--wr-cascader-opt-py: .625rem}.wr-cascader-panel .wr-cascader__col{list-style:none;margin:0;padding:.25rem;width:var(--wr-cascader-col-width, 12rem);max-height:var(--wr-cascader-max-height, 16rem);overflow-y:auto;display:flex;flex-direction:column;gap:.125rem}.wr-cascader-panel .wr-cascader__col+.wr-cascader__col{border-inline-start:1px solid var(--wr-color-outline)}.wr-cascader-panel .wr-cascader__opt{display:flex;align-items:center;gap:.5rem;padding:var(--wr-cascader-opt-py) .625rem;border-radius:var(--wr-border-radius-sm);color:var(--wr-color-on-surface);cursor:pointer;transition:background var(--wr-transition-short)}.wr-cascader-panel .wr-cascader__opt:hover{background:var(--wr-color-hover)}.wr-cascader-panel .wr-cascader__opt--active{background:var(--wr-color-primary-soft);color:var(--wr-color-primary-ink);font-weight:500}.wr-cascader-panel .wr-cascader__opt--disabled{color:var(--wr-color-on-surface-muted);cursor:not-allowed;opacity:var(--wr-disabled-opacity)}.wr-cascader-panel .wr-cascader__opt--disabled:hover{background:transparent}.wr-cascader-panel .wr-cascader__opt-label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader-panel .wr-cascader__opt-arrow{--wr-icon-size: .875rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted)}[dir=rtl] .wr-cascader-panel .wr-cascader__opt-arrow{transform:scaleX(-1)}@media(pointer:coarse){.wr-cascader__clear{--wr-icon-size: 1.125rem;width:2rem;height:2rem}.wr-cascader-panel .wr-cascader__opt{padding-top:.75rem;padding-bottom:.75rem}}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
396
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrCascader, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
397
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.6", type: WrCascader, isStandalone: true, selector: "wr-cascader", inputs: { clearLabel: { classPropertyName: "clearLabel", publicName: "clearLabel", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, changeOnSelect: { classPropertyName: "changeOnSelect", publicName: "changeOnSelect", isSignal: true, isRequired: false, transformFunction: null }, separator: { classPropertyName: "separator", publicName: "separator", 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()" } }, viewQueries: [{ propertyName: "panelTpl", first: true, predicate: ["panelTpl"], descendants: true, read: TemplateRef, isSignal: true }], ngImport: i0, template: "<button\n type=\"button\"\n class=\"wr-cascader__trigger\"\n role=\"combobox\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKeydown($event)\"\n (blur)=\"touch.emit()\"\n>\n @if (displayLabel(); as label) {\n <span class=\"wr-cascader__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-cascader__placeholder\">{{ placeholder() }}</span>\n }\n\n @if (clearable() && hasSelection() && !disabled() && !readonly()) {\n <span\n class=\"wr-cascader__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClearLabel()\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-cascader__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n</button>\n\n<ng-template #panelTpl>\n <div\n class=\"wr-cascader-panel\"\n [class.wr-cascader-panel--sm]=\"size() === 'sm'\"\n [class.wr-cascader-panel--lg]=\"size() === 'lg'\"\n role=\"tree\"\n [attr.id]=\"panelId\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n >\n <!--\n tree / group / treeitem, and NOT menu. A combobox's popup may be a listbox,\n a tree, a grid or a dialog and nothing else, so `aria-haspopup=\"menu\"` on\n the trigger was an author error \u2014 and a `menu` may own menuitems and\n groups, never other menus, so the columns were a second one. Neither is\n visible to axe: `menu` is a valid token for the global `aria-haspopup`, and\n `aria-required-children` passes a menu-inside-menu (measured against this\n exact fragment). A tree is what this control has always been \u2014 the value is\n a PATH, and only `treeitem` supports aria-expanded, aria-level,\n aria-setsize, aria-posinset and aria-selected at once.\n\n The columns stay `group` rather than collapsing to `role=\"presentation\"`,\n which is also axe-clean: the DOM is column-MAJOR, so a flat tree would\n leave level plus document order as the only structure, and \"Germany\"\n (level 2) would read as a child of \"Antarctica\" (level 1, the item\n immediately before it in source order).\n -->\n @for (col of columns(); track $index; let colIndex = $index) {\n <ul\n class=\"wr-cascader__col\"\n role=\"group\"\n [attr.id]=\"columnId(colIndex)\"\n [attr.aria-labelledby]=\"parentOptionId(colIndex)\"\n >\n @for (opt of col; track opt.value; let optIndex = $index) {\n <!--\n `aria-expanded` is exactly `isActiveAt`: `columns()` renders the next\n column for the active option and only when it has children, so the\n state can never claim a column that is not on screen \u2014 and\n `aria-controls` rides that same invariant, which is what makes\n \"expanded\" refer to something when the expanded content is a SIBLING\n rather than a descendant. It is emitted only while expanded: a\n reference to an absent id is a violation with `aria-expanded=\"true\"`\n and clean while collapsed.\n\n `aria-level` is load-bearing rather than decorative. The columns are\n siblings, so the DOM ancestry represents no level at all and every\n option would read as level 1. `aria-setsize` / `aria-posinset` are\n not strictly required \u2014 each column IS a complete sibling set \u2014 and\n are written anyway, because a tree that owns sibling groups is the\n uncommon shape where browser/AT pairs are known to miscompute both.\n\n `aria-selected` is written on every option that can be COMMITTED,\n `false` included, matching `wr-tree`. The alternative a reviewer may\n prefer: only the selected node, leaning on treeitem's implicit false,\n which is quieter in a long column and loses the \"this row is\n selectable\" signal that presence carries.\n -->\n <li\n class=\"wr-cascader__opt\"\n role=\"treeitem\"\n [attr.id]=\"optionId(colIndex, optIndex)\"\n [class.wr-cascader__opt--active]=\"isActiveAt(colIndex, opt.value)\"\n [class.wr-cascader__opt--disabled]=\"opt.disabled\"\n [attr.tabindex]=\"opt.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n [attr.aria-level]=\"colIndex + 1\"\n [attr.aria-setsize]=\"$count\"\n [attr.aria-posinset]=\"optIndex + 1\"\n [attr.aria-selected]=\"isSelectedAt(colIndex, opt)\"\n [attr.aria-expanded]=\"opt.children?.length ? isActiveAt(colIndex, opt.value) : null\"\n [attr.aria-controls]=\"\n opt.children?.length && isActiveAt(colIndex, opt.value) ? columnId(colIndex + 1) : null\n \"\n (click)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.enter)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.space)=\"onOptionClick(colIndex, opt, $event)\"\n >\n <span class=\"wr-cascader__opt-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <svg\n class=\"wr-icon__svg wr-cascader__opt-arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n</ng-template>\n", styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader{--wr-cascader-color: var(--wr-color-on-surface);--wr-cascader-bg: var(--wr-color-surface);--wr-cascader-border: var(--wr-color-outline);--wr-cascader-radius: var(--wr-control-radius-md);--wr-cascader-padding-y: var(--wr-control-padding-y-md);--wr-cascader-padding-x: var(--wr-control-padding-x-md);--wr-cascader-font-size: var(--wr-control-font-size-md);--wr-cascader-line-height: var(--wr-control-line-height-md);--wr-cascader-col-width: 12rem;--wr-cascader-max-height: 16rem;--wr-cascader-min-width: 12rem;display:inline-flex;vertical-align:middle}.wr-cascader--disabled{--wr-cascader-color: var(--wr-color-on-surface-muted);--wr-cascader-bg: var(--wr-color-fill)}.wr-cascader--sm{--wr-cascader-radius: var(--wr-control-radius-sm);--wr-cascader-padding-y: var(--wr-control-padding-y-sm);--wr-cascader-padding-x: var(--wr-control-padding-x-sm);--wr-cascader-font-size: var(--wr-control-font-size-sm);--wr-cascader-line-height: var(--wr-control-line-height-sm)}.wr-cascader--lg{--wr-cascader-radius: var(--wr-control-radius-lg);--wr-cascader-padding-y: var(--wr-control-padding-y-lg);--wr-cascader-padding-x: var(--wr-control-padding-x-lg);--wr-cascader-font-size: var(--wr-control-font-size-lg);--wr-cascader-line-height: var(--wr-control-line-height-lg)}.wr-cascader__trigger{display:inline-flex;align-items:center;gap:.5rem;width:100%;min-width:var(--wr-cascader-min-width);appearance:none;background:var(--wr-cascader-bg);color:var(--wr-cascader-color);border:1px solid var(--wr-cascader-border);border-radius:var(--wr-cascader-radius);padding:calc(var(--wr-cascader-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-cascader-padding-x) * var(--wr-density-x, 1));font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-font-size);line-height:var(--wr-cascader-line-height);cursor:pointer;text-align:start;transition:border-color var(--wr-transition-base),box-shadow var(--wr-transition-base)}.wr-cascader__trigger:focus-visible{border-color:var(--wr-color-primary);outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader__trigger:disabled{cursor:not-allowed}.wr-cascader--readonly .wr-cascader__trigger{cursor:default}.wr-cascader--open .wr-cascader__trigger{border-color:var(--wr-color-primary);box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.15)}.wr-cascader__value,.wr-cascader__placeholder{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader__placeholder{color:var(--wr-color-text-muted)}.wr-cascader__chevron{--wr-icon-size: 1rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted);transition:transform var(--wr-transition-base)}.wr-cascader--open .wr-cascader__chevron{transform:rotate(180deg)}.wr-cascader__clear{--wr-icon-size: .875rem;display:inline-flex;align-items:center;justify-content:center;width:1.125rem;height:1.125rem;border-radius:999px;color:var(--wr-color-on-surface-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.wr-cascader__clear:hover{background:rgba(var(--wr-color-on-surface-rgb),.06);color:var(--wr-color-on-surface)}.wr-cascader-overlay{padding-top:.25rem}.wr-cascader-panel{--wr-cascader-opt-font: var(--wr-control-font-size-md);--wr-cascader-opt-py: .5rem;display:flex;background:var(--wr-color-surface);border:1px solid var(--wr-color-outline);border-radius:var(--wr-border-radius-base);box-shadow:var(--wr-shadow-overlay);font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-opt-font);overflow:hidden}.wr-cascader-panel--sm{--wr-cascader-opt-font: var(--wr-control-font-size-sm);--wr-cascader-opt-py: .375rem}.wr-cascader-panel--lg{--wr-cascader-opt-font: var(--wr-control-font-size-lg);--wr-cascader-opt-py: .625rem}.wr-cascader-panel .wr-cascader__col{list-style:none;margin:0;padding:.25rem;width:var(--wr-cascader-col-width, 12rem);max-height:var(--wr-cascader-max-height, 16rem);overflow-y:auto;display:flex;flex-direction:column;gap:.125rem}.wr-cascader-panel .wr-cascader__col+.wr-cascader__col{border-inline-start:1px solid var(--wr-color-outline)}.wr-cascader-panel .wr-cascader__opt{display:flex;align-items:center;gap:.5rem;padding:var(--wr-cascader-opt-py) .625rem;border-radius:var(--wr-border-radius-sm);color:var(--wr-color-on-surface);cursor:pointer;transition:background var(--wr-transition-short)}.wr-cascader-panel .wr-cascader__opt:hover{background:var(--wr-color-hover)}.wr-cascader-panel .wr-cascader__opt--active{background:var(--wr-color-primary-soft);color:var(--wr-color-primary-ink);font-weight:500}.wr-cascader-panel .wr-cascader__opt--disabled{color:var(--wr-color-on-surface-muted);cursor:not-allowed;opacity:var(--wr-disabled-opacity)}.wr-cascader-panel .wr-cascader__opt--disabled:hover{background:transparent}.wr-cascader-panel .wr-cascader__opt-label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader-panel .wr-cascader__opt-arrow{--wr-icon-size: .875rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted)}[dir=rtl] .wr-cascader-panel .wr-cascader__opt-arrow{transform:scaleX(-1)}@media(pointer:coarse){.wr-cascader__clear{--wr-icon-size: 1.125rem;width:2rem;height:2rem}.wr-cascader-panel .wr-cascader__opt{padding-top:.75rem;padding-bottom:.75rem}}\n"], encapsulation: i0.ViewEncapsulation.None });
|
|
339
398
|
}
|
|
340
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.
|
|
399
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.6", ngImport: i0, type: WrCascader, decorators: [{
|
|
341
400
|
type: Component,
|
|
342
|
-
args: [{ selector: 'wr-cascader', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "<button\n type=\"button\"\n class=\"wr-cascader__trigger\"\n role=\"combobox\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'menu'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKeydown($event)\"\n (blur)=\"touch.emit()\"\n>\n @if (displayLabel(); as label) {\n <span class=\"wr-cascader__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-cascader__placeholder\">{{ placeholder() }}</span>\n }\n\n @if (clearable() && hasSelection() && !disabled() && !readonly()) {\n <span\n class=\"wr-cascader__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClearLabel()\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n (keydown.enter)=\"clearSelection($event)\"\n (keydown.space)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-cascader__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n</button>\n\n<ng-template #panelTpl>\n <div\n class=\"wr-cascader-panel\"\n [class.wr-cascader-panel--sm]=\"size() === 'sm'\"\n [class.wr-cascader-panel--lg]=\"size() === 'lg'\"\n role=\"menu\"\n [attr.id]=\"panelId\"\n >\n @for (col of columns(); track $index; let colIndex = $index) {\n <ul class=\"wr-cascader__col\" role=\"menu\">\n @for (opt of col; track opt.value) {\n <li\n class=\"wr-cascader__opt\"\n role=\"menuitem\"\n [class.wr-cascader__opt--active]=\"isActiveAt(colIndex, opt.value)\"\n [class.wr-cascader__opt--disabled]=\"opt.disabled\"\n [attr.tabindex]=\"opt.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n (click)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.enter)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.space)=\"onOptionClick(colIndex, opt, $event)\"\n >\n <span class=\"wr-cascader__opt-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <svg\n class=\"wr-icon__svg wr-cascader__opt-arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n</ng-template>\n", styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader{--wr-cascader-color: var(--wr-color-on-surface);--wr-cascader-bg: var(--wr-color-surface);--wr-cascader-border: var(--wr-color-outline);--wr-cascader-radius: var(--wr-control-radius-md);--wr-cascader-padding-y: var(--wr-control-padding-y-md);--wr-cascader-padding-x: var(--wr-control-padding-x-md);--wr-cascader-font-size: var(--wr-control-font-size-md);--wr-cascader-line-height: var(--wr-control-line-height-md);--wr-cascader-col-width: 12rem;--wr-cascader-max-height: 16rem;--wr-cascader-min-width: 12rem;display:inline-flex;vertical-align:middle}.wr-cascader--disabled{--wr-cascader-color: var(--wr-color-on-surface-muted);--wr-cascader-bg: var(--wr-color-fill)}.wr-cascader--sm{--wr-cascader-radius: var(--wr-control-radius-sm);--wr-cascader-padding-y: var(--wr-control-padding-y-sm);--wr-cascader-padding-x: var(--wr-control-padding-x-sm);--wr-cascader-font-size: var(--wr-control-font-size-sm);--wr-cascader-line-height: var(--wr-control-line-height-sm)}.wr-cascader--lg{--wr-cascader-radius: var(--wr-control-radius-lg);--wr-cascader-padding-y: var(--wr-control-padding-y-lg);--wr-cascader-padding-x: var(--wr-control-padding-x-lg);--wr-cascader-font-size: var(--wr-control-font-size-lg);--wr-cascader-line-height: var(--wr-control-line-height-lg)}.wr-cascader__trigger{display:inline-flex;align-items:center;gap:.5rem;width:100%;min-width:var(--wr-cascader-min-width);appearance:none;background:var(--wr-cascader-bg);color:var(--wr-cascader-color);border:1px solid var(--wr-cascader-border);border-radius:var(--wr-cascader-radius);padding:calc(var(--wr-cascader-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-cascader-padding-x) * var(--wr-density-x, 1));font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-font-size);line-height:var(--wr-cascader-line-height);cursor:pointer;text-align:start;transition:border-color var(--wr-transition-base),box-shadow var(--wr-transition-base)}.wr-cascader__trigger:focus-visible{border-color:var(--wr-color-primary);outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader__trigger:disabled{cursor:not-allowed}.wr-cascader--readonly .wr-cascader__trigger{cursor:default}.wr-cascader--open .wr-cascader__trigger{border-color:var(--wr-color-primary);box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.15)}.wr-cascader__value,.wr-cascader__placeholder{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader__placeholder{color:var(--wr-color-text-muted)}.wr-cascader__chevron{--wr-icon-size: 1rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted);transition:transform var(--wr-transition-base)}.wr-cascader--open .wr-cascader__chevron{transform:rotate(180deg)}.wr-cascader__clear{--wr-icon-size: .875rem;display:inline-flex;align-items:center;justify-content:center;width:1.125rem;height:1.125rem;border-radius:999px;color:var(--wr-color-on-surface-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.wr-cascader__clear:hover{background:rgba(var(--wr-color-on-surface-rgb),.06);color:var(--wr-color-on-surface)}.wr-cascader-overlay{padding-top:.25rem}.wr-cascader-panel{--wr-cascader-opt-font: var(--wr-control-font-size-md);--wr-cascader-opt-py: .5rem;display:flex;background:var(--wr-color-surface);border:1px solid var(--wr-color-outline);border-radius:var(--wr-border-radius-base);box-shadow:var(--wr-shadow-overlay);font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-opt-font);overflow:hidden}.wr-cascader-panel--sm{--wr-cascader-opt-font: var(--wr-control-font-size-sm);--wr-cascader-opt-py: .375rem}.wr-cascader-panel--lg{--wr-cascader-opt-font: var(--wr-control-font-size-lg);--wr-cascader-opt-py: .625rem}.wr-cascader-panel .wr-cascader__col{list-style:none;margin:0;padding:.25rem;width:var(--wr-cascader-col-width, 12rem);max-height:var(--wr-cascader-max-height, 16rem);overflow-y:auto;display:flex;flex-direction:column;gap:.125rem}.wr-cascader-panel .wr-cascader__col+.wr-cascader__col{border-inline-start:1px solid var(--wr-color-outline)}.wr-cascader-panel .wr-cascader__opt{display:flex;align-items:center;gap:.5rem;padding:var(--wr-cascader-opt-py) .625rem;border-radius:var(--wr-border-radius-sm);color:var(--wr-color-on-surface);cursor:pointer;transition:background var(--wr-transition-short)}.wr-cascader-panel .wr-cascader__opt:hover{background:var(--wr-color-hover)}.wr-cascader-panel .wr-cascader__opt--active{background:var(--wr-color-primary-soft);color:var(--wr-color-primary-ink);font-weight:500}.wr-cascader-panel .wr-cascader__opt--disabled{color:var(--wr-color-on-surface-muted);cursor:not-allowed;opacity:var(--wr-disabled-opacity)}.wr-cascader-panel .wr-cascader__opt--disabled:hover{background:transparent}.wr-cascader-panel .wr-cascader__opt-label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader-panel .wr-cascader__opt-arrow{--wr-icon-size: .875rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted)}[dir=rtl] .wr-cascader-panel .wr-cascader__opt-arrow{transform:scaleX(-1)}@media(pointer:coarse){.wr-cascader__clear{--wr-icon-size: 1.125rem;width:2rem;height:2rem}.wr-cascader-panel .wr-cascader__opt{padding-top:.75rem;padding-bottom:.75rem}}\n"] }]
|
|
401
|
+
args: [{ selector: 'wr-cascader', encapsulation: ViewEncapsulation.None, host: { '[class]': 'classes()' }, template: "<button\n type=\"button\"\n class=\"wr-cascader__trigger\"\n role=\"combobox\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n [disabled]=\"disabled()\"\n [attr.aria-haspopup]=\"'tree'\"\n [attr.aria-expanded]=\"open()\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-readonly]=\"readonly() || null\"\n [attr.aria-invalid]=\"fieldAria.ariaInvalid()\"\n [attr.aria-describedby]=\"fieldAria.describedBy()\"\n (click)=\"onTriggerClick()\"\n (keydown)=\"onTriggerKeydown($event)\"\n (blur)=\"touch.emit()\"\n>\n @if (displayLabel(); as label) {\n <span class=\"wr-cascader__value\">{{ label }}</span>\n } @else {\n <span class=\"wr-cascader__placeholder\">{{ placeholder() }}</span>\n }\n\n @if (clearable() && hasSelection() && !disabled() && !readonly()) {\n <span\n class=\"wr-cascader__clear\"\n role=\"button\"\n [attr.aria-label]=\"resolvedClearLabel()\"\n tabindex=\"-1\"\n (click)=\"clearSelection($event)\"\n >\n <svg\n class=\"wr-icon__svg\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n </span>\n }\n\n <svg\n class=\"wr-icon__svg wr-cascader__chevron\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n</button>\n\n<ng-template #panelTpl>\n <div\n class=\"wr-cascader-panel\"\n [class.wr-cascader-panel--sm]=\"size() === 'sm'\"\n [class.wr-cascader-panel--lg]=\"size() === 'lg'\"\n role=\"tree\"\n [attr.id]=\"panelId\"\n [attr.aria-label]=\"resolvedAriaLabel()\"\n >\n <!--\n tree / group / treeitem, and NOT menu. A combobox's popup may be a listbox,\n a tree, a grid or a dialog and nothing else, so `aria-haspopup=\"menu\"` on\n the trigger was an author error \u2014 and a `menu` may own menuitems and\n groups, never other menus, so the columns were a second one. Neither is\n visible to axe: `menu` is a valid token for the global `aria-haspopup`, and\n `aria-required-children` passes a menu-inside-menu (measured against this\n exact fragment). A tree is what this control has always been \u2014 the value is\n a PATH, and only `treeitem` supports aria-expanded, aria-level,\n aria-setsize, aria-posinset and aria-selected at once.\n\n The columns stay `group` rather than collapsing to `role=\"presentation\"`,\n which is also axe-clean: the DOM is column-MAJOR, so a flat tree would\n leave level plus document order as the only structure, and \"Germany\"\n (level 2) would read as a child of \"Antarctica\" (level 1, the item\n immediately before it in source order).\n -->\n @for (col of columns(); track $index; let colIndex = $index) {\n <ul\n class=\"wr-cascader__col\"\n role=\"group\"\n [attr.id]=\"columnId(colIndex)\"\n [attr.aria-labelledby]=\"parentOptionId(colIndex)\"\n >\n @for (opt of col; track opt.value; let optIndex = $index) {\n <!--\n `aria-expanded` is exactly `isActiveAt`: `columns()` renders the next\n column for the active option and only when it has children, so the\n state can never claim a column that is not on screen \u2014 and\n `aria-controls` rides that same invariant, which is what makes\n \"expanded\" refer to something when the expanded content is a SIBLING\n rather than a descendant. It is emitted only while expanded: a\n reference to an absent id is a violation with `aria-expanded=\"true\"`\n and clean while collapsed.\n\n `aria-level` is load-bearing rather than decorative. The columns are\n siblings, so the DOM ancestry represents no level at all and every\n option would read as level 1. `aria-setsize` / `aria-posinset` are\n not strictly required \u2014 each column IS a complete sibling set \u2014 and\n are written anyway, because a tree that owns sibling groups is the\n uncommon shape where browser/AT pairs are known to miscompute both.\n\n `aria-selected` is written on every option that can be COMMITTED,\n `false` included, matching `wr-tree`. The alternative a reviewer may\n prefer: only the selected node, leaning on treeitem's implicit false,\n which is quieter in a long column and loses the \"this row is\n selectable\" signal that presence carries.\n -->\n <li\n class=\"wr-cascader__opt\"\n role=\"treeitem\"\n [attr.id]=\"optionId(colIndex, optIndex)\"\n [class.wr-cascader__opt--active]=\"isActiveAt(colIndex, opt.value)\"\n [class.wr-cascader__opt--disabled]=\"opt.disabled\"\n [attr.tabindex]=\"opt.disabled ? -1 : 0\"\n [attr.aria-disabled]=\"opt.disabled ? true : null\"\n [attr.aria-level]=\"colIndex + 1\"\n [attr.aria-setsize]=\"$count\"\n [attr.aria-posinset]=\"optIndex + 1\"\n [attr.aria-selected]=\"isSelectedAt(colIndex, opt)\"\n [attr.aria-expanded]=\"opt.children?.length ? isActiveAt(colIndex, opt.value) : null\"\n [attr.aria-controls]=\"\n opt.children?.length && isActiveAt(colIndex, opt.value) ? columnId(colIndex + 1) : null\n \"\n (click)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.enter)=\"onOptionClick(colIndex, opt, $event)\"\n (keydown.space)=\"onOptionClick(colIndex, opt, $event)\"\n >\n <span class=\"wr-cascader__opt-label\">{{ opt.label }}</span>\n @if (opt.children?.length) {\n <svg\n class=\"wr-icon__svg wr-cascader__opt-arrow\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n }\n </li>\n }\n </ul>\n }\n </div>\n</ng-template>\n", styles: [".wr-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-table__sort-btn:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-tabs__tab:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-sidebar__entry:focus-visible,.wr-sidebar__group-toggle:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-sidebar__item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-anchor__link:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-collapse__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo);outline-offset:-2px}.wr-command-palette__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-mention-panel__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-segmented__option:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-back-top:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-carousel__nav:focus-visible,.wr-carousel__dot:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-speed-dial__trigger:focus-visible,.wr-speed-dial__action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-stepper__header:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-window__chrome-action:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-date-picker__trigger:focus-visible,.wr-time-picker__step:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-dropdown-item:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-alert__close:focus-visible{outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader{--wr-cascader-color: var(--wr-color-on-surface);--wr-cascader-bg: var(--wr-color-surface);--wr-cascader-border: var(--wr-color-outline);--wr-cascader-radius: var(--wr-control-radius-md);--wr-cascader-padding-y: var(--wr-control-padding-y-md);--wr-cascader-padding-x: var(--wr-control-padding-x-md);--wr-cascader-font-size: var(--wr-control-font-size-md);--wr-cascader-line-height: var(--wr-control-line-height-md);--wr-cascader-col-width: 12rem;--wr-cascader-max-height: 16rem;--wr-cascader-min-width: 12rem;display:inline-flex;vertical-align:middle}.wr-cascader--disabled{--wr-cascader-color: var(--wr-color-on-surface-muted);--wr-cascader-bg: var(--wr-color-fill)}.wr-cascader--sm{--wr-cascader-radius: var(--wr-control-radius-sm);--wr-cascader-padding-y: var(--wr-control-padding-y-sm);--wr-cascader-padding-x: var(--wr-control-padding-x-sm);--wr-cascader-font-size: var(--wr-control-font-size-sm);--wr-cascader-line-height: var(--wr-control-line-height-sm)}.wr-cascader--lg{--wr-cascader-radius: var(--wr-control-radius-lg);--wr-cascader-padding-y: var(--wr-control-padding-y-lg);--wr-cascader-padding-x: var(--wr-control-padding-x-lg);--wr-cascader-font-size: var(--wr-control-font-size-lg);--wr-cascader-line-height: var(--wr-control-line-height-lg)}.wr-cascader__trigger{display:inline-flex;align-items:center;gap:.5rem;width:100%;min-width:var(--wr-cascader-min-width);appearance:none;background:var(--wr-cascader-bg);color:var(--wr-cascader-color);border:1px solid var(--wr-cascader-border);border-radius:var(--wr-cascader-radius);padding:calc(var(--wr-cascader-padding-y) * var(--wr-density-y, 1)) calc(var(--wr-cascader-padding-x) * var(--wr-density-x, 1));font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-font-size);line-height:var(--wr-cascader-line-height);cursor:pointer;text-align:start;transition:border-color var(--wr-transition-base),box-shadow var(--wr-transition-base)}.wr-cascader__trigger:focus-visible{border-color:var(--wr-color-primary);outline:var(--wr-focus-ring-width) solid var(--wr-focus-ring-color);outline-offset:var(--wr-focus-ring-offset);box-shadow:0 0 0 var(--wr-focus-ring-offset) var(--wr-focus-ring-halo)}.wr-cascader__trigger:disabled{cursor:not-allowed}.wr-cascader--readonly .wr-cascader__trigger{cursor:default}.wr-cascader--open .wr-cascader__trigger{border-color:var(--wr-color-primary);box-shadow:0 0 0 3px rgba(var(--wr-color-primary-rgb),.15)}.wr-cascader__value,.wr-cascader__placeholder{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader__placeholder{color:var(--wr-color-text-muted)}.wr-cascader__chevron{--wr-icon-size: 1rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted);transition:transform var(--wr-transition-base)}.wr-cascader--open .wr-cascader__chevron{transform:rotate(180deg)}.wr-cascader__clear{--wr-icon-size: .875rem;display:inline-flex;align-items:center;justify-content:center;width:1.125rem;height:1.125rem;border-radius:999px;color:var(--wr-color-on-surface-muted);cursor:pointer;transition:background .12s ease,color .12s ease}.wr-cascader__clear:hover{background:rgba(var(--wr-color-on-surface-rgb),.06);color:var(--wr-color-on-surface)}.wr-cascader-overlay{padding-top:.25rem}.wr-cascader-panel{--wr-cascader-opt-font: var(--wr-control-font-size-md);--wr-cascader-opt-py: .5rem;display:flex;background:var(--wr-color-surface);border:1px solid var(--wr-color-outline);border-radius:var(--wr-border-radius-base);box-shadow:var(--wr-shadow-overlay);font-family:var(--wr-font-family-base);font-size:var(--wr-cascader-opt-font);overflow:hidden}.wr-cascader-panel--sm{--wr-cascader-opt-font: var(--wr-control-font-size-sm);--wr-cascader-opt-py: .375rem}.wr-cascader-panel--lg{--wr-cascader-opt-font: var(--wr-control-font-size-lg);--wr-cascader-opt-py: .625rem}.wr-cascader-panel .wr-cascader__col{list-style:none;margin:0;padding:.25rem;width:var(--wr-cascader-col-width, 12rem);max-height:var(--wr-cascader-max-height, 16rem);overflow-y:auto;display:flex;flex-direction:column;gap:.125rem}.wr-cascader-panel .wr-cascader__col+.wr-cascader__col{border-inline-start:1px solid var(--wr-color-outline)}.wr-cascader-panel .wr-cascader__opt{display:flex;align-items:center;gap:.5rem;padding:var(--wr-cascader-opt-py) .625rem;border-radius:var(--wr-border-radius-sm);color:var(--wr-color-on-surface);cursor:pointer;transition:background var(--wr-transition-short)}.wr-cascader-panel .wr-cascader__opt:hover{background:var(--wr-color-hover)}.wr-cascader-panel .wr-cascader__opt--active{background:var(--wr-color-primary-soft);color:var(--wr-color-primary-ink);font-weight:500}.wr-cascader-panel .wr-cascader__opt--disabled{color:var(--wr-color-on-surface-muted);cursor:not-allowed;opacity:var(--wr-disabled-opacity)}.wr-cascader-panel .wr-cascader__opt--disabled:hover{background:transparent}.wr-cascader-panel .wr-cascader__opt-label{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.wr-cascader-panel .wr-cascader__opt-arrow{--wr-icon-size: .875rem;flex:0 0 auto;color:var(--wr-color-on-surface-muted)}[dir=rtl] .wr-cascader-panel .wr-cascader__opt-arrow{transform:scaleX(-1)}@media(pointer:coarse){.wr-cascader__clear{--wr-icon-size: 1.125rem;width:2rem;height:2rem}.wr-cascader-panel .wr-cascader__opt{padding-top:.75rem;padding-bottom:.75rem}}\n"] }]
|
|
343
402
|
}], ctorParameters: () => [], propDecorators: { clearLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearLabel", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], changeOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "changeOnSelect", required: false }] }], separator: [{ type: i0.Input, args: [{ isSignal: true, alias: "separator", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], touch: [{ type: i0.Output, args: ["touch"] }], panelTpl: [{ type: i0.ViewChild, args: ['panelTpl', { ...{ read: TemplateRef }, isSignal: true }] }] } });
|
|
344
403
|
|
|
345
404
|
/**
|