@cdevhub/ngx-tw 0.4.0 → 0.6.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 +78 -15
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs +16 -5
- package/fesm2022/cdevhub-ngx-tw-accordion.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs +26 -15
- package/fesm2022/cdevhub-ngx-tw-avatar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-badge.mjs +17 -5
- package/fesm2022/cdevhub-ngx-tw-badge.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs +27 -6
- package/fesm2022/cdevhub-ngx-tw-breadcrumbs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-button.mjs +23 -11
- package/fesm2022/cdevhub-ngx-tw-button.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs +5 -5
- package/fesm2022/cdevhub-ngx-tw-calendar-luxon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs +3 -3
- package/fesm2022/cdevhub-ngx-tw-calendar-testing.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs +427 -122
- package/fesm2022/cdevhub-ngx-tw-calendar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-card.mjs +21 -11
- package/fesm2022/cdevhub-ngx-tw-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs +215 -96
- package/fesm2022/cdevhub-ngx-tw-carousel.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs +108 -64
- package/fesm2022/cdevhub-ngx-tw-checkbox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs +18 -6
- package/fesm2022/cdevhub-ngx-tw-code-block.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs +55 -30
- package/fesm2022/cdevhub-ngx-tw-collapsible.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs +218 -0
- package/fesm2022/cdevhub-ngx-tw-combobox-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs +236 -211
- package/fesm2022/cdevhub-ngx-tw-combobox.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs +200 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs +34 -7
- package/fesm2022/cdevhub-ngx-tw-command-palette.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-core.mjs +135 -15
- package/fesm2022/cdevhub-ngx-tw-core.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs +203 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs +160 -102
- package/fesm2022/cdevhub-ngx-tw-date-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs +209 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs +182 -107
- package/fesm2022/cdevhub-ngx-tw-date-range-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs +198 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-dialog-renderer-DoIhoV3d.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs +122 -0
- package/fesm2022/cdevhub-ngx-tw-dialog-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs +199 -220
- package/fesm2022/cdevhub-ngx-tw-dialog.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-empty-state.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs +149 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs +57 -67
- package/fesm2022/cdevhub-ngx-tw-file-upload.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs +42 -24
- package/fesm2022/cdevhub-ngx-tw-flip-card.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs +114 -21
- package/fesm2022/cdevhub-ngx-tw-form-field.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-icon.mjs +16 -6
- package/fesm2022/cdevhub-ngx-tw-icon.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-input.mjs +52 -61
- package/fesm2022/cdevhub-ngx-tw-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-item.mjs +18 -3
- package/fesm2022/cdevhub-ngx-tw-item.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs +168 -0
- package/fesm2022/cdevhub-ngx-tw-menu-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-menu.mjs +58 -21
- package/fesm2022/cdevhub-ngx-tw-menu.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs +34 -1
- package/fesm2022/cdevhub-ngx-tw-number-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs +95 -45
- package/fesm2022/cdevhub-ngx-tw-paginator.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-popover.mjs +81 -32
- package/fesm2022/cdevhub-ngx-tw-popover.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs +1 -1
- package/fesm2022/cdevhub-ngx-tw-progress-bar.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-radio.mjs +131 -98
- package/fesm2022/cdevhub-ngx-tw-radio.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs +207 -42
- package/fesm2022/cdevhub-ngx-tw-segmented-control.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs +165 -0
- package/fesm2022/cdevhub-ngx-tw-select-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-select.mjs +386 -210
- package/fesm2022/cdevhub-ngx-tw-select.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs +256 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-sheet-renderer-CqVJwgmp.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs +129 -0
- package/fesm2022/cdevhub-ngx-tw-sheet-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs +197 -278
- package/fesm2022/cdevhub-ngx-tw-sheet.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-slider.mjs +89 -54
- package/fesm2022/cdevhub-ngx-tw-slider.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-sort.mjs +122 -17
- package/fesm2022/cdevhub-ngx-tw-sort.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-split.mjs +72 -19
- package/fesm2022/cdevhub-ngx-tw-split.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stat.mjs +63 -25
- package/fesm2022/cdevhub-ngx-tw-stat.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs +35 -8
- package/fesm2022/cdevhub-ngx-tw-stepper.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-switch.mjs +54 -48
- package/fesm2022/cdevhub-ngx-tw-switch.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs +12 -15
- package/fesm2022/cdevhub-ngx-tw-tab-nav.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-table.mjs +74 -13
- package/fesm2022/cdevhub-ngx-tw-table.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs +84 -30
- package/fesm2022/cdevhub-ngx-tw-tabs.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs +172 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs +107 -71
- package/fesm2022/cdevhub-ngx-tw-tags-input.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs +41 -9
- package/fesm2022/cdevhub-ngx-tw-textarea.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-theme.mjs +257 -45
- package/fesm2022/cdevhub-ngx-tw-theme.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs +201 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs +184 -77
- package/fesm2022/cdevhub-ngx-tw-time-picker.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs +110 -27
- package/fesm2022/cdevhub-ngx-tw-timeline.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs +616 -0
- package/fesm2022/cdevhub-ngx-tw-toast-toast-renderer-BlDxemsU.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-toast.mjs +556 -945
- package/fesm2022/cdevhub-ngx-tw-toast.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs +102 -15
- package/fesm2022/cdevhub-ngx-tw-tooltip.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs +219 -0
- package/fesm2022/cdevhub-ngx-tw-transfer-testing.mjs.map +1 -0
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs +88 -69
- package/fesm2022/cdevhub-ngx-tw-transfer.mjs.map +1 -1
- package/fesm2022/cdevhub-ngx-tw-tree.mjs +68 -19
- package/fesm2022/cdevhub-ngx-tw-tree.mjs.map +1 -1
- package/index.json +1 -1
- package/package.json +63 -2
- package/theme/_base.css +13 -0
- package/theme/_dark.css +110 -36
- package/theme/_high-contrast-dark.css +367 -0
- package/theme/_high-contrast.css +13 -2
- package/theme/_light.css +276 -0
- package/theme/_semantic.css +47 -12
- package/theme/_typography.css +17 -0
- package/theme/index.css +86 -7
- package/types/cdevhub-ngx-tw-accordion.d.ts +12 -4
- package/types/cdevhub-ngx-tw-avatar.d.ts +10 -3
- package/types/cdevhub-ngx-tw-button.d.ts +1 -0
- package/types/cdevhub-ngx-tw-calendar-luxon.d.ts +2 -2
- package/types/cdevhub-ngx-tw-calendar-testing.d.ts +1 -1
- package/types/cdevhub-ngx-tw-calendar.d.ts +179 -73
- package/types/cdevhub-ngx-tw-card.d.ts +11 -3
- package/types/cdevhub-ngx-tw-carousel.d.ts +89 -20
- package/types/cdevhub-ngx-tw-checkbox.d.ts +40 -12
- package/types/cdevhub-ngx-tw-code-block.d.ts +11 -2
- package/types/cdevhub-ngx-tw-collapsible.d.ts +32 -5
- package/types/cdevhub-ngx-tw-combobox-testing.d.ts +157 -0
- package/types/cdevhub-ngx-tw-combobox.d.ts +94 -53
- package/types/cdevhub-ngx-tw-command-palette-testing.d.ts +136 -0
- package/types/cdevhub-ngx-tw-command-palette.d.ts +33 -5
- package/types/cdevhub-ngx-tw-core.d.ts +152 -21
- package/types/cdevhub-ngx-tw-date-picker-testing.d.ts +141 -0
- package/types/cdevhub-ngx-tw-date-picker.d.ts +37 -29
- package/types/cdevhub-ngx-tw-date-range-picker-testing.d.ts +148 -0
- package/types/cdevhub-ngx-tw-date-range-picker.d.ts +36 -29
- package/types/cdevhub-ngx-tw-dialog-testing.d.ts +98 -0
- package/types/cdevhub-ngx-tw-dialog.d.ts +89 -19
- package/types/cdevhub-ngx-tw-file-upload-testing.d.ts +120 -0
- package/types/cdevhub-ngx-tw-file-upload.d.ts +8 -10
- package/types/cdevhub-ngx-tw-flip-card.d.ts +18 -11
- package/types/cdevhub-ngx-tw-form-field.d.ts +19 -2
- package/types/cdevhub-ngx-tw-icon.d.ts +3 -3
- package/types/cdevhub-ngx-tw-input.d.ts +5 -8
- package/types/cdevhub-ngx-tw-item.d.ts +2 -0
- package/types/cdevhub-ngx-tw-menu-testing.d.ts +131 -0
- package/types/cdevhub-ngx-tw-menu.d.ts +2 -2
- package/types/cdevhub-ngx-tw-number-input.d.ts +20 -0
- package/types/cdevhub-ngx-tw-paginator.d.ts +58 -24
- package/types/cdevhub-ngx-tw-popover.d.ts +41 -10
- package/types/cdevhub-ngx-tw-progress-bar.d.ts +1 -1
- package/types/cdevhub-ngx-tw-radio.d.ts +68 -25
- package/types/cdevhub-ngx-tw-segmented-control.d.ts +79 -16
- package/types/cdevhub-ngx-tw-select-testing.d.ts +114 -0
- package/types/cdevhub-ngx-tw-select.d.ts +104 -33
- package/types/cdevhub-ngx-tw-sheet-testing.d.ts +104 -0
- package/types/cdevhub-ngx-tw-sheet.d.ts +96 -21
- package/types/cdevhub-ngx-tw-slider.d.ts +79 -25
- package/types/cdevhub-ngx-tw-sort.d.ts +45 -4
- package/types/cdevhub-ngx-tw-split.d.ts +32 -2
- package/types/cdevhub-ngx-tw-stat.d.ts +14 -4
- package/types/cdevhub-ngx-tw-stepper.d.ts +16 -2
- package/types/cdevhub-ngx-tw-switch.d.ts +35 -13
- package/types/cdevhub-ngx-tw-tab-nav.d.ts +7 -6
- package/types/cdevhub-ngx-tw-table.d.ts +53 -10
- package/types/cdevhub-ngx-tw-tabs.d.ts +41 -10
- package/types/cdevhub-ngx-tw-tags-input-testing.d.ts +135 -0
- package/types/cdevhub-ngx-tw-tags-input.d.ts +26 -11
- package/types/cdevhub-ngx-tw-textarea.d.ts +3 -2
- package/types/cdevhub-ngx-tw-theme.d.ts +245 -39
- package/types/cdevhub-ngx-tw-time-picker-testing.d.ts +129 -0
- package/types/cdevhub-ngx-tw-time-picker.d.ts +76 -19
- package/types/cdevhub-ngx-tw-timeline.d.ts +36 -12
- package/types/cdevhub-ngx-tw-toast.d.ts +61 -12
- package/types/cdevhub-ngx-tw-tooltip.d.ts +28 -6
- package/types/cdevhub-ngx-tw-transfer-testing.d.ts +152 -0
- package/types/cdevhub-ngx-tw-transfer.d.ts +21 -8
- package/types/cdevhub-ngx-tw-tree.d.ts +6 -1
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/** Filters accepted by `FileUploadFileHarness.with`. */
|
|
4
|
+
interface FileUploadFileHarnessFilters extends BaseHarnessFilters {
|
|
5
|
+
/** Match by the attached file's name. */
|
|
6
|
+
name?: string | RegExp;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Harness for a single attached file in a `tw-file-upload`'s list.
|
|
10
|
+
*
|
|
11
|
+
* Reach these through {@link FileUploadHarness.getFiles}.
|
|
12
|
+
*
|
|
13
|
+
* Everything here reads the *default* row rendering. A consumer who projects a
|
|
14
|
+
* `*twFileUploadItem` template replaces the row wholesale — including the
|
|
15
|
+
* remove control this harness drives — so {@link getName} and {@link remove}
|
|
16
|
+
* apply only to the built-in row.
|
|
17
|
+
*/
|
|
18
|
+
declare class FileUploadFileHarness extends ComponentHarness {
|
|
19
|
+
static hostSelector: string;
|
|
20
|
+
private readonly removeButton;
|
|
21
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
22
|
+
static with(options?: FileUploadFileHarnessFilters): HarnessPredicate<FileUploadFileHarness>;
|
|
23
|
+
/**
|
|
24
|
+
* The attached file's name, read from the remove control's accessible name
|
|
25
|
+
* (`Remove <name>`). That is the one place the name is exposed through an
|
|
26
|
+
* accessibility contract rather than through presentational markup.
|
|
27
|
+
*/
|
|
28
|
+
getName(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* The row's full rendered text, whitespace-collapsed.
|
|
31
|
+
*
|
|
32
|
+
* The name and the meta line sit in adjacent `<span>`s with only a
|
|
33
|
+
* whitespace-only text node between them, which Angular strips, so they run
|
|
34
|
+
* together here (`notes.txt10 B`). Prefer {@link getName} and
|
|
35
|
+
* {@link getMetaText} for the parts; this is the raw read that still says
|
|
36
|
+
* something about a row rendered from a projected template.
|
|
37
|
+
*/
|
|
38
|
+
getText(): Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* The row's meta line — the formatted size, plus the status and error text
|
|
41
|
+
* once the item leaves `pending` (`10 B`, `10 B · Uploading`,
|
|
42
|
+
* `10 B · Failed — <error>`).
|
|
43
|
+
*
|
|
44
|
+
* This string is the only place per-item status and error surface in the
|
|
45
|
+
* DOM: there is no `data-status` hook, and the status otherwise shows up
|
|
46
|
+
* only in Tailwind classes, which a harness must not read. Derived by
|
|
47
|
+
* subtracting {@link getName} from {@link getText} for the same reason.
|
|
48
|
+
*/
|
|
49
|
+
getMetaText(): Promise<string>;
|
|
50
|
+
/**
|
|
51
|
+
* Clicks the row's remove control.
|
|
52
|
+
*
|
|
53
|
+
* The component retargets focus in an `afterNextRender` — deliberately, so
|
|
54
|
+
* that the list has re-rendered before focus moves — so the focus assertion
|
|
55
|
+
* a caller makes after this resolves is the post-render one.
|
|
56
|
+
*/
|
|
57
|
+
remove(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Filters accepted by `FileUploadHarness.with`. */
|
|
61
|
+
interface FileUploadHarnessFilters extends BaseHarnessFilters {
|
|
62
|
+
/** Match by the control's accessible name (its `aria-label`). */
|
|
63
|
+
label?: string | RegExp;
|
|
64
|
+
/** Match disabled / enabled controls. */
|
|
65
|
+
disabled?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Harness for `tw-file-upload`.
|
|
69
|
+
*
|
|
70
|
+
* ## What this harness deliberately cannot do
|
|
71
|
+
*
|
|
72
|
+
* It cannot attach a file. Selecting a file means populating
|
|
73
|
+
* `HTMLInputElement.files`, which is read-only to script and which CDK's
|
|
74
|
+
* `TestElement` — the whole reason a harness runs unchanged against a real
|
|
75
|
+
* browser — has no operation for. The only way to do it is
|
|
76
|
+
* `Object.defineProperty` on the raw DOM node, which exists solely in the
|
|
77
|
+
* Testbed environment. Exposing that would make the harness silently
|
|
78
|
+
* unusable in every other environment, so attaching stays the caller's job:
|
|
79
|
+
* seed files through the bound form control (`writeValue` takes a `File[]`),
|
|
80
|
+
* or through the component's own API, and use this harness for everything
|
|
81
|
+
* downstream of the attachment.
|
|
82
|
+
*
|
|
83
|
+
* Nothing here needs a CDK overlay, so the ordinary fixture loader is enough.
|
|
84
|
+
*
|
|
85
|
+
* Note where the ARIA lives: the host is a `role="group"`, which ARIA 1.2 does
|
|
86
|
+
* not allow to carry `aria-required` / `aria-invalid`, so both sit on the
|
|
87
|
+
* hidden `<input type="file">` — the element that actually owns the value.
|
|
88
|
+
* {@link isRequired} and {@link isInvalid} read them from there;
|
|
89
|
+
* {@link isDisabled} reads `aria-disabled` from the group, which is allowed.
|
|
90
|
+
*/
|
|
91
|
+
declare class FileUploadHarness extends ComponentHarness {
|
|
92
|
+
static hostSelector: string;
|
|
93
|
+
/** The hidden native control. It carries the value-owning ARIA and state. */
|
|
94
|
+
private readonly nativeInput;
|
|
95
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
96
|
+
static with(options?: FileUploadHarnessFilters): HarnessPredicate<FileUploadHarness>;
|
|
97
|
+
/** The control's accessible name, from `aria-label` when one is set. */
|
|
98
|
+
getLabel(): Promise<string | null>;
|
|
99
|
+
/** Whether the group reports `aria-disabled="true"`. */
|
|
100
|
+
isDisabled(): Promise<boolean>;
|
|
101
|
+
/** Whether the native file input is marked required. */
|
|
102
|
+
isRequired(): Promise<boolean>;
|
|
103
|
+
/** Whether the native file input reports `aria-invalid="true"`. */
|
|
104
|
+
isInvalid(): Promise<boolean>;
|
|
105
|
+
/**
|
|
106
|
+
* Every attached file, in list order. Returns `[]` when nothing is attached
|
|
107
|
+
* — the list element is always rendered, just empty.
|
|
108
|
+
*/
|
|
109
|
+
getFiles(filters?: FileUploadFileHarnessFilters): Promise<FileUploadFileHarness[]>;
|
|
110
|
+
/** The name of every attached file, in list order. */
|
|
111
|
+
getFileNames(): Promise<string[]>;
|
|
112
|
+
/**
|
|
113
|
+
* Removes the first attached file whose name matches. Throws when nothing
|
|
114
|
+
* matches, rather than failing silently.
|
|
115
|
+
*/
|
|
116
|
+
removeFile(name: string | RegExp): Promise<void>;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { FileUploadFileHarness, FileUploadHarness };
|
|
120
|
+
export type { FileUploadFileHarnessFilters, FileUploadHarnessFilters };
|
|
@@ -65,17 +65,17 @@ declare class FileUploadComponent extends FormFieldControl<File[]> implements Co
|
|
|
65
65
|
readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
66
66
|
/** Marks the control as required. Mirrors to `aria-required`. Also inferred from `Validators.required` on a bound `NgControl`. Defaults to `false`. */
|
|
67
67
|
readonly requiredInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
68
|
-
/** Headline text rendered inside the drop zone (e.g., `'Drag files here'`). Projected `[twFileUploadHeadline]` content takes precedence over this input. */
|
|
68
|
+
/** Headline text rendered inside the drop zone (e.g., `'Drag files here'`). Projected `[twFileUploadHeadline]` content takes precedence over this input. Defaults to `undefined`. */
|
|
69
69
|
readonly label: _angular_core.InputSignal<string | undefined>;
|
|
70
|
-
/** Secondary text rendered under the label (e.g., `'PDF up to 10MB'`). Projected `[twFileUploadDescription]` content takes precedence. */
|
|
70
|
+
/** Secondary text rendered under the label (e.g., `'PDF up to 10MB'`). Projected `[twFileUploadDescription]` content takes precedence. Defaults to `undefined`. */
|
|
71
71
|
readonly description: _angular_core.InputSignal<string | undefined>;
|
|
72
72
|
/** Label rendered inside the trigger button. Defaults to `'Choose files'`. Use `'Choose file'` when `multiple` is `false` (consumer responsibility). */
|
|
73
73
|
readonly triggerLabel: _angular_core.InputSignal<string>;
|
|
74
|
-
/** Accessible name applied to the host when no visible label is projected. Mirrored to `aria-label`. */
|
|
74
|
+
/** Accessible name applied to the host when no visible label is projected. Mirrored to `aria-label`. Defaults to `undefined`. */
|
|
75
75
|
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
76
|
-
/** ID of an external element that labels the control. Mirrored to `aria-labelledby`. */
|
|
76
|
+
/** ID of an external element that labels the control. Mirrored to `aria-labelledby`. Defaults to `undefined`. */
|
|
77
77
|
readonly ariaLabelledby: _angular_core.InputSignal<string | undefined>;
|
|
78
|
-
/** ID of an external element that describes the control. Form-field merges its hint/error ids alongside. */
|
|
78
|
+
/** ID of an external element that describes the control. Form-field merges its hint/error ids alongside. Defaults to `undefined`. Alias: `aria-describedby`. */
|
|
79
79
|
readonly ariaDescribedby: _angular_core.InputSignal<string | undefined>;
|
|
80
80
|
/** Optional `name` attribute on the hidden `<input type="file">` for native form submissions. */
|
|
81
81
|
readonly name: _angular_core.InputSignal<string | undefined>;
|
|
@@ -92,20 +92,18 @@ declare class FileUploadComponent extends FormFieldControl<File[]> implements Co
|
|
|
92
92
|
/** Fires when all files are cleared at once via programmatic `clear()`. Does not fire on `writeValue`, even when the new value is empty. */
|
|
93
93
|
readonly cleared: _angular_core.OutputEmitterRef<void>;
|
|
94
94
|
private readonly elementRef;
|
|
95
|
+
private readonly injector;
|
|
95
96
|
private readonly focusMonitor;
|
|
96
97
|
private readonly liveAnnouncer;
|
|
97
98
|
private readonly destroyRef;
|
|
98
99
|
private readonly ngControl;
|
|
99
|
-
private readonly parentForm;
|
|
100
|
-
private readonly parentFormGroup;
|
|
101
|
-
private readonly defaultMatcher;
|
|
102
100
|
private readonly itemsSignal;
|
|
103
101
|
private readonly cvaDisabled;
|
|
104
102
|
private readonly isDraggingSignal;
|
|
105
103
|
private readonly dragHasInvalidFilesSignal;
|
|
106
104
|
private readonly _focused;
|
|
107
|
-
|
|
108
|
-
private readonly
|
|
105
|
+
/** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
|
|
106
|
+
private readonly errorWiring;
|
|
109
107
|
private readonly describedByIdsSignal;
|
|
110
108
|
private readonly labelledByIdsSignal;
|
|
111
109
|
private dragCounter;
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
|
|
3
3
|
/** Visual style of the flip card chrome. Mirrors `tw-card`. */
|
|
4
|
-
type FlipCardVariant = '
|
|
4
|
+
type FlipCardVariant = 'outline' | 'elevated' | 'ghost' | FlipCardVariantLegacy;
|
|
5
|
+
/**
|
|
6
|
+
* Legacy `variant` spellings, kept so existing templates keep compiling.
|
|
7
|
+
* @deprecated `'outlined'` is an alias for `'outline'` and renders identically.
|
|
8
|
+
* It will be removed in the next major — prefer `'outline'`.
|
|
9
|
+
*/
|
|
10
|
+
type FlipCardVariantLegacy = 'outlined';
|
|
5
11
|
/** Axis of rotation for the flip animation. */
|
|
6
12
|
type FlipCardDirection = 'horizontal' | 'vertical';
|
|
7
13
|
/** Which user interaction flips the card. */
|
|
@@ -22,8 +28,9 @@ type FlipCardTrigger = 'hover' | 'click' | 'manual' | 'both';
|
|
|
22
28
|
declare class FlipCardComponent {
|
|
23
29
|
/**
|
|
24
30
|
* Visual style of the card chrome. Mirrors `tw-card`'s variant vocabulary.
|
|
25
|
-
* Defaults to `'
|
|
31
|
+
* Defaults to `'outline'` (vs `tw-card`'s `'elevated'` default) so the flip
|
|
26
32
|
* animation reads more clearly without a baseline shadow underneath.
|
|
33
|
+
* `'outlined'` is a deprecated alias for `'outline'` and renders identically.
|
|
27
34
|
*/
|
|
28
35
|
readonly variant: _angular_core.InputSignal<FlipCardVariant>;
|
|
29
36
|
/** Axis of rotation. `'horizontal'` rotates around the Y axis (left/right flip); `'vertical'` rotates around the X axis (top/bottom flip). Defaults to `'horizontal'`. */
|
|
@@ -35,12 +42,12 @@ declare class FlipCardComponent {
|
|
|
35
42
|
/** Whether the back face is currently visible. Two-way bindable via `[(flipped)]`. Defaults to `false`. The `flippedChange` event fires on every toggle. */
|
|
36
43
|
readonly flipped: _angular_core.ModelSignal<boolean>;
|
|
37
44
|
/**
|
|
38
|
-
* Accessible name for the host element
|
|
39
|
-
* `'manual'` (the host renders as `role="region"`, which
|
|
40
|
-
* have an accessible name); a default of `'Flip card'` is
|
|
41
|
-
* mode if no value is provided. In interactive modes the host's
|
|
42
|
-
* name is normally derived from the visible face's content — set
|
|
43
|
-
* input to override.
|
|
45
|
+
* Accessible name for the host element, mirrored to `aria-label`. Required
|
|
46
|
+
* when `trigger` is `'manual'` (the host renders as `role="region"`, which
|
|
47
|
+
* AXE requires to have an accessible name); a default of `'Flip card'` is
|
|
48
|
+
* used in that mode if no value is provided. In interactive modes the host's
|
|
49
|
+
* accessible name is normally derived from the visible face's content — set
|
|
50
|
+
* this input to override. Defaults to `undefined`.
|
|
44
51
|
*/
|
|
45
52
|
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
46
53
|
private readonly liveAnnouncer;
|
|
@@ -58,8 +65,6 @@ declare class FlipCardComponent {
|
|
|
58
65
|
/** @internal */
|
|
59
66
|
readonly ariaPressed: _angular_core.Signal<string | null>;
|
|
60
67
|
/** @internal */
|
|
61
|
-
readonly ariaLive: _angular_core.Signal<"polite" | null>;
|
|
62
|
-
/** @internal */
|
|
63
68
|
readonly ariaDisabled: _angular_core.Signal<"true" | null>;
|
|
64
69
|
/** @internal */
|
|
65
70
|
readonly hostAriaLabel: _angular_core.Signal<string | null>;
|
|
@@ -71,6 +76,8 @@ declare class FlipCardComponent {
|
|
|
71
76
|
readonly frontInert: _angular_core.Signal<"" | null>;
|
|
72
77
|
/** @internal */
|
|
73
78
|
readonly backInert: _angular_core.Signal<"" | null>;
|
|
79
|
+
/** @internal Canonical variant with legacy spellings folded in. */
|
|
80
|
+
private readonly resolvedVariant;
|
|
74
81
|
private readonly variantResult;
|
|
75
82
|
readonly rootClasses: _angular_core.Signal<string>;
|
|
76
83
|
readonly innerClasses: _angular_core.Signal<string>;
|
|
@@ -88,7 +95,7 @@ declare class FlipCardComponent {
|
|
|
88
95
|
private toggle;
|
|
89
96
|
private setFlipped;
|
|
90
97
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FlipCardComponent, never>;
|
|
91
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlipCardComponent, "tw-flip-card", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "flipped": { "alias": "flipped"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "
|
|
98
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FlipCardComponent, "tw-flip-card", never, { "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "direction": { "alias": "direction"; "required": false; "isSignal": true; }; "trigger": { "alias": "trigger"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "flipped": { "alias": "flipped"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; }, { "flipped": "flippedChange"; }, never, ["[slot='front']", "[slot='back']"], true, never>;
|
|
92
99
|
}
|
|
93
100
|
|
|
94
101
|
export { FlipCardComponent };
|
|
@@ -28,7 +28,24 @@ declare abstract class FormFieldControl<T = unknown> {
|
|
|
28
28
|
abstract readonly required: Signal<boolean>;
|
|
29
29
|
/** Whether the control should be rendered as invalid. Usually derived from `NgControl.invalid` combined with `touched`/`submitted`. */
|
|
30
30
|
abstract readonly errorState: Signal<boolean>;
|
|
31
|
-
/**
|
|
31
|
+
/**
|
|
32
|
+
* Active validation errors map keyed by validator name (e.g. `{ required: true, email: true }`).
|
|
33
|
+
* Returns `null` when the control has no validation errors.
|
|
34
|
+
*
|
|
35
|
+
* This is the *only* source the form-field consults for `[twError match="…"]` filtering: it
|
|
36
|
+
* feeds `FormFieldComponent.activeErrorKeys`, and an error with a `match` renders only while
|
|
37
|
+
* that key is present. A control that leaves this undefined therefore reports an empty key set,
|
|
38
|
+
* and **every `match`-targeted message under it is permanently hidden** — in all three form
|
|
39
|
+
* strategies, with no warning. Unmatched `[twError]` messages are unaffected; they follow
|
|
40
|
+
* `errorState` alone.
|
|
41
|
+
*
|
|
42
|
+
* Optional only so the member can be added to existing controls without a breaking change. Any
|
|
43
|
+
* control that resolves an `NgControl` should implement it — typically as
|
|
44
|
+
* `computed(() => ngControl?.control?.errors ?? null)`, reading whatever revision signal the
|
|
45
|
+
* control already uses to invalidate `errorState`, so the map tracks validator transitions that
|
|
46
|
+
* do not flip `VALID`/`INVALID`. Omit it only for a control that genuinely has no validation
|
|
47
|
+
* errors to report.
|
|
48
|
+
*/
|
|
32
49
|
readonly errors?: Signal<Record<string, unknown> | null>;
|
|
33
50
|
/** Optional control-type identifier (e.g. `'input'`, `'select'`). When set, the form-field appends `tw-form-field-type-{controlType}` to its host for styling hooks. */
|
|
34
51
|
abstract readonly controlType?: string;
|
|
@@ -141,7 +158,7 @@ declare class SuffixIconDirective extends SuffixDirective {
|
|
|
141
158
|
declare class FormFieldComponent implements AfterContentInit, TwFormFieldParent {
|
|
142
159
|
/** Visual appearance of the field container. `'outline'` draws a full border around the control; `'filled'` uses a filled surface with a bottom border. Defaults to `'outline'`. */
|
|
143
160
|
readonly appearance: i0.InputSignal<FormFieldAppearance>;
|
|
144
|
-
/** Density of the field container. Maps to the inline-padding scale (`px-2 py-1` xs … `px-5 py-3` xl) and the
|
|
161
|
+
/** Density of the field container. Maps to the inline-padding scale (`px-2 py-1` xs … `px-5 py-3` xl), the control-row font scale (`text-xs` xs, `text-sm` sm/md, `text-base` lg/xl — inherited by the nested control and by prefix/suffix adornments), the label font scale, and a `min-h-*` floor on the control row from the control-height scale (24/32/36/44/48px). The floor is a minimum, not a fixed height: the row grows for a textarea or any other multi-line control. Defaults to `'md'`. */
|
|
145
162
|
readonly size: i0.InputSignal<TwSize>;
|
|
146
163
|
/** Floating label behavior. `'auto'` floats when focused or non-empty; `'always'` stays floated; `'never'` disables floating entirely (the label wrapper is not rendered and the wrapped control's placeholder is always visible). Defaults to `'auto'`. */
|
|
147
164
|
readonly floatLabel: i0.InputSignal<FloatLabel>;
|
|
@@ -38,7 +38,7 @@ interface TwIconSvgConfig {
|
|
|
38
38
|
* ```html
|
|
39
39
|
* <tw-icon name="star" />
|
|
40
40
|
* <tw-icon name="check" color="success" size="lg" />
|
|
41
|
-
* <tw-icon name="alert-triangle" color="warning"
|
|
41
|
+
* <tw-icon name="alert-triangle" color="warning" aria-label="Warning" />
|
|
42
42
|
* <tw-icon name="star" [svg]="{ strokeWidth: 1.5, absoluteStrokeWidth: true }" />
|
|
43
43
|
* ```
|
|
44
44
|
*/
|
|
@@ -56,7 +56,7 @@ declare class IconComponent {
|
|
|
56
56
|
readonly color: _angular_core.InputSignal<TwIconColor>;
|
|
57
57
|
/** Icon size. Defaults to `'md'` (20px). */
|
|
58
58
|
readonly size: _angular_core.InputSignal<TwSize>;
|
|
59
|
-
/** Accessible label
|
|
59
|
+
/** Accessible label, supplied as the plain `aria-label` attribute. When set, the generated SVG takes `role="img"` plus the label instead of `aria-hidden="true"`. Defaults to `undefined` (icon is decorative, `aria-hidden="true"`). */
|
|
60
60
|
readonly ariaLabel: _angular_core.InputSignal<string | undefined>;
|
|
61
61
|
/**
|
|
62
62
|
* SVG-author configuration: `strokeWidth`, `absoluteStrokeWidth`, `viewBox`.
|
|
@@ -82,7 +82,7 @@ declare class IconComponent {
|
|
|
82
82
|
constructor();
|
|
83
83
|
private renderSvg;
|
|
84
84
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<IconComponent, never>;
|
|
85
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "tw-icon", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "img": { "alias": "img"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "
|
|
85
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<IconComponent, "tw-icon", never, { "name": { "alias": "name"; "required": false; "isSignal": true; }; "img": { "alias": "img"; "required": false; "isSignal": true; }; "color": { "alias": "color"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "aria-label"; "required": false; "isSignal": true; }; "svg": { "alias": "svg"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/**
|
|
@@ -23,7 +23,7 @@ declare const TW_INPUT_VALUE_ACCESSOR: InjectionToken<{
|
|
|
23
23
|
* and provide under `TW_FORM_FIELD_CONTROL`.
|
|
24
24
|
* - Swap value storage for an existing `<input twInput>` (masked input,
|
|
25
25
|
* date parser, etc.) → provide {@link TW_INPUT_VALUE_ACCESSOR}.
|
|
26
|
-
* - Change when errors show → override
|
|
26
|
+
* - Change when errors show → override `TW_ERROR_STATE_MATCHER` at any
|
|
27
27
|
* injector level, or pass `errorStateMatcher` per instance.
|
|
28
28
|
*
|
|
29
29
|
* Forms integration is inherited: Angular's native value accessors attach to
|
|
@@ -38,9 +38,6 @@ declare class InputDirective extends FormFieldControl<string> implements OnInit
|
|
|
38
38
|
private readonly destroyRef;
|
|
39
39
|
private readonly formField;
|
|
40
40
|
private readonly ngControl;
|
|
41
|
-
private readonly parentForm;
|
|
42
|
-
private readonly parentFormGroup;
|
|
43
|
-
private readonly defaultMatcher;
|
|
44
41
|
private readonly valueAccessor;
|
|
45
42
|
/** @internal */
|
|
46
43
|
readonly _isTextarea: boolean;
|
|
@@ -51,7 +48,7 @@ declare class InputDirective extends FormFieldControl<string> implements OnInit
|
|
|
51
48
|
readonly idInput: _angular_core.InputSignal<string | undefined>;
|
|
52
49
|
/** Native HTML input `type`. Defaults to `'text'`. Dev-mode throws on unsupported values (`checkbox`, `radio`, `submit`, etc.) — use the dedicated component instead. Ignored on `<textarea>`. */
|
|
53
50
|
readonly type: _angular_core.InputSignal<string>;
|
|
54
|
-
/** Density of a standalone field. Maps to the
|
|
51
|
+
/** Density of a standalone field. Maps to the pinned control-height scale (24/32/36/44/48px, `h-6` xs … `h-12` xl), the horizontal-padding scale (`px-2` xs … `px-6` xl), and the font scale (`text-xs` xs, `text-sm` sm/md, `text-base` lg/xl). On a `<textarea>` the height becomes a `min-h-*` floor and the vertical padding is retained. Ignored inside a `<tw-form-field>` — the wrapper's `size` carries density. Defaults to `'md'`. */
|
|
55
52
|
readonly size: _angular_core.InputSignal<TwSize>;
|
|
56
53
|
/** Disables the control. Also reflects `ngControl.disabled` when the element is bound to a reactive form. Defaults to `false`. */
|
|
57
54
|
readonly disabledInput: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
@@ -68,8 +65,8 @@ declare class InputDirective extends FormFieldControl<string> implements OnInit
|
|
|
68
65
|
private readonly _value;
|
|
69
66
|
private readonly _focused;
|
|
70
67
|
private readonly _autofilled;
|
|
71
|
-
|
|
72
|
-
private readonly
|
|
68
|
+
/** @internal Shared `errorState` / `required` / `errors` derivation — see `wireErrorState`. */
|
|
69
|
+
private readonly errorWiring;
|
|
73
70
|
/** @internal */
|
|
74
71
|
readonly id: Signal<string>;
|
|
75
72
|
/** @internal */
|
|
@@ -84,7 +81,7 @@ declare class InputDirective extends FormFieldControl<string> implements OnInit
|
|
|
84
81
|
readonly required: Signal<boolean>;
|
|
85
82
|
/** @internal */
|
|
86
83
|
readonly errorState: Signal<boolean>;
|
|
87
|
-
/** @internal Active validation errors map from the bound `NgControl
|
|
84
|
+
/** @internal Active validation errors map from the bound `NgControl`, for `[twError match="…"]` filtering. */
|
|
88
85
|
readonly errors: Signal<Record<string, unknown> | null>;
|
|
89
86
|
/** @internal */
|
|
90
87
|
readonly classes: Signal<string>;
|
|
@@ -36,7 +36,9 @@ declare class ItemComponent implements OnInit {
|
|
|
36
36
|
readonly descriptionClasses: _angular_core.Signal<string>;
|
|
37
37
|
readonly trailingClasses: _angular_core.Signal<string>;
|
|
38
38
|
ngOnInit(): void;
|
|
39
|
+
/** @internal Emits `selected` on click when the item is interactive and enabled. */
|
|
39
40
|
onActivate(event: Event): void;
|
|
41
|
+
/** @internal Emits `selected` on Enter/Space when the item is interactive and enabled. */
|
|
40
42
|
onKeydown(event: KeyboardEvent): void;
|
|
41
43
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ItemComponent, never>;
|
|
42
44
|
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ItemComponent, "tw-item", never, { "size": { "alias": "size"; "required": false; "isSignal": true; }; "align": { "alias": "align"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "current": { "alias": "current"; "required": false; "isSignal": true; }; }, { "selected": "selected"; }, never, ["[twItemLeading]", "[twItemTitle]", "[twItemDescription]", "[twItemTrailing]"], true, never>;
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { BaseHarnessFilters, ComponentHarness, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/** Filters accepted by `MenuItemHarness.with`. */
|
|
4
|
+
interface MenuItemHarnessFilters extends BaseHarnessFilters {
|
|
5
|
+
/** Match by the item's visible text. */
|
|
6
|
+
text?: string | RegExp;
|
|
7
|
+
/** Match disabled / enabled items. */
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
/** Match checked / unchecked checkbox and radio items. Never matches a plain item. */
|
|
10
|
+
checked?: boolean;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Harness for a single item inside an open `tw-menu` panel.
|
|
14
|
+
*
|
|
15
|
+
* Hosts on the ARIA role rather than on the `twMenuItem*` attribute selectors,
|
|
16
|
+
* so one harness covers plain items, checkbox items and radio items — the roles
|
|
17
|
+
* are contributed by the CDK directives `tw-menu` composes and are the same
|
|
18
|
+
* thing assistive technology reads.
|
|
19
|
+
*
|
|
20
|
+
* Items render into the CDK overlay, not inside the trigger, so they are reached
|
|
21
|
+
* through {@link MenuHarness} rather than located directly against a fixture.
|
|
22
|
+
*/
|
|
23
|
+
declare class MenuItemHarness extends ComponentHarness {
|
|
24
|
+
static hostSelector: string;
|
|
25
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
26
|
+
static with(options?: MenuItemHarnessFilters): HarnessPredicate<MenuItemHarness>;
|
|
27
|
+
/** The item's rendered text, trimmed. Includes any projected description or shortcut text. */
|
|
28
|
+
getText(): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* The item's ARIA role — `'menuitem'`, `'menuitemcheckbox'` or
|
|
31
|
+
* `'menuitemradio'`. Lets a test tell the three kinds apart.
|
|
32
|
+
*/
|
|
33
|
+
getRole(): Promise<string | null>;
|
|
34
|
+
/** Whether the item reports `aria-disabled="true"`. */
|
|
35
|
+
isDisabled(): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Checked state of a checkbox or radio item, or `null` for a plain item,
|
|
38
|
+
* which carries no `aria-checked` at all.
|
|
39
|
+
*/
|
|
40
|
+
isChecked(): Promise<boolean | null>;
|
|
41
|
+
/** Clicks the item. A disabled item ignores the click, as in the browser. */
|
|
42
|
+
click(): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Filters accepted by `MenuHarness.with`. */
|
|
46
|
+
interface MenuHarnessFilters extends BaseHarnessFilters {
|
|
47
|
+
/** Match by the text rendered in the trigger. */
|
|
48
|
+
triggerText?: string | RegExp;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Harness for a `[twMenuTrigger]` and the `tw-menu` panel it opens.
|
|
52
|
+
*
|
|
53
|
+
* ## Why this is a parallel harness and not a delegating one
|
|
54
|
+
*
|
|
55
|
+
* `tw-menu` composes `CdkMenu` / `CdkMenuItem` through `hostDirectives`, so a
|
|
56
|
+
* thin harness delegating to a CDK one would be preferable — except that
|
|
57
|
+
* `@angular/cdk` ships **no component harnesses at all**. Its only testing
|
|
58
|
+
* entry points are `@angular/cdk/testing`, `@angular/cdk/testing/testbed` and
|
|
59
|
+
* `@angular/cdk/testing/selenium-webdriver`, all of which are harness
|
|
60
|
+
* *infrastructure*; the component harnesses live in `@angular/material/*\/testing`,
|
|
61
|
+
* and `@angular/material` is not a dependency of this library. There is nothing
|
|
62
|
+
* to delegate to. What composition does buy us is that the locators below are
|
|
63
|
+
* ARIA roles and attributes CDK guarantees (`role="menuitem"`,
|
|
64
|
+
* `aria-expanded`, `aria-controls`), not ngx-tw class names.
|
|
65
|
+
*
|
|
66
|
+
* ## Why the host selector is not `[twMenuTrigger]`
|
|
67
|
+
*
|
|
68
|
+
* `twMenuTrigger` takes a required `TemplateRef`, so it is always written as a
|
|
69
|
+
* property binding — `[twMenuTrigger]="menu"` — and Angular renders **no
|
|
70
|
+
* attribute** for a bound input. `[twMenuTrigger]` therefore matches nothing in
|
|
71
|
+
* the DOM. `MenuTriggerDirective` adds no host class or attribute of its own
|
|
72
|
+
* (contrast Material, whose `MatMenuTrigger` adds `.mat-mdc-menu-trigger`
|
|
73
|
+
* precisely so its harness can find it), so the only durable marker is the one
|
|
74
|
+
* CDK contributes: `aria-haspopup="menu"`, bound unconditionally by
|
|
75
|
+
* `CdkMenuTrigger` whenever it has a template. Nothing else in ngx-tw renders
|
|
76
|
+
* that value — `[twContextMenuTrigger]` deliberately renders none — so the match
|
|
77
|
+
* is exact today. If `MenuTriggerDirective` ever grows a host marker, widening
|
|
78
|
+
* this selector to it is a non-breaking change.
|
|
79
|
+
*
|
|
80
|
+
* ## Loading it
|
|
81
|
+
*
|
|
82
|
+
* The host is the trigger, which lives in the fixture, so the ordinary
|
|
83
|
+
* `TestbedHarnessEnvironment.loader(fixture)` is correct. The panel renders into
|
|
84
|
+
* the CDK overlay container outside the fixture, and this harness resolves it
|
|
85
|
+
* internally via `documentRootLocatorFactory()` — a consumer never needs
|
|
86
|
+
* `documentRootLoader`.
|
|
87
|
+
*
|
|
88
|
+
* The panel is located by the id in the trigger's `aria-controls`, so a fixture
|
|
89
|
+
* holding several menus (or an open submenu) still resolves each trigger to its
|
|
90
|
+
* own panel.
|
|
91
|
+
*
|
|
92
|
+
* Only `[twMenuTrigger]` is covered. `[twContextMenuTrigger]` opens on a
|
|
93
|
+
* `contextmenu` event at pointer coordinates and exposes neither `aria-expanded`
|
|
94
|
+
* nor `aria-haspopup`; it is deliberately out of scope.
|
|
95
|
+
*/
|
|
96
|
+
declare class MenuHarness extends ComponentHarness {
|
|
97
|
+
static hostSelector: string;
|
|
98
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
99
|
+
static with(options?: MenuHarnessFilters): HarnessPredicate<MenuHarness>;
|
|
100
|
+
/** The text currently rendered in the trigger, trimmed. */
|
|
101
|
+
getTriggerText(): Promise<string>;
|
|
102
|
+
/** Whether the menu is open, read from the trigger's `aria-expanded`. */
|
|
103
|
+
isOpen(): Promise<boolean>;
|
|
104
|
+
/** Opens the menu by clicking the trigger. No-op when already open. */
|
|
105
|
+
open(): Promise<void>;
|
|
106
|
+
/** Closes the menu by clicking the trigger again. No-op when already closed. */
|
|
107
|
+
close(): Promise<void>;
|
|
108
|
+
/**
|
|
109
|
+
* Every item in the open panel — plain, checkbox and radio alike. Returns an
|
|
110
|
+
* empty array when the menu is closed, because CDK removes the panel from the
|
|
111
|
+
* DOM rather than hiding it.
|
|
112
|
+
*/
|
|
113
|
+
getItems(filters?: MenuItemHarnessFilters): Promise<MenuItemHarness[]>;
|
|
114
|
+
/**
|
|
115
|
+
* Opens the menu if needed and clicks the first item whose text matches.
|
|
116
|
+
* Throws when nothing matches, rather than failing silently.
|
|
117
|
+
*
|
|
118
|
+
* CDK closes the menu when an item is activated, so a `getItems()` chained
|
|
119
|
+
* after this returns an empty array — call {@link open} again before
|
|
120
|
+
* re-reading item state.
|
|
121
|
+
*/
|
|
122
|
+
clickItem(text: string | RegExp): Promise<void>;
|
|
123
|
+
/**
|
|
124
|
+
* A loader rooted at this trigger's own panel, or `null` when the menu is
|
|
125
|
+
* closed. Scoping by `aria-controls` keeps sibling menus and submenus apart.
|
|
126
|
+
*/
|
|
127
|
+
private getPanelLoader;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export { MenuHarness, MenuItemHarness };
|
|
131
|
+
export type { MenuHarnessFilters, MenuItemHarnessFilters };
|
|
@@ -6,9 +6,9 @@ import { TwSize, TwColor } from '@cdevhub/ngx-tw/core';
|
|
|
6
6
|
declare class MenuComponent {
|
|
7
7
|
/** Controls item density and padding. Defaults to `'md'`. */
|
|
8
8
|
readonly size: i0.InputSignal<TwSize>;
|
|
9
|
-
/** Accessible label for the menu panel. Use when no visible heading describes the menu (e.g. a kebab-icon trigger). */
|
|
9
|
+
/** Accessible label for the menu panel. Use when no visible heading describes the menu (e.g. a kebab-icon trigger). Defaults to `undefined`. Alias: `aria-label`. */
|
|
10
10
|
readonly ariaLabel: i0.InputSignal<string | undefined>;
|
|
11
|
-
/** ID of an element that labels the menu panel. Ignored when `ariaLabel` is set. */
|
|
11
|
+
/** ID of an element that labels the menu panel. Ignored when `ariaLabel` is set. Defaults to `undefined`. Alias: `aria-labelledby`. */
|
|
12
12
|
readonly ariaLabelledBy: i0.InputSignal<string | undefined>;
|
|
13
13
|
readonly classes: i0.Signal<string>;
|
|
14
14
|
static ɵfac: i0.ɵɵFactoryDeclaration<MenuComponent, never>;
|
|
@@ -42,6 +42,26 @@ declare class NumberInputDirective implements ControlValueAccessor {
|
|
|
42
42
|
readonly disabled: _angular_core.Signal<boolean>;
|
|
43
43
|
/** True when the host input carries the `readonly` attribute (static / declarative, seeded after render). A runtime toggle of the bare `readonly` attribute is not reactively tracked (v2). Read by the companion stepper so its buttons disable in lock-step. */
|
|
44
44
|
readonly readonly: _angular_core.Signal<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* @internal `aria-disabled` for the host `<input>`.
|
|
47
|
+
*
|
|
48
|
+
* Derived from the CVA disabled state ALONE, deliberately not from
|
|
49
|
+
* {@link disabled}. Three reasons, in order of weight:
|
|
50
|
+
*
|
|
51
|
+
* 1. It is the only case that needs the attribute. When the element is
|
|
52
|
+
* natively disabled (`el.disabled`, whether from a static attribute or
|
|
53
|
+
* from the sibling `InputDirective`'s `[disabled]` binding) assistive tech
|
|
54
|
+
* already has the state. The gap is `setDisabledState(true)` on a
|
|
55
|
+
* standalone `input[twNumberInput]` — no sibling directive, so nothing
|
|
56
|
+
* writes the native property and the spinbutton looked enabled.
|
|
57
|
+
* 2. `disabled` reads the non-reactive `el.disabled`. Read from a host
|
|
58
|
+
* binding it would memoize during the host-binding phase, so its value
|
|
59
|
+
* would depend on which of the two directives on the element runs first —
|
|
60
|
+
* and could latch a stale `true` across a `control.enable()`.
|
|
61
|
+
* 3. `[disabled]` itself is not an option: `InputDirective` already binds it,
|
|
62
|
+
* and this directive's `disabled` reads the very property it would write.
|
|
63
|
+
*/
|
|
64
|
+
readonly ariaDisabled: _angular_core.Signal<"true" | null>;
|
|
45
65
|
/** @internal Mobile-keyboard hint: `'numeric'` for integer-only formats, else `'decimal'`. */
|
|
46
66
|
readonly inputMode: _angular_core.Signal<"numeric" | "decimal">;
|
|
47
67
|
/** @internal Locale group / decimal separators, memoized per `locale()`. */
|