@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
|
@@ -1,84 +1,195 @@
|
|
|
1
1
|
import * as _angular_core from '@angular/core';
|
|
2
2
|
import { OnDestroy, InjectionToken, EnvironmentProviders } from '@angular/core';
|
|
3
3
|
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
/**
|
|
5
|
+
* The user-selectable theme. `'system'` defers to the OS, resolving
|
|
6
|
+
* `prefers-color-scheme` and `prefers-contrast` as two independent axes: dark
|
|
7
|
+
* plus increased contrast lands on `'high-contrast-dark'`, light plus increased
|
|
8
|
+
* contrast on `'high-contrast'`.
|
|
9
|
+
*/
|
|
10
|
+
type TwTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark' | 'system';
|
|
11
|
+
/**
|
|
12
|
+
* The theme actually applied to the DOM after resolving `'system'` against the
|
|
13
|
+
* OS preference.
|
|
14
|
+
*
|
|
15
|
+
* The two axes are appearance (light / dark) and contrast (normal / increased),
|
|
16
|
+
* so the four values are their product: `'high-contrast'` is the light-based
|
|
17
|
+
* increased-contrast scheme and `'high-contrast-dark'` the dark-based one.
|
|
18
|
+
*/
|
|
19
|
+
type TwResolvedTheme = 'light' | 'dark' | 'high-contrast' | 'high-contrast-dark';
|
|
8
20
|
/** Ordered list of every {@link TwTheme} value, used by `cycleTheme()` and for UI iteration. */
|
|
9
|
-
declare const TW_THEMES: readonly ["light", "dark", "high-contrast", "system"];
|
|
21
|
+
declare const TW_THEMES: readonly ["light", "dark", "high-contrast", "high-contrast-dark", "system"];
|
|
10
22
|
/** Ordered list of every {@link TwResolvedTheme} value (i.e. {@link TW_THEMES} minus `'system'`). */
|
|
11
|
-
declare const TW_RESOLVED_THEMES: readonly ["light", "dark", "high-contrast"];
|
|
12
|
-
/**
|
|
23
|
+
declare const TW_RESOLVED_THEMES: readonly ["light", "dark", "high-contrast", "high-contrast-dark"];
|
|
24
|
+
/**
|
|
25
|
+
* Runtime configuration for {@link provideTheme}; controls storage, attribute
|
|
26
|
+
* name, target element, and default.
|
|
27
|
+
*
|
|
28
|
+
* Every member is optional. This interface only ever reaches consumers through
|
|
29
|
+
* `provideTheme(config?: Partial<TwThemeConfig>)`, which fills each unset key
|
|
30
|
+
* from {@link DEFAULT_TW_THEME_CONFIG} — so a consumer holding a config object
|
|
31
|
+
* typed as `TwThemeConfig` must not be forced to restate keys they do not
|
|
32
|
+
* override, and adding a member in a future minor must not break them. The
|
|
33
|
+
* resolved value handed to {@link TW_THEME_CONFIG} is `Required<TwThemeConfig>`.
|
|
34
|
+
*/
|
|
13
35
|
interface TwThemeConfig {
|
|
14
36
|
/** The default theme when no preference is stored. Defaults to `'system'`. */
|
|
15
|
-
defaultTheme
|
|
16
|
-
/**
|
|
17
|
-
|
|
37
|
+
defaultTheme?: TwTheme;
|
|
38
|
+
/**
|
|
39
|
+
* localStorage key for persisting an explicit theme choice. Defaults to
|
|
40
|
+
* `'ngx-tw-theme'`. Only `setTheme()` / `cycleTheme()` write it — providing
|
|
41
|
+
* the service never does.
|
|
42
|
+
*/
|
|
43
|
+
storageKey?: string;
|
|
18
44
|
/** The HTML attribute written to the target element. Defaults to `'data-theme'`. */
|
|
19
|
-
attribute
|
|
45
|
+
attribute?: string;
|
|
20
46
|
/** Which element receives the theme attribute. Defaults to `'documentElement'`. */
|
|
21
|
-
target
|
|
47
|
+
target?: 'documentElement' | 'body';
|
|
22
48
|
}
|
|
23
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Composite snapshot of `ThemeService` state — selected, resolved, system, and
|
|
51
|
+
* boolean flags.
|
|
52
|
+
*
|
|
53
|
+
* The three flags are **not** mutually exclusive: `'high-contrast-dark'` sets
|
|
54
|
+
* both {@link isDark} and {@link isHighContrast}, because it is dark *and*
|
|
55
|
+
* high contrast. Branch on {@link resolvedTheme} when you need one case.
|
|
56
|
+
*/
|
|
24
57
|
interface TwThemeState {
|
|
25
58
|
/** The user-selected theme — may be `'system'`. */
|
|
26
59
|
readonly theme: TwTheme;
|
|
27
60
|
/** The theme actually applied to the DOM — never `'system'`. */
|
|
28
61
|
readonly resolvedTheme: TwResolvedTheme;
|
|
29
|
-
/** The OS
|
|
62
|
+
/** The OS appearance preference detected via `prefers-color-scheme` and `prefers-contrast`. */
|
|
30
63
|
readonly systemTheme: TwResolvedTheme;
|
|
31
|
-
/** True when {@link resolvedTheme} is `'dark'`. */
|
|
64
|
+
/** True when {@link resolvedTheme} is a dark scheme — `'dark'` or `'high-contrast-dark'`. */
|
|
32
65
|
readonly isDark: boolean;
|
|
33
|
-
/** True when {@link resolvedTheme} is `'light'
|
|
66
|
+
/** True when {@link resolvedTheme} is exactly `'light'`; the light-based `'high-contrast'` does not set it. */
|
|
34
67
|
readonly isLight: boolean;
|
|
35
|
-
/** True when {@link resolvedTheme} is `'high-contrast'`. */
|
|
68
|
+
/** True when {@link resolvedTheme} is an increased-contrast scheme — `'high-contrast'` or `'high-contrast-dark'`. */
|
|
36
69
|
readonly isHighContrast: boolean;
|
|
37
70
|
}
|
|
38
|
-
/**
|
|
39
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Built-in defaults merged under any user-provided {@link TwThemeConfig} by
|
|
73
|
+
* `provideTheme()`. Typed `Required<TwThemeConfig>` so readers keep a
|
|
74
|
+
* non-optional `string` / `TwTheme` for every field even though the interface
|
|
75
|
+
* itself is all-optional.
|
|
76
|
+
*/
|
|
77
|
+
declare const DEFAULT_TW_THEME_CONFIG: Required<TwThemeConfig>;
|
|
40
78
|
|
|
41
79
|
/**
|
|
42
80
|
* Stateful runtime service that owns the active theme, reacts to OS
|
|
43
|
-
* `prefers-color-scheme` changes, persists
|
|
44
|
-
* `localStorage`, and writes the resolved theme onto the
|
|
45
|
-
* target as a `data-theme` attribute.
|
|
81
|
+
* `prefers-color-scheme` / `prefers-contrast` changes, persists an explicit
|
|
82
|
+
* user selection to `localStorage`, and writes the resolved theme onto the
|
|
83
|
+
* configured DOM target as a `data-theme` attribute.
|
|
46
84
|
*
|
|
47
85
|
* The selected {@link theme} may be `'system'` (defer to the OS); the
|
|
48
86
|
* {@link resolvedTheme} computed from it is always one of `'light'`,
|
|
49
|
-
* `'dark'`, or `'high-contrast'` — never `'system'`.
|
|
50
|
-
*
|
|
87
|
+
* `'dark'`, `'high-contrast'`, or `'high-contrast-dark'` — never `'system'`.
|
|
88
|
+
* Register via
|
|
89
|
+
* {@link provideTheme} in the app's environment providers; `provideTheme`
|
|
90
|
+
* also constructs the service at bootstrap, so injecting it is only needed
|
|
91
|
+
* to read or change the theme.
|
|
92
|
+
*
|
|
93
|
+
* Storage is written **only** by {@link setTheme} / {@link cycleTheme}.
|
|
94
|
+
* Merely providing the service never touches `localStorage`, so the
|
|
95
|
+
* configured `defaultTheme` keeps applying until the user actually picks
|
|
96
|
+
* something, and apps under a storage-consent flow can provide the service
|
|
97
|
+
* before consent is granted.
|
|
51
98
|
*/
|
|
52
99
|
declare class ThemeService implements OnDestroy {
|
|
53
100
|
private readonly config;
|
|
54
101
|
private readonly document;
|
|
55
102
|
private readonly isBrowser;
|
|
56
103
|
private readonly ngZone;
|
|
57
|
-
private
|
|
104
|
+
private darkQuery;
|
|
105
|
+
private contrastQuery;
|
|
58
106
|
private readonly mediaListener;
|
|
59
107
|
/** The user-selected theme (may be `'system'`). */
|
|
60
108
|
readonly theme: _angular_core.WritableSignal<TwTheme>;
|
|
61
|
-
/** The OS color
|
|
109
|
+
/** The OS appearance preference — `prefers-color-scheme` plus `prefers-contrast`. */
|
|
62
110
|
readonly systemTheme: _angular_core.WritableSignal<TwResolvedTheme>;
|
|
63
111
|
/** The resolved theme actually applied to the DOM (never `'system'`). */
|
|
64
112
|
readonly resolvedTheme: _angular_core.Signal<TwResolvedTheme>;
|
|
65
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* True when the resolved theme is a **dark** scheme — `'dark'` or
|
|
115
|
+
* `'high-contrast-dark'`.
|
|
116
|
+
*
|
|
117
|
+
* It answers the appearance question, not "which scheme": the canonical use
|
|
118
|
+
* is picking a colour that has to sit on the page background (a chart grid,
|
|
119
|
+
* a canvas fill), and dark high contrast needs the dark answer there just as
|
|
120
|
+
* much as plain dark does. It is therefore **not** mutually exclusive with
|
|
121
|
+
* {@link isHighContrast}; branch on {@link resolvedTheme} for one case.
|
|
122
|
+
*/
|
|
66
123
|
readonly isDark: _angular_core.Signal<boolean>;
|
|
67
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* True when the resolved theme is exactly `'light'`.
|
|
126
|
+
*
|
|
127
|
+
* Deliberately narrower than {@link isDark}'s mirror image: the light-based
|
|
128
|
+
* `'high-contrast'` does **not** set it, because widening it would change
|
|
129
|
+
* what a shipped scheme reports to consumers already reading this flag.
|
|
130
|
+
* Use `!isDark()` for the appearance question.
|
|
131
|
+
*/
|
|
68
132
|
readonly isLight: _angular_core.Signal<boolean>;
|
|
69
|
-
/**
|
|
133
|
+
/**
|
|
134
|
+
* True when the resolved theme is an **increased-contrast** scheme —
|
|
135
|
+
* `'high-contrast'` or `'high-contrast-dark'`.
|
|
136
|
+
*
|
|
137
|
+
* It answers the contrast question, so it can be true at the same time as
|
|
138
|
+
* {@link isDark}.
|
|
139
|
+
*/
|
|
70
140
|
readonly isHighContrast: _angular_core.Signal<boolean>;
|
|
71
141
|
/** Snapshot of the full theme state — selected, resolved, system, and boolean flags. */
|
|
72
142
|
readonly state: _angular_core.Signal<TwThemeState>;
|
|
73
143
|
constructor();
|
|
74
|
-
/**
|
|
144
|
+
/**
|
|
145
|
+
* Sets the selected theme and persists it. Pass `'system'` to follow the OS
|
|
146
|
+
* preference.
|
|
147
|
+
*
|
|
148
|
+
* This is the only entry point that writes to `localStorage` — see the note
|
|
149
|
+
* on the class.
|
|
150
|
+
*/
|
|
75
151
|
setTheme(theme: TwTheme): void;
|
|
76
|
-
/** Advances the selected theme to the next entry in {@link TW_THEMES}, wrapping around. */
|
|
152
|
+
/** Advances the selected theme to the next entry in {@link TW_THEMES}, wrapping around, and persists it. */
|
|
77
153
|
cycleTheme(): void;
|
|
78
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Writes the configured theme attribute onto an arbitrary element, scoping
|
|
156
|
+
* that subtree to the given theme.
|
|
157
|
+
*
|
|
158
|
+
* Each of the four schemes ships an element-agnostic `[data-theme=…]` block
|
|
159
|
+
* (`_light.css`, `_dark.css`, `_high-contrast.css`,
|
|
160
|
+
* `_high-contrast-dark.css`), so the tokens really do re-resolve on the
|
|
161
|
+
* element and cascade into its descendants — including back to `'light'`
|
|
162
|
+
* from inside a dark page.
|
|
163
|
+
*
|
|
164
|
+
* Caveat: those CSS blocks key off the literal `data-theme` attribute. If
|
|
165
|
+
* `provideTheme({ attribute })` renamed it, this method writes the renamed
|
|
166
|
+
* attribute and the shipped stylesheet will not react — a custom attribute
|
|
167
|
+
* only works with matching custom CSS.
|
|
168
|
+
*/
|
|
79
169
|
applyToElement(element: HTMLElement, theme: TwResolvedTheme): void;
|
|
80
170
|
ngOnDestroy(): void;
|
|
81
171
|
private loadInitialTheme;
|
|
172
|
+
/**
|
|
173
|
+
* Resolves `'system'` against the OS.
|
|
174
|
+
*
|
|
175
|
+
* The two preferences are treated as independent axes and composed, not
|
|
176
|
+
* ranked: `prefers-color-scheme` picks the appearance and
|
|
177
|
+
* `prefers-contrast: more` picks the contrast, giving the full 2×2 —
|
|
178
|
+
* `light` / `dark` / `high-contrast` / `high-contrast-dark`.
|
|
179
|
+
*
|
|
180
|
+
* This is only correct because the library ships **both** high-contrast
|
|
181
|
+
* ramps. While `_high-contrast.css` was the only one, contrast had to be
|
|
182
|
+
* suppressed whenever the OS also asked for dark, or a user running dark +
|
|
183
|
+
* increased contrast — a common pairing — would have been moved from a dark
|
|
184
|
+
* surface onto a white one. `_high-contrast-dark.css` removed that
|
|
185
|
+
* constraint, so the ranking is gone; if a future change ever drops one of
|
|
186
|
+
* the two ramps, this method has to go back to ranking them.
|
|
187
|
+
*
|
|
188
|
+
* Both queries are minted here (not in the constructor) because the
|
|
189
|
+
* `systemTheme` field initialiser calls this before the constructor body
|
|
190
|
+
* runs; the constructor then attaches `change` listeners to the same two
|
|
191
|
+
* objects, so the resolution stays live rather than read-once.
|
|
192
|
+
*/
|
|
82
193
|
private detectSystemTheme;
|
|
83
194
|
private applyToDocument;
|
|
84
195
|
private persistTheme;
|
|
@@ -87,20 +198,115 @@ declare class ThemeService implements OnDestroy {
|
|
|
87
198
|
}
|
|
88
199
|
|
|
89
200
|
declare class ThemeDirective {
|
|
90
|
-
/**
|
|
201
|
+
/**
|
|
202
|
+
* Scopes a subtree to a specific resolved theme by writing `data-theme` on
|
|
203
|
+
* the host. Required.
|
|
204
|
+
*
|
|
205
|
+
* Works in every direction: each of the four schemes ships an
|
|
206
|
+
* element-agnostic `[data-theme="…"]` block (`_light.css`, `_dark.css`,
|
|
207
|
+
* `_high-contrast.css`, `_high-contrast-dark.css`), so a `'light'` pane
|
|
208
|
+
* inside a dark page re-resolves the tokens rather than inheriting the
|
|
209
|
+
* ancestor's.
|
|
210
|
+
*
|
|
211
|
+
* The attribute name is the literal `data-theme` that the shipped CSS keys
|
|
212
|
+
* off — it deliberately ignores `provideTheme({ attribute })`, since a
|
|
213
|
+
* renamed attribute matches none of those blocks.
|
|
214
|
+
*/
|
|
91
215
|
readonly twTheme: _angular_core.InputSignal<TwResolvedTheme>;
|
|
92
216
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeDirective, never>;
|
|
93
217
|
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<ThemeDirective, "[twTheme]", never, { "twTheme": { "alias": "twTheme"; "required": true; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
94
218
|
}
|
|
95
219
|
|
|
96
|
-
/** Injection token carrying the resolved {@link TwThemeConfig} (storage key, attribute, target element, default theme). */
|
|
97
|
-
declare const THEME_CONFIG: InjectionToken<TwThemeConfig>;
|
|
98
220
|
/**
|
|
99
|
-
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
221
|
+
* Injection token carrying the resolved {@link TwThemeConfig} (storage key,
|
|
222
|
+
* attribute, target element, default theme).
|
|
223
|
+
*
|
|
224
|
+
* The value is `Required<TwThemeConfig>`: `TwThemeConfig`'s members are
|
|
225
|
+
* optional so consumers can pass a partial config, but `provideTheme` fills
|
|
226
|
+
* every key from {@link DEFAULT_TW_THEME_CONFIG} before providing it. Injectors
|
|
227
|
+
* therefore still read a non-optional field for each setting, exactly as
|
|
228
|
+
* before this token's type was tightened.
|
|
229
|
+
*/
|
|
230
|
+
declare const TW_THEME_CONFIG: InjectionToken<Required<TwThemeConfig>>;
|
|
231
|
+
/**
|
|
232
|
+
* @deprecated Renamed to {@link TW_THEME_CONFIG} for consistency with every
|
|
233
|
+
* other ngx-tw injection token. This is the *same token instance*, not a copy —
|
|
234
|
+
* providing under either name and injecting under the other resolves — so the
|
|
235
|
+
* rename is safe to adopt incrementally. Removed in the next major.
|
|
236
|
+
*/
|
|
237
|
+
declare const THEME_CONFIG: InjectionToken<Required<TwThemeConfig>>;
|
|
238
|
+
/**
|
|
239
|
+
* Registers {@link ThemeService}, a {@link TW_THEME_CONFIG} value built by merging
|
|
240
|
+
* `config` over {@link DEFAULT_TW_THEME_CONFIG}, and an environment initializer
|
|
241
|
+
* that constructs the service at bootstrap. Call once in the app's environment
|
|
242
|
+
* providers.
|
|
243
|
+
*
|
|
244
|
+
* The initializer is what makes the call self-sufficient. Everything that
|
|
245
|
+
* applies a theme lives in `ThemeService`'s field initialisers and constructor
|
|
246
|
+
* effect, so without it the stored preference was read — and `data-theme`
|
|
247
|
+
* written — only once something happened to `inject(ThemeService)`. An app
|
|
248
|
+
* whose theme toggle sits in a lazily-loaded route therefore rendered every
|
|
249
|
+
* other route with no `data-theme` at all, silently falling back to the
|
|
250
|
+
* `prefers-color-scheme` CSS branch; the failure looked intermittent because
|
|
251
|
+
* it disappeared whenever the stored choice agreed with the OS. Injecting the
|
|
252
|
+
* service yourself is still supported and is idempotent.
|
|
253
|
+
*
|
|
254
|
+
* Keys explicitly set to `undefined` are dropped before merging. Root
|
|
255
|
+
* `tsconfig.json` does not set `exactOptionalPropertyTypes`, so
|
|
256
|
+
* `provideTheme({ storageKey: env.themeKey })` type-checks even when
|
|
257
|
+
* `env.themeKey` is `string | undefined` — and a plain spread would then write
|
|
258
|
+
* `undefined` into a field `TwThemeConfig` types as `string`, making
|
|
259
|
+
* `ThemeService` persist under the literal `localStorage` key `"undefined"`
|
|
260
|
+
* (and, for `attribute`, call `setAttribute("undefined", …)`).
|
|
261
|
+
*
|
|
262
|
+
* Providing the service does **not** write to `localStorage`; only an explicit
|
|
263
|
+
* `setTheme()` / `cycleTheme()` does. For a flash-free first paint when the
|
|
264
|
+
* stored choice disagrees with the OS, pair this with
|
|
265
|
+
* {@link TW_THEME_BOOTSTRAP_SCRIPT} in `index.html`.
|
|
102
266
|
*/
|
|
103
267
|
declare function provideTheme(config?: Partial<TwThemeConfig>): EnvironmentProviders;
|
|
104
268
|
|
|
105
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Body of an inline `<head>` script that applies a previously persisted theme
|
|
271
|
+
* before the app bundle runs, eliminating the flash of the wrong theme on
|
|
272
|
+
* reload.
|
|
273
|
+
*
|
|
274
|
+
* `ThemeService` cannot cover this case: it is JavaScript in the application
|
|
275
|
+
* bundle, so the browser has already painted by the time it writes
|
|
276
|
+
* `data-theme` — and `provideTheme`'s environment initializer does not change
|
|
277
|
+
* that. The CSS `@media (prefers-color-scheme: dark)` fallback covers users
|
|
278
|
+
* who never chose a theme; the flash is what an *explicit* choice that
|
|
279
|
+
* disagrees with the OS looks like — light chosen on a dark machine, or
|
|
280
|
+
* either high-contrast scheme chosen on a machine not already asking for
|
|
281
|
+
* increased contrast (the CSS has a `prefers-color-scheme` branch but
|
|
282
|
+
* deliberately no `prefers-contrast` one, so neither contrast scheme is
|
|
283
|
+
* reachable without an explicit `data-theme`).
|
|
284
|
+
*
|
|
285
|
+
* The string is built from {@link DEFAULT_TW_THEME_CONFIG}, so the storage key
|
|
286
|
+
* and attribute cannot drift from what `ThemeService` actually uses — that
|
|
287
|
+
* drift is the reason this ships as code rather than as a README snippet
|
|
288
|
+
* alone. Copy the literal script into `index.html`, or interpolate this
|
|
289
|
+
* constant during an SSR / index transform:
|
|
290
|
+
*
|
|
291
|
+
* ```html
|
|
292
|
+
* <head>
|
|
293
|
+
* <script>try{var t=localStorage.getItem('ngx-tw-theme');if(t&&t!=='system')document.documentElement.setAttribute('data-theme',t)}catch(e){}</script>
|
|
294
|
+
* </head>
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* Notes on the behaviour it deliberately does *not* have:
|
|
298
|
+
* - A stored `'system'` writes nothing, so the CSS `prefers-color-scheme`
|
|
299
|
+
* fallback keeps deciding — which is exactly what `'system'` means.
|
|
300
|
+
* - It assumes the default `target: 'documentElement'`. A `<head>` script runs
|
|
301
|
+
* before `<body>` exists, so `target: 'body'` cannot be bootstrapped this
|
|
302
|
+
* way.
|
|
303
|
+
* - If you overrode `storageKey` or `attribute` via `provideTheme`, adapt the
|
|
304
|
+
* literal snippet to match; this constant only encodes the defaults.
|
|
305
|
+
* - It is dependency-free and wrapped in `try`/`catch`, so a browser with
|
|
306
|
+
* storage blocked falls through to the CSS behaviour instead of throwing
|
|
307
|
+
* before the app loads.
|
|
308
|
+
*/
|
|
309
|
+
declare const TW_THEME_BOOTSTRAP_SCRIPT: string;
|
|
310
|
+
|
|
311
|
+
export { DEFAULT_TW_THEME_CONFIG, THEME_CONFIG, TW_RESOLVED_THEMES, TW_THEMES, TW_THEME_BOOTSTRAP_SCRIPT, TW_THEME_CONFIG, ThemeDirective, ThemeService, provideTheme };
|
|
106
312
|
export type { TwResolvedTheme, TwTheme, TwThemeConfig, TwThemeState };
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { ComponentHarness, BaseHarnessFilters, HarnessPredicate } from '@angular/cdk/testing';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The editable numeric fields, in render order. Mirrored here rather than
|
|
5
|
+
* imported from `@cdevhub/ngx-tw/time-picker` so a test file does not have to
|
|
6
|
+
* pull in the component entry point just to name a field.
|
|
7
|
+
*/
|
|
8
|
+
type TimePickerHarnessField = 'hour' | 'minute' | 'second';
|
|
9
|
+
/** The two meridiem options of the 12h format. */
|
|
10
|
+
type TimePickerHarnessMeridiem = 'AM' | 'PM';
|
|
11
|
+
/** Filters accepted by `TimePickerHarness.with`. */
|
|
12
|
+
interface TimePickerHarnessFilters extends BaseHarnessFilters {
|
|
13
|
+
/** Match by the field group's accessible name. */
|
|
14
|
+
label?: string | RegExp;
|
|
15
|
+
/** Match disabled / enabled time pickers. */
|
|
16
|
+
disabled?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Harness for `tw-time-picker`.
|
|
20
|
+
*
|
|
21
|
+
* Unlike every other picker in the library this component has **no CDK
|
|
22
|
+
* overlay** — it renders three `input[role="spinbutton"]` fields inline inside
|
|
23
|
+
* a `role="group"`, plus an optional stepper pair, an optional AM/PM
|
|
24
|
+
* radiogroup, and an optional clear button. Nothing here reaches outside the
|
|
25
|
+
* host, so no `documentRootLocatorFactory()` is involved.
|
|
26
|
+
*
|
|
27
|
+
* Fields are addressed by position, not by `aria-label`: every visible string
|
|
28
|
+
* on this component comes from the injectable `TimePickerIntl` and a localized
|
|
29
|
+
* app would break a label-based selector.
|
|
30
|
+
*/
|
|
31
|
+
declare class TimePickerHarness extends ComponentHarness {
|
|
32
|
+
static hostSelector: string;
|
|
33
|
+
private readonly group;
|
|
34
|
+
private readonly fields;
|
|
35
|
+
/**
|
|
36
|
+
* The two stepper buttons, up then down. They are the only buttons inside a
|
|
37
|
+
* plain (role-less) wrapper div — the meridiem buttons live in a
|
|
38
|
+
* `role="radiogroup"` and the clear button is a direct child of the host.
|
|
39
|
+
*/
|
|
40
|
+
private readonly steppers;
|
|
41
|
+
/** The AM then PM radio, present only while `format` is `'12h'`. */
|
|
42
|
+
private readonly meridiemButtons;
|
|
43
|
+
/** Predicate for `locatorFor` / `locatorForAll`. */
|
|
44
|
+
static with(options?: TimePickerHarnessFilters): HarnessPredicate<TimePickerHarness>;
|
|
45
|
+
/**
|
|
46
|
+
* The field group's accessible name, from `aria-label` on the
|
|
47
|
+
* `role="group"` wrapper. `null` when the group is named by reference
|
|
48
|
+
* (`aria-labelledby`) instead — a `<tw-form-field>` label does exactly that.
|
|
49
|
+
*/
|
|
50
|
+
getLabel(): Promise<string | null>;
|
|
51
|
+
/** Whether the seconds field is rendered (`showSeconds`). */
|
|
52
|
+
hasSeconds(): Promise<boolean>;
|
|
53
|
+
/** Whether the stepper buttons are rendered (`showSteppers`, suppressed at `xs` density). */
|
|
54
|
+
hasSteppers(): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* The numeric value of one field, read from its `aria-valuenow`. `null` when
|
|
57
|
+
* the field is blank. In `12h` format the hour is 1–12 and the meridiem is
|
|
58
|
+
* read separately via {@link getMeridiem}.
|
|
59
|
+
*/
|
|
60
|
+
getValue(field: TimePickerHarnessField): Promise<number | null>;
|
|
61
|
+
/**
|
|
62
|
+
* The spoken text of one field, from `aria-valuetext` — `'Empty'` for a blank
|
|
63
|
+
* field, and the hour additionally carries the meridiem in `12h` format.
|
|
64
|
+
* Exposed because it is what a screen reader announces, which no other read
|
|
65
|
+
* on this harness reproduces.
|
|
66
|
+
*/
|
|
67
|
+
getValueText(field: TimePickerHarnessField): Promise<string | null>;
|
|
68
|
+
/**
|
|
69
|
+
* Types `value` into one field as two digits, exactly as a user would.
|
|
70
|
+
*
|
|
71
|
+
* The component drives entry from `beforeinput`, buffering one digit at a
|
|
72
|
+
* time, so the first digit lands on its own before the second replaces the
|
|
73
|
+
* buffer. That means a *partial* time may be committed in between — the same
|
|
74
|
+
* intermediate emission a real keystroke pair produces. Pass values inside
|
|
75
|
+
* the field's range (hour 0–23, or 1–12 in `12h` format; minute/second 0–59)
|
|
76
|
+
* or the component will reject the digit that overflows.
|
|
77
|
+
*/
|
|
78
|
+
setValue(field: TimePickerHarnessField, value: number): Promise<void>;
|
|
79
|
+
/** Clears one field's text, leaving the time incomplete. */
|
|
80
|
+
clearValue(field: TimePickerHarnessField): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* The current meridiem, or `null` in `24h` format where no radiogroup is
|
|
83
|
+
* rendered.
|
|
84
|
+
*/
|
|
85
|
+
getMeridiem(): Promise<TimePickerHarnessMeridiem | null>;
|
|
86
|
+
/**
|
|
87
|
+
* Clicks the AM or PM radio. Throws in `24h` format, where the control does
|
|
88
|
+
* not exist. Selecting the already-selected meridiem is a no-op, as it is for
|
|
89
|
+
* a user.
|
|
90
|
+
*/
|
|
91
|
+
setMeridiem(meridiem: TimePickerHarnessMeridiem): Promise<void>;
|
|
92
|
+
/**
|
|
93
|
+
* Focuses `field` and clicks the up stepper, which steps whichever field
|
|
94
|
+
* holds focus by that field's configured step, wrapping at its bounds.
|
|
95
|
+
* Throws when the steppers are not rendered.
|
|
96
|
+
*/
|
|
97
|
+
stepUp(field?: TimePickerHarnessField): Promise<void>;
|
|
98
|
+
/** Focuses `field` and clicks the down stepper. Throws when the steppers are not rendered. */
|
|
99
|
+
stepDown(field?: TimePickerHarnessField): Promise<void>;
|
|
100
|
+
/** Whether every field reports `aria-disabled="true"`. */
|
|
101
|
+
isDisabled(): Promise<boolean>;
|
|
102
|
+
/** Whether the fields report `aria-invalid="true"`. */
|
|
103
|
+
isInvalid(): Promise<boolean>;
|
|
104
|
+
/**
|
|
105
|
+
* Whether the fields report `aria-required="true"`. Reflects the `required`
|
|
106
|
+
* input *and* a `Validators.required` on a bound control.
|
|
107
|
+
*/
|
|
108
|
+
isRequired(): Promise<boolean>;
|
|
109
|
+
/**
|
|
110
|
+
* Whether the clear control is rendered. It appears only while `showClear` is
|
|
111
|
+
* on, the picker is enabled and not readonly, and a value is set.
|
|
112
|
+
*/
|
|
113
|
+
hasClearButton(): Promise<boolean>;
|
|
114
|
+
/** Clicks the clear control. Throws when none is rendered. */
|
|
115
|
+
clear(): Promise<void>;
|
|
116
|
+
/** @internal Resolves one field by its position in the spinbutton sequence. */
|
|
117
|
+
private field;
|
|
118
|
+
/**
|
|
119
|
+
* @internal The clear button — the only `<button>` that is a direct child of
|
|
120
|
+
* the host, the steppers and meridiem radios both sitting inside wrapper
|
|
121
|
+
* divs.
|
|
122
|
+
*/
|
|
123
|
+
private clearButton;
|
|
124
|
+
/** @internal Focuses a field, then clicks the stepper at `index` (0 = up, 1 = down). */
|
|
125
|
+
private clickStepper;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export { TimePickerHarness };
|
|
129
|
+
export type { TimePickerHarnessField, TimePickerHarnessFilters, TimePickerHarnessMeridiem };
|