ngwr 14.3.1 → 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 +3 -3
- 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
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// `prefers-contrast: more` for the whole token layer.
|
|
2
|
+
//
|
|
3
|
+
// Why this lives in one file, next to `_motion.scss` and for the same reason:
|
|
4
|
+
// the thing being answered is a request the USER made of the operating system,
|
|
5
|
+
// about the page as a whole, and a component cannot answer it on its own. Every
|
|
6
|
+
// declaration below is a token, so a component that reads the tokens — which is
|
|
7
|
+
// all of them — comes along without being edited.
|
|
8
|
+
//
|
|
9
|
+
// What "more contrast" is being read to mean here, since the media query says
|
|
10
|
+
// nothing about how much: **AAA where the role is text (7:1), and the WCAG
|
|
11
|
+
// 1.4.11 bar where the role is a boundary (3:1)**. Those are the two numbers
|
|
12
|
+
// the default palette deliberately does not meet, each for a recorded reason.
|
|
13
|
+
//
|
|
14
|
+
// THE DE-EMPHASIS TIER IS WHAT HIGH CONTRAST SPENDS. `--wr-color-text-faint`
|
|
15
|
+
// and `--wr-color-text-muted` are the muted ink at 0.6 and 0.95 alpha, and
|
|
16
|
+
// under this query both go to 1.0 and collapse onto the deepened role. That is
|
|
17
|
+
// not a shortcut: 7:1 is UNREACHABLE at any alpha in the light theme, because
|
|
18
|
+
// the base itself only reaches 5.35:1 — the alpha is not the lever, the base
|
|
19
|
+
// is. Keeping a visibly fainter tier at 7:1 would need a base of `#353c46`,
|
|
20
|
+
// which measures 11.13:1 on its own and is no longer a muted role at all. A
|
|
21
|
+
// reader who asked for more contrast is asking for the tiers to close up.
|
|
22
|
+
//
|
|
23
|
+
// A LIVE DEFECT THIS EXPOSED, and it is not fixed here. At the default 0.6,
|
|
24
|
+
// `text-faint` measures **2.43:1** in light and 3.46:1 in dark, and its three
|
|
25
|
+
// consumers are an `input-otp` `::placeholder` (text, 1.4.3) plus the textarea
|
|
26
|
+
// resize grip and the avatar spinner (graphics, 1.4.11 → 3:1). All three fail
|
|
27
|
+
// today, in the DEFAULT theme, where `_colors.scss` calls them "decorative by
|
|
28
|
+
// design" — a resize affordance and a loading indicator are not decorative.
|
|
29
|
+
// High contrast repairs them incidentally; the default still needs a decision.
|
|
30
|
+
//
|
|
31
|
+
// TWO BLOCKS, NOT ONE, and this is the part that would silently half-work. A
|
|
32
|
+
// `@media { :root { … } }` resolves its `var()` references against the element
|
|
33
|
+
// it declares on, so a single `:root` block freezes LIGHT values into any
|
|
34
|
+
// subtree-scoped `[data-theme='dark']`. The dark half has to be declared on the
|
|
35
|
+
// dark selector itself.
|
|
36
|
+
//
|
|
37
|
+
// Every figure in the comments below is WCAG relative-luminance arithmetic on
|
|
38
|
+
// solid colours, which reproduces what axe measures. Figures involving an alpha
|
|
39
|
+
// composite are marked as such — those carry ±0.05 and the browser is the
|
|
40
|
+
// authority. `pnpm check:contrast --contrast=more` is that authority.
|
|
41
|
+
|
|
42
|
+
@use 'sass:map';
|
|
43
|
+
@use 'colors';
|
|
44
|
+
@use 'dark';
|
|
45
|
+
|
|
46
|
+
/// The `-ink` shares under high contrast.
|
|
47
|
+
///
|
|
48
|
+
/// `-ink` is text by definition, so the target moves from the default 5.0:1 to
|
|
49
|
+
/// AAA 7:1 — measured, as the default shares are, against the intent's own
|
|
50
|
+
/// `-soft` tint rather than the plain canvas, because the tint is the darker of
|
|
51
|
+
/// the two backgrounds `-ink` is documented for and therefore the binding one.
|
|
52
|
+
///
|
|
53
|
+
/// Each share is the MOST saturated value that still reaches 7:1 in BOTH
|
|
54
|
+
/// themes, so the binding theme decides it. Dark binds for six of the seven;
|
|
55
|
+
/// `warning` is the exception and binds on light, where white cannot reach it
|
|
56
|
+
/// at any tone worth shipping.
|
|
57
|
+
$ink-mix-more: (
|
|
58
|
+
primary: 53%,
|
|
59
|
+
secondary: 47%,
|
|
60
|
+
success: 55%,
|
|
61
|
+
warning: 36%,
|
|
62
|
+
danger: 53%,
|
|
63
|
+
info: 54%,
|
|
64
|
+
medium: 57%,
|
|
65
|
+
) !default;
|
|
66
|
+
|
|
67
|
+
@media (prefers-contrast: more) {
|
|
68
|
+
:root {
|
|
69
|
+
// 8.16:1 on the page, 7.07:1 on `#ebeff4` — the lightest surface the
|
|
70
|
+
// library paints, and the reference the rest of the theme layer solves
|
|
71
|
+
// against. The default `#5f6c7d` reaches 5.35 and 4.63 respectively.
|
|
72
|
+
--wr-color-muted-text: #47505d;
|
|
73
|
+
--wr-color-muted-text-rgb: 71, 80, 93;
|
|
74
|
+
|
|
75
|
+
// The de-emphasis tier closes up — see the note at the top of this file.
|
|
76
|
+
--wr-color-text-muted: rgba(var(--wr-color-muted-text-rgb), 1);
|
|
77
|
+
// unused-ok: the library paints with nothing at the faint strength any
|
|
78
|
+
// more — see the note at its declaration in `_colors.scss`. The override
|
|
79
|
+
// stays so a CONSUMER using the tier is carried into high contrast too.
|
|
80
|
+
--wr-color-text-faint: rgba(var(--wr-color-muted-text-rgb), 1);
|
|
81
|
+
|
|
82
|
+
// 3.47:1 on the page and 3.00:1 on `#ebeff4`, against the default
|
|
83
|
+
// `#cbd5e1`'s 1.48:1. This is the value AGENTS.md already records as the
|
|
84
|
+
// honest one, and the reason it is not the default is recorded there too:
|
|
85
|
+
// the token carries 103 declarations, only 15 of which are control
|
|
86
|
+
// boundaries that 1.4.11 reaches, and darkening all 103 was refused on how
|
|
87
|
+
// it looks. Under an explicit request for more contrast that trade flips —
|
|
88
|
+
// the reader has said which side they want.
|
|
89
|
+
--wr-color-outline: #718cad;
|
|
90
|
+
--wr-color-outline-rgb: 113, 140, 173;
|
|
91
|
+
|
|
92
|
+
@each $name, $share in $ink-mix-more {
|
|
93
|
+
--wr-color-#{$name}-ink: color-mix(in srgb, var(--wr-color-#{$name}) #{$share}, var(--wr-color-dark));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#{dark.dark-selector()} {
|
|
98
|
+
// 8.30:1 on the dark canvas. Dark needed far less than light — the default
|
|
99
|
+
// `#9aa6b8` already reaches 7.64 there and only misses on `fill-strong`,
|
|
100
|
+
// the harshest surface the library paints, which this closes.
|
|
101
|
+
--wr-color-muted-text: #a2adbe;
|
|
102
|
+
--wr-color-muted-text-rgb: 162, 173, 190;
|
|
103
|
+
|
|
104
|
+
--wr-color-text-muted: rgba(var(--wr-color-muted-text-rgb), 1);
|
|
105
|
+
// unused-ok: the library paints with nothing at the faint strength any
|
|
106
|
+
// more — see the note at its declaration in `_colors.scss`. The override
|
|
107
|
+
// stays so a CONSUMER using the tier is carried into high contrast too.
|
|
108
|
+
--wr-color-text-faint: rgba(var(--wr-color-muted-text-rgb), 1);
|
|
109
|
+
|
|
110
|
+
// 3.56:1 on the dark canvas, against the default `#262f44`'s 1.41:1.
|
|
111
|
+
--wr-color-outline: #566b9b;
|
|
112
|
+
--wr-color-outline-rgb: 86, 107, 155;
|
|
113
|
+
|
|
114
|
+
@each $name, $share in $ink-mix-more {
|
|
115
|
+
--wr-color-#{$name}-ink: color-mix(in srgb, var(--wr-color-#{$name}) #{$share}, var(--wr-color-dark));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Adding a tenth intent to `$base-colors` without a share here would leave it
|
|
121
|
+
// on its default ink under high contrast — a silent hole rather than a build
|
|
122
|
+
// error, which is the failure this repo keeps finding in its own claims. So the
|
|
123
|
+
// two lists are held together at COMPILE time.
|
|
124
|
+
//
|
|
125
|
+
// `light` and `dark` are excluded on both sides for the reason `_colors.scss`
|
|
126
|
+
// records: `light` is a surface tone with no darkening that stays recognisable
|
|
127
|
+
// AND readable, and `dark` already IS the ink.
|
|
128
|
+
@each $name, $seed in colors.$base-colors {
|
|
129
|
+
@if $name != 'light' and $name != 'dark' {
|
|
130
|
+
@if not map.has-key($ink-mix-more, $name) {
|
|
131
|
+
@error 'No high-contrast ink share for intent `#{$name}`. Add one to ' +
|
|
132
|
+
'`$ink-mix-more` in theme/styles/_contrast.scss, derived at 7:1 against ' +
|
|
133
|
+
'that intent\'s own `-soft` tint in whichever theme binds.';
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
package/theme/styles/_index.scss
CHANGED
|
@@ -5,15 +5,22 @@
|
|
|
5
5
|
// .thing { @include wr.smooth-br(0.625rem); }
|
|
6
6
|
|
|
7
7
|
/// Smooth border-radius — opts into the native `corner-shape: squircle`
|
|
8
|
-
///
|
|
9
|
-
///
|
|
8
|
+
/// when the browser supports it, and falls back to a plain
|
|
9
|
+
/// `border-radius` when it does not.
|
|
10
10
|
///
|
|
11
|
-
/// **
|
|
12
|
-
///
|
|
13
|
-
///
|
|
14
|
-
///
|
|
15
|
-
///
|
|
16
|
-
///
|
|
11
|
+
/// **This is the one place that describes the support picture, on
|
|
12
|
+
/// purpose.** Six files used to name a Chrome version in a comment, all
|
|
13
|
+
/// six naming the wrong one — the property shipped four releases before
|
|
14
|
+
/// the number they quoted. A version in a comment is a claim nobody
|
|
15
|
+
/// re-checks, so the comments elsewhere now say "where supported" and
|
|
16
|
+
/// point here.
|
|
17
|
+
///
|
|
18
|
+
/// Where it stands: Chromium has shipped it since 139, WebKit has it in
|
|
19
|
+
/// Technology Preview, Gecko does not have it yet. That is why the
|
|
20
|
+
/// `@supports` guard below is the contract rather than a courtesy — a
|
|
21
|
+
/// browser without the property gets the rounded corner it would have
|
|
22
|
+
/// had anyway, and nothing an app relies on changes. There is no state
|
|
23
|
+
/// in which a consumer has to do something about this.
|
|
17
24
|
///
|
|
18
25
|
/// `corner-shape: squircle` renders a continuous-curvature corner (iOS /
|
|
19
26
|
/// macOS style) instead of a circular arc. The squircle reads as
|
|
@@ -40,21 +40,48 @@
|
|
|
40
40
|
z-index: 1;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
// Each intent gets a SILHOUETTE, because the dot is an empty 12px span with
|
|
44
|
+
// no glyph and nothing beside it that names the state: `title` and `time` are
|
|
45
|
+
// both optional, so an item written as `<wr-timeline-item color="danger">`
|
|
46
|
+
// may carry no text of its own at all. Colour cannot do the work here —
|
|
47
|
+
// success, danger and medium sit within 1.006:1 of each other in dark and
|
|
48
|
+
// 1.006:1 in light, and success against danger is 1.004:1.
|
|
49
|
+
//
|
|
50
|
+
// The shapes follow the vocabulary the library already uses: a triangle is a
|
|
51
|
+
// warning in `wr-alert` and `wr-result`, so it is a warning here. The base
|
|
52
|
+
// dot stays a plain circle on purpose — it means "no intent given", and the
|
|
53
|
+
// quietest shape is the right one for it.
|
|
43
54
|
&--success &__dot {
|
|
55
|
+
// A filled block: finished.
|
|
56
|
+
border-radius: 2px;
|
|
44
57
|
background: var(--wr-color-success);
|
|
45
58
|
}
|
|
46
59
|
|
|
47
60
|
&--warning &__dot {
|
|
61
|
+
clip-path: polygon(50% 0%, 100% 100%, 0% 100%);
|
|
62
|
+
border-radius: 0;
|
|
48
63
|
background: var(--wr-color-warning);
|
|
49
64
|
}
|
|
50
65
|
|
|
51
66
|
&--danger &__dot {
|
|
67
|
+
// A diamond — the loudest silhouette at this size, and unmistakable
|
|
68
|
+
// against the square and the triangle above it.
|
|
69
|
+
rotate: 45deg;
|
|
70
|
+
border-radius: 2px;
|
|
52
71
|
background: var(--wr-color-danger);
|
|
53
72
|
}
|
|
54
73
|
|
|
74
|
+
// color-ok: `background: transparent` plus an inset ring makes this dot
|
|
75
|
+
// HOLLOW — a silhouette, like the three above it. Both declarations happen
|
|
76
|
+
// to be colour-valued, which is the one shape this gate cannot read.
|
|
55
77
|
&--medium &__dot {
|
|
78
|
+
// Hollow, which reads as the quiet one. The second shadow keeps the 2px
|
|
79
|
+
// surface halo every dot carries, so the ring does not swallow it.
|
|
56
80
|
// The `color="medium"` INTENT, not the muted-text role — keep the literal.
|
|
57
|
-
background:
|
|
81
|
+
background: transparent;
|
|
82
|
+
box-shadow:
|
|
83
|
+
inset 0 0 0 2px var(--wr-color-medium),
|
|
84
|
+
0 0 0 2px var(--wr-color-surface);
|
|
58
85
|
}
|
|
59
86
|
|
|
60
87
|
&__body {
|
package/toast/styles/_index.scss
CHANGED
|
@@ -155,6 +155,17 @@ $toast-colors: (
|
|
|
155
155
|
animation: wr-toast-in 0.18s ease-out;
|
|
156
156
|
overflow: hidden;
|
|
157
157
|
|
|
158
|
+
// The status glyph. Sized off the title's line box so it reads as part of the
|
|
159
|
+
// first line rather than floating above it, and inked with the accent the
|
|
160
|
+
// type already carries — the SHAPE is the channel, the colour reinforces it.
|
|
161
|
+
&__icon {
|
|
162
|
+
flex: 0 0 auto;
|
|
163
|
+
width: 1.125rem;
|
|
164
|
+
height: 1.125rem;
|
|
165
|
+
margin-block-start: 0.0625rem;
|
|
166
|
+
color: var(--wr-toast-accent);
|
|
167
|
+
}
|
|
168
|
+
|
|
158
169
|
&__body {
|
|
159
170
|
flex: 1 1 auto;
|
|
160
171
|
min-width: 0;
|
package/tree/styles/_index.scss
CHANGED
|
@@ -24,6 +24,9 @@
|
|
|
24
24
|
cursor: pointer;
|
|
25
25
|
user-select: none;
|
|
26
26
|
outline: 0;
|
|
27
|
+
// Positioning context for the `--active` cursor bar below. Nothing inside
|
|
28
|
+
// a row is absolutely positioned, so this establishes one for that alone.
|
|
29
|
+
position: relative;
|
|
27
30
|
transition:
|
|
28
31
|
background var(--wr-transition-base),
|
|
29
32
|
color var(--wr-transition-base);
|
|
@@ -32,8 +35,13 @@
|
|
|
32
35
|
background: var(--wr-color-hover);
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
// A selected row had nothing but the tint, and `wr-tree` — unlike its
|
|
39
|
+
// sibling data view `wr-table` — ships NO checkbox mode, so in
|
|
40
|
+
// `selectionMode="multiple"` any number of rows were marked by a 1.17:1
|
|
41
|
+
// wash and nothing else. The weight is what a reader without hue has.
|
|
35
42
|
&--selected {
|
|
36
43
|
background: var(--wr-color-primary-soft);
|
|
44
|
+
font-weight: var(--wr-font-weight-medium);
|
|
37
45
|
// Text on the `-soft` tint: `-ink`. Bare measured 4.19:1 light / 3.63:1 dark.
|
|
38
46
|
color: var(--wr-color-primary-ink);
|
|
39
47
|
}
|
|
@@ -50,9 +58,24 @@
|
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
// Active-descendant cursor when virtualized — focus lives on the list
|
|
53
|
-
// container, so the "current" row
|
|
61
|
+
// container, so the "current" row cannot use the focus ring.
|
|
62
|
+
//
|
|
63
|
+
// The tint alone was the byte-identical declaration `:hover` uses above,
|
|
64
|
+
// which made the keyboard cursor indistinguishable from a mouse resting on
|
|
65
|
+
// another row. The bar is what separates them, and it is a shape rather
|
|
66
|
+
// than a colour so a selected row (also a tint) stays distinct too.
|
|
54
67
|
&--active {
|
|
55
68
|
background: var(--wr-color-hover);
|
|
69
|
+
|
|
70
|
+
&::before {
|
|
71
|
+
content: '';
|
|
72
|
+
position: absolute;
|
|
73
|
+
inset-block: 0;
|
|
74
|
+
inset-inline-start: 0;
|
|
75
|
+
width: 2px;
|
|
76
|
+
border-radius: inherit;
|
|
77
|
+
background: var(--wr-color-primary);
|
|
78
|
+
}
|
|
56
79
|
}
|
|
57
80
|
}
|
|
58
81
|
|
|
@@ -205,6 +228,9 @@
|
|
|
205
228
|
}
|
|
206
229
|
}
|
|
207
230
|
|
|
231
|
+
// color-ok: opening attaches the panel and flips the chevron 180deg, so the
|
|
232
|
+
// state is a thing appearing and a glyph rotating; this only tints the edge
|
|
233
|
+
// underneath both.
|
|
208
234
|
&--open &__trigger {
|
|
209
235
|
border-color: var(--wr-color-primary);
|
|
210
236
|
box-shadow: 0 0 0 3px rgba(var(--wr-color-primary-rgb), 0.15);
|
package/types/ngwr-badge.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ import * as _angular_core from '@angular/core';
|
|
|
12
12
|
* - `rounded` (default) — small radius, matches the rest of the form vocabulary.
|
|
13
13
|
* - `pill` — fully rounded ends; common for count chips and status pills.
|
|
14
14
|
* - `squircle` — iOS-style continuous-curvature corners via the
|
|
15
|
-
* `corner-shape: squircle` CSS spec (
|
|
15
|
+
* `corner-shape: squircle` CSS spec (where supported, falls back to a
|
|
16
16
|
* plain rounded corner elsewhere).
|
|
17
17
|
*/
|
|
18
18
|
type WrBadgeShape = 'rounded' | 'pill' | 'squircle';
|
|
@@ -77,7 +77,17 @@ declare class WrBarChartHarness extends ComponentHarness {
|
|
|
77
77
|
getBarCount(): Promise<number>;
|
|
78
78
|
/** Whether the values are printed above the bars (`showValues`). */
|
|
79
79
|
hasValues(): Promise<boolean>;
|
|
80
|
-
/**
|
|
80
|
+
/**
|
|
81
|
+
* The plot's height in pixels, read off the `style` ATTRIBUTE.
|
|
82
|
+
*
|
|
83
|
+
* NOT `getCssValue()`, which is `getComputedStyle()` — the same rule this
|
|
84
|
+
* file's class note already states and this method alone broke. A computed
|
|
85
|
+
* read answers from the LAID-OUT box, so it agrees with the inline value in
|
|
86
|
+
* jsdom (which lays nothing out and echoes the declaration) and disagrees in a
|
|
87
|
+
* browser, where sub-pixel rounding turns a declared 240 into 239.5. A harness
|
|
88
|
+
* that answers differently in the two places it runs is worse than one that
|
|
89
|
+
* refuses.
|
|
90
|
+
*/
|
|
81
91
|
getPlotHeight(): Promise<number>;
|
|
82
92
|
}
|
|
83
93
|
|
package/types/ngwr-button.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ type WrButtonSize = 'sm' | 'md' | 'lg';
|
|
|
24
24
|
* - `rounded` (default) — small radius, matches the rest of the form vocabulary.
|
|
25
25
|
* - `pill` — fully rounded ends; ideal for solitary CTAs.
|
|
26
26
|
* - `squircle` — iOS-style continuous-curvature corners via the
|
|
27
|
-
* `corner-shape: squircle` CSS spec (
|
|
27
|
+
* `corner-shape: squircle` CSS spec (where supported, falls back to a
|
|
28
28
|
* plain rounded corner elsewhere). For a deterministic
|
|
29
29
|
* clip-path-based squircle that works across browsers, wrap the
|
|
30
30
|
* button in `[wrSquircle]` instead.
|
|
@@ -36,9 +36,14 @@ interface WrCalendarHeatmapCell {
|
|
|
36
36
|
*
|
|
37
37
|
* **Every square is `aria-hidden`, and that is the design.** The grid is one
|
|
38
38
|
* `role="img"` with a name; a year of individually announced days would be unusable
|
|
39
|
-
* with a screen reader. What each square carries instead is
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* with a screen reader. What each square carries instead is `data-date` and
|
|
40
|
+
* `data-value`, which is what {@link getCells} reads.
|
|
41
|
+
*
|
|
42
|
+
* NOT the `title`, which it used to parse. The tooltip is human-facing text now
|
|
43
|
+
* — the date formatted for the reader's locale, the count through
|
|
44
|
+
* `Intl.NumberFormat`, and the sentence composed in the catalog — so parsing it
|
|
45
|
+
* would have made every assertion here depend on the locale the suite happens to
|
|
46
|
+
* run under, and on wording a translator is free to change.
|
|
42
47
|
*
|
|
43
48
|
* **Four of the seven weekday labels are blank on purpose**: seven do not fit beside
|
|
44
49
|
* a grid this dense. {@link getWeekdayLabels} returns them as they are, empties
|
|
@@ -61,8 +66,8 @@ declare class WrCalendarHeatmapHarness extends ComponentHarness {
|
|
|
61
66
|
/**
|
|
62
67
|
* Every square, from its tooltip and its grid placement.
|
|
63
68
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
69
|
+
* Read from `data-date` / `data-value`, which the component writes for exactly
|
|
70
|
+
* this. Everything else about a square is colour.
|
|
66
71
|
*/
|
|
67
72
|
getCells(): Promise<WrCalendarHeatmapCell[]>;
|
|
68
73
|
/** The value a given ISO date's square reports, or `null` when that day is not drawn. */
|
|
@@ -8,6 +8,8 @@ interface WrHeatmapDatum {
|
|
|
8
8
|
|
|
9
9
|
interface Cell {
|
|
10
10
|
readonly iso: string;
|
|
11
|
+
/** The day as the reader's locale writes it — see `cellTitle`. */
|
|
12
|
+
readonly date: Date;
|
|
11
13
|
readonly value: number;
|
|
12
14
|
readonly intensity: number;
|
|
13
15
|
readonly week: number;
|
|
@@ -34,6 +36,26 @@ declare class WrCalendarHeatmap {
|
|
|
34
36
|
*/
|
|
35
37
|
readonly ariaLabel: _angular_core.InputSignal<string | null>;
|
|
36
38
|
protected readonly resolvedAriaLabel: _angular_core.Signal<string>;
|
|
39
|
+
private readonly cellText;
|
|
40
|
+
/**
|
|
41
|
+
* A cell's tooltip, with both halves formatted and the sentence in the catalog.
|
|
42
|
+
*
|
|
43
|
+
* It used to be `` `${cell.iso}: ${cell.value}` `` — a raw ISO date beside an
|
|
44
|
+
* unformatted number, joined by a hard-coded `': '`. Three things were wrong
|
|
45
|
+
* at once and none of them are visible from the template: `2026-09-10` is not
|
|
46
|
+
* how most of the world writes a date, `1234` is not how every locale groups
|
|
47
|
+
* digits (`ar-SA` does not even use these ones), and the separator and order
|
|
48
|
+
* were frozen into a shape a translator could not reach.
|
|
49
|
+
*
|
|
50
|
+
* Both halves go through `Intl` on the SAME locale the rest of the component
|
|
51
|
+
* resolves — `WR_DATE_LOCALE`, which since v14 follows Angular's `LOCALE_ID`.
|
|
52
|
+
* The key ships as `{{date}}: {{count}}` everywhere, so nothing reorders today
|
|
53
|
+
* and every locale can.
|
|
54
|
+
*/
|
|
55
|
+
protected cellTitle(cell: {
|
|
56
|
+
readonly date: Date;
|
|
57
|
+
readonly value: number;
|
|
58
|
+
}): string;
|
|
37
59
|
/** Last day to render. @default today */
|
|
38
60
|
readonly endDate: _angular_core.InputSignal<string | Date | null>;
|
|
39
61
|
/** Number of weeks (columns) to render. @default 53 */
|
package/types/ngwr-calendar.d.ts
CHANGED
|
@@ -170,7 +170,28 @@ declare class WrCalendar {
|
|
|
170
170
|
protected next(): void;
|
|
171
171
|
/** Header label click — zooms out (`day → month → year`). No-op at year view. */
|
|
172
172
|
protected onLabelClick(): void;
|
|
173
|
+
/**
|
|
174
|
+
* Picking a month drops to the day grid — and takes real focus with it.
|
|
175
|
+
*
|
|
176
|
+
* The `@switch (viewMode())` in the template destroys the chip that holds DOM
|
|
177
|
+
* focus, so without the two lines below `document.activeElement` became
|
|
178
|
+
* `<body>`: the ring appeared on the new view and focus did not, the arrow
|
|
179
|
+
* keys went dead (the keydown handler is a HOST binding, so nothing reaches
|
|
180
|
+
* the component from `<body>`), and the next Tab restarted from the top of the
|
|
181
|
+
* document — out of the calendar entirely. It is the same trap the two
|
|
182
|
+
* keyboard paths in this file already fix, and for the same reason
|
|
183
|
+
* `afterNextRender` rather than `queueMicrotask`: under zoneless CD the
|
|
184
|
+
* microtask runs before the new view is in the DOM.
|
|
185
|
+
*
|
|
186
|
+
* `focusedDate` has to move too, and that half is easy to miss. The grid marks
|
|
187
|
+
* its focusable cell by comparing against `focusedDate`, not `viewDate`, so
|
|
188
|
+
* choosing a DIFFERENT month rendered a grid with no `--focused` cell and no
|
|
189
|
+
* `tabindex="0"` at all — unreachable by keyboard from either direction. The
|
|
190
|
+
* day is preserved when the month already holds it and otherwise falls to the
|
|
191
|
+
* first, which is where `viewDate` lands anyway.
|
|
192
|
+
*/
|
|
173
193
|
protected onMonthSelect(monthIdx: number): void;
|
|
194
|
+
/** Year → month view, with the same focus restoration; the landing view is chips. */
|
|
174
195
|
protected onYearSelect(year: number): void;
|
|
175
196
|
/**
|
|
176
197
|
* Switch views and drop the chip ring with them.
|
|
@@ -56,21 +56,25 @@ interface WrCascaderOptionHarnessFilters extends BaseHarnessFilters {
|
|
|
56
56
|
*
|
|
57
57
|
* An option is either a BRANCH (it has children, so clicking it opens the next
|
|
58
58
|
* column) or a LEAF (clicking it commits the whole path and closes the panel).
|
|
59
|
-
* {@link hasChildren}
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
59
|
+
* {@link hasChildren} reads the chevron the template draws for branches;
|
|
60
|
+
* {@link isExpanded} reads the state that same branch announces. The two are
|
|
61
|
+
* not one question — a branch always HAS children and is expanded only while
|
|
62
|
+
* the column to its right is showing them.
|
|
63
|
+
*
|
|
64
|
+
* The panel is a `role="tree"` and an option is a `treeitem`. It was a `menu`
|
|
65
|
+
* of `menuitem`s until the roles were corrected, and this class documented that
|
|
66
|
+
* a branch announced nothing at all; both are historical now.
|
|
63
67
|
*
|
|
64
68
|
* @see https://ngwr.dev/guides/testing
|
|
65
69
|
*/
|
|
66
70
|
declare class WrCascaderOptionHarness extends ComponentHarness {
|
|
67
|
-
/** The `<li role="
|
|
71
|
+
/** The `<li role="treeitem">` a column renders per option. */
|
|
68
72
|
static hostSelector: string;
|
|
69
73
|
/** Build a predicate that narrows the query. */
|
|
70
74
|
static with(options?: WrCascaderOptionHarnessFilters): HarnessPredicate<WrCascaderOptionHarness>;
|
|
71
75
|
/** The option's label, trimmed. The branch chevron contributes no text. */
|
|
72
76
|
getText(): Promise<string>;
|
|
73
|
-
/** The role the option announces — `
|
|
77
|
+
/** The role the option announces — `treeitem`. */
|
|
74
78
|
getRole(): Promise<string | null>;
|
|
75
79
|
/** Whether the option refuses selection, from the state a screen reader is given. */
|
|
76
80
|
isDisabled(): Promise<boolean>;
|
|
@@ -79,11 +83,40 @@ declare class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
79
83
|
* whose children the column to the right is showing, or the committed segment
|
|
80
84
|
* at this level.
|
|
81
85
|
*
|
|
82
|
-
* Read from the `--active` modifier
|
|
83
|
-
*
|
|
84
|
-
*
|
|
86
|
+
* Read from the `--active` modifier, and NOT the same question as
|
|
87
|
+
* {@link isSelected}: this one tracks where the user has navigated, that one
|
|
88
|
+
* tracks what they committed. They agree only once a leaf is picked, and a
|
|
89
|
+
* harness that collapsed them would hide exactly the divergence it exists to
|
|
90
|
+
* catch.
|
|
85
91
|
*/
|
|
86
92
|
isActive(): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* Whether this option is the committed choice, or `null` when it is not a
|
|
95
|
+
* choice at all.
|
|
96
|
+
*
|
|
97
|
+
* `null` — the attribute absent — for a branch while `changeOnSelect` is off,
|
|
98
|
+
* because such a branch genuinely cannot be chosen. Answering a plausible
|
|
99
|
+
* `false` there would report an unselectable row as merely unselected, which
|
|
100
|
+
* is the distinction the attribute exists to carry.
|
|
101
|
+
*/
|
|
102
|
+
isSelected(): Promise<boolean | null>;
|
|
103
|
+
/**
|
|
104
|
+
* Whether this branch's children are the column to its right, or `null` for a
|
|
105
|
+
* leaf.
|
|
106
|
+
*
|
|
107
|
+
* `null` rather than `false`, and the difference is the whole point: a leaf
|
|
108
|
+
* does not have a collapsed subtree, it has none. `aria-expanded="false"` on
|
|
109
|
+
* one would state that a subtree exists and is shut.
|
|
110
|
+
*/
|
|
111
|
+
isExpanded(): Promise<boolean | null>;
|
|
112
|
+
/**
|
|
113
|
+
* The option's depth, 1-based — its `aria-level`.
|
|
114
|
+
*
|
|
115
|
+
* Worth reading in a spec rather than trusting: the columns are DOM SIBLINGS,
|
|
116
|
+
* so nothing about the markup's shape carries depth. Every option would be
|
|
117
|
+
* level 1 if this attribute were dropped, and no gate would say so.
|
|
118
|
+
*/
|
|
119
|
+
getLevel(): Promise<number | null>;
|
|
87
120
|
/** Whether the option opens a deeper level rather than ending the path. */
|
|
88
121
|
hasChildren(): Promise<boolean>;
|
|
89
122
|
/**
|
|
@@ -117,10 +150,10 @@ declare class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
117
150
|
* This is the component's entire keyboard model — the columns bind
|
|
118
151
|
* `keydown.enter` / `keydown.space` per option and nothing else, so there are
|
|
119
152
|
* no arrow keys to walk levels with. A keyboard user reaches the option they
|
|
120
|
-
* want with Tab and presses Enter
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
153
|
+
* want with Tab and presses Enter. Opening the panel does move focus into it —
|
|
154
|
+
* `focusPanelOption()` lands on the active option, or the first enabled one —
|
|
155
|
+
* so the walk starts there rather than from the trigger; this JSDoc claimed
|
|
156
|
+
* the opposite for a while and was simply wrong.
|
|
124
157
|
*/
|
|
125
158
|
selectByKeyboard(): Promise<void>;
|
|
126
159
|
/**
|
|
@@ -165,11 +198,11 @@ declare class WrCascaderOptionHarness extends ComponentHarness {
|
|
|
165
198
|
* @see https://ngwr.dev/guides/testing
|
|
166
199
|
*/
|
|
167
200
|
declare class WrCascaderColumnHarness extends ComponentHarness {
|
|
168
|
-
/** The `<ul role="
|
|
201
|
+
/** The `<ul role="group">` the panel renders per level, inside the `tree`. */
|
|
169
202
|
static hostSelector: string;
|
|
170
203
|
/** Build a predicate that narrows the query. */
|
|
171
204
|
static with(options?: WrCascaderColumnHarnessFilters): HarnessPredicate<WrCascaderColumnHarness>;
|
|
172
|
-
/** The role the column announces — `
|
|
205
|
+
/** The role the column announces — `group`, inside the panel's `tree`. */
|
|
173
206
|
getRole(): Promise<string | null>;
|
|
174
207
|
/** The options this level offers, in order. */
|
|
175
208
|
getOptions(filters?: WrCascaderOptionHarnessFilters): Promise<WrCascaderOptionHarness[]>;
|
|
@@ -269,9 +302,16 @@ declare class WrCascaderHarness extends ComponentHarness {
|
|
|
269
302
|
* nothing selected and no placeholder would otherwise have no name at all.
|
|
270
303
|
*/
|
|
271
304
|
getAccessibleName(): Promise<string | null>;
|
|
272
|
-
/**
|
|
305
|
+
/**
|
|
306
|
+
* The kind of popup the trigger promises via `aria-haspopup` — `tree`.
|
|
307
|
+
*
|
|
308
|
+
* Worth pinning rather than assuming: a combobox's popup may be a listbox, a
|
|
309
|
+
* tree, a grid or a dialog and nothing else, and this one said `menu` for a
|
|
310
|
+
* long time. `menu` is a valid token for the global `aria-haspopup`, so axe
|
|
311
|
+
* reports nothing either way — an assertion here is the only guard there is.
|
|
312
|
+
*/
|
|
273
313
|
getPopupRole(): Promise<string | null>;
|
|
274
|
-
/** The role the panel announces — `
|
|
314
|
+
/** The role the panel announces — `tree`, matching what the trigger promised. */
|
|
275
315
|
getPanelRole(): Promise<string | null>;
|
|
276
316
|
/**
|
|
277
317
|
* The id the trigger publishes as `aria-controls`.
|
|
@@ -368,6 +408,23 @@ declare class WrCascaderHarness extends ComponentHarness {
|
|
|
368
408
|
* rendered at all in either case (nor while disabled).
|
|
369
409
|
*/
|
|
370
410
|
clear(): Promise<void>;
|
|
411
|
+
/**
|
|
412
|
+
* Clear from the keyboard — Backspace on the closed trigger.
|
|
413
|
+
*
|
|
414
|
+
* The × {@link clear} clicks is a `tabindex="-1"` span inside the trigger, so no
|
|
415
|
+
* key can ever reach it; Backspace on the trigger is its keyboard twin, and the
|
|
416
|
+
* route a keyboard-only user actually has. Prefer this one in a spec that cares
|
|
417
|
+
* about that user — {@link clear} proves the pointer path and nothing more.
|
|
418
|
+
*
|
|
419
|
+
* The component honours the key only on the CLOSED trigger, so an open panel
|
|
420
|
+
* is closed first with Escape — the step a keyboard user takes too. Sending
|
|
421
|
+
* Backspace into an open panel and returning would be a plausible nothing.
|
|
422
|
+
*
|
|
423
|
+
* Does nothing, rather than throwing, when there is nothing to clear, `clearable`
|
|
424
|
+
* is off, or the cascader is disabled or read-only: that silence IS the
|
|
425
|
+
* component's contract, so a spec asserts it on the value.
|
|
426
|
+
*/
|
|
427
|
+
clearByKeyboard(): Promise<void>;
|
|
371
428
|
/** Move keyboard focus to the trigger. */
|
|
372
429
|
focus(): Promise<void>;
|
|
373
430
|
/** Take focus off the trigger, which is what makes a bound form field touched. */
|
package/types/ngwr-cascader.d.ts
CHANGED
|
@@ -148,6 +148,34 @@ declare class WrCascader<T = string> implements FormValueControl<unknown> {
|
|
|
148
148
|
protected onOptionClick(colIndex: number, opt: WrCascaderOption<T>, event: Event): void;
|
|
149
149
|
protected clearSelection(event: Event): void;
|
|
150
150
|
protected isActiveAt(colIndex: number, value: T): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Whether this option is the committed choice — `null` when it is not a
|
|
153
|
+
* choice at all.
|
|
154
|
+
*
|
|
155
|
+
* Two questions the panel has to keep apart, and `--active` answers only the
|
|
156
|
+
* first: `activePath()` is where the user has NAVIGATED to, `path()` is what
|
|
157
|
+
* they have COMMITTED. They agree once a leaf is picked and diverge for the
|
|
158
|
+
* whole walk down.
|
|
159
|
+
*
|
|
160
|
+
* `null` — the attribute absent — on a branch while `changeOnSelect` is off,
|
|
161
|
+
* because such a branch genuinely cannot be chosen; ARIA reads a missing
|
|
162
|
+
* `aria-selected` as "not selectable", which is exactly true here. That makes
|
|
163
|
+
* this binding the first expression the `changeOnSelect` contract has ever had
|
|
164
|
+
* in ARIA, in both directions.
|
|
165
|
+
*/
|
|
166
|
+
protected isSelectedAt(colIndex: number, opt: WrCascaderOption<T>): boolean | null;
|
|
167
|
+
/** Stable id for one option — what a column's `aria-labelledby` points at. */
|
|
168
|
+
protected optionId(colIndex: number, optIndex: number): string;
|
|
169
|
+
/** Stable id for one column — what an expanded branch's `aria-controls` points at. */
|
|
170
|
+
protected columnId(colIndex: number): string;
|
|
171
|
+
/**
|
|
172
|
+
* The option whose children a column holds, by id — its accessible name.
|
|
173
|
+
*
|
|
174
|
+
* The columns are DOM SIBLINGS, so nothing in the markup says the second one
|
|
175
|
+
* belongs to "Europe". Column 0 has no parent and stays unnamed; the tree
|
|
176
|
+
* itself already carries the control's name.
|
|
177
|
+
*/
|
|
178
|
+
protected parentOptionId(colIndex: number): string | null;
|
|
151
179
|
private pathsEqual;
|
|
152
180
|
private openOverlay;
|
|
153
181
|
/**
|
|
@@ -61,7 +61,18 @@ declare class WrCheckboxHarness extends ComponentHarness {
|
|
|
61
61
|
*/
|
|
62
62
|
isIndeterminate(): Promise<boolean>;
|
|
63
63
|
isDisabled(): Promise<boolean>;
|
|
64
|
-
/**
|
|
64
|
+
/**
|
|
65
|
+
* The group identity — `checkboxValue`, not the form value.
|
|
66
|
+
*
|
|
67
|
+
* Read off the host's `data-checkbox-value`, which the component reflects for
|
|
68
|
+
* exactly this. It used to read `value` from the inner `<input>`, an attribute
|
|
69
|
+
* nothing writes, so it answered `null` for every checkbox whatever its
|
|
70
|
+
* identity — the shape these harnesses are not allowed to have.
|
|
71
|
+
*
|
|
72
|
+
* `null` still means one honest thing: no identity, or an identity that is not
|
|
73
|
+
* a primitive. An object or an array has no attribute form, and a harness
|
|
74
|
+
* cannot reach a TypeScript value the DOM never carried.
|
|
75
|
+
*/
|
|
65
76
|
getCheckboxValue(): Promise<string | null>;
|
|
66
77
|
/** Flip the box. A disabled checkbox does not move; assert rather than assume. */
|
|
67
78
|
toggle(): Promise<void>;
|