@bitforgehq/ui 0.3.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/CHANGELOG.md +3665 -0
- package/LICENSE +21 -0
- package/README.md +175 -0
- package/ai/MANIFEST.index.json +383 -0
- package/ai/MANIFEST.json +7528 -0
- package/ai/REFERENCE.index.json +1461 -0
- package/ai/REFERENCE.json +7213 -0
- package/ai/UI_GUIDE.md +1159 -0
- package/ai/components/action-bar.md +209 -0
- package/ai/components/action-sheet.md +526 -0
- package/ai/components/alert-dialog.md +509 -0
- package/ai/components/alert.md +376 -0
- package/ai/components/avatar.md +146 -0
- package/ai/components/back-button.md +286 -0
- package/ai/components/badge.md +171 -0
- package/ai/components/button.md +431 -0
- package/ai/components/card.md +303 -0
- package/ai/components/checkbox.md +418 -0
- package/ai/components/chip-group.md +205 -0
- package/ai/components/chip.md +300 -0
- package/ai/components/content.md +474 -0
- package/ai/components/desktop-toast.md +420 -0
- package/ai/components/dialog.md +962 -0
- package/ai/components/empty-state.md +146 -0
- package/ai/components/field.md +319 -0
- package/ai/components/header.md +809 -0
- package/ai/components/icon-button.md +221 -0
- package/ai/components/icon.md +176 -0
- package/ai/components/input.md +455 -0
- package/ai/components/list-item.md +326 -0
- package/ai/components/list.md +178 -0
- package/ai/components/menu-button.md +377 -0
- package/ai/components/menu.md +661 -0
- package/ai/components/modal.md +613 -0
- package/ai/components/number-input.md +423 -0
- package/ai/components/page.md +299 -0
- package/ai/components/progress.md +215 -0
- package/ai/components/radio-group.md +432 -0
- package/ai/components/refresher.md +377 -0
- package/ai/components/segmented.md +517 -0
- package/ai/components/select.md +510 -0
- package/ai/components/sheet.md +845 -0
- package/ai/components/spinner.md +171 -0
- package/ai/components/stack-outlet.md +661 -0
- package/ai/components/tab-bar.md +427 -0
- package/ai/components/tab.md +295 -0
- package/ai/components/tabs.md +408 -0
- package/ai/components/textarea.md +371 -0
- package/ai/components/toast.md +522 -0
- package/ai/components/toggle.md +387 -0
- package/ai/reference/bf-action-directive.md +21 -0
- package/ai/reference/bf-action-sheet-action-role.md +27 -0
- package/ai/reference/bf-action-sheet-action.md +28 -0
- package/ai/reference/bf-action-sheet-options.md +28 -0
- package/ai/reference/bf-action-sheet-service.md +33 -0
- package/ai/reference/bf-alert-dialog-button-role.md +27 -0
- package/ai/reference/bf-alert-dialog-button.md +27 -0
- package/ai/reference/bf-alert-dialog-options.md +29 -0
- package/ai/reference/bf-alert-dialog-service.md +34 -0
- package/ai/reference/bf-alert-variant.md +28 -0
- package/ai/reference/bf-autocapitalize.md +30 -0
- package/ai/reference/bf-avatar-size.md +27 -0
- package/ai/reference/bf-avatar-variant.md +28 -0
- package/ai/reference/bf-back-at-root.md +28 -0
- package/ai/reference/bf-back-button-service.md +40 -0
- package/ai/reference/bf-badge-variant.md +29 -0
- package/ai/reference/bf-button-size.md +29 -0
- package/ai/reference/bf-button-type.md +28 -0
- package/ai/reference/bf-button-variant.md +29 -0
- package/ai/reference/bf-card-padding.md +26 -0
- package/ai/reference/bf-card-variant.md +28 -0
- package/ai/reference/bf-chip-group-mode.md +27 -0
- package/ai/reference/bf-chip-variant.md +26 -0
- package/ai/reference/bf-compare-with.md +24 -0
- package/ai/reference/bf-component-overlay-ref.md +33 -0
- package/ai/reference/bf-confirm-button-role.md +26 -0
- package/ai/reference/bf-confirm-button.md +27 -0
- package/ai/reference/bf-confirm-options.md +31 -0
- package/ai/reference/bf-confirm-size.md +26 -0
- package/ai/reference/bf-content-scroll-event.md +21 -0
- package/ai/reference/bf-defaults-options.md +32 -0
- package/ai/reference/bf-defaults.md +28 -0
- package/ai/reference/bf-desktop-toast-config.md +28 -0
- package/ai/reference/bf-desktop-toast-harness.md +33 -0
- package/ai/reference/bf-desktop-toast-options.md +28 -0
- package/ai/reference/bf-desktop-toast-position.md +28 -0
- package/ai/reference/bf-desktop-toast-service.md +42 -0
- package/ai/reference/bf-dialog-config.md +44 -0
- package/ai/reference/bf-dialog-harness.md +52 -0
- package/ai/reference/bf-dialog-ref.md +44 -0
- package/ai/reference/bf-dialog-role.md +26 -0
- package/ai/reference/bf-dialog-service.md +55 -0
- package/ai/reference/bf-dialog-size.md +31 -0
- package/ai/reference/bf-dialog-template-context.md +32 -0
- package/ai/reference/bf-empty-state-heading-level.md +26 -0
- package/ai/reference/bf-enter-key-hint.md +31 -0
- package/ai/reference/bf-field-control-class.md +32 -0
- package/ai/reference/bf-field-control-state.md +28 -0
- package/ai/reference/bf-field-size.md +29 -0
- package/ai/reference/bf-haptics-impact-style.md +27 -0
- package/ai/reference/bf-haptics-notification-type.md +27 -0
- package/ai/reference/bf-haptics-service.md +41 -0
- package/ai/reference/bf-harness-filters.md +29 -0
- package/ai/reference/bf-horizontal-scroll-directive.md +129 -0
- package/ai/reference/bf-icon-button-variant.md +28 -0
- package/ai/reference/bf-icon-size.md +27 -0
- package/ai/reference/bf-input-autocapitalize.md +36 -0
- package/ai/reference/bf-input-enter-key-hint.md +38 -0
- package/ai/reference/bf-input-input-mode.md +38 -0
- package/ai/reference/bf-input-mode.md +32 -0
- package/ai/reference/bf-input-type.md +35 -0
- package/ai/reference/bf-jsdom-shim-options.md +22 -0
- package/ai/reference/bf-keyboard-assist-behavior.md +26 -0
- package/ai/reference/bf-keyboard-assist-directive.md +185 -0
- package/ai/reference/bf-keyboard-phase.md +30 -0
- package/ai/reference/bf-keyboard-service.md +50 -0
- package/ai/reference/bf-labels-overrides.md +26 -0
- package/ai/reference/bf-labels.md +44 -0
- package/ai/reference/bf-menu-button-harness.md +40 -0
- package/ai/reference/bf-menu-button-variant.md +27 -0
- package/ai/reference/bf-menu-divider-directive.md +13 -0
- package/ai/reference/bf-menu-group-directive.md +14 -0
- package/ai/reference/bf-menu-harness.md +55 -0
- package/ai/reference/bf-menu-item-checkbox-directive.md +31 -0
- package/ai/reference/bf-menu-item-directive.md +31 -0
- package/ai/reference/bf-menu-item-harness.md +52 -0
- package/ai/reference/bf-menu-item-radio-directive.md +29 -0
- package/ai/reference/bf-menu-placement.md +29 -0
- package/ai/reference/bf-menu-trigger-directive.md +46 -0
- package/ai/reference/bf-modal-options.md +30 -0
- package/ai/reference/bf-modal-presentation.md +26 -0
- package/ai/reference/bf-modal-service.md +38 -0
- package/ai/reference/bf-nav-controller.md +59 -0
- package/ai/reference/bf-nav-direction.md +23 -0
- package/ai/reference/bf-nav-target.md +21 -0
- package/ai/reference/bf-number-input-mode.md +28 -0
- package/ai/reference/bf-number-input-step.md +25 -0
- package/ai/reference/bf-overlay-auto-focus.md +29 -0
- package/ai/reference/bf-overlay-controller.md +22 -0
- package/ai/reference/bf-overlay-host.md +36 -0
- package/ai/reference/bf-overlay-options.md +53 -0
- package/ai/reference/bf-overlay-position.md +30 -0
- package/ai/reference/bf-overlay-ref.md +53 -0
- package/ai/reference/bf-overlay-role.md +27 -0
- package/ai/reference/bf-overlay-service.md +53 -0
- package/ai/reference/bf-overlay-stack-options.md +24 -0
- package/ai/reference/bf-overlay-stack.md +81 -0
- package/ai/reference/bf-overlay-template-context.md +24 -0
- package/ai/reference/bf-overscroll-stretch-directive.md +163 -0
- package/ai/reference/bf-page-context.md +24 -0
- package/ai/reference/bf-platform-service.md +53 -0
- package/ai/reference/bf-platform.md +28 -0
- package/ai/reference/bf-progress-size.md +26 -0
- package/ai/reference/bf-progress-tone.md +28 -0
- package/ai/reference/bf-radio-group-harness.md +49 -0
- package/ai/reference/bf-radio-group-orientation.md +26 -0
- package/ai/reference/bf-radio-option.md +30 -0
- package/ai/reference/bf-refresher-refresh-event.md +22 -0
- package/ai/reference/bf-segment-option.md +29 -0
- package/ai/reference/bf-segmented-harness.md +48 -0
- package/ai/reference/bf-segmented-size.md +29 -0
- package/ai/reference/bf-select-harness.md +70 -0
- package/ai/reference/bf-select-option.md +29 -0
- package/ai/reference/bf-sheet-auto-focus.md +29 -0
- package/ai/reference/bf-sheet-options.md +32 -0
- package/ai/reference/bf-sheet-ref.md +45 -0
- package/ai/reference/bf-sheet-service.md +34 -0
- package/ai/reference/bf-shell-config-mode.md +28 -0
- package/ai/reference/bf-shell-config.md +38 -0
- package/ai/reference/bf-shell-dynamic-type-limit.md +21 -0
- package/ai/reference/bf-shell-dynamic-type.md +25 -0
- package/ai/reference/bf-shell-mode.md +28 -0
- package/ai/reference/bf-shell-testing-options.md +26 -0
- package/ai/reference/bf-size.md +45 -0
- package/ai/reference/bf-spinner-size.md +27 -0
- package/ai/reference/bf-stack-change.md +22 -0
- package/ai/reference/bf-stack-reuse-strategy.md +32 -0
- package/ai/reference/bf-stack-transition-event.md +26 -0
- package/ai/reference/bf-stack-transition.md +26 -0
- package/ai/reference/bf-stacked-overlay.md +23 -0
- package/ai/reference/bf-system-bars-style.md +38 -0
- package/ai/reference/bf-tab-bar-controller.md +51 -0
- package/ai/reference/bf-tab-bar-host.md +52 -0
- package/ai/reference/bf-tab-context.md +32 -0
- package/ai/reference/bf-tab-links.md +37 -0
- package/ai/reference/bf-testing-options.md +27 -0
- package/ai/reference/bf-text-scale-service.md +35 -0
- package/ai/reference/bf-theme.md +27 -0
- package/ai/reference/bf-toast-action.md +25 -0
- package/ai/reference/bf-toast-controller.md +17 -0
- package/ai/reference/bf-toast-dismiss-reason.md +29 -0
- package/ai/reference/bf-toast-options.md +29 -0
- package/ai/reference/bf-toast-position.md +26 -0
- package/ai/reference/bf-toast-ref.md +41 -0
- package/ai/reference/bf-toast-service.md +39 -0
- package/ai/reference/bf-toggle-label-position.md +26 -0
- package/ai/reference/bf-transition-kind.md +28 -0
- package/ai/reference/bf-validation-message.md +31 -0
- package/ai/reference/bf-validation-messages.md +33 -0
- package/ai/reference/bf-view-event.md +28 -0
- package/ai/reference/bf-view-lifecycle.md +41 -0
- package/ai/reference/bf-view-state.md +28 -0
- package/ai/reference/bf_default_labels.md +21 -0
- package/ai/reference/bf_default_values.md +21 -0
- package/ai/reference/bf_defaults.md +21 -0
- package/ai/reference/bf_desktop_toast_defaults.md +21 -0
- package/ai/reference/bf_dialog_data.md +17 -0
- package/ai/reference/bf_labels.md +21 -0
- package/ai/reference/bf_overlay_data.md +19 -0
- package/ai/reference/bf_overlay_host.md +21 -0
- package/ai/reference/bf_sheet_default_snap_points.md +17 -0
- package/ai/reference/bf_shell_config.md +21 -0
- package/ai/reference/bf_shell_defaults.md +21 -0
- package/ai/reference/bf_tab_bar.md +21 -0
- package/ai/reference/bf_tab_bar_controller.md +21 -0
- package/ai/reference/bf_tab_context.md +21 -0
- package/ai/reference/bf_tab_links.md +21 -0
- package/ai/reference/bf_theme_storage.md +19 -0
- package/ai/reference/create-transition.md +36 -0
- package/ai/reference/duration_fast.md +17 -0
- package/ai/reference/duration_md.md +17 -0
- package/ai/reference/duration_overlay.md +17 -0
- package/ai/reference/duration_push.md +17 -0
- package/ai/reference/fade-down.md +26 -0
- package/ai/reference/fade-in.md +25 -0
- package/ai/reference/fade-out.md +25 -0
- package/ai/reference/fade-up.md +26 -0
- package/ai/reference/inject-shell-mode.md +23 -0
- package/ai/reference/install-bf-jsdom-shims.md +31 -0
- package/ai/reference/ios_duration.md +17 -0
- package/ai/reference/ios_easing.md +17 -0
- package/ai/reference/is-text-entry.md +25 -0
- package/ai/reference/max_complete_ms.md +17 -0
- package/ai/reference/md-transition.md +31 -0
- package/ai/reference/md_duration.md +17 -0
- package/ai/reference/md_easing.md +17 -0
- package/ai/reference/overlay_duration.md +21 -0
- package/ai/reference/overlay_easing.md +19 -0
- package/ai/reference/overlay_reduced_duration.md +17 -0
- package/ai/reference/pop-frames-at.md +25 -0
- package/ai/reference/prefers-reduced-motion.md +25 -0
- package/ai/reference/provide-bf-defaults.md +33 -0
- package/ai/reference/provide-bf-desktop-toast.md +28 -0
- package/ai/reference/provide-bf-labels.md +38 -0
- package/ai/reference/provide-bf-shell-testing.md +34 -0
- package/ai/reference/provide-bf-shell.md +41 -0
- package/ai/reference/provide-bf-testing.md +33 -0
- package/ai/reference/reduced-transition.md +28 -0
- package/ai/reference/reduced_duration.md +17 -0
- package/ai/reference/resolve-shell-mode.md +33 -0
- package/ai/reference/scale-in.md +25 -0
- package/ai/reference/settle-duration.md +25 -0
- package/ai/reference/settle-pop.md +33 -0
- package/ai/reference/settle_easing.md +17 -0
- package/ai/reference/should-complete-pop.md +26 -0
- package/ai/reference/slide-down.md +26 -0
- package/ai/reference/slide-up.md +26 -0
- package/ai/reference/with-bf-shell-routing.md +19 -0
- package/bin/bf-ui.js +81 -0
- package/fesm2022/bitforgehq-ui-icons.mjs +230 -0
- package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-mobile.mjs +5530 -0
- package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-number-input.mjs +680 -0
- package/fesm2022/bitforgehq-ui-number-input.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-overlay.mjs +2675 -0
- package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui-testing.mjs +402 -0
- package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -0
- package/fesm2022/bitforgehq-ui.mjs +7765 -0
- package/fesm2022/bitforgehq-ui.mjs.map +1 -0
- package/llms-full.txt +25394 -0
- package/llms.txt +329 -0
- package/package.json +94 -0
- package/theme.css +253 -0
- package/types/bitforgehq-ui-icons.d.ts +50 -0
- package/types/bitforgehq-ui-mobile.d.ts +2914 -0
- package/types/bitforgehq-ui-number-input.d.ts +282 -0
- package/types/bitforgehq-ui-overlay.d.ts +1514 -0
- package/types/bitforgehq-ui-testing.d.ts +495 -0
- package/types/bitforgehq-ui.d.ts +3499 -0
|
@@ -0,0 +1,2914 @@
|
|
|
1
|
+
import * as i0 from "@angular/core";
|
|
2
|
+
import { AfterViewInit, ComponentRef, EnvironmentInjector, EnvironmentProviders, InjectionToken, Injector, OnDestroy, OnInit, Signal, TemplateRef, Type } from "@angular/core";
|
|
3
|
+
import { SystemBarsStyle } from "@capacitor/core";
|
|
4
|
+
import { ActivatedRoute, ActivatedRouteSnapshot, BaseRouteReuseStrategy, Data, NavigationExtras, RouterConfigurationFeature, RouterOutletContract, Routes, UrlTree } from "@angular/router";
|
|
5
|
+
import * as core from "@bitforgehq/ui/overlay";
|
|
6
|
+
import { BfOverlayController, BfOverlayRef as BfOverlayRef$1, BfOverlayTemplateContext as BfOverlayTemplateContext$1, BfToastAction, BfToastAction as BfToastAction$1, BfToastDismissReason, BfToastRef, BfToastRef as BfToastRef$1, prefersReducedMotion } from "@bitforgehq/ui/overlay";
|
|
7
|
+
import { BfButtonVariant, BfTabBarController } from "@bitforgehq/ui";
|
|
8
|
+
import { IconNode } from "lucide";
|
|
9
|
+
/**
|
|
10
|
+
* The shell's transition and gesture style: `ios`, `md` (Material), or `auto` (iOS on iOS, else
|
|
11
|
+
* `md`).
|
|
12
|
+
*
|
|
13
|
+
* @summary The shell style setting, iOS, Material or automatic from the platform
|
|
14
|
+
* @since 0.3.0
|
|
15
|
+
*/
|
|
16
|
+
type BfShellConfigMode = 'ios' | 'md' | 'auto';
|
|
17
|
+
/**
|
|
18
|
+
* The cap of iOS Dynamic Type: the largest root font scale the shell applies.
|
|
19
|
+
*
|
|
20
|
+
* @summary The largest root font scale iOS Dynamic Type may apply in the shell
|
|
21
|
+
* @since 0.3.0
|
|
22
|
+
*/
|
|
23
|
+
interface BfShellDynamicTypeLimit {
|
|
24
|
+
/** The largest root font scale (2.35, the AX3 size, by default); `Infinity` removes the cap. */
|
|
25
|
+
maxScale: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The shell's iOS Dynamic Type setting: `false` opts out, a `BfShellDynamicTypeLimit` caps it.
|
|
29
|
+
*
|
|
30
|
+
* @summary Whether the shell follows iOS Dynamic Type, and up to which scale
|
|
31
|
+
* @since 0.3.0
|
|
32
|
+
*/
|
|
33
|
+
type BfShellDynamicType = false | BfShellDynamicTypeLimit;
|
|
34
|
+
/**
|
|
35
|
+
* What the Android back button does at the root of every stack, when no overlay or page claims
|
|
36
|
+
* it: `minimize` moves the app to the background (`App.minimizeApp()`), so a relaunch resumes it
|
|
37
|
+
* warm; `exit` finishes the activity (`App.exitApp()`), so the next launch starts cold.
|
|
38
|
+
*
|
|
39
|
+
* @summary What Android back does at a stack root, background the app or exit it
|
|
40
|
+
* @since 0.3.0
|
|
41
|
+
*/
|
|
42
|
+
type BfBackAtRoot = 'minimize' | 'exit';
|
|
43
|
+
/**
|
|
44
|
+
* Configuration of the mobile shell, set once through `provideBfShell()`.
|
|
45
|
+
*
|
|
46
|
+
* @summary The mobile shell settings: mode, swipe-back, haptics, Dynamic Type and system bars
|
|
47
|
+
* @since 0.2.0
|
|
48
|
+
*/
|
|
49
|
+
interface BfShellConfig {
|
|
50
|
+
/**
|
|
51
|
+
* Transition and gesture style: `ios`, `md` (Material), or `auto` (iOS on iOS, else `md`).
|
|
52
|
+
* Overscroll is not part of it: `bf-content`'s iOS bounce and Android stretch and
|
|
53
|
+
* `bf-refresher`'s iOS bounce mode follow the engine (`BfPlatformService.mode()`), because the
|
|
54
|
+
* bounce is WebKit's own and Chrome never reports a negative `scrollTop`.
|
|
55
|
+
* @default 'auto'
|
|
56
|
+
*/
|
|
57
|
+
mode: BfShellConfigMode;
|
|
58
|
+
/**
|
|
59
|
+
* Enables the iOS edge swipe-back in every stack outlet (iOS mode only).
|
|
60
|
+
* @default true
|
|
61
|
+
*/
|
|
62
|
+
swipeBack: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Holds a transition at frame 0 for two animation frames while the entering page renders.
|
|
65
|
+
* @default true
|
|
66
|
+
*/
|
|
67
|
+
deferTransitionStart: boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Plays a light haptic tick on tab changes (native only).
|
|
70
|
+
* @default true
|
|
71
|
+
*/
|
|
72
|
+
hapticsOnTabChange: boolean;
|
|
73
|
+
/**
|
|
74
|
+
* iOS Dynamic Type (native iOS only; see `BfTextScaleService`): the root font size follows the
|
|
75
|
+
* user's text size. `false` opts out; `maxScale` caps the root scale (default 2.35, the AX3
|
|
76
|
+
* size, at least 200 %). `Infinity` removes the cap entirely; a non-finite value other than
|
|
77
|
+
* `Infinity` (e.g. `NaN`) falls back to the default cap. Left out, the default applies. Android
|
|
78
|
+
* needs no setting: its WebView applies the system font scale.
|
|
79
|
+
* @default { maxScale: 2.35 }
|
|
80
|
+
*/
|
|
81
|
+
dynamicType?: BfShellDynamicType;
|
|
82
|
+
/**
|
|
83
|
+
* Native iOS and Android only: the status-bar and navigation-bar icons follow the in-app theme
|
|
84
|
+
* (`BfPlatformService.dark()`) through Capacitor's `SystemBars.setStyle()`, on start and on every
|
|
85
|
+
* theme change (see `bfSystemBarsStyle()`). `false` leaves the system bars to the app.
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
syncSystemBars?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Native Android only: what the back button does when no overlay and no stack can go back
|
|
91
|
+
* (every stack is at its first page). `minimize` (default) moves the app to the background, as
|
|
92
|
+
* Android does for a root activity, so a relaunch resumes it warm on the same tab; `exit`
|
|
93
|
+
* finishes the activity, as 0.2 did, so the next launch starts cold.
|
|
94
|
+
* @default 'minimize'
|
|
95
|
+
*/
|
|
96
|
+
backAtRoot?: BfBackAtRoot;
|
|
97
|
+
/**
|
|
98
|
+
* How many pages of one stack stay alive in each `bf-stack-outlet` (default `Infinity`: every
|
|
99
|
+
* page). Above it, the deepest pages are destroyed and kept as a record (route, URL, history
|
|
100
|
+
* position and the content's scroll position); a pop back to one creates the page again, fires
|
|
101
|
+
* its lifecycle and restores its scroll. Deep pages come back fresh: their component state and
|
|
102
|
+
* the stacks of outlets nested in them are gone. Values below 1 count as 1.
|
|
103
|
+
* @default Infinity
|
|
104
|
+
*/
|
|
105
|
+
maxLivePages?: number;
|
|
106
|
+
}
|
|
107
|
+
/** The default Dynamic Type cap: the AX3 size (40 / 17 px), at least 200 %. Internal. */
|
|
108
|
+
declare const DEFAULT_MAX_TEXT_SCALE = 2.35;
|
|
109
|
+
/**
|
|
110
|
+
* The shell defaults, merged under the overrides given to `provideBfShell()`.
|
|
111
|
+
*
|
|
112
|
+
* @summary The mobile shell defaults that provideBfShell merges the app settings over
|
|
113
|
+
* @since 0.2.0
|
|
114
|
+
*/
|
|
115
|
+
export declare const BF_SHELL_DEFAULTS: Readonly<BfShellConfig>;
|
|
116
|
+
/**
|
|
117
|
+
* The resolved shell configuration.
|
|
118
|
+
*
|
|
119
|
+
* @summary Injection token holding the resolved mobile shell configuration of the app
|
|
120
|
+
* @since 0.2.0
|
|
121
|
+
*/
|
|
122
|
+
export declare const BF_SHELL_CONFIG: InjectionToken<BfShellConfig>;
|
|
123
|
+
/**
|
|
124
|
+
* The platform the app runs on: native iOS, native Android, or a browser.
|
|
125
|
+
*
|
|
126
|
+
* @summary The platform the app runs on, native iOS, native Android or the web
|
|
127
|
+
* @since 0.2.0
|
|
128
|
+
*/
|
|
129
|
+
type BfPlatform = 'ios' | 'android' | 'web';
|
|
130
|
+
/**
|
|
131
|
+
* The shell's look and motion: `ios`, or `md` (Material) everywhere else.
|
|
132
|
+
*
|
|
133
|
+
* @summary The shell's look and motion conventions, iOS or Material Design
|
|
134
|
+
* @since 0.2.0
|
|
135
|
+
*/
|
|
136
|
+
type BfShellMode = 'ios' | 'md';
|
|
137
|
+
/**
|
|
138
|
+
* The app theme choice: follow the system, or force light or dark.
|
|
139
|
+
*
|
|
140
|
+
* @summary The app theme choice, following the system or forcing light or dark
|
|
141
|
+
* @since 0.2.0
|
|
142
|
+
*/
|
|
143
|
+
type BfTheme = 'system' | 'light' | 'dark';
|
|
144
|
+
/** A theme store in memory, gone with the app: where `localStorage` is unavailable, and in tests. Internal. */
|
|
145
|
+
declare function createMemoryThemeStorage(): Pick<Storage, 'getItem' | 'setItem'>;
|
|
146
|
+
/**
|
|
147
|
+
* Where `BfPlatformService` keeps the theme choice (the key `bf-theme`): `localStorage` when it is
|
|
148
|
+
* available, otherwise an in-memory map. Provide another store (a native preferences plugin, or an
|
|
149
|
+
* in-memory one in tests, as `provideBfShellTesting()` does) to keep the choice elsewhere.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* providers: [{ provide: BF_THEME_STORAGE, useValue: sessionStorage }]
|
|
153
|
+
* @summary Injection token for the store that keeps the app theme choice between visits
|
|
154
|
+
* @since 0.3.0
|
|
155
|
+
*/
|
|
156
|
+
export declare const BF_THEME_STORAGE: InjectionToken<Pick<Storage, "getItem" | "setItem">>;
|
|
157
|
+
/**
|
|
158
|
+
* The SystemBars style for a theme: Dark = light icons. Android WebView < 140 pads the WebView, so
|
|
159
|
+
* the bar areas show the activity's window background (which follows the system theme): use
|
|
160
|
+
* Default there.
|
|
161
|
+
*
|
|
162
|
+
* The WebView ≥ 140 case assumes the shell's setup: `viewport-fit=cover` and Capacitor's default
|
|
163
|
+
* `SystemBars.insetsHandling: 'css'`, so the page draws under the bars. With `insetsHandling`
|
|
164
|
+
* `'disable'` or `'native'` the page never reaches under them and the bars show the window
|
|
165
|
+
* background as on older WebViews; pass `syncSystemBars: false` and style them yourself there.
|
|
166
|
+
* `webViewMajor` is read from `Chrome/<n>` in the user agent (Capacitor reads the WebView
|
|
167
|
+
* package, which normally agrees).
|
|
168
|
+
*
|
|
169
|
+
* @example
|
|
170
|
+
* await SystemBars.setStyle({ style: bfSystemBarsStyle(true, 'ios', null) });
|
|
171
|
+
* @param dark Whether the app is dark now (`BfPlatformService.dark()`).
|
|
172
|
+
* @param platform The platform the app runs on.
|
|
173
|
+
* @param webViewMajor The Android WebView's major version (`Chrome/<n>` in the user agent), or
|
|
174
|
+
* `null` when unknown.
|
|
175
|
+
* @returns The `SystemBarsStyle` to pass to `SystemBars.setStyle()`.
|
|
176
|
+
* @summary The system-bar icon style that keeps the bars readable in the in-app theme
|
|
177
|
+
* @since 0.3.0
|
|
178
|
+
*/
|
|
179
|
+
export declare function bfSystemBarsStyle(dark: boolean, platform: BfPlatform, webViewMajor: number | null): SystemBarsStyle;
|
|
180
|
+
/**
|
|
181
|
+
* Platform facts and the app theme: native or web, iOS or Android, the shell mode that follows
|
|
182
|
+
* from it, and the user's theme choice (system, light, dark) reflected as the `dark` class on
|
|
183
|
+
* `<html>`. `matchMedia('(prefers-color-scheme: dark)')` is the single source for the system
|
|
184
|
+
* theme on every platform.
|
|
185
|
+
*
|
|
186
|
+
* The `theme`/`dark` signals always compute, but the `<html>` class and storage writes
|
|
187
|
+
* only run when `provideBfShell()` provided `BF_SHELL_CONFIG` — i.e. this service is the app's
|
|
188
|
+
* own shell, not merely injected by something that wants `platform`/`mode`. Without it (e.g. a
|
|
189
|
+
* docs demo that instantiates `BfPlatformService` directly to preview `bf-tabs`), this service
|
|
190
|
+
* would otherwise fight the host page's own theme: its `effect` runs on construction and would
|
|
191
|
+
* immediately overwrite `<html class="dark">` with whatever `prefers-color-scheme` says.
|
|
192
|
+
*
|
|
193
|
+
* With `provideBfShell()` on a native platform it also makes the viewport meta forbid zoom
|
|
194
|
+
* (`maximum-scale=1, user-scalable=no`, other directives kept; the meta is created if missing):
|
|
195
|
+
* WKWebView zooms a focused control whose font is under 16 px and never zooms back, so the native
|
|
196
|
+
* shell forbids zoom — pinch, double tap and focus alike — and honours the system text size
|
|
197
|
+
* instead (iOS Dynamic Type through `BfTextScaleService`, Android's font scale in the WebView).
|
|
198
|
+
* On the web the meta is never touched, so a web build keeps pinch zoom (the owner's ruling,
|
|
199
|
+
* audit §12): ship `index.html` without `maximum-scale`/`user-scalable`.
|
|
200
|
+
*
|
|
201
|
+
* With `provideBfShell()` on native iOS and Android (unless `syncSystemBars: false`) the status-bar
|
|
202
|
+
* and navigation-bar icons follow `dark()`: `SystemBars.setStyle()` with `bfSystemBarsStyle()`,
|
|
203
|
+
* on start and on every theme change (Android WebView < 140 keeps `Default`, see there).
|
|
204
|
+
* @summary Platform facts and the app theme: native or web, iOS or Android, light or dark
|
|
205
|
+
* @since 0.2.0
|
|
206
|
+
*/
|
|
207
|
+
export declare class BfPlatformService {
|
|
208
|
+
private readonly document;
|
|
209
|
+
private readonly shellConfig;
|
|
210
|
+
private readonly storage;
|
|
211
|
+
/** True inside the native iOS or Android app, false in a browser. */
|
|
212
|
+
readonly isNative: boolean;
|
|
213
|
+
/** The platform the app runs on. */
|
|
214
|
+
readonly platform: BfPlatform;
|
|
215
|
+
/** The platform's shell mode: `ios` on iOS, else `md`; `resolveShellMode()` applies the config. */
|
|
216
|
+
readonly mode: import("@angular/core").Signal<BfShellMode>;
|
|
217
|
+
/** The user's theme choice, stored in `BF_THEME_STORAGE` (`localStorage`); set it with `theme.set(…)`. */
|
|
218
|
+
readonly theme: import("@angular/core").WritableSignal<BfTheme>;
|
|
219
|
+
private readonly systemDark;
|
|
220
|
+
/** Whether the app is dark now: the theme choice, or the system's under `system`. */
|
|
221
|
+
readonly dark: import("@angular/core").Signal<boolean>;
|
|
222
|
+
constructor();
|
|
223
|
+
/** The native system bars are outside the page; a failed call leaves them as they were. */
|
|
224
|
+
private applySystemBars;
|
|
225
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfPlatformService, never>;
|
|
226
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* The shell mode in effect: `config.mode`, or the platform's (`BfPlatformService.mode()`: iOS on
|
|
230
|
+
* iOS, else Material) when it is `'auto'`. The one resolution every mode-dependent part of the
|
|
231
|
+
* shell (stack outlet, modal, header, back button) shares; apps use it (or `injectShellMode()`)
|
|
232
|
+
* to follow the same per-mode conventions, e.g. text vs icon header actions.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* const mode = resolveShellMode(inject(BF_SHELL_CONFIG), inject(BfPlatformService));
|
|
236
|
+
* @param config The shell configuration, usually `inject(BF_SHELL_CONFIG)`.
|
|
237
|
+
* @param platform The platform service.
|
|
238
|
+
* @returns The mode in effect.
|
|
239
|
+
* @summary Resolves the shell mode in effect from the configuration and the platform
|
|
240
|
+
* @since 0.2.0
|
|
241
|
+
*/
|
|
242
|
+
export declare function resolveShellMode(config: Readonly<BfShellConfig>, platform: BfPlatformService): BfShellMode;
|
|
243
|
+
/**
|
|
244
|
+
* `resolveShellMode()` from the injector: `BF_SHELL_CONFIG` (the defaults, i.e. `'auto'`, without
|
|
245
|
+
* `provideBfShell()`) and `BfPlatformService`. Call it in an injection context (a field
|
|
246
|
+
* initializer or constructor); the mode is fixed for the app's lifetime.
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* protected readonly ios = injectShellMode() === 'ios';
|
|
250
|
+
* @returns The mode in effect.
|
|
251
|
+
* @summary Reads the shell mode in effect from the injector, iOS or Material
|
|
252
|
+
* @since 0.2.0
|
|
253
|
+
*/
|
|
254
|
+
export declare function injectShellMode(): BfShellMode;
|
|
255
|
+
/**
|
|
256
|
+
* The hardware back button queue: on native Android it listens to `@capacitor/app`'s
|
|
257
|
+
* `backButton` event; on iOS and web nothing is registered (there is no hardware button to
|
|
258
|
+
* listen to), but `register` and `dispatch` still work so overlays and tests can drive the same
|
|
259
|
+
* queue. `register` adds a handler at a priority (an open overlay registers at 100,
|
|
260
|
+
* `BfNavController` at 0 — it pops the deepest active `bf-stack-outlet`); `dispatch` runs the
|
|
261
|
+
* queue from the highest priority down until one handler returns true; on equal priority the
|
|
262
|
+
* newest registration runs first, so stacked overlays close top-down. When none does (every
|
|
263
|
+
* stack is at its first page), the app moves to the background (`App.minimizeApp()`), so a
|
|
264
|
+
* relaunch resumes it warm; `provideBfShell({ backAtRoot: 'exit' })` finishes it instead
|
|
265
|
+
* (`App.exitApp()`).
|
|
266
|
+
*
|
|
267
|
+
* @example
|
|
268
|
+
* const unregister = backButton.register(100, () => {
|
|
269
|
+
* closeTopOverlay();
|
|
270
|
+
* return true;
|
|
271
|
+
* });
|
|
272
|
+
* @summary The Android hardware back button queue that overlays and navigation stacks share
|
|
273
|
+
* @since 0.2.0
|
|
274
|
+
*/
|
|
275
|
+
export declare class BfBackButtonService {
|
|
276
|
+
private readonly platform;
|
|
277
|
+
private readonly destroyRef;
|
|
278
|
+
private readonly backAtRoot;
|
|
279
|
+
private readonly handlers;
|
|
280
|
+
private sequence;
|
|
281
|
+
constructor();
|
|
282
|
+
/**
|
|
283
|
+
* Adds a handler at `priority` (higher priority runs first; on a tie, the handler registered
|
|
284
|
+
* last runs first). Returns a function that removes
|
|
285
|
+
* it again; call it when the registrant (an overlay, an outlet) is torn down.
|
|
286
|
+
* @param priority Higher runs first: an open overlay uses 100, `BfNavController` 0.
|
|
287
|
+
* @param handler Returns (or resolves) true when it handled the press.
|
|
288
|
+
*/
|
|
289
|
+
register(priority: number, handler: () => boolean | Promise<boolean>): () => void;
|
|
290
|
+
/**
|
|
291
|
+
* Runs the registered handlers from highest to lowest priority until one claims the event
|
|
292
|
+
* (returns true); when none does, minimizes the app (or exits it with `backAtRoot: 'exit'`).
|
|
293
|
+
* Public so tests and the native listener share one code path, and so overlays outside the
|
|
294
|
+
* native listener's reach (phase 2c) can still be driven by it, e.g. `Escape`.
|
|
295
|
+
*/
|
|
296
|
+
dispatch(): Promise<void>;
|
|
297
|
+
private attachNativeListener;
|
|
298
|
+
private minimizeApp;
|
|
299
|
+
private exitApp;
|
|
300
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfBackButtonService, never>;
|
|
301
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Impact weight, mapped to `ImpactStyle.Light` / `Medium` / `Heavy` on native.
|
|
305
|
+
*
|
|
306
|
+
* @summary The weight of an impact haptic, light, medium or heavy
|
|
307
|
+
* @since 0.2.0
|
|
308
|
+
*/
|
|
309
|
+
type BfHapticsImpactStyle = 'light' | 'medium' | 'heavy';
|
|
310
|
+
/**
|
|
311
|
+
* Outcome of a task, mapped to `NotificationType.Success` / `Warning` / `Error` on native.
|
|
312
|
+
*
|
|
313
|
+
* @summary The outcome a notification haptic reports: success, warning or error
|
|
314
|
+
* @since 0.2.0
|
|
315
|
+
*/
|
|
316
|
+
type BfHapticsNotificationType = 'success' | 'warning' | 'error';
|
|
317
|
+
/**
|
|
318
|
+
* Haptic feedback: `impact`, `selection` and `notification` forward to `@capacitor/haptics` on
|
|
319
|
+
* native (loaded lazily on first use, the import cached like `BfKeyboardService`'s plugin); on
|
|
320
|
+
* the web, and when the plugin fails to load (an app that didn't add the optional dependency),
|
|
321
|
+
* every method resolves as a silent no-op.
|
|
322
|
+
*
|
|
323
|
+
* @example
|
|
324
|
+
* const haptics = inject(BfHapticsService);
|
|
325
|
+
* await haptics.impact('light');
|
|
326
|
+
* @since 0.2.0
|
|
327
|
+
* @summary Haptic feedback on native devices that silently does nothing on the web
|
|
328
|
+
*/
|
|
329
|
+
export declare class BfHapticsService {
|
|
330
|
+
private readonly platformService;
|
|
331
|
+
private modulePromise;
|
|
332
|
+
/**
|
|
333
|
+
* Impact feedback: a collision between UI elements of the given weight.
|
|
334
|
+
* @param style The weight of the impact.
|
|
335
|
+
*/
|
|
336
|
+
impact(style: BfHapticsImpactStyle): Promise<void>;
|
|
337
|
+
/** A light tick for a discrete selection change (scrubbing a picker, crossing a threshold). */
|
|
338
|
+
selection(): Promise<void>;
|
|
339
|
+
/**
|
|
340
|
+
* Feedback for the outcome of a task.
|
|
341
|
+
* @param type The outcome of the task.
|
|
342
|
+
*/
|
|
343
|
+
notification(type: BfHapticsNotificationType): Promise<void>;
|
|
344
|
+
private run;
|
|
345
|
+
/**
|
|
346
|
+
* Resolves the plugin, or `null` when it is not installed. The `import()` stays lexically inside
|
|
347
|
+
* the `try` so esbuild tolerates an unresolved optional peer at build time (as in
|
|
348
|
+
* `BfBackButtonService` and `BfKeyboardService`); a bare `import()` fails the consumer's build.
|
|
349
|
+
*/
|
|
350
|
+
private loadPlugin;
|
|
351
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfHapticsService, never>;
|
|
352
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Scales the root font size with iOS Dynamic Type inside the native shell. WKWebView resolves the
|
|
356
|
+
* system text style `font: -apple-system-body` to the user's text size (17 px at the default
|
|
357
|
+
* "Large", 21 px at xxL, 40 px at AX3, 53 px at AX5); a hidden, persistent probe element with that
|
|
358
|
+
* font gives the size, and `<html>` gets `font-size: probe / 17 × 100 %` (rounded to 0.1 %). Every
|
|
359
|
+
* type token and spacing step of the library is in `rem`, so text and rem-based layout grow
|
|
360
|
+
* together, as UIKit's Dynamic Type does.
|
|
361
|
+
*
|
|
362
|
+
* A `ResizeObserver` on the probe re-applies the scale when the setting changes while the app
|
|
363
|
+
* runs (WebKit re-resolves system fonts then); `visibilitychange` re-probes as the fallback. The
|
|
364
|
+
* scale never goes below 1 (the smaller iOS sizes, and a Mac running the iOS app, keep the design
|
|
365
|
+
* size) and is capped at `BfShellConfig.dynamicType.maxScale` (default 2.35; `Infinity` means no
|
|
366
|
+
* cap; `NaN` falls back to the default). A missing or non-finite probe value gives 1; at 1 the
|
|
367
|
+
* root font size is left unset.
|
|
368
|
+
*
|
|
369
|
+
* Acts only with `provideBfShell()` (which starts it at bootstrap), on native iOS, and while
|
|
370
|
+
* `dynamicType` is not `false`. Android needs nothing: its WebView applies the system font scale
|
|
371
|
+
* (`textZoom`) itself, so probing there would scale twice. On the web the browser's own text
|
|
372
|
+
* size and zoom apply. Destroying the service removes the probe, its listeners and the root font
|
|
373
|
+
* size.
|
|
374
|
+
*
|
|
375
|
+
* @example
|
|
376
|
+
* const textScale = inject(BfTextScaleService);
|
|
377
|
+
* const compact = computed(() => textScale.scale() > 1.5);
|
|
378
|
+
* @since 0.2.0
|
|
379
|
+
* @summary Follows iOS Dynamic Type by scaling the root font size of the app
|
|
380
|
+
*/
|
|
381
|
+
export declare class BfTextScaleService {
|
|
382
|
+
private readonly document;
|
|
383
|
+
private readonly platformService;
|
|
384
|
+
private readonly config;
|
|
385
|
+
private readonly destroyRef;
|
|
386
|
+
private readonly scaleState;
|
|
387
|
+
/** Current root scale (1 = the system default "Large"); always 1 on Android and the web. */
|
|
388
|
+
readonly scale: import("@angular/core").Signal<number>;
|
|
389
|
+
constructor();
|
|
390
|
+
private createProbe;
|
|
391
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfTextScaleService, never>;
|
|
392
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
393
|
+
}
|
|
394
|
+
/**
|
|
395
|
+
* Keyboard lifecycle phase, for animations only; never gate logic on the order of the phases.
|
|
396
|
+
* `showing` starts at `keyboardWillShow`, `shown` at `keyboardDidShow`. Either hide event
|
|
397
|
+
* (`keyboardWillHide` or `keyboardDidHide`, whichever arrives first — iOS does not guarantee
|
|
398
|
+
* the order) moves straight to `hidden`, so there is no `hiding` phase.
|
|
399
|
+
*
|
|
400
|
+
* @summary The soft keyboard phase, hidden, showing or shown, for animations only
|
|
401
|
+
* @since 0.2.0
|
|
402
|
+
*/
|
|
403
|
+
type BfKeyboardPhase = 'hidden' | 'showing' | 'shown';
|
|
404
|
+
/**
|
|
405
|
+
* True for an element that opens the soft keyboard when focused: a text-like `input` (not a
|
|
406
|
+
* button, checkbox, color, file, hidden, image, radio, range, reset or submit), a `textarea`, or
|
|
407
|
+
* a `[contenteditable]` element other than `contenteditable="false"`.
|
|
408
|
+
*
|
|
409
|
+
* @param element The element to test, usually `document.activeElement`.
|
|
410
|
+
* @returns Whether it opens the soft keyboard.
|
|
411
|
+
* @summary Tells whether focusing an element opens the soft keyboard on a phone
|
|
412
|
+
* @since 0.2.0
|
|
413
|
+
*/
|
|
414
|
+
export declare function isTextEntry(element: Element | null): element is HTMLElement;
|
|
415
|
+
/**
|
|
416
|
+
* The soft keyboard as signals. On native it listens to the Capacitor Keyboard plugin
|
|
417
|
+
* (`@capacitor/keyboard`, loaded lazily, height known at `keyboardWillShow`); on the web it falls
|
|
418
|
+
* back to `visualViewport` resizes with an 80 px threshold (height known only once the viewport has
|
|
419
|
+
* shrunk; ignored while the page is pinch-zoomed, `visualViewport.scale` ≠ 1); in Jest and SSR it
|
|
420
|
+
* stays inert (height 0, never visible). The rest height (viewport with the keyboard hidden) comes
|
|
421
|
+
* from a fixed `100lvh` probe element, never `innerHeight`, which sticks at a wrong value after a
|
|
422
|
+
* field-to-field focus jump on iOS; it is measured at construction and on window resizes while the
|
|
423
|
+
* keyboard is hidden and no text control is focused, never at will-show. `imminent` flags a focused
|
|
424
|
+
* text control before any keyboard event, and `keyboardTop()` gives the keyboard's top edge in
|
|
425
|
+
* viewport px. It also writes the height as `--bf-keyboard-height` on `<html>` (`0px` while hidden)
|
|
426
|
+
* for CSS that follows the keyboard.
|
|
427
|
+
*
|
|
428
|
+
* @example
|
|
429
|
+
* const keyboard = inject(BfKeyboardService);
|
|
430
|
+
* const hideTabBar = computed(() => keyboard.visible());
|
|
431
|
+
* @since 0.2.0
|
|
432
|
+
* @summary The soft keyboard state as signals: visible, its height and its phase
|
|
433
|
+
*/
|
|
434
|
+
export declare class BfKeyboardService {
|
|
435
|
+
private readonly platformService;
|
|
436
|
+
private readonly document;
|
|
437
|
+
private readonly destroyRef;
|
|
438
|
+
private readonly heightState;
|
|
439
|
+
private readonly phaseState;
|
|
440
|
+
private readonly restHeightState;
|
|
441
|
+
private readonly willShowState;
|
|
442
|
+
private readonly imminentState;
|
|
443
|
+
private imminentTarget;
|
|
444
|
+
private imminentTimer;
|
|
445
|
+
private plugin;
|
|
446
|
+
private probe;
|
|
447
|
+
private destroyed;
|
|
448
|
+
/** Keyboard height in CSS px (iOS: includes the home-indicator strip); 0 when hidden. */
|
|
449
|
+
readonly height: import("@angular/core").Signal<number>;
|
|
450
|
+
/** Lifecycle phase for animations; see `BfKeyboardPhase`. */
|
|
451
|
+
readonly phase: import("@angular/core").Signal<BfKeyboardPhase>;
|
|
452
|
+
/** True from will-show until either hide event: the moment to hide chrome such as the tab bar. */
|
|
453
|
+
readonly visible: import("@angular/core").Signal<boolean>;
|
|
454
|
+
/** True when the keyboard overlays the WebView (native iOS, `resize: 'none'`); false when the WebView resizes. */
|
|
455
|
+
readonly overlaysContent: import("@angular/core").Signal<boolean>;
|
|
456
|
+
/** Viewport height with the keyboard hidden, in CSS px, from a fixed `100lvh` probe. */
|
|
457
|
+
readonly restHeight: import("@angular/core").Signal<number>;
|
|
458
|
+
/** Increments once per keyboard show (at will-show), for one-off reactions such as closing popovers. */
|
|
459
|
+
readonly willShow: import("@angular/core").Signal<number>;
|
|
460
|
+
/**
|
|
461
|
+
* True from `focusin` on a text-entry control (see `isTextEntry`) until that control's
|
|
462
|
+
* `focusout` or either keyboard hide event; never cleared by will-show. Hide chrome such as the
|
|
463
|
+
* tab bar on `visible() || imminent()`: on Android the WebView shrinks before the plugin's
|
|
464
|
+
* will-show, which lifts `position: fixed` elements above the keyboard; `focusin` is the only
|
|
465
|
+
* earlier signal. When it turns true without the keyboard up, it also clears itself after
|
|
466
|
+
* `IMMINENT_TIMEOUT_MS` (2500 ms) unless will-show or a visible keyboard arrives first, so a
|
|
467
|
+
* hardware keyboard, which fires no keyboard event, does not keep the tab bar hidden.
|
|
468
|
+
*/
|
|
469
|
+
readonly imminent: import("@angular/core").Signal<boolean>;
|
|
470
|
+
constructor();
|
|
471
|
+
/** Hides the keyboard: `Keyboard.hide()` on native, blurs the focused element on the web. */
|
|
472
|
+
hide(): Promise<void>;
|
|
473
|
+
/**
|
|
474
|
+
* The keyboard's top edge in viewport CSS px, read on demand. While the keyboard overlays the
|
|
475
|
+
* WebView (native iOS) it is `restHeight() - height()`; where the viewport shrinks for it
|
|
476
|
+
* (Android, the web) it is the bottom of `visualViewport` (else `innerHeight`). With the
|
|
477
|
+
* keyboard hidden it is `restHeight()`.
|
|
478
|
+
*/
|
|
479
|
+
keyboardTop(): number;
|
|
480
|
+
private createProbe;
|
|
481
|
+
private measureRestHeight;
|
|
482
|
+
/** Never measures the rest height: on Android the WebView has already shrunk by will-show. */
|
|
483
|
+
private onWillShow;
|
|
484
|
+
private onDidShow;
|
|
485
|
+
private onHidden;
|
|
486
|
+
/** Either plugin hide event: the keyboard is gone even if the control keeps focus. */
|
|
487
|
+
private onHideEvent;
|
|
488
|
+
private clearImminent;
|
|
489
|
+
/** Arms the hardware-keyboard fallback; a keyboard already up needs none. */
|
|
490
|
+
private armImminentTimeout;
|
|
491
|
+
private cancelImminentTimeout;
|
|
492
|
+
private setHeight;
|
|
493
|
+
private writeHeightVariable;
|
|
494
|
+
private attachPlugin;
|
|
495
|
+
private attachVisualViewport;
|
|
496
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfKeyboardService, never>;
|
|
497
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Provides the mobile shell: its configuration, the stack-aware route reuse strategy
|
|
501
|
+
* (`BfStackReuseStrategy`) and `BF_OVERLAY_HOST` (the hardware back button closes the top overlay
|
|
502
|
+
* through `BfBackButtonService`, which on native Android also stands in for the overlays'
|
|
503
|
+
* `CloseWatcher`, and the document never scrolls, so overlays skip the scroll lock). An environment initializer starts `BfPlatformService` (theme sync, the `dark` class),
|
|
504
|
+
* `BfBackButtonService` (the Android hardware back listener), `BfKeyboardService` (keyboard
|
|
505
|
+
* listeners and the rest-height probe), `BfHapticsService` (its native plugin loads lazily on first
|
|
506
|
+
* use, so this only makes the singleton available) and `BfTextScaleService` (iOS Dynamic Type on
|
|
507
|
+
* the root font size) at bootstrap, before any page renders. Every service is
|
|
508
|
+
* `providedIn: 'root'`, so this function lists none of them: `BfNavController` and the overlay
|
|
509
|
+
* services (`BfOverlayStack`, `BfOverlayService`, `BfSheetService`, `BfModalService`,
|
|
510
|
+
* `BfToastService`, `BfActionSheetService`, `BfAlertDialogService`) are created on first
|
|
511
|
+
* injection, and an app that never injects an overlay service bundles no overlay code. Use it
|
|
512
|
+
* together with `provideRouter(routes, withComponentInputBinding(), withBfShellRouting())`, in the
|
|
513
|
+
* application providers: in a lazy route's environment injector the services still resolve from
|
|
514
|
+
* the root injector.
|
|
515
|
+
*
|
|
516
|
+
* @param config The settings to change; any left out keep `BF_SHELL_DEFAULTS`.
|
|
517
|
+
* @returns The shell's environment providers.
|
|
518
|
+
* @summary Provides the Capacitor app shell: its configuration, navigation and platform services
|
|
519
|
+
* @since 0.2.0
|
|
520
|
+
*/
|
|
521
|
+
export declare function provideBfShell(config?: Partial<BfShellConfig>): EnvironmentProviders;
|
|
522
|
+
/**
|
|
523
|
+
* The router feature the stack needs: `canceledNavigationResolution: 'computed'`, so a refused
|
|
524
|
+
* back navigation (a guard stopping a swipe-back) restores the browser history position and the
|
|
525
|
+
* stack stays in sync with it. Pass it to `provideRouter()`.
|
|
526
|
+
*
|
|
527
|
+
* @returns The router configuration feature.
|
|
528
|
+
* @summary The router setting the mobile shell's stack needs, passed to provideRouter
|
|
529
|
+
* @since 0.2.0
|
|
530
|
+
*/
|
|
531
|
+
export declare function withBfShellRouting(): RouterConfigurationFeature;
|
|
532
|
+
/**
|
|
533
|
+
* The route reuse strategy the stack needs: the default one, except that a route whose *path
|
|
534
|
+
* params* change (`/items/4` → `/items/5`) is a new page, not an in-place update. The default only
|
|
535
|
+
* compares `routeConfig`, so the router would reuse the component and never call the outlet, and
|
|
536
|
+
* the stack would no longer match the history. Query-param changes still reuse the page (filters,
|
|
537
|
+
* tabs). Exported so an app can extend it for its own reuse rules.
|
|
538
|
+
* @summary Route reuse strategy that treats a changed path parameter as a new stack page
|
|
539
|
+
* @since 0.2.0
|
|
540
|
+
*/
|
|
541
|
+
export declare class BfStackReuseStrategy extends BaseRouteReuseStrategy {
|
|
542
|
+
/**
|
|
543
|
+
* Whether the router may reuse the current page for `future`: same route config and path params.
|
|
544
|
+
* @param future The route being navigated to.
|
|
545
|
+
* @param curr The route shown now.
|
|
546
|
+
* @returns True to reuse the page in place.
|
|
547
|
+
*/
|
|
548
|
+
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean;
|
|
549
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfStackReuseStrategy, never>;
|
|
550
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
551
|
+
}
|
|
552
|
+
/**
|
|
553
|
+
* Where a stacked page is in its lifecycle.
|
|
554
|
+
*
|
|
555
|
+
* @summary Where a stacked page is in its lifecycle: entering, active, leaving or inactive
|
|
556
|
+
* @since 0.2.0
|
|
557
|
+
*/
|
|
558
|
+
type BfViewState = 'entering' | 'active' | 'leaving' | 'inactive';
|
|
559
|
+
/**
|
|
560
|
+
* One lifecycle event of a stacked page.
|
|
561
|
+
*
|
|
562
|
+
* @summary The four lifecycle events of a stacked page as it enters and leaves
|
|
563
|
+
* @since 0.2.0
|
|
564
|
+
*/
|
|
565
|
+
type BfViewEvent = 'willEnter' | 'didEnter' | 'willLeave' | 'didLeave';
|
|
566
|
+
/**
|
|
567
|
+
* Per-page lifecycle. `bf-stack-outlet` creates one per page and provides it through the page's
|
|
568
|
+
* element injector; `bf-page` re-exposes it as outputs, and any page or service can
|
|
569
|
+
* `inject(BfViewLifecycle)` to react to the page entering or leaving the top of the stack.
|
|
570
|
+
* `state` and the counters are signals for `computed`/`effect`; `on()` delivers every event
|
|
571
|
+
* synchronously, including the ones that happen before the page's first change detection and
|
|
572
|
+
* right before a popped page is destroyed.
|
|
573
|
+
* @summary The lifecycle of one stacked page as signals and events, from enter to leave
|
|
574
|
+
* @since 0.2.0
|
|
575
|
+
*/
|
|
576
|
+
export declare class BfViewLifecycle {
|
|
577
|
+
/** The page's current lifecycle state. */
|
|
578
|
+
readonly state: import("@angular/core").WritableSignal<BfViewState>;
|
|
579
|
+
/** How often the page started entering; monotonic, so a page can `effect()` on it. */
|
|
580
|
+
readonly willEnter: import("@angular/core").WritableSignal<number>;
|
|
581
|
+
/** How often the page became the top page (its enter transition ended). */
|
|
582
|
+
readonly didEnter: import("@angular/core").WritableSignal<number>;
|
|
583
|
+
/** How often the page started leaving the top of the stack. */
|
|
584
|
+
readonly willLeave: import("@angular/core").WritableSignal<number>;
|
|
585
|
+
/** How often the page stopped being the top page (its leave transition ended). */
|
|
586
|
+
readonly didLeave: import("@angular/core").WritableSignal<number>;
|
|
587
|
+
private readonly listeners;
|
|
588
|
+
/**
|
|
589
|
+
* Calls `listener` synchronously on every event; returns a function that removes it.
|
|
590
|
+
* @param listener Called with each event, synchronously.
|
|
591
|
+
*/
|
|
592
|
+
on(listener: (event: BfViewEvent) => void): () => void;
|
|
593
|
+
/**
|
|
594
|
+
* Moves the page to its `willEnter` state and notifies; called by `bf-stack-outlet`.
|
|
595
|
+
* @internal
|
|
596
|
+
*/
|
|
597
|
+
fireWillEnter(): void;
|
|
598
|
+
/**
|
|
599
|
+
* Moves the page to its `didEnter` state and notifies; called by `bf-stack-outlet`.
|
|
600
|
+
* @internal
|
|
601
|
+
*/
|
|
602
|
+
fireDidEnter(): void;
|
|
603
|
+
/**
|
|
604
|
+
* Moves the page to its `willLeave` state and notifies; called by `bf-stack-outlet`.
|
|
605
|
+
* @internal
|
|
606
|
+
*/
|
|
607
|
+
fireWillLeave(): void;
|
|
608
|
+
/**
|
|
609
|
+
* Moves the page to its `didLeave` state and notifies; called by `bf-stack-outlet`.
|
|
610
|
+
* @internal
|
|
611
|
+
*/
|
|
612
|
+
fireDidLeave(): void;
|
|
613
|
+
private notify;
|
|
614
|
+
}
|
|
615
|
+
/**
|
|
616
|
+
* The direction a navigation should animate in.
|
|
617
|
+
*
|
|
618
|
+
* @summary The direction a stack navigation animates in: forward, back or a new root
|
|
619
|
+
* @since 0.2.0
|
|
620
|
+
*/
|
|
621
|
+
type BfNavDirection = 'forward' | 'back' | 'root';
|
|
622
|
+
/**
|
|
623
|
+
* A router target: a URL string, a `UrlTree` or a commands array, as `Router` accepts.
|
|
624
|
+
*
|
|
625
|
+
* @summary A navigation target as the router accepts it: a URL, a UrlTree or commands
|
|
626
|
+
* @since 0.2.0
|
|
627
|
+
*/
|
|
628
|
+
type BfNavTarget = string | UrlTree | readonly unknown[];
|
|
629
|
+
/** What a stack outlet tells `BfNavController` when it registers (see `registerOutlet`). */
|
|
630
|
+
interface BfNavOutlet {
|
|
631
|
+
/** Number of pages in the outlet's shown stack. */
|
|
632
|
+
readonly depth: Signal<number>;
|
|
633
|
+
/** False while the page that hosts the outlet is parked under another page (or leaving). */
|
|
634
|
+
readonly active: Signal<boolean>;
|
|
635
|
+
/** The (negative) history step that pops the outlet's top page, or null when unknown. */
|
|
636
|
+
popDelta(): number | null;
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Stack-aware navigation. `forward` pushes, `back` pops through the real history (so the browser
|
|
640
|
+
* or WebView history stays in sync), `root` replaces the whole stack. Each call leaves a direction
|
|
641
|
+
* hint that `bf-stack-outlet` consumes on the next activation; without a hint the outlet infers
|
|
642
|
+
* the direction from the router event. A hint lives only as long as the navigation it started:
|
|
643
|
+
* when that navigation ends without an activation (a guard refused it), the hint is dropped so it
|
|
644
|
+
* cannot mislabel the next one. Every primary `bf-stack-outlet` registers here with its nesting
|
|
645
|
+
* level; `depth`, `canGoBack` and `back()` follow the **deepest active outlet** (the innermost one
|
|
646
|
+
* whose page is shown, e.g. the outlet inside `bf-tabs`, or the root outlet once it pushed a page
|
|
647
|
+
* above the tabs page). The controller also owns the priority-0 hardware back handler: it pops the
|
|
648
|
+
* deepest active outlet that has a page to pop, and lets the app exit only when every active
|
|
649
|
+
* outlet is at its first page (a parked outlet cannot be popped, so it never blocks the exit).
|
|
650
|
+
* @summary Stack-aware navigation that pushes, pops through the history and replaces the root
|
|
651
|
+
* @since 0.2.0
|
|
652
|
+
*/
|
|
653
|
+
export declare class BfNavController {
|
|
654
|
+
private readonly router;
|
|
655
|
+
private readonly location;
|
|
656
|
+
private readonly outlets;
|
|
657
|
+
private hint;
|
|
658
|
+
/** Id of the navigation the hint belongs to; null until that navigation starts. */
|
|
659
|
+
private hintNavigationId;
|
|
660
|
+
/** The active outlets, deepest first (on equal level, the one registered last first). */
|
|
661
|
+
private readonly activeOutlets;
|
|
662
|
+
/** Number of pages in the deepest active stack outlet (0 without an outlet). */
|
|
663
|
+
readonly depth: Signal<number>;
|
|
664
|
+
/** True when the deepest active stack has a page to go back to. */
|
|
665
|
+
readonly canGoBack: Signal<boolean>;
|
|
666
|
+
constructor();
|
|
667
|
+
/**
|
|
668
|
+
* Pushes a page.
|
|
669
|
+
* @param url Where to go.
|
|
670
|
+
* @param extras Router navigation extras, such as `queryParams`.
|
|
671
|
+
* @returns Whether the navigation succeeded.
|
|
672
|
+
*/
|
|
673
|
+
forward(url: BfNavTarget, extras?: NavigationExtras): Promise<boolean>;
|
|
674
|
+
/**
|
|
675
|
+
* Replaces the whole stack with one page (`replaceUrl`, no animation).
|
|
676
|
+
* @param url Where to go.
|
|
677
|
+
* @param extras Router navigation extras, such as `queryParams`.
|
|
678
|
+
* @returns Whether the navigation succeeded.
|
|
679
|
+
*/
|
|
680
|
+
root(url: BfNavTarget, extras?: NavigationExtras): Promise<boolean>;
|
|
681
|
+
/**
|
|
682
|
+
* Pops the top page of the deepest active outlet that has one to pop: always a real history
|
|
683
|
+
* step. When the page added history entries of its own (a query-only or nested child
|
|
684
|
+
* navigation), it goes back past them in one step (`Location.historyGo(-n)`) so the page below
|
|
685
|
+
* is shown; otherwise `Location.back()`.
|
|
686
|
+
*/
|
|
687
|
+
back(): void;
|
|
688
|
+
/**
|
|
689
|
+
* Called by every primary stack outlet on init with its nesting level (the number of stack
|
|
690
|
+
* outlets around it). Returns a function that removes it again.
|
|
691
|
+
* @internal
|
|
692
|
+
*/
|
|
693
|
+
registerOutlet(outlet: BfNavOutlet, level: number): () => void;
|
|
694
|
+
/**
|
|
695
|
+
* Returns the pending direction hint and clears it; called by the stack outlet.
|
|
696
|
+
* @internal
|
|
697
|
+
*/
|
|
698
|
+
consumeHint(): BfNavDirection | null;
|
|
699
|
+
/**
|
|
700
|
+
* Drops a pending hint (its navigation never happened).
|
|
701
|
+
* @internal
|
|
702
|
+
*/
|
|
703
|
+
clearHint(): void;
|
|
704
|
+
/** The deepest active outlet with a page to pop, else the deepest active outlet. */
|
|
705
|
+
private popTarget;
|
|
706
|
+
/**
|
|
707
|
+
* The hardware back button: pops while an active outlet has a page to pop; returns false (and
|
|
708
|
+
* the back button service exits the app) when every active outlet is at depth 1 or less. A
|
|
709
|
+
* parked outlet cannot be popped by `back()`, so it does not keep the app from exiting.
|
|
710
|
+
*/
|
|
711
|
+
private handleBackButton;
|
|
712
|
+
private setHint;
|
|
713
|
+
private go;
|
|
714
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfNavController, never>;
|
|
715
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
716
|
+
}
|
|
717
|
+
/**
|
|
718
|
+
* Motion constants of the mobile shell, shared by the page transitions, the overlays and the
|
|
719
|
+
* refresher. `theme.css` mirrors them for CSS: `--ease-ios`, `--ease-md`, `--ease-settle`
|
|
720
|
+
* (`@theme`) and `--bf-duration-fast`, `--bf-duration-overlay`, `--bf-duration-push` (`:root`).
|
|
721
|
+
*/
|
|
722
|
+
/**
|
|
723
|
+
* UIKit's navigation and sheet curve (push/pop, overlays, modal depth); `OVERLAY_EASING` too.
|
|
724
|
+
*
|
|
725
|
+
* @summary The UIKit navigation and sheet easing curve of pushes, pops and overlays
|
|
726
|
+
* @since 0.2.0
|
|
727
|
+
*/
|
|
728
|
+
export declare const IOS_EASING = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
729
|
+
/**
|
|
730
|
+
* Material standard easing (the Android fade-up).
|
|
731
|
+
*
|
|
732
|
+
* @summary The Material standard easing curve of the Android page fade-up transition
|
|
733
|
+
* @since 0.2.0
|
|
734
|
+
*/
|
|
735
|
+
export declare const MD_EASING = "cubic-bezier(0.2, 0, 0, 1)";
|
|
736
|
+
/**
|
|
737
|
+
* Ease-out of a released gesture settling into place (swipe-back, refresher).
|
|
738
|
+
*
|
|
739
|
+
* @summary The ease-out curve a released swipe-back or refresher gesture settles with
|
|
740
|
+
* @since 0.2.0
|
|
741
|
+
*/
|
|
742
|
+
export declare const SETTLE_EASING = "cubic-bezier(0.2, 0.8, 0.3, 1)";
|
|
743
|
+
/**
|
|
744
|
+
* Colour transitions and the reduced-motion cross-fade (ms); the overlay core's reduced fade.
|
|
745
|
+
*
|
|
746
|
+
* @summary The duration of colour transitions and the reduced-motion fade, in milliseconds
|
|
747
|
+
* @since 0.2.0
|
|
748
|
+
*/
|
|
749
|
+
export declare const DURATION_FAST = 150;
|
|
750
|
+
/**
|
|
751
|
+
* Overlay enter/exit and the modal depth effect (ms); the overlay core's duration.
|
|
752
|
+
*
|
|
753
|
+
* @summary The duration of overlay enter and exit and the modal depth effect, in milliseconds
|
|
754
|
+
* @since 0.2.0
|
|
755
|
+
*/
|
|
756
|
+
export declare const DURATION_OVERLAY = 260;
|
|
757
|
+
/**
|
|
758
|
+
* iOS push/pop (ms).
|
|
759
|
+
*
|
|
760
|
+
* @summary The duration of the iOS push and pop page transitions, in milliseconds
|
|
761
|
+
* @since 0.2.0
|
|
762
|
+
*/
|
|
763
|
+
export declare const DURATION_PUSH = 500;
|
|
764
|
+
/**
|
|
765
|
+
* Material fade-up and the refresher settle (ms).
|
|
766
|
+
*
|
|
767
|
+
* @summary The duration of the Material fade-up and the refresher settle, in milliseconds
|
|
768
|
+
* @since 0.2.0
|
|
769
|
+
*/
|
|
770
|
+
export declare const DURATION_MD = 220;
|
|
771
|
+
/**
|
|
772
|
+
* The iOS push and pop (ms), `DURATION_PUSH`.
|
|
773
|
+
*
|
|
774
|
+
* @summary The duration of the iOS push and pop stack transitions, in milliseconds
|
|
775
|
+
* @since 0.2.0
|
|
776
|
+
*/
|
|
777
|
+
export declare const IOS_DURATION = 500;
|
|
778
|
+
/**
|
|
779
|
+
* Upper bound of the settle animation after a released swipe.
|
|
780
|
+
*
|
|
781
|
+
* @summary The longest a released swipe-back may take to settle, in milliseconds
|
|
782
|
+
* @since 0.2.0
|
|
783
|
+
*/
|
|
784
|
+
export declare const MAX_COMPLETE_MS = 540;
|
|
785
|
+
/**
|
|
786
|
+
* Material fade-up.
|
|
787
|
+
*
|
|
788
|
+
* @summary The duration of the Material fade-up stack transition, in milliseconds
|
|
789
|
+
* @since 0.2.0
|
|
790
|
+
*/
|
|
791
|
+
export declare const MD_DURATION = 220;
|
|
792
|
+
/**
|
|
793
|
+
* Cross-fade used under `prefers-reduced-motion`.
|
|
794
|
+
*
|
|
795
|
+
* @summary The duration of the cross-fade that replaces page motion under reduced motion
|
|
796
|
+
* @since 0.2.0
|
|
797
|
+
*/
|
|
798
|
+
export declare const REDUCED_DURATION = 150;
|
|
799
|
+
/**
|
|
800
|
+
* A running set of animations that finish together.
|
|
801
|
+
*
|
|
802
|
+
* @summary A running set of page transition animations that finish together
|
|
803
|
+
* @since 0.2.0
|
|
804
|
+
*/
|
|
805
|
+
interface BfStackTransition {
|
|
806
|
+
/** The Web Animations of the transition, one per moving layer. */
|
|
807
|
+
readonly animations: Animation[];
|
|
808
|
+
/** Their shared duration (ms). */
|
|
809
|
+
readonly duration: number;
|
|
810
|
+
/** Resolves when every animation finished or was cancelled; never rejects. */
|
|
811
|
+
readonly finished: Promise<void>;
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* The direction of a stack transition: a page pushed on, or popped off.
|
|
815
|
+
*
|
|
816
|
+
* @summary The direction of a stack transition, a page pushed on or popped off
|
|
817
|
+
* @since 0.2.0
|
|
818
|
+
*/
|
|
819
|
+
type BfTransitionKind = 'push' | 'pop';
|
|
820
|
+
/**
|
|
821
|
+
* The iOS push or pop. `pop` is written as the literal reverse of a push but as forward
|
|
822
|
+
* keyframes, so `currentTime` maps directly to swipe progress (0 = nothing moved, duration = pop
|
|
823
|
+
* complete). Returns three animations: the top page (slide and edge shadow), the page under it
|
|
824
|
+
* (parallax) and the dim layer.
|
|
825
|
+
*
|
|
826
|
+
* @param kind `push` or `pop`.
|
|
827
|
+
* @param entering The page that becomes visible.
|
|
828
|
+
* @param leaving The page that goes away.
|
|
829
|
+
* @param dim The dimming layer between the two pages.
|
|
830
|
+
* @param width The width the pages travel (the outlet width, px).
|
|
831
|
+
* @param easing The curve of the transition.
|
|
832
|
+
* @returns The three running animations.
|
|
833
|
+
* @summary Builds the iOS push or pop with its slide, parallax and dimming layers
|
|
834
|
+
* @since 0.2.0
|
|
835
|
+
*/
|
|
836
|
+
export declare function createTransition(kind: BfTransitionKind, entering: HTMLElement, leaving: HTMLElement, dim: HTMLElement, width: number, easing?: string): BfStackTransition;
|
|
837
|
+
/**
|
|
838
|
+
* Material fade-up: the entering page fades in while rising 16 px; a pop is the reverse on the
|
|
839
|
+
* leaving page. No parallax, no dim.
|
|
840
|
+
*
|
|
841
|
+
* @param kind `push` or `pop`.
|
|
842
|
+
* @param entering The page that becomes visible.
|
|
843
|
+
* @param leaving The page that goes away.
|
|
844
|
+
* @returns The running animation.
|
|
845
|
+
* @summary Builds the Material fade-up page transition of a push or a pop
|
|
846
|
+
* @since 0.2.0
|
|
847
|
+
*/
|
|
848
|
+
export declare function mdTransition(kind: BfTransitionKind, entering: HTMLElement, leaving: HTMLElement): BfStackTransition;
|
|
849
|
+
/**
|
|
850
|
+
* Reduced motion: a 150 ms cross-fade of the two pages, nothing moves.
|
|
851
|
+
*
|
|
852
|
+
* @param entering The page that becomes visible.
|
|
853
|
+
* @param leaving The page that goes away.
|
|
854
|
+
* @returns The two running fades.
|
|
855
|
+
* @summary Builds the cross-fade that replaces page motion when the user reduces motion
|
|
856
|
+
* @since 0.2.0
|
|
857
|
+
*/
|
|
858
|
+
export declare function reducedTransition(entering: HTMLElement, leaving: HTMLElement): BfStackTransition;
|
|
859
|
+
/**
|
|
860
|
+
* Frame values of the pop at progress `p` (0 = start, 1 = done), used to hand a scrubbed gesture
|
|
861
|
+
* over to a fresh eased animation on release.
|
|
862
|
+
*
|
|
863
|
+
* @param p The pop progress, 0 (start) to 1 (done).
|
|
864
|
+
* @param width The outlet width (px).
|
|
865
|
+
* @returns The top page offset, the page under it and the dim opacity.
|
|
866
|
+
* @summary The positions of the pop layers at a given progress, for scrubbing a swipe
|
|
867
|
+
* @since 0.2.0
|
|
868
|
+
*/
|
|
869
|
+
export declare function popFramesAt(p: number, width: number): {
|
|
870
|
+
top: number;
|
|
871
|
+
under: number;
|
|
872
|
+
dim: number;
|
|
873
|
+
};
|
|
874
|
+
/**
|
|
875
|
+
* Animates top, under and dim from pop progress `from` to `to` with an ease-out.
|
|
876
|
+
*
|
|
877
|
+
* @param top The page being popped.
|
|
878
|
+
* @param under The page under it.
|
|
879
|
+
* @param dim The dimming layer.
|
|
880
|
+
* @param width The outlet width (px).
|
|
881
|
+
* @param from The progress at release, 0 to 1.
|
|
882
|
+
* @param to The progress to settle at: 1 completes the pop, 0 cancels it.
|
|
883
|
+
* @param duration The settle duration (ms), see `settleDuration`.
|
|
884
|
+
* @returns The three running animations.
|
|
885
|
+
* @summary Animates a released swipe-back from its progress to done or back to the start
|
|
886
|
+
* @since 0.2.0
|
|
887
|
+
*/
|
|
888
|
+
export declare function settlePop(top: HTMLElement, under: HTMLElement, dim: HTMLElement, width: number, from: number, to: number, duration: number): BfStackTransition;
|
|
889
|
+
/**
|
|
890
|
+
* The release rule of the swipe-back: a flick (`velocity` above 0.2 px/ms) or a drag past half
|
|
891
|
+
* the width completes the pop; anything else settles back.
|
|
892
|
+
*
|
|
893
|
+
* @param velocity The release speed (px/ms, positive towards the end edge).
|
|
894
|
+
* @param delta The distance swiped (px).
|
|
895
|
+
* @param width The outlet width (px).
|
|
896
|
+
* @returns True when the pop completes.
|
|
897
|
+
* @summary Decides whether a released swipe-back completes the pop or settles back
|
|
898
|
+
* @since 0.2.0
|
|
899
|
+
*/
|
|
900
|
+
export declare function shouldCompletePop(velocity: number, delta: number, width: number): boolean;
|
|
901
|
+
/**
|
|
902
|
+
* Duration of the settle animation after a release: the remaining distance at the release speed
|
|
903
|
+
* (at least 0.5 px/ms), clamped to 120 ms … `MAX_COMPLETE_MS`.
|
|
904
|
+
*
|
|
905
|
+
* @param remainingPx The distance left to travel (px).
|
|
906
|
+
* @param velocity The release speed (px/ms).
|
|
907
|
+
* @returns The duration (ms), 120 to `MAX_COMPLETE_MS`.
|
|
908
|
+
* @summary The duration of the settle animation after a released swipe-back gesture
|
|
909
|
+
* @since 0.2.0
|
|
910
|
+
*/
|
|
911
|
+
export declare function settleDuration(remainingPx: number, velocity: number): number;
|
|
912
|
+
/**
|
|
913
|
+
* Emitted by `bf-stack-outlet` after every change of its stack.
|
|
914
|
+
*
|
|
915
|
+
* @summary What a stack outlet reports after its stack changed: the depth and the tab
|
|
916
|
+
* @since 0.2.0
|
|
917
|
+
*/
|
|
918
|
+
interface BfStackChange {
|
|
919
|
+
/** Number of pages in the active stack. */
|
|
920
|
+
depth: number;
|
|
921
|
+
/** Key of the active tab's stack inside `bf-tabs`; null for an outlet outside `bf-tabs`. */
|
|
922
|
+
tabKey: string | null;
|
|
923
|
+
}
|
|
924
|
+
/**
|
|
925
|
+
* Emitted by `bf-stack-outlet` around a transition between two pages.
|
|
926
|
+
*
|
|
927
|
+
* @summary What a stack outlet reports around a page transition: its kind and animation
|
|
928
|
+
* @since 0.2.0
|
|
929
|
+
*/
|
|
930
|
+
interface BfStackTransitionEvent {
|
|
931
|
+
/** `push` for a new page (also a `replaceUrl` navigation), `pop` for going back. */
|
|
932
|
+
kind: BfTransitionKind;
|
|
933
|
+
/** False when the pages switched without an animation (`animated=false`). */
|
|
934
|
+
animated: boolean;
|
|
935
|
+
}
|
|
936
|
+
/**
|
|
937
|
+
* A router outlet that keeps a stack of live pages: a push slides the new page in and parks the
|
|
938
|
+
* previous one (still in the DOM, so scroll and state survive), a pop slides the top page out and
|
|
939
|
+
* destroys it, and on iOS a finger's edge swipe scrubs the pop (touch only: a mouse or pen drag
|
|
940
|
+
* never arms it). `provideBfShell({ maxLivePages })` bounds the live pages of each stack: the
|
|
941
|
+
* deepest ones are destroyed and created again, scroll restored, on a pop back to them. Replaces
|
|
942
|
+
* `<router-outlet>` in a mobile app.
|
|
943
|
+
* Pages receive route params, query params and route data as inputs, bound by the outlet itself.
|
|
944
|
+
* Inside `bf-tabs` it keeps one stack per tab and switches between them without a transition.
|
|
945
|
+
* Outlets nest: an outlet inside a page (the tabs page) keeps its stacks while an outer outlet
|
|
946
|
+
* parks that page, and `BfNavController` follows the innermost outlet whose page is shown.
|
|
947
|
+
*
|
|
948
|
+
* @example
|
|
949
|
+
* <bf-stack-outlet />
|
|
950
|
+
* @summary Router outlet keeping a live page stack with slide transitions and iOS swipe back
|
|
951
|
+
* @category Navigation
|
|
952
|
+
* @since 0.2.0
|
|
953
|
+
*/
|
|
954
|
+
export declare class BfStackOutletComponent implements RouterOutletContract, OnInit, AfterViewInit, OnDestroy {
|
|
955
|
+
/** Outlet name, as on `router-outlet`. */
|
|
956
|
+
readonly name: import("@angular/core").InputSignal<string>;
|
|
957
|
+
/** Enables the iOS edge swipe-back for this outlet (ignored in Material mode). */
|
|
958
|
+
readonly swipeGesture: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
959
|
+
/** Animates push and pop; false switches pages instantly (lifecycle events still fire). */
|
|
960
|
+
readonly animated: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
961
|
+
/** Emitted with the new depth after every change of the stack. */
|
|
962
|
+
readonly stackChanged: import("@angular/core").OutputEmitterRef<BfStackChange>;
|
|
963
|
+
/** Emitted when a transition between two pages starts (also the start of a swipe-back). */
|
|
964
|
+
readonly transitionStarted: import("@angular/core").OutputEmitterRef<BfStackTransitionEvent>;
|
|
965
|
+
/** Emitted when a transition between two pages has settled. */
|
|
966
|
+
readonly transitionEnded: import("@angular/core").OutputEmitterRef<BfStackTransitionEvent>;
|
|
967
|
+
/**
|
|
968
|
+
* Emitted with the new depth after every change of the stack, together with `stackChanged`.
|
|
969
|
+
* @deprecated 0.3.0 use stackChanged; removed in 0.4.0
|
|
970
|
+
*/
|
|
971
|
+
readonly stackChange: import("@angular/core").OutputEmitterRef<BfStackChange>;
|
|
972
|
+
/**
|
|
973
|
+
* Emitted when a transition starts, together with `transitionStarted`.
|
|
974
|
+
* @deprecated 0.3.0 use transitionStarted; removed in 0.4.0
|
|
975
|
+
*/
|
|
976
|
+
readonly transitionStart: import("@angular/core").OutputEmitterRef<BfStackTransitionEvent>;
|
|
977
|
+
/**
|
|
978
|
+
* Emitted when a transition has settled, together with `transitionEnded`.
|
|
979
|
+
* @deprecated 0.3.0 use transitionEnded; removed in 0.4.0
|
|
980
|
+
*/
|
|
981
|
+
readonly transitionEnd: import("@angular/core").OutputEmitterRef<BfStackTransitionEvent>;
|
|
982
|
+
readonly supportsBindingToComponentInputs: true;
|
|
983
|
+
private readonly parentContexts;
|
|
984
|
+
private readonly router;
|
|
985
|
+
private readonly location;
|
|
986
|
+
private readonly nav;
|
|
987
|
+
private readonly overlays;
|
|
988
|
+
private readonly config;
|
|
989
|
+
private readonly platform;
|
|
990
|
+
private readonly host;
|
|
991
|
+
private readonly document;
|
|
992
|
+
private readonly tabContext;
|
|
993
|
+
/** The stack outlet around this one (this outlet is inside one of its pages), if any. */
|
|
994
|
+
private readonly parentOutlet;
|
|
995
|
+
/** The page of the parent outlet this outlet lives in, if any. */
|
|
996
|
+
private readonly outletHost;
|
|
997
|
+
/** Lifecycle of the page hosting this outlet (null for a root outlet); forwarded to our page. */
|
|
998
|
+
private readonly hostLifecycle;
|
|
999
|
+
/** Removes the listener on `hostLifecycle`. */
|
|
1000
|
+
private hostLifecycleOff;
|
|
1001
|
+
/** Number of stack outlets around this one: 0 for the root outlet. */
|
|
1002
|
+
private readonly level;
|
|
1003
|
+
/** False while the page hosting this outlet is parked, so none of its pages is shown. */
|
|
1004
|
+
private readonly shown;
|
|
1005
|
+
private readonly depthState;
|
|
1006
|
+
private readonly anchor;
|
|
1007
|
+
private readonly dim;
|
|
1008
|
+
private readonly mode;
|
|
1009
|
+
private readonly injector;
|
|
1010
|
+
/** Pages of one stack kept alive (`BfShellConfig.maxLivePages`): at least 1, else every page. */
|
|
1011
|
+
private readonly maxLivePages;
|
|
1012
|
+
/** One stack per tab key inside `bf-tabs`; a single stack under the `null` key otherwise. */
|
|
1013
|
+
private readonly stacks;
|
|
1014
|
+
/** Key of the stack that is shown; always null outside `bf-tabs`. */
|
|
1015
|
+
private activeTab;
|
|
1016
|
+
private active;
|
|
1017
|
+
private leaving;
|
|
1018
|
+
/**
|
|
1019
|
+
* The page deactivated while the host page was parked (an outer outlet pushed above it): kept,
|
|
1020
|
+
* with every stack, and resumed as it was when the host page comes back.
|
|
1021
|
+
*/
|
|
1022
|
+
private suspended;
|
|
1023
|
+
private pending;
|
|
1024
|
+
private viewReady;
|
|
1025
|
+
/** The running transition and the completion that must run if it gets interrupted. */
|
|
1026
|
+
private current;
|
|
1027
|
+
/** Final frame of a completed swipe, held until the router re-activates the page below. */
|
|
1028
|
+
private held;
|
|
1029
|
+
/** Set while the swipe gesture has already animated the pop the router now performs. */
|
|
1030
|
+
private gestureCommitted;
|
|
1031
|
+
private gesture;
|
|
1032
|
+
private lastStart;
|
|
1033
|
+
private destroyed;
|
|
1034
|
+
/** Pending rAF of the deferred transition start. */
|
|
1035
|
+
private startFrame;
|
|
1036
|
+
/** Fallback timer after a completed swipe's `Location.back()`. */
|
|
1037
|
+
private backFallback;
|
|
1038
|
+
/** Unregisters this outlet from `BfNavController`; primary outlets only. */
|
|
1039
|
+
private navUnregister;
|
|
1040
|
+
/** Unregisters the host as a page root of `BfOverlayStack`; outermost outlets only. */
|
|
1041
|
+
private rootUnregister;
|
|
1042
|
+
/** History position after the last completed navigation (see `pageIdOf`). */
|
|
1043
|
+
private settledPageId;
|
|
1044
|
+
/** Element that had focus in the top page when a swipe was claimed, restored on cancel. */
|
|
1045
|
+
private swipeFocus;
|
|
1046
|
+
/** The stack that is shown (the active tab's stack inside `bf-tabs`). */
|
|
1047
|
+
private get stack();
|
|
1048
|
+
constructor();
|
|
1049
|
+
get isActivated(): boolean;
|
|
1050
|
+
get component(): object;
|
|
1051
|
+
get activatedRoute(): ActivatedRoute;
|
|
1052
|
+
get activatedRouteData(): Data;
|
|
1053
|
+
get activatedComponentRef(): ComponentRef<unknown> | null;
|
|
1054
|
+
ngOnInit(): void;
|
|
1055
|
+
ngAfterViewInit(): void;
|
|
1056
|
+
ngOnDestroy(): void;
|
|
1057
|
+
/**
|
|
1058
|
+
* The router tears down the active page. It is NOT destroyed here: it either stays under the
|
|
1059
|
+
* next page (push) or is removed after the pop animation (decided in `activateWith`).
|
|
1060
|
+
* @internal
|
|
1061
|
+
*/
|
|
1062
|
+
deactivate(): void;
|
|
1063
|
+
/**
|
|
1064
|
+
* The router shows a page: pushed, popped to, or a new root (the router outlet contract).
|
|
1065
|
+
* @internal
|
|
1066
|
+
*/
|
|
1067
|
+
activateWith(activatedRoute: ActivatedRoute, environmentInjector: EnvironmentInjector): void;
|
|
1068
|
+
/**
|
|
1069
|
+
* Only called by a store/retrieve `RouteReuseStrategy`; the stack itself never needs one.
|
|
1070
|
+
* @internal
|
|
1071
|
+
*/
|
|
1072
|
+
detach(): ComponentRef<unknown>;
|
|
1073
|
+
/**
|
|
1074
|
+
* Re-attaches a page a store/retrieve `RouteReuseStrategy` kept (the router outlet contract).
|
|
1075
|
+
* @internal
|
|
1076
|
+
*/
|
|
1077
|
+
attach(ref: ComponentRef<unknown>, activatedRoute: ActivatedRoute): void;
|
|
1078
|
+
/**
|
|
1079
|
+
* The URL of the top page of a tab's stack (inside `bf-tabs`), or null when that tab has no
|
|
1080
|
+
* stack yet. `bf-tabs` navigates there on a tab switch, so the tab comes back as it was left.
|
|
1081
|
+
* @param tabKey The key of the tab, the URL segment after `tabsPath`.
|
|
1082
|
+
*/
|
|
1083
|
+
lastUrlOf(tabKey: string): string | null;
|
|
1084
|
+
/**
|
|
1085
|
+
* Pops the active stack back to its first page in one history step (`Location.historyGo(-n)`
|
|
1086
|
+
* to the entry before the second page was pushed), keeping that page alive. Returns false, and
|
|
1087
|
+
* does nothing, when the stack has one page or the history position is unknown.
|
|
1088
|
+
*/
|
|
1089
|
+
popToRoot(): boolean;
|
|
1090
|
+
/**
|
|
1091
|
+
* Scrolls the active page's `bf-content` back to the top (a re-selected tab).
|
|
1092
|
+
* @param behavior `smooth` (the default) or `instant`.
|
|
1093
|
+
*/
|
|
1094
|
+
scrollActiveContentToTop(behavior?: ScrollBehavior): void;
|
|
1095
|
+
/**
|
|
1096
|
+
* A navigation onto another tab's key: parks the whole current stack and shows the target
|
|
1097
|
+
* stack (its page for this URL, the pages above it dropped) or starts it with a new page. No
|
|
1098
|
+
* transition and no gesture; `fresh` (a `root` navigation) discards the target stack first.
|
|
1099
|
+
*/
|
|
1100
|
+
private switchStack;
|
|
1101
|
+
/** Shows a page of the stack again: a live one as it was, a dormant one created anew. */
|
|
1102
|
+
private bringBack;
|
|
1103
|
+
/**
|
|
1104
|
+
* Creates a dormant page again from the route the router re-activated, in a new frame, keeping
|
|
1105
|
+
* its record (key, history position, URL); its scroller gets the `scrollTop` it had back after
|
|
1106
|
+
* the first render. Its nested outlets start empty ("deep pages come back fresh").
|
|
1107
|
+
*/
|
|
1108
|
+
private revive;
|
|
1109
|
+
/**
|
|
1110
|
+
* Keeps at most `maxLivePages` pages of the shown stack alive: the deepest ones beyond it go
|
|
1111
|
+
* dormant (component destroyed, frame removed, record kept). The top pages stay alive.
|
|
1112
|
+
*/
|
|
1113
|
+
private trimStack;
|
|
1114
|
+
private makeDormant;
|
|
1115
|
+
/** Shows a kept page again: new route, nested outlets re-attached, change detection back on. */
|
|
1116
|
+
private reactivate;
|
|
1117
|
+
private tabOf;
|
|
1118
|
+
private destroyAllStacks;
|
|
1119
|
+
private classify;
|
|
1120
|
+
private createEntry;
|
|
1121
|
+
/**
|
|
1122
|
+
* Moves the page host into its own positioned frame. The host stays a view of the anchor's
|
|
1123
|
+
* `ViewContainerRef` (Angular removes a destroyed host from whatever parent it has); the frame
|
|
1124
|
+
* is what gets animated, parked and focused, so the page host stays free of outlet state.
|
|
1125
|
+
*/
|
|
1126
|
+
private wrap;
|
|
1127
|
+
/**
|
|
1128
|
+
* The outlet's own component-input binder: the router's (`RoutedComponentInputBinder` behind
|
|
1129
|
+
* the private `INPUT_BINDER` token) only serves `RouterOutlet`. Mirrors its Angular 22.1
|
|
1130
|
+
* behaviour with the default options, whether or not `withComponentInputBinding()` is present:
|
|
1131
|
+
* query params, then path params, then route data (including resolved data), each input set
|
|
1132
|
+
* (or cleared with `undefined`) on every emission. Not supported: the feature's
|
|
1133
|
+
* `queryParams: false` and `unmatchedInputBehavior` options and the experimental route
|
|
1134
|
+
* `resources`.
|
|
1135
|
+
*/
|
|
1136
|
+
private bindInputs;
|
|
1137
|
+
private destroyEntry;
|
|
1138
|
+
private emitTransitionStart;
|
|
1139
|
+
private emitTransitionEnd;
|
|
1140
|
+
private emitDepth;
|
|
1141
|
+
/** Makes `entry` the active page; the page it replaces is parked for its nested outlets. */
|
|
1142
|
+
private setActive;
|
|
1143
|
+
/**
|
|
1144
|
+
* The host page is back (the outer outlet popped to it): shows the page that was active when
|
|
1145
|
+
* it was parked, as it was, when the router activates the same route key on the same stack.
|
|
1146
|
+
* Returns false for any other route, which then goes through the normal classification.
|
|
1147
|
+
*/
|
|
1148
|
+
private resume;
|
|
1149
|
+
/**
|
|
1150
|
+
* The host page entered or left (the parent outlet parked or restored it): the page this outlet
|
|
1151
|
+
* shows follows it. Fires only on a real state change, so a page that just ran its own
|
|
1152
|
+
* transition (or its first activation) does not get an event twice.
|
|
1153
|
+
*/
|
|
1154
|
+
private forwardHostEvent;
|
|
1155
|
+
private requireActive;
|
|
1156
|
+
/**
|
|
1157
|
+
* Layers the two pages, fires the lifecycle, animates (unless `kind` is null, `animated` is
|
|
1158
|
+
* off or a swipe already animated the pop), then destroys `removed`, parks `leaving` when it
|
|
1159
|
+
* stays in the stack and moves focus.
|
|
1160
|
+
*/
|
|
1161
|
+
private runTransition;
|
|
1162
|
+
private createAnimation;
|
|
1163
|
+
/** A new activation during a running transition finishes the old one at once. */
|
|
1164
|
+
private interruptTransition;
|
|
1165
|
+
private clearBackFallback;
|
|
1166
|
+
private releaseHeld;
|
|
1167
|
+
private moveFocus;
|
|
1168
|
+
/** During a transition: both pages visible, only the entering one interactive. */
|
|
1169
|
+
private layer;
|
|
1170
|
+
/** Final state: only the top page visible and interactive; the rest parked. */
|
|
1171
|
+
private settleLayers;
|
|
1172
|
+
/**
|
|
1173
|
+
* Non-passive `touchmove` guard, attached only while a swipe is armed (which happens only inside
|
|
1174
|
+
* the 50 px edge zone). Once the swipe is claimed, native scrolling must not start: a horizontal
|
|
1175
|
+
* scroller under the finger (any `overflow-x-auto` row, which pans on its own) would take over
|
|
1176
|
+
* the touch and cancel the pointer stream. Inside the edge zone the gesture wins; outside it the
|
|
1177
|
+
* guard is never attached, so such scrollers keep their own pan.
|
|
1178
|
+
*/
|
|
1179
|
+
private readonly touchMoveGuard;
|
|
1180
|
+
private readonly onPointerDown;
|
|
1181
|
+
private readonly onPointerMove;
|
|
1182
|
+
private readonly onPointerUp;
|
|
1183
|
+
private readonly onPointerCancel;
|
|
1184
|
+
/** Settles a swipe that did not pop: the top page stays, the page under it is parked again. */
|
|
1185
|
+
private cancelSwipe;
|
|
1186
|
+
/**
|
|
1187
|
+
* The history step that pops the top page in one navigation: back to the entry before the page
|
|
1188
|
+
* was pushed, skipping the entries it added itself (query-only or nested child navigations).
|
|
1189
|
+
* Null when unknown, and `Location.back()` is used instead.
|
|
1190
|
+
*/
|
|
1191
|
+
private popDelta;
|
|
1192
|
+
private endGesture;
|
|
1193
|
+
/** The router refused a swiped pop (a guard): slide the top page back in over 300 ms. */
|
|
1194
|
+
private restoreAfterRefusedPop;
|
|
1195
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfStackOutletComponent, never>;
|
|
1196
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfStackOutletComponent, "bf-stack-outlet", never, {
|
|
1197
|
+
"name": {
|
|
1198
|
+
"alias": "name";
|
|
1199
|
+
"required": false;
|
|
1200
|
+
"isSignal": true;
|
|
1201
|
+
};
|
|
1202
|
+
"swipeGesture": {
|
|
1203
|
+
"alias": "swipeGesture";
|
|
1204
|
+
"required": false;
|
|
1205
|
+
"isSignal": true;
|
|
1206
|
+
};
|
|
1207
|
+
"animated": {
|
|
1208
|
+
"alias": "animated";
|
|
1209
|
+
"required": false;
|
|
1210
|
+
"isSignal": true;
|
|
1211
|
+
};
|
|
1212
|
+
}, {
|
|
1213
|
+
"stackChanged": "stackChanged";
|
|
1214
|
+
"transitionStarted": "transitionStarted";
|
|
1215
|
+
"transitionEnded": "transitionEnded";
|
|
1216
|
+
"stackChange": "stackChange";
|
|
1217
|
+
"transitionStart": "transitionStart";
|
|
1218
|
+
"transitionEnd": "transitionEnd";
|
|
1219
|
+
}, never, never, true, never>;
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* The page frame of a mobile app: `bf-stack-outlet` positions one per stacked page and provides
|
|
1223
|
+
* its `BfViewLifecycle` through the element injector. Everything scrollable inside a page goes
|
|
1224
|
+
* into `bf-content`; `bf-page` is only the frame, the lifecycle signal and a per-page
|
|
1225
|
+
* `BfPageContext` (provided for its children, where `bf-content` registers its scroller). The
|
|
1226
|
+
* page an outlet shows makes its `bf-content` the document's `main` landmark. Used
|
|
1227
|
+
* standalone (outside an outlet, e.g. in a docs demo) it falls back to a local, inert lifecycle
|
|
1228
|
+
* instance instead of throwing, and exposes no `main` landmark.
|
|
1229
|
+
*
|
|
1230
|
+
* @example
|
|
1231
|
+
* <bf-page (bfViewDidEnter)="load()">
|
|
1232
|
+
* <p>Page content</p>
|
|
1233
|
+
* </bf-page>
|
|
1234
|
+
* @summary Frame for one stacked mobile screen that supplies lifecycle events and shared page state
|
|
1235
|
+
* @category Navigation
|
|
1236
|
+
* @since 0.2.0
|
|
1237
|
+
* @slot default The page: a `bf-header` and a `bf-content`.
|
|
1238
|
+
*/
|
|
1239
|
+
export declare class BfPageComponent {
|
|
1240
|
+
private readonly lifecycle;
|
|
1241
|
+
/** The page's current lifecycle state, mirrored from `BfViewLifecycle`. */
|
|
1242
|
+
readonly viewState: import("@angular/core").Signal<import("@bitforgehq/ui/mobile").BfViewState>;
|
|
1243
|
+
/** Emitted when the page starts entering the top of the stack. */
|
|
1244
|
+
readonly bfViewWillEnter: import("@angular/core").OutputEmitterRef<void>;
|
|
1245
|
+
/** Emitted once the page is active at the top of the stack. */
|
|
1246
|
+
readonly bfViewDidEnter: import("@angular/core").OutputEmitterRef<void>;
|
|
1247
|
+
/** Emitted when the page starts leaving the top of the stack. */
|
|
1248
|
+
readonly bfViewWillLeave: import("@angular/core").OutputEmitterRef<void>;
|
|
1249
|
+
/** Emitted once the page has left the top of the stack. */
|
|
1250
|
+
readonly bfViewDidLeave: import("@angular/core").OutputEmitterRef<void>;
|
|
1251
|
+
constructor();
|
|
1252
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfPageComponent, never>;
|
|
1253
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfPageComponent, "bf-page", never, {}, {
|
|
1254
|
+
"bfViewWillEnter": "bfViewWillEnter";
|
|
1255
|
+
"bfViewDidEnter": "bfViewDidEnter";
|
|
1256
|
+
"bfViewWillLeave": "bfViewWillLeave";
|
|
1257
|
+
"bfViewDidLeave": "bfViewDidLeave";
|
|
1258
|
+
}, never, ["*"], true, never>;
|
|
1259
|
+
}
|
|
1260
|
+
/**
|
|
1261
|
+
* Per-page state shared between the parts of one `bf-page`. `bf-page` provides a fresh instance
|
|
1262
|
+
* for each page through its element injector; `bf-content` registers its scroll container here
|
|
1263
|
+
* on init (and clears it on destroy), so siblings such as `bf-header` can follow the page's
|
|
1264
|
+
* scroll without querying the DOM. A plain class, like `BfViewLifecycle`: it is only ever
|
|
1265
|
+
* provided per page, never from the root injector.
|
|
1266
|
+
*
|
|
1267
|
+
* @example
|
|
1268
|
+
* const scroller = inject(BfPageContext, { optional: true })?.scroller;
|
|
1269
|
+
* @since 0.2.0
|
|
1270
|
+
* @summary Per-page state that the header and content of one page share
|
|
1271
|
+
*/
|
|
1272
|
+
export declare class BfPageContext {
|
|
1273
|
+
/** The page's scroll container (`bf-content`'s scroller), or `null` before one registers. */
|
|
1274
|
+
readonly scroller: import("@angular/core").WritableSignal<HTMLElement | null>;
|
|
1275
|
+
/**
|
|
1276
|
+
* Height (px) of a `translucent` `bf-header` drawn over the content, which `bf-content` pads its
|
|
1277
|
+
* scroller by (`--bf-header-height`); 0 while the header sits in the page's flow (or none).
|
|
1278
|
+
*/
|
|
1279
|
+
readonly headerHeight: import("@angular/core").WritableSignal<number>;
|
|
1280
|
+
/**
|
|
1281
|
+
* Whether the page reaches the top of the screen, so its `bf-header` toolbar (and a `fullscreen`
|
|
1282
|
+
* `bf-content`) pads by the top safe area. True for a page; `bf-modal` in the `sheet`
|
|
1283
|
+
* presentation sets it to false, because its card already sits below the status bar.
|
|
1284
|
+
*/
|
|
1285
|
+
readonly safeAreaTop: import("@angular/core").WritableSignal<boolean>;
|
|
1286
|
+
/**
|
|
1287
|
+
* Whether the page's `bf-content` scroller is the document's `main` landmark (`role="main"`).
|
|
1288
|
+
* True for the page a `bf-stack-outlet` shows; `bf-modal` sets it to false (content in a dialog
|
|
1289
|
+
* is not `main`), and so does a `bf-page` outside an outlet (a docs illustration) or nested in
|
|
1290
|
+
* another page, so the document keeps exactly one `main`: parked pages are `inert` and
|
|
1291
|
+
* `aria-hidden`, so only the shown page's landmark is exposed.
|
|
1292
|
+
*/
|
|
1293
|
+
readonly mainLandmark: import("@angular/core").WritableSignal<boolean>;
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Provided by `bf-stack-outlet` for each stacked page: the page's outermost `bf-page` registers
|
|
1297
|
+
* its `BfPageContext` here (a nested `bf-page` finds the slot taken and leaves it), so the outlet
|
|
1298
|
+
* can reach the page's scroller, e.g. to scroll it to the top when its tab is re-selected.
|
|
1299
|
+
* Internal to the mobile entry.
|
|
1300
|
+
*/
|
|
1301
|
+
declare class BfPageContextSlot {
|
|
1302
|
+
context: BfPageContext | null;
|
|
1303
|
+
}
|
|
1304
|
+
/**
|
|
1305
|
+
* Back button for a `bf-header` start slot (or anywhere else in a page): pops the shown stack,
|
|
1306
|
+
* or replaces it with `defaultHref` when there's nothing to pop back to, e.g. a deep link that
|
|
1307
|
+
* landed on this page directly. Hidden when neither applies. Its anatomy follows the shell mode:
|
|
1308
|
+
* iOS, a chevron with the `label` as text; Material, a bare arrow icon button named by `label`.
|
|
1309
|
+
*
|
|
1310
|
+
* @example
|
|
1311
|
+
* <bf-back-button defaultHref="/tabs/today" />
|
|
1312
|
+
* @summary Header back button that pops the page stack or falls back to a default route
|
|
1313
|
+
* @category Navigation
|
|
1314
|
+
* @since 0.2.0
|
|
1315
|
+
*/
|
|
1316
|
+
export declare class BfBackButtonComponent {
|
|
1317
|
+
private readonly nav;
|
|
1318
|
+
private readonly labels;
|
|
1319
|
+
/** Destination `nav.root()` navigates to when there's no page to pop back to. */
|
|
1320
|
+
readonly defaultHref: import("@angular/core").InputSignal<string>;
|
|
1321
|
+
/**
|
|
1322
|
+
* The previous page's name: the text beside the chevron in iOS mode, the arrow button's
|
|
1323
|
+
* accessible name in Material mode. Empty falls back to `provideBfLabels()`'s `back` ("Back").
|
|
1324
|
+
*/
|
|
1325
|
+
readonly label: import("@angular/core").InputSignal<string>;
|
|
1326
|
+
/** The shell mode (`provideBfShell({ mode })`, or the platform's for `'auto'`). */
|
|
1327
|
+
protected readonly mode: BfShellMode;
|
|
1328
|
+
protected readonly iosClasses: string;
|
|
1329
|
+
protected readonly chevronLeft: import("lucide").IconNode;
|
|
1330
|
+
protected readonly arrowLeft: import("lucide").IconNode;
|
|
1331
|
+
/** The rendered label: `label`, else the `back` label. */
|
|
1332
|
+
readonly name: import("@angular/core").Signal<string>;
|
|
1333
|
+
/** Shown when the stack has a page to go back to, or a `defaultHref` is set. */
|
|
1334
|
+
readonly visible: import("@angular/core").Signal<boolean>;
|
|
1335
|
+
/** Goes back one page, or to `defaultHref` when the stack has none to go back to. */
|
|
1336
|
+
go(): void;
|
|
1337
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfBackButtonComponent, never>;
|
|
1338
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfBackButtonComponent, "bf-back-button", never, {
|
|
1339
|
+
"defaultHref": {
|
|
1340
|
+
"alias": "defaultHref";
|
|
1341
|
+
"required": false;
|
|
1342
|
+
"isSignal": true;
|
|
1343
|
+
};
|
|
1344
|
+
"label": {
|
|
1345
|
+
"alias": "label";
|
|
1346
|
+
"required": false;
|
|
1347
|
+
"isSignal": true;
|
|
1348
|
+
};
|
|
1349
|
+
}, {}, never, never, true, never>;
|
|
1350
|
+
}
|
|
1351
|
+
/**
|
|
1352
|
+
* Sets `touch-action: pan-x pan-y` (and a `data-bf-horizontal-scroll` marker) on a horizontally
|
|
1353
|
+
* scrolling element inside a `bf-stack-outlet` page. Not needed: `touch-action` is not inherited,
|
|
1354
|
+
* and a touch's effective value is the intersection of the values from the touched element up to
|
|
1355
|
+
* its nearest scroll container only, so an `overflow-x-auto` row (a chips row, a carousel) pans
|
|
1356
|
+
* on its own under the outlet's `touch-action: pan-y`, on iOS and on Android. Only the 50 px
|
|
1357
|
+
* left-edge zone belongs to the swipe-back, with or without the directive.
|
|
1358
|
+
*
|
|
1359
|
+
* @example
|
|
1360
|
+
* <div bfHorizontalScroll class="flex gap-2 overflow-x-auto">
|
|
1361
|
+
* <bf-chip>All</bf-chip>
|
|
1362
|
+
* <bf-chip>Open</bf-chip>
|
|
1363
|
+
* </div>
|
|
1364
|
+
* @deprecated 0.3.0 use a plain overflow-x-auto scroller, which pans on its own; removed in 0.4.0
|
|
1365
|
+
* @category Navigation
|
|
1366
|
+
* @since 0.2.0
|
|
1367
|
+
* @summary Deprecated touch-action opt-in for horizontal scrollers in stack pages, not needed
|
|
1368
|
+
*/
|
|
1369
|
+
export declare class BfHorizontalScrollDirective {
|
|
1370
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfHorizontalScrollDirective, never>;
|
|
1371
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<BfHorizontalScrollDirective, "[bfHorizontalScroll]", never, {}, {}, never, never, true, never>;
|
|
1372
|
+
}
|
|
1373
|
+
/**
|
|
1374
|
+
* The payload of `bf-content`'s `scrolled` output: the scroller's `scrollTop` after the scroll.
|
|
1375
|
+
*
|
|
1376
|
+
* @summary What a content scroll event carries: the scroller's current top offset
|
|
1377
|
+
* @since 0.3.0
|
|
1378
|
+
*/
|
|
1379
|
+
interface BfContentScrollEvent {
|
|
1380
|
+
/** The scroller's `scrollTop`, in px. */
|
|
1381
|
+
scrollTop: number;
|
|
1382
|
+
}
|
|
1383
|
+
/**
|
|
1384
|
+
* The page's single scroll container: fills the rest of `bf-page` under the header, keeps the
|
|
1385
|
+
* focused text control clear of the soft keyboard (`bfKeyboardAssist`), pads for the horizontal
|
|
1386
|
+
* safe areas, for the floating tab bar (`--bf-tab-bar-inset`), for a `translucent` header drawn
|
|
1387
|
+
* over it (`--bf-header-height`, from `BfPageContext`) and at the bottom for the height a solid
|
|
1388
|
+
* `bf-header` has collapsed by (`--bf-header-collapse`, written by the header, so the scroll range
|
|
1389
|
+
* stays the same while the large title collapses), and contains overscroll so the document
|
|
1390
|
+
* never scrolls. On iOS (`ios.scrollEnabled: false`) it is the only thing that scrolls. The
|
|
1391
|
+
* projected content sits in a block body inside the scroller: in iOS mode the body is 1 px taller
|
|
1392
|
+
* than the scroller, so WebKit rubber-bands even a short page; in Material mode the scroller gets
|
|
1393
|
+
* `bfOverscrollStretch`, the Android edge stretch the WebView does not draw itself, except in iOS
|
|
1394
|
+
* WebKit (Safari or a home-screen app, platform `web`), which rubber-bands natively. Both follow the
|
|
1395
|
+
* engine (`BfPlatformService.mode()`), not `provideBfShell({ mode })`. In the page a
|
|
1396
|
+
* `bf-stack-outlet` shows, the scroller is the document's `main` landmark (`role="main"`; not in a
|
|
1397
|
+
* `bf-modal`, see `BfPageContext.mainLandmark`). While it overflows and holds nothing focusable,
|
|
1398
|
+
* it is a tab stop (`tabindex="0"`), so a keyboard can scroll it in Safari too (axe
|
|
1399
|
+
* `scrollable-region-focusable`); otherwise Tab reaches its controls and the arrow keys scroll it.
|
|
1400
|
+
*
|
|
1401
|
+
* @example
|
|
1402
|
+
* <bf-page>
|
|
1403
|
+
* <bf-content>
|
|
1404
|
+
* <bf-list>…</bf-list>
|
|
1405
|
+
* </bf-content>
|
|
1406
|
+
* </bf-page>
|
|
1407
|
+
* @summary Page's single scroll container that keeps focused fields clear of the soft keyboard
|
|
1408
|
+
* @category Navigation
|
|
1409
|
+
* @since 0.2.0
|
|
1410
|
+
* @slot default The page content, in the scroll container.
|
|
1411
|
+
*/
|
|
1412
|
+
export declare class BfContentComponent {
|
|
1413
|
+
/** Extends the content under the status bar: adds the top safe-area padding (no header above). */
|
|
1414
|
+
readonly fullscreen: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1415
|
+
/** Keeps the focused text control clear of the soft keyboard; false for screens that handle it themselves. */
|
|
1416
|
+
readonly keyboardAssist: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1417
|
+
/** Emits `scrolled` on every scroll; off by default so plain pages add no listener. */
|
|
1418
|
+
readonly scrollEvents: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1419
|
+
/** The scroller's `scrollTop` on each scroll, only while `scrollEvents` is true. */
|
|
1420
|
+
readonly scrolled: import("@angular/core").OutputEmitterRef<BfContentScrollEvent>;
|
|
1421
|
+
private readonly scroller;
|
|
1422
|
+
private readonly pageContext;
|
|
1423
|
+
private readonly platform;
|
|
1424
|
+
private readonly iosWebKit;
|
|
1425
|
+
protected readonly ios: import("@angular/core").Signal<boolean>;
|
|
1426
|
+
/** The edge stretch only where nothing rubber-bands natively: never in iOS mode or iOS WebKit. */
|
|
1427
|
+
protected readonly stretch: import("@angular/core").Signal<boolean>;
|
|
1428
|
+
protected readonly bodyClasses: import("@angular/core").Signal<"" | "min-h-[calc(100%+1px)]">;
|
|
1429
|
+
/** The shown page's content is the document's `main` landmark; a modal's is not. */
|
|
1430
|
+
protected readonly role: import("@angular/core").Signal<"main" | null>;
|
|
1431
|
+
/** True while the scroller overflows and holds nothing a keyboard can Tab to. */
|
|
1432
|
+
protected readonly tabStop: import("@angular/core").WritableSignal<boolean>;
|
|
1433
|
+
/** A page-sheet modal already sits below the status bar (`BfPageContext.safeAreaTop`). */
|
|
1434
|
+
private readonly safeAreaTop;
|
|
1435
|
+
protected readonly scrollerClasses: import("@angular/core").Signal<string>;
|
|
1436
|
+
constructor();
|
|
1437
|
+
/**
|
|
1438
|
+
* Keeps `tabStop` current: re-checked once per frame after the scroller or its content resizes
|
|
1439
|
+
* or the content changes (rows added, a control enabled, shown, hidden or made inert). Hidden,
|
|
1440
|
+
* inert and unrendered controls do not count.
|
|
1441
|
+
*/
|
|
1442
|
+
private watchKeyboardReach;
|
|
1443
|
+
/** The scroll container element, for code that needs to read or drive it directly. */
|
|
1444
|
+
get scrollElement(): HTMLElement;
|
|
1445
|
+
/**
|
|
1446
|
+
* Scrolls back to the top (e.g. on a second tap of the active tab).
|
|
1447
|
+
* @param behavior `smooth` (the default) or `instant`.
|
|
1448
|
+
*/
|
|
1449
|
+
scrollToTop(behavior?: ScrollBehavior): void;
|
|
1450
|
+
/**
|
|
1451
|
+
* Scrolls to the given offset in px.
|
|
1452
|
+
* @param x The horizontal offset (px).
|
|
1453
|
+
* @param y The vertical offset (px).
|
|
1454
|
+
* @param behavior `smooth` (the default) or `instant`.
|
|
1455
|
+
*/
|
|
1456
|
+
scrollToPoint(x: number, y: number, behavior?: ScrollBehavior): void;
|
|
1457
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfContentComponent, never>;
|
|
1458
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfContentComponent, "bf-content", never, {
|
|
1459
|
+
"fullscreen": {
|
|
1460
|
+
"alias": "fullscreen";
|
|
1461
|
+
"required": false;
|
|
1462
|
+
"isSignal": true;
|
|
1463
|
+
};
|
|
1464
|
+
"keyboardAssist": {
|
|
1465
|
+
"alias": "keyboardAssist";
|
|
1466
|
+
"required": false;
|
|
1467
|
+
"isSignal": true;
|
|
1468
|
+
};
|
|
1469
|
+
"scrollEvents": {
|
|
1470
|
+
"alias": "scrollEvents";
|
|
1471
|
+
"required": false;
|
|
1472
|
+
"isSignal": true;
|
|
1473
|
+
};
|
|
1474
|
+
}, {
|
|
1475
|
+
"scrolled": "scrolled";
|
|
1476
|
+
}, never, ["*"], true, never>;
|
|
1477
|
+
}
|
|
1478
|
+
/**
|
|
1479
|
+
* How `bfKeyboardAssist` scrolls the focused control into view: `smooth` or `instant`.
|
|
1480
|
+
*
|
|
1481
|
+
* @summary Whether the keyboard assist scrolls a focused field into view smoothly or at once
|
|
1482
|
+
* @since 0.3.0
|
|
1483
|
+
*/
|
|
1484
|
+
type BfKeyboardAssistBehavior = 'smooth' | 'instant';
|
|
1485
|
+
/**
|
|
1486
|
+
* Keeps the focused text control of a scroll container clear of the soft keyboard. On keyboard
|
|
1487
|
+
* will-show it pads the scroller by the part below the keyboard's top edge
|
|
1488
|
+
* (`BfKeyboardService.keyboardTop()`: `padding-bottom`, plus `scroll-padding-bottom` with the
|
|
1489
|
+
* margin for engine scrolls), then scrolls the focused `input`, `textarea` or `[contenteditable]`
|
|
1490
|
+
* up until it sits `bfKeyboardAssistMargin` px above the keyboard (or down until it sits the margin
|
|
1491
|
+
* below the scroller's top edge; in a scroller too short for the control and both margins, the gap
|
|
1492
|
+
* above the control shrinks first, then the one above the keyboard, so a control shorter than the
|
|
1493
|
+
* scroller stays whole; a taller one keeps its bottom at the keyboard top). The covered part is
|
|
1494
|
+
* measured again at did-show and on every window or `visualViewport` resize, so a WebView that
|
|
1495
|
+
* resizes for the keyboard (Android) gets no padding and a padding never outlives the keyboard,
|
|
1496
|
+
* even on a detached page. A hidden host (a parked page, `visibility: hidden`) is never padded or
|
|
1497
|
+
* scrolled. The reveal waits for the engine's own focus scroll to settle (100 ms without a `scroll`
|
|
1498
|
+
* event, 120 ms if none arrives, at most 400 ms), then scrolls once; one correction follows at
|
|
1499
|
+
* did-show once the scroller is quiet (skipped while a reveal is pending). Focus moving to another
|
|
1500
|
+
* field while the keyboard is open re-arms the reveal, and both paddings go away on hide.
|
|
1501
|
+
* `refresh()` measures and corrects again for a container that moved on its own. `bf-content`
|
|
1502
|
+
* applies it to its own scroller; use it directly only on a custom scroll container.
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* <div class="h-full overflow-y-auto" bfKeyboardAssist [bfKeyboardAssistMargin]="32">
|
|
1506
|
+
* <bf-input label="Name" />
|
|
1507
|
+
* </div>
|
|
1508
|
+
* @category Navigation
|
|
1509
|
+
* @since 0.2.0
|
|
1510
|
+
* @summary Keeps the focused text field of a scroll container clear of the soft keyboard
|
|
1511
|
+
*/
|
|
1512
|
+
export declare class BfKeyboardAssistDirective {
|
|
1513
|
+
/** Enables the assist; set it false for screens that manage the keyboard themselves (a chat composer). */
|
|
1514
|
+
readonly bfKeyboardAssist: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1515
|
+
/** Gap kept between the focused control and the top of the keyboard, in px. */
|
|
1516
|
+
readonly bfKeyboardAssistMargin: import("@angular/core").InputSignal<number>;
|
|
1517
|
+
/** Scroll behaviour of the reveal. */
|
|
1518
|
+
readonly bfKeyboardAssistBehavior: import("@angular/core").InputSignal<BfKeyboardAssistBehavior>;
|
|
1519
|
+
private readonly host;
|
|
1520
|
+
private readonly document;
|
|
1521
|
+
private readonly keyboard;
|
|
1522
|
+
private settleCallback;
|
|
1523
|
+
private quietTimer;
|
|
1524
|
+
private maxWaitTimer;
|
|
1525
|
+
private revealPending;
|
|
1526
|
+
private lastScrollAt;
|
|
1527
|
+
constructor();
|
|
1528
|
+
/**
|
|
1529
|
+
* The did-show correction's measurement: the scroll it needs now, or 0 when it is skipped (a
|
|
1530
|
+
* reveal is pending, the assist is off, the keyboard is no longer shown) or deferred until the
|
|
1531
|
+
* scroller is quiet.
|
|
1532
|
+
*/
|
|
1533
|
+
private settledCorrection;
|
|
1534
|
+
/**
|
|
1535
|
+
* Measures the covered part again and, while the keyboard is up, corrects the reveal once
|
|
1536
|
+
* (instantly, after any scroll in progress). For a container that moves with the keyboard
|
|
1537
|
+
* outside the keyboard events — `bf-sheet` calls it once its lift above the keyboard has ended.
|
|
1538
|
+
*/
|
|
1539
|
+
refresh(): void;
|
|
1540
|
+
/**
|
|
1541
|
+
* False for a host that is not rendered visibly. A parked page is `visibility: hidden`, which
|
|
1542
|
+
* `checkVisibility()` ignores unless asked with `visibilityProperty`.
|
|
1543
|
+
*/
|
|
1544
|
+
private hostVisible;
|
|
1545
|
+
/** Part of the host below the keyboard's top edge, in px; 0 while hidden or not applicable. */
|
|
1546
|
+
private covered;
|
|
1547
|
+
/** Measures and applies the paddings at once, outside change detection (resize, `refresh()`). */
|
|
1548
|
+
private updatePadding;
|
|
1549
|
+
/** The keyboard height the paddings answer to and the part of the host it covers. */
|
|
1550
|
+
private measurePadding;
|
|
1551
|
+
private applyPadding;
|
|
1552
|
+
/**
|
|
1553
|
+
* Arms a single-shot reveal: it runs once the scroller has been quiet for `REVEAL_QUIET_MS`
|
|
1554
|
+
* after its last `scroll` event, `REVEAL_SETTLE_MS` after arming if none arrives, and at most
|
|
1555
|
+
* `REVEAL_MAX_WAIT_MS` after arming.
|
|
1556
|
+
*/
|
|
1557
|
+
private scheduleReveal;
|
|
1558
|
+
/** Runs `callback` now if the scroller is quiet, else once it has been quiet for `REVEAL_QUIET_MS`. */
|
|
1559
|
+
private whenScrollSettled;
|
|
1560
|
+
private waitForQuiet;
|
|
1561
|
+
private restartQuietTimer;
|
|
1562
|
+
private finishSettle;
|
|
1563
|
+
/** Drops a pending reveal or correction and its timers. */
|
|
1564
|
+
private cancelReveal;
|
|
1565
|
+
/** Scrolls the focused text control so that its bottom plus the margin clears the keyboard top. */
|
|
1566
|
+
private reveal;
|
|
1567
|
+
/** How far the scroller must scroll for the focused text control to clear the keyboard; 0 when
|
|
1568
|
+
* nothing needs revealing. */
|
|
1569
|
+
private revealDelta;
|
|
1570
|
+
private scrollReveal;
|
|
1571
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfKeyboardAssistDirective, never>;
|
|
1572
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<BfKeyboardAssistDirective, "[bfKeyboardAssist]", never, {
|
|
1573
|
+
"bfKeyboardAssist": {
|
|
1574
|
+
"alias": "bfKeyboardAssist";
|
|
1575
|
+
"required": false;
|
|
1576
|
+
"isSignal": true;
|
|
1577
|
+
};
|
|
1578
|
+
"bfKeyboardAssistMargin": {
|
|
1579
|
+
"alias": "bfKeyboardAssistMargin";
|
|
1580
|
+
"required": false;
|
|
1581
|
+
"isSignal": true;
|
|
1582
|
+
};
|
|
1583
|
+
"bfKeyboardAssistBehavior": {
|
|
1584
|
+
"alias": "bfKeyboardAssistBehavior";
|
|
1585
|
+
"required": false;
|
|
1586
|
+
"isSignal": true;
|
|
1587
|
+
};
|
|
1588
|
+
}, {}, never, never, true, never>;
|
|
1589
|
+
}
|
|
1590
|
+
/**
|
|
1591
|
+
* Android-style edge stretch for a scroll container: a vertical touch drag past the top or bottom
|
|
1592
|
+
* edge scales the container's first element child (the content body) up along the y axis from
|
|
1593
|
+
* that edge — `scaleY(1 + 0.14 × (1 − e^(−pull / 240)))` — and springs it back on release (220 ms,
|
|
1594
|
+
* the settle curve; instant under `prefers-reduced-motion`). Touch only, with passive listeners:
|
|
1595
|
+
* it never prevents a touch, so scrolling is untouched. It follows the finger that started the
|
|
1596
|
+
* gesture and ignores any other. A horizontal-dominant gesture (decided after 8 px) is ignored,
|
|
1597
|
+
* and the top edge is left alone while an active `bf-refresher` (`[data-bf-refresher]`) inside
|
|
1598
|
+
* the container owns the top pull. `bf-content` applies it to its
|
|
1599
|
+
* scroller in Material mode, where the WebView draws no overscroll effect of its own.
|
|
1600
|
+
*
|
|
1601
|
+
* @example
|
|
1602
|
+
* <div class="h-full overflow-y-auto" bfOverscrollStretch>
|
|
1603
|
+
* <div>…</div>
|
|
1604
|
+
* </div>
|
|
1605
|
+
* @category Navigation
|
|
1606
|
+
* @since 0.2.0
|
|
1607
|
+
* @summary Android-style stretch of a scroll container dragged past its top or bottom edge
|
|
1608
|
+
*/
|
|
1609
|
+
export declare class BfOverscrollStretchDirective {
|
|
1610
|
+
/** Enables the stretch; false leaves the container inert. */
|
|
1611
|
+
readonly bfOverscrollStretch: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1612
|
+
private readonly host;
|
|
1613
|
+
private readonly document;
|
|
1614
|
+
private gesture;
|
|
1615
|
+
private settle;
|
|
1616
|
+
constructor();
|
|
1617
|
+
private readonly onTouchStart;
|
|
1618
|
+
private readonly onTouchMove;
|
|
1619
|
+
private readonly onTouchEnd;
|
|
1620
|
+
private apply;
|
|
1621
|
+
private stopSettle;
|
|
1622
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfOverscrollStretchDirective, never>;
|
|
1623
|
+
static ɵdir: i0.ɵɵDirectiveDeclaration<BfOverscrollStretchDirective, "[bfOverscrollStretch]", never, {
|
|
1624
|
+
"bfOverscrollStretch": {
|
|
1625
|
+
"alias": "bfOverscrollStretch";
|
|
1626
|
+
"required": false;
|
|
1627
|
+
"isSignal": true;
|
|
1628
|
+
};
|
|
1629
|
+
}, {}, never, never, true, never>;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* The page header: a persistent bar (`start` | title | `end`) and, with `largeTitle` (the
|
|
1633
|
+
* default), the Meadow Sage large title below it that collapses into the bar's title as the
|
|
1634
|
+
* page's `bf-content` scrolls. The bar follows the shell mode (`provideBfShell({ mode })`, the
|
|
1635
|
+
* platform's for `'auto'`): iOS, at least 44 px with a semibold title centred on the bar whatever
|
|
1636
|
+
* the slots hold (symmetric insets of the wider slot's width plus 8 px, measured with a
|
|
1637
|
+
* `ResizeObserver`); Material, at least 64 px with a regular title leading after the `start` slot.
|
|
1638
|
+
* The bar grows with its content at large text sizes: the title wraps to at most two lines (the
|
|
1639
|
+
* bar is never shorter than the measured title, `--bf-header-title-height`), the `start` slot may
|
|
1640
|
+
* shrink (a back button drops its text before its chevron; in iOS mode capped by
|
|
1641
|
+
* `--bf-header-start-max` so the centred title keeps up to half the bar) and the `end` slot never
|
|
1642
|
+
* does. At
|
|
1643
|
+
* compact heights (`(max-height: 500px)`, phone landscape) it renders no large title: the title is
|
|
1644
|
+
* the bar's `h1`, the bar is 44 px in both modes and nothing collapses. Once content scrolls under
|
|
1645
|
+
* it (the large title fully collapsed; without one, `scrollTop > 0`, overscroll excluded) the
|
|
1646
|
+
* host gets `data-bf-scrolled`: iOS turns translucent with a blur and a 1 px hairline, Material
|
|
1647
|
+
* takes a tonal tint. Reads its sibling scroller through the page's `BfPageContext` (set by
|
|
1648
|
+
* `bf-content`) and, from a passive scroll listener, writes `--bf-header-progress` (0…1, over the
|
|
1649
|
+
* large title block's rendered height, bounded to 44–200 px (a taller title collapses faster), of the scroll position clamped to the
|
|
1650
|
+
* scrollable range, so overscroll never moves it, and 0 on a page that cannot scroll that far) on
|
|
1651
|
+
* its host and the large title block's height (its natural height, measured once and on resize,
|
|
1652
|
+
* times `1 − progress`), so at progress 1 the header is exactly the toolbar; scrolling schedules
|
|
1653
|
+
* no Angular change detection. Solid, it also writes the collapsed height as
|
|
1654
|
+
* `--bf-header-collapse` on the scroller, which `bf-content` adds to its bottom padding: the
|
|
1655
|
+
* scroller grows by what the header gives up, so its scroll range stays the same through the
|
|
1656
|
+
* collapse and the short-page rule reads one stable value. When a scroll ends part-way
|
|
1657
|
+
* (`scrollend`, or 120 ms without a `scroll` event) with nothing pressed on the scroller, it snaps
|
|
1658
|
+
* the scroller to fully expanded or fully collapsed, whichever is nearer, like UIKit. Solid
|
|
1659
|
+
* (default), it sits in the page's flow above the content; `translucent`, it is drawn over the
|
|
1660
|
+
* content and `bf-content` pads its scroller by the header's height (`--bf-header-height`).
|
|
1661
|
+
*
|
|
1662
|
+
* @example
|
|
1663
|
+
* <bf-header title="Today" subtitle="Wed, 23 Sep">
|
|
1664
|
+
* <bf-icon-button bfSlot="end" variant="text" label="Profile">
|
|
1665
|
+
* <bf-icon [icon]="userIcon" />
|
|
1666
|
+
* </bf-icon-button>
|
|
1667
|
+
* </bf-header>
|
|
1668
|
+
* @summary Page header toolbar with a large title that collapses into the toolbar on scroll
|
|
1669
|
+
* @category Navigation
|
|
1670
|
+
* @since 0.2.0
|
|
1671
|
+
* @slot start Toolbar buttons at the start, such as `bf-back-button`.
|
|
1672
|
+
* @slot default The toolbar title, when the `title` input is empty.
|
|
1673
|
+
* @slot end Toolbar buttons at the end.
|
|
1674
|
+
*/
|
|
1675
|
+
export declare class BfHeaderComponent {
|
|
1676
|
+
/** The page title, rendered in the toolbar and, with `largeTitle`, in the large title block. */
|
|
1677
|
+
readonly title: import("@angular/core").InputSignal<string>;
|
|
1678
|
+
/** Eyebrow line above the large title (e.g. a date); rendered only with `largeTitle`. */
|
|
1679
|
+
readonly subtitle: import("@angular/core").InputSignal<string>;
|
|
1680
|
+
/**
|
|
1681
|
+
* Renders the collapsing large title block below the toolbar; never at compact heights
|
|
1682
|
+
* (`(max-height: 500px)`), where the title is the bar's `h1`.
|
|
1683
|
+
*/
|
|
1684
|
+
readonly largeTitle: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1685
|
+
/**
|
|
1686
|
+
* Draws the header over the content (`absolute`) instead of in the page's flow, so content
|
|
1687
|
+
* scrolls under its scroll-under surface; `bf-content` pads its scroller by the header's height.
|
|
1688
|
+
*/
|
|
1689
|
+
readonly translucent: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1690
|
+
private readonly host;
|
|
1691
|
+
private readonly pageContext;
|
|
1692
|
+
/** The status-bar band, unless the page sits below the status bar already (a page-sheet modal). */
|
|
1693
|
+
protected readonly toolbarClasses: import("@angular/core").Signal<"" | "pt-safe-top">;
|
|
1694
|
+
private readonly keyboard;
|
|
1695
|
+
private readonly document;
|
|
1696
|
+
private readonly toolbar;
|
|
1697
|
+
private readonly startSlot;
|
|
1698
|
+
private readonly endSlot;
|
|
1699
|
+
private readonly largeClip;
|
|
1700
|
+
private readonly largeBlock;
|
|
1701
|
+
private readonly titleText;
|
|
1702
|
+
private readonly titleSizer;
|
|
1703
|
+
/**
|
|
1704
|
+
* True at compact heights (`(max-height: 500px)`: phone landscape, split screen), read with
|
|
1705
|
+
* `matchMedia` and followed live: no large title, the title in the bar, a 44 px bar.
|
|
1706
|
+
*/
|
|
1707
|
+
protected readonly compact: import("@angular/core").WritableSignal<boolean>;
|
|
1708
|
+
/** Whether the large title block renders: `largeTitle`, except at compact heights. */
|
|
1709
|
+
protected readonly showLarge: import("@angular/core").Signal<boolean>;
|
|
1710
|
+
/** The shell mode (`provideBfShell({ mode })`, or the platform's for `'auto'`), fixed per header. */
|
|
1711
|
+
protected readonly mode: BfShellMode;
|
|
1712
|
+
protected readonly barClasses: import("@angular/core").Signal<string>;
|
|
1713
|
+
protected readonly titleBoxClasses: string;
|
|
1714
|
+
protected readonly titleTextClasses: string;
|
|
1715
|
+
protected readonly startSlotClasses: string;
|
|
1716
|
+
protected readonly largeBlockClasses = "bf-large px-gutter pb-2 opacity-[calc(1_-_var(--bf-header-progress,0))] motion-safe:-translate-y-[calc(var(--bf-header-progress,0)_*_8px)]";
|
|
1717
|
+
protected readonly largeTitleClasses = "text-display text-[length:min(var(--text-display),80px)] leading-[min(var(--text-display--line-height),88px)] wrap-anywhere";
|
|
1718
|
+
protected readonly hostClasses: import("@angular/core").Signal<string>;
|
|
1719
|
+
/** Last written progress (0…1). */
|
|
1720
|
+
private progress;
|
|
1721
|
+
/** Natural height of the large title block, 0 until measured (or without one). */
|
|
1722
|
+
private largeHeight;
|
|
1723
|
+
/** The scroller `--bf-header-collapse` was last written on, so it can be cleared again. */
|
|
1724
|
+
private compensated;
|
|
1725
|
+
constructor();
|
|
1726
|
+
/**
|
|
1727
|
+
* The iOS `start` slot's cap (px), or `null` when the title fits on one line beside the slots
|
|
1728
|
+
* at their full width. A back button's text (`[data-bf-back-text]`) is the only part that gives
|
|
1729
|
+
* way: the cap is at least the slot's width with every back text gone (down to the button's own
|
|
1730
|
+
* minimum width) and at least one 44 px hit area.
|
|
1731
|
+
* @param width The bar's width.
|
|
1732
|
+
* @param titleWidth The title's one-line width.
|
|
1733
|
+
* @param start The start slot.
|
|
1734
|
+
* @param end The end slot.
|
|
1735
|
+
*/
|
|
1736
|
+
private startCap;
|
|
1737
|
+
/**
|
|
1738
|
+
* The scroll distance (px) over which the large title collapses: its block's rendered height
|
|
1739
|
+
* (the eyebrow, the wrapped title and its bottom padding), so the collapse ends exactly when the
|
|
1740
|
+
* title has scrolled away, bounded to 44–200 px (a taller title collapses its whole height over
|
|
1741
|
+
* 200 px, so faster than it scrolls); 56 px until it is measured.
|
|
1742
|
+
*/
|
|
1743
|
+
private collapseRange;
|
|
1744
|
+
/**
|
|
1745
|
+
* Collapses the large title block's height with the progress, so the header ends at exactly the
|
|
1746
|
+
* toolbar (left at its natural (auto) height until measured), and writes the height it gave up
|
|
1747
|
+
* as `--bf-header-collapse` on the page's scroller (`0px` at rest). Solid, the header is in the
|
|
1748
|
+
* page's column, so the scroller grows by that much and `bf-content` pads its bottom by the same
|
|
1749
|
+
* amount, keeping the scroll range constant; translucent, the header is drawn over the scroller,
|
|
1750
|
+
* which never resizes, so the compensation stays `0px`.
|
|
1751
|
+
*/
|
|
1752
|
+
private applyCollapse;
|
|
1753
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfHeaderComponent, never>;
|
|
1754
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfHeaderComponent, "bf-header", never, {
|
|
1755
|
+
"title": {
|
|
1756
|
+
"alias": "title";
|
|
1757
|
+
"required": false;
|
|
1758
|
+
"isSignal": true;
|
|
1759
|
+
};
|
|
1760
|
+
"subtitle": {
|
|
1761
|
+
"alias": "subtitle";
|
|
1762
|
+
"required": false;
|
|
1763
|
+
"isSignal": true;
|
|
1764
|
+
};
|
|
1765
|
+
"largeTitle": {
|
|
1766
|
+
"alias": "largeTitle";
|
|
1767
|
+
"required": false;
|
|
1768
|
+
"isSignal": true;
|
|
1769
|
+
};
|
|
1770
|
+
"translucent": {
|
|
1771
|
+
"alias": "translucent";
|
|
1772
|
+
"required": false;
|
|
1773
|
+
"isSignal": true;
|
|
1774
|
+
};
|
|
1775
|
+
}, {}, never, ["[bfSlot=start]", "*", "[bfSlot=end]", "*"], true, never>;
|
|
1776
|
+
}
|
|
1777
|
+
/**
|
|
1778
|
+
* The payload of `bf-refresher`'s `refreshRequested` output: call `complete()` once the reload is
|
|
1779
|
+
* done to animate the disc away.
|
|
1780
|
+
*
|
|
1781
|
+
* @summary What a pull-to-refresh request carries: the callback that ends the refresh
|
|
1782
|
+
* @since 0.3.0
|
|
1783
|
+
*/
|
|
1784
|
+
interface BfRefresherRefreshEvent {
|
|
1785
|
+
/** Ends the refresh: animates the disc away and resets the refresher. */
|
|
1786
|
+
complete: () => void;
|
|
1787
|
+
}
|
|
1788
|
+
/**
|
|
1789
|
+
* Pull-to-refresh, placed as the first child of `bf-content`. It tracks Pointer Events on the
|
|
1790
|
+
* page's scroller (read from `BfPageContext`, or its nearest scrolling ancestor when used without one)
|
|
1791
|
+
* only while the scroller is at `scrollTop === 0`: the disc resists the pull (half the pointer's
|
|
1792
|
+
* travel, capped) from a resting position above the clipped content to a 64 px threshold, ticks
|
|
1793
|
+
* `BfHapticsService.impact('light')` once on crossing it, and on release past the threshold
|
|
1794
|
+
* parks at the top with a spinner and emits `refreshRequested` — call `complete()` on the event to animate
|
|
1795
|
+
* the disc away and reset. A press by itself changes nothing: only once a pointermove clears an
|
|
1796
|
+
* 8 px downward slop (out-vertical'ing any horizontal travel) does it claim the gesture and
|
|
1797
|
+
* capture the pointer on the scroller, so a plain click on the content underneath (a row, a
|
|
1798
|
+
* button) still reaches it. For touch, a non-passive `touchmove` guard (attached only while a
|
|
1799
|
+
* press is tracked) keeps the browser from taking a downward drag at the top as a pan, which
|
|
1800
|
+
* would cancel the pointer stream; upward drags still scroll the list. The disc itself is
|
|
1801
|
+
* `aria-hidden`; a permanent, visually hidden `role="status"` region announces
|
|
1802
|
+
* `provideBfLabels()`'s `refreshing` ("Refreshing"). `prefers-reduced-motion` still follows the
|
|
1803
|
+
* pointer 1:1 during the pull (direct manipulation is not motion); only the settle, park and `complete()` animations
|
|
1804
|
+
* become instant.
|
|
1805
|
+
*
|
|
1806
|
+
* That pull is the Material (and mouse/pen) mode. A touch in iOS mode (`BfPlatformService.mode()`)
|
|
1807
|
+
* is the bounce mode instead: the refresher claims nothing (no capture, no `preventDefault`, no
|
|
1808
|
+
* guard), the scroller rubber-bands natively, and while the finger is down a negative `scrollTop`
|
|
1809
|
+
* shows the disc inside the gap the bounce opens, at its resting −48 px, with opacity and scale
|
|
1810
|
+
* (0.6 → 1) following `−scrollTop / 64` once it passes 8 px; one light haptic at 64 px. Lifting the
|
|
1811
|
+
* finger at 64 px or more parks the disc and emits `refreshRequested`, like `UIRefreshControl`; a bounce
|
|
1812
|
+
* with no finger down (a fling's overshoot) never shows it. The host carries `data-bf-refresher`
|
|
1813
|
+
* while enabled, so `bfOverscrollStretch` leaves the top edge to it.
|
|
1814
|
+
*
|
|
1815
|
+
* @example
|
|
1816
|
+
* <bf-content>
|
|
1817
|
+
* <bf-refresher (refreshRequested)="reload($event.complete)" />
|
|
1818
|
+
* <bf-list>…</bf-list>
|
|
1819
|
+
* </bf-content>
|
|
1820
|
+
* @summary Pull-to-refresh indicator with haptic feedback, native iOS bounce and an Android-style pull
|
|
1821
|
+
* @category Navigation
|
|
1822
|
+
* @since 0.2.0
|
|
1823
|
+
*/
|
|
1824
|
+
export declare class BfRefresherComponent implements AfterViewInit {
|
|
1825
|
+
/** Disables pull tracking; the disc never moves and `refreshRequested` never emits. */
|
|
1826
|
+
readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
|
|
1827
|
+
/** Emitted when a pull past the threshold is released; call `complete()` to end it. */
|
|
1828
|
+
readonly refreshRequested: import("@angular/core").OutputEmitterRef<BfRefresherRefreshEvent>;
|
|
1829
|
+
/**
|
|
1830
|
+
* Emitted with the same event as `refreshRequested`, together with it.
|
|
1831
|
+
* @deprecated 0.3.0 use refreshRequested; removed in 0.4.0
|
|
1832
|
+
*/
|
|
1833
|
+
readonly refresh: import("@angular/core").OutputEmitterRef<BfRefresherRefreshEvent>;
|
|
1834
|
+
private readonly host;
|
|
1835
|
+
private readonly disc;
|
|
1836
|
+
private readonly pageContext;
|
|
1837
|
+
private readonly haptics;
|
|
1838
|
+
protected readonly labels: import("@bitforgehq/ui").BfLabels;
|
|
1839
|
+
private readonly document;
|
|
1840
|
+
private readonly platform;
|
|
1841
|
+
private readonly ios;
|
|
1842
|
+
private readonly refreshingState;
|
|
1843
|
+
/** True from the moment a completed pull is released until `complete()` is called. */
|
|
1844
|
+
readonly refreshing: import("@angular/core").Signal<boolean>;
|
|
1845
|
+
private scroller;
|
|
1846
|
+
private gesture;
|
|
1847
|
+
private settleAnimation;
|
|
1848
|
+
private currentOffset;
|
|
1849
|
+
/** A finger is on the scroller (tracked in iOS mode only). */
|
|
1850
|
+
private touchActive;
|
|
1851
|
+
private bounce;
|
|
1852
|
+
constructor();
|
|
1853
|
+
/** Paints the disc's resting, hidden transform once the view exists (no template `style`). */
|
|
1854
|
+
ngAfterViewInit(): void;
|
|
1855
|
+
/** Emits one refresh event on `refreshRequested` and the deprecated `refresh`. */
|
|
1856
|
+
private requestRefresh;
|
|
1857
|
+
/** Ends a refresh: animates the disc away (skipped under reduced motion) and resets state. */
|
|
1858
|
+
complete(): void;
|
|
1859
|
+
private readonly onPointerDown;
|
|
1860
|
+
private readonly onTouchStart;
|
|
1861
|
+
/**
|
|
1862
|
+
* While a finger is down, a negative `scrollTop` is WebKit's rubber band at the top: the disc,
|
|
1863
|
+
* which sits in the content above its top edge, shows in the gap the bounce opens. Direct
|
|
1864
|
+
* manipulation (styles set straight from the scroll position, no animation).
|
|
1865
|
+
*/
|
|
1866
|
+
private readonly onBounceScroll;
|
|
1867
|
+
private readonly onTouchEnd;
|
|
1868
|
+
private endBounce;
|
|
1869
|
+
private hideBounceDisc;
|
|
1870
|
+
/**
|
|
1871
|
+
* Non-passive `touchmove` guard, attached only while a press is tracked (the pattern of the
|
|
1872
|
+
* stack outlet's swipe guard). The scroller is `touch-pan-y`, so without it the browser takes a
|
|
1873
|
+
* downward drag as a pan and ends the pointer stream with `pointercancel`. It prevents a
|
|
1874
|
+
* cancelable move once the pull is claimed, or — before the claim — a downward-dominant move
|
|
1875
|
+
* while the scroller is at the top, where a pan has nothing to scroll anyway. Upward and
|
|
1876
|
+
* horizontal drags are left alone, so the list (and any horizontal scroller) keeps its pan.
|
|
1877
|
+
*/
|
|
1878
|
+
private readonly touchMoveGuard;
|
|
1879
|
+
/**
|
|
1880
|
+
* A touch pointer is implicitly captured by the element under the finger; claiming it for the
|
|
1881
|
+
* scroller makes that child fire its own `lostpointercapture`, which bubbles here. Only the
|
|
1882
|
+
* scroller losing the capture it took ends the pull.
|
|
1883
|
+
*/
|
|
1884
|
+
private readonly onLostPointerCapture;
|
|
1885
|
+
private readonly onPointerMove;
|
|
1886
|
+
private readonly onPointerUp;
|
|
1887
|
+
private readonly onPointerCancel;
|
|
1888
|
+
private endGesture;
|
|
1889
|
+
private removeDragListeners;
|
|
1890
|
+
private setOffset;
|
|
1891
|
+
private settleTo;
|
|
1892
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfRefresherComponent, never>;
|
|
1893
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfRefresherComponent, "bf-refresher", never, {
|
|
1894
|
+
"disabled": {
|
|
1895
|
+
"alias": "disabled";
|
|
1896
|
+
"required": false;
|
|
1897
|
+
"isSignal": true;
|
|
1898
|
+
};
|
|
1899
|
+
}, {
|
|
1900
|
+
"refreshRequested": "refreshRequested";
|
|
1901
|
+
"refresh": "refresh";
|
|
1902
|
+
}, never, never, true, never>;
|
|
1903
|
+
}
|
|
1904
|
+
/**
|
|
1905
|
+
* What `bf-tabs` tells the `bf-stack-outlet` inside it: which tab a URL belongs to. The outlet
|
|
1906
|
+
* keeps one stack per tab key and switches stacks when a navigation lands on another key.
|
|
1907
|
+
*
|
|
1908
|
+
* @since 0.2.0
|
|
1909
|
+
* @summary What the tabs page tells its stack outlet: which tab a URL belongs to
|
|
1910
|
+
*/
|
|
1911
|
+
interface BfTabContext {
|
|
1912
|
+
/** The active tab's key (the URL segment after the tabs route), or null outside the tabs. */
|
|
1913
|
+
readonly tabKey: Signal<string | null>;
|
|
1914
|
+
/**
|
|
1915
|
+
* The tab key of `url` (query and fragment ignored), or null when it is not under the tabs route.
|
|
1916
|
+
* @param url The URL to read.
|
|
1917
|
+
*/
|
|
1918
|
+
keyOf(url: string): string | null;
|
|
1919
|
+
}
|
|
1920
|
+
/**
|
|
1921
|
+
* Provided by `bf-tabs`; injected optionally by `bf-stack-outlet`.
|
|
1922
|
+
*
|
|
1923
|
+
* @summary Injection token through which the tabs page tells its outlet about the tabs
|
|
1924
|
+
* @since 0.2.0
|
|
1925
|
+
*/
|
|
1926
|
+
export declare const BF_TAB_CONTEXT: InjectionToken<BfTabContext>;
|
|
1927
|
+
/**
|
|
1928
|
+
* The tabs page of a mobile app: one navigation stack per tab. It wraps a `bf-stack-outlet`, which
|
|
1929
|
+
* keeps a separate stack for every tab (keyed by the URL segment after `tabsPath`), and a
|
|
1930
|
+
* `bf-tab-bar`, which it drives through `BF_TAB_BAR_CONTROLLER`: the bar shows the tab of the
|
|
1931
|
+
* in-flight navigation's target, else of the current URL, and hides while the keyboard is open,
|
|
1932
|
+
* without anything writing into it. Selecting another tab brings
|
|
1933
|
+
* that tab back as it was left; re-selecting the active tab pops its stack to the root, or scrolls
|
|
1934
|
+
* its content to the top when it is already there. The bar hides while the soft keyboard is open
|
|
1935
|
+
* or about to open (a focused text control), and `--bf-tab-bar-inset` on the host tells
|
|
1936
|
+
* `bf-content` how much to pad its bottom (the bar's measured height, a `ResizeObserver` on its
|
|
1937
|
+
* `nav`, plus its bottom offset and 8 px; 64 px for the height until it is measured); the same value is mirrored on `<html>` as
|
|
1938
|
+
* `--bf-tab-bar-inset-global` for overlays (the toast), which render outside the host. It is removed when the tabs are destroyed.
|
|
1939
|
+
* It also provides `BF_TAB_LINKS`, so the projected bar is a `nav` of links to each tab's root URL
|
|
1940
|
+
* (`aria-current` on the active one: `page` at the tab's root, `true` on a child page of it)
|
|
1941
|
+
* instead of a `tablist`.
|
|
1942
|
+
*
|
|
1943
|
+
* @example
|
|
1944
|
+
* <bf-tabs tabsPath="tabs">
|
|
1945
|
+
* <bf-stack-outlet />
|
|
1946
|
+
* <bf-tab-bar>
|
|
1947
|
+
* <bf-tab id="today" label="Today"><bf-icon [icon]="Sun" /></bf-tab>
|
|
1948
|
+
* <bf-tab id="me" label="Me"><bf-icon [icon]="User" /></bf-tab>
|
|
1949
|
+
* </bf-tab-bar>
|
|
1950
|
+
* </bf-tabs>
|
|
1951
|
+
* @summary Tabs page with one navigation stack per tab, wiring the tab bar to the router
|
|
1952
|
+
* @category Navigation
|
|
1953
|
+
* @since 0.2.0
|
|
1954
|
+
* @slot default The tabs page body: a `bf-stack-outlet` and a `bf-tab-bar`.
|
|
1955
|
+
*/
|
|
1956
|
+
export declare class BfTabsComponent implements BfTabContext, BfTabBarController {
|
|
1957
|
+
/** Route path of the tabs page (e.g. `'tabs'`); the URL segment after it is the tab key. */
|
|
1958
|
+
readonly tabsPath: import("@angular/core").InputSignal<string>;
|
|
1959
|
+
private readonly router;
|
|
1960
|
+
private readonly nav;
|
|
1961
|
+
private readonly haptics;
|
|
1962
|
+
private readonly keyboard;
|
|
1963
|
+
private readonly platform;
|
|
1964
|
+
private readonly config;
|
|
1965
|
+
private readonly host;
|
|
1966
|
+
private readonly document;
|
|
1967
|
+
private readonly overlays;
|
|
1968
|
+
private readonly locationStrategy;
|
|
1969
|
+
private readonly bar;
|
|
1970
|
+
private readonly barHost;
|
|
1971
|
+
/** The bar's measured height (px), `null` until its `nav` is first measured. */
|
|
1972
|
+
private readonly barHeight;
|
|
1973
|
+
private readonly outlet;
|
|
1974
|
+
/** The settled URL: the last successful navigation's (after redirects), else the router's. */
|
|
1975
|
+
private readonly url;
|
|
1976
|
+
/** The active tab's key, from the router URL; null while the URL is not under `tabsPath`. */
|
|
1977
|
+
readonly tabKey: Signal<string | null>;
|
|
1978
|
+
/**
|
|
1979
|
+
* The tab the bar shows: the in-flight navigation's target (after redirects once they are
|
|
1980
|
+
* applied), else the settled URL's. A refused or cancelled navigation ends, so the bar drops
|
|
1981
|
+
* back to the settled tab by itself. While neither is under `tabsPath` (a page pushed above the
|
|
1982
|
+
* tabs page) it keeps the last tab it showed.
|
|
1983
|
+
*/
|
|
1984
|
+
private readonly currentTab;
|
|
1985
|
+
/** The tab the bar shows (read-only): the in-flight navigation's target, else the current URL's;
|
|
1986
|
+
* null when unknown. */
|
|
1987
|
+
readonly current: Signal<string | null>;
|
|
1988
|
+
/** Hide the bar while the keyboard is open or about to open (a focused text control: on Android
|
|
1989
|
+
* the WebView shrinks before will-show and would lift the fixed bar above the keyboard). */
|
|
1990
|
+
readonly hidden: Signal<boolean>;
|
|
1991
|
+
/** The bar hides animated on iOS, instantly on Android and the web. */
|
|
1992
|
+
readonly hideTransition: Signal<boolean>;
|
|
1993
|
+
constructor();
|
|
1994
|
+
/**
|
|
1995
|
+
* The tab key of `url`: the primary segment after `tabsPath`. Query, fragment, matrix params and
|
|
1996
|
+
* auxiliary routes (`(popup:…)`) are ignored.
|
|
1997
|
+
* @param url The URL to read.
|
|
1998
|
+
*/
|
|
1999
|
+
keyOf(url: string): string | null;
|
|
2000
|
+
/** `keyOf` for a parsed URL. */
|
|
2001
|
+
private keyOfTree;
|
|
2002
|
+
/**
|
|
2003
|
+
* The URL of tab `id`'s root page (`/tabs/<id>`, with the app's base href), the `href` of its
|
|
2004
|
+
* link in the bar: a new browser tab opens the tab's root. A plain click still restores the page
|
|
2005
|
+
* the tab was left on.
|
|
2006
|
+
* @param id The `id` of the tab.
|
|
2007
|
+
*/
|
|
2008
|
+
href(id: string): string;
|
|
2009
|
+
/**
|
|
2010
|
+
* Whether the current URL is tab `id`'s root page (`…/<tabsPath>/<id>` with nothing after it,
|
|
2011
|
+
* ignoring query, fragment and auxiliary routes); reactive through the router's signals.
|
|
2012
|
+
* @param id The `id` of the tab.
|
|
2013
|
+
*/
|
|
2014
|
+
isRoot(id: string): boolean;
|
|
2015
|
+
/** The non-empty segments of `tabsPath`; empty when the tabs are mounted at the root URL. */
|
|
2016
|
+
private baseSegments;
|
|
2017
|
+
/**
|
|
2018
|
+
* Another tab, selected by the user in the bar: go back to where that tab was left (its stack's
|
|
2019
|
+
* top page), or its root. The bar shows the target while the navigation is in flight and drops
|
|
2020
|
+
* back by itself when a guard refuses it.
|
|
2021
|
+
* @param id The `id` of the selected tab.
|
|
2022
|
+
*/
|
|
2023
|
+
select(id: string): void;
|
|
2024
|
+
/**
|
|
2025
|
+
* The active tab again: pop its stack back to its existing root page (a history step), or
|
|
2026
|
+
* replace the stack with the root when the history position is unknown; at the root, scroll its
|
|
2027
|
+
* content to the top.
|
|
2028
|
+
* @param id The `id` of the active tab.
|
|
2029
|
+
*/
|
|
2030
|
+
reselect(id: string): void;
|
|
2031
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfTabsComponent, never>;
|
|
2032
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfTabsComponent, "bf-tabs", never, {
|
|
2033
|
+
"tabsPath": {
|
|
2034
|
+
"alias": "tabsPath";
|
|
2035
|
+
"required": true;
|
|
2036
|
+
"isSignal": true;
|
|
2037
|
+
};
|
|
2038
|
+
}, {}, ["bar", "barHost", "outlet"], ["*"], true, never>;
|
|
2039
|
+
}
|
|
2040
|
+
/** @deprecated 0.3.0 use BF_OVERLAY_DATA from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2041
|
+
export declare const BF_OVERLAY_DATA: import("@angular/core").InjectionToken<unknown>;
|
|
2042
|
+
/** @deprecated 0.3.0 use BfOverlayRef from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2043
|
+
export declare const BfOverlayRef: typeof core.BfOverlayRef;
|
|
2044
|
+
/** @deprecated 0.3.0 use BfOverlayRef from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2045
|
+
export type BfOverlayRef<T = unknown> = core.BfOverlayRef<T>;
|
|
2046
|
+
/** @deprecated 0.3.0 use BfComponentOverlayRef from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2047
|
+
export declare const BfComponentOverlayRef: typeof core.BfComponentOverlayRef;
|
|
2048
|
+
/** @deprecated 0.3.0 use BfComponentOverlayRef from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2049
|
+
export type BfComponentOverlayRef<C, T = unknown> = core.BfComponentOverlayRef<C, T>;
|
|
2050
|
+
/** @deprecated 0.3.0 use BfOverlayStack from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2051
|
+
export declare const BfOverlayStack: typeof core.BfOverlayStack;
|
|
2052
|
+
/** @deprecated 0.3.0 use BfOverlayStack from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2053
|
+
export type BfOverlayStack = core.BfOverlayStack;
|
|
2054
|
+
/** @deprecated 0.3.0 use BfOverlayStackOptions from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2055
|
+
type BfOverlayStackOptions = core.BfOverlayStackOptions;
|
|
2056
|
+
/** @deprecated 0.3.0 use BfStackedOverlay from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2057
|
+
type BfStackedOverlay = core.BfStackedOverlay;
|
|
2058
|
+
/** @deprecated 0.3.0 use BfOverlayService from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2059
|
+
export declare const BfOverlayService: typeof core.BfOverlayService;
|
|
2060
|
+
/** @deprecated 0.3.0 use BfOverlayService from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2061
|
+
export type BfOverlayService = core.BfOverlayService;
|
|
2062
|
+
/** @deprecated 0.3.0 use BfOverlayOptions from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2063
|
+
type BfOverlayOptions = core.BfOverlayOptions;
|
|
2064
|
+
/** @deprecated 0.3.0 use BfOverlayPosition from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2065
|
+
type BfOverlayPosition = core.BfOverlayPosition;
|
|
2066
|
+
/** @deprecated 0.3.0 use BfOverlayTemplateContext from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2067
|
+
type BfOverlayTemplateContext = core.BfOverlayTemplateContext;
|
|
2068
|
+
/** @deprecated 0.3.0 use OVERLAY_DURATION from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2069
|
+
export declare const OVERLAY_DURATION = 260;
|
|
2070
|
+
/** @deprecated 0.3.0 use OVERLAY_EASING from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2071
|
+
export declare const OVERLAY_EASING = "cubic-bezier(0.32, 0.72, 0, 1)";
|
|
2072
|
+
/** @deprecated 0.3.0 use fadeDown from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2073
|
+
export declare const fadeDown: typeof core.fadeDown;
|
|
2074
|
+
/** @deprecated 0.3.0 use fadeIn from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2075
|
+
export declare const fadeIn: typeof core.fadeIn;
|
|
2076
|
+
/** @deprecated 0.3.0 use fadeOut from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2077
|
+
export declare const fadeOut: typeof core.fadeOut;
|
|
2078
|
+
/** @deprecated 0.3.0 use fadeUp from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2079
|
+
export declare const fadeUp: typeof core.fadeUp;
|
|
2080
|
+
/** @deprecated 0.3.0 use scaleIn from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2081
|
+
export declare const scaleIn: typeof core.scaleIn;
|
|
2082
|
+
/** @deprecated 0.3.0 use slideDown from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2083
|
+
export declare const slideDown: typeof core.slideDown;
|
|
2084
|
+
/** @deprecated 0.3.0 use slideUp from '@bitforgehq/ui/overlay'; removed in 0.4.0 */
|
|
2085
|
+
export declare const slideUp: typeof core.slideUp;
|
|
2086
|
+
/** What `BfSheetService` does for a sheet ref; internal. */
|
|
2087
|
+
interface BfSheetController extends BfOverlayController {
|
|
2088
|
+
/** True while the underlying overlay is closing (backdrop, `Escape`, back button, drag). */
|
|
2089
|
+
isClosing(): boolean;
|
|
2090
|
+
}
|
|
2091
|
+
/**
|
|
2092
|
+
* Handle to an open bottom sheet, returned by `BfSheetService.open()` and injectable in the
|
|
2093
|
+
* sheet's content as `BfSheetRef` (and as `BfOverlayRef`). On top of `close(result)` and
|
|
2094
|
+
* `afterClosed` it moves the sheet between its snap points: `snapTo(index)` animates to a point
|
|
2095
|
+
* and `snapIndex()` tracks the current one (also after a drag).
|
|
2096
|
+
*
|
|
2097
|
+
* @example
|
|
2098
|
+
* const ref = sheets.open(FiltersComponent, { snapPoints: [0.4, 0.9] });
|
|
2099
|
+
* ref.snapTo(1);
|
|
2100
|
+
* const filters = await ref.afterClosed;
|
|
2101
|
+
* @since 0.2.0
|
|
2102
|
+
* @summary Handle on an open bottom sheet that moves it between snap points and closes it
|
|
2103
|
+
*/
|
|
2104
|
+
export declare class BfSheetRef<T = unknown> extends BfOverlayRef$1<T> {
|
|
2105
|
+
private readonly sheetController;
|
|
2106
|
+
private readonly snapIndexState;
|
|
2107
|
+
/** Index of the snap point the sheet rests at (or is settling to). */
|
|
2108
|
+
readonly snapIndex: Signal<number>;
|
|
2109
|
+
private snapHandler;
|
|
2110
|
+
constructor(sheetController: BfSheetController, initialIndex?: number);
|
|
2111
|
+
/** True from the first close on, whichever way the sheet is being closed. */
|
|
2112
|
+
get isClosing(): boolean;
|
|
2113
|
+
/**
|
|
2114
|
+
* Animates the sheet to the snap point at `index` (clamped to the configured points).
|
|
2115
|
+
* @param index The position of the snap point in `snapPoints`.
|
|
2116
|
+
*/
|
|
2117
|
+
snapTo(index: number): void;
|
|
2118
|
+
/** @internal Connects the `bf-sheet` container that performs `snapTo`. */
|
|
2119
|
+
connect(handler: (index: number) => void): void;
|
|
2120
|
+
/** @internal Set by `bf-sheet` whenever the sheet settles on a snap point. */
|
|
2121
|
+
setSnapIndex(index: number): void;
|
|
2122
|
+
}
|
|
2123
|
+
/** What `BfSheetService` hands the `bf-sheet` container (as its `BF_OVERLAY_DATA`); internal. */
|
|
2124
|
+
interface BfSheetConfig {
|
|
2125
|
+
content: Type<unknown> | TemplateRef<unknown>;
|
|
2126
|
+
/** Ascending fractions of the viewport height. */
|
|
2127
|
+
snapPoints: number[];
|
|
2128
|
+
initial: number;
|
|
2129
|
+
dismissible: boolean;
|
|
2130
|
+
/** The caller's data, re-provided to the content as `BF_OVERLAY_DATA`. */
|
|
2131
|
+
data: unknown;
|
|
2132
|
+
/** No `ariaLabel` was given: the panel is named by the content's first heading, if any. */
|
|
2133
|
+
labelledByHeading: boolean;
|
|
2134
|
+
ref: BfSheetRef<unknown>;
|
|
2135
|
+
}
|
|
2136
|
+
/**
|
|
2137
|
+
* The bottom-sheet container that `BfSheetService.open()` renders on the overlay core: a
|
|
2138
|
+
* bottom-anchored `bg-surface` card with a grabber, resting at snap points (fractions of the
|
|
2139
|
+
* viewport height, applied as `--bf-sheet-height`) and rendering the content component or
|
|
2140
|
+
* template with `BF_OVERLAY_DATA` and `BfSheetRef` injectable. Dragging the handle row, any
|
|
2141
|
+
* element marked `data-bf-sheet-drag` (a header) or the content (unless it can scroll up) moves
|
|
2142
|
+
* the sheet with Pointer Events under pointer capture: rubber-banded above the top point, released
|
|
2143
|
+
* onto the nearest point (a fling faster than 0.3 px/ms picks the direction), and dismissed when
|
|
2144
|
+
* released more than 25 % below the lowest point or flung down from it — if the sheet is
|
|
2145
|
+
* dismissible. The content scrolls only at the top snap point, and at every point while the soft
|
|
2146
|
+
* keyboard is up. While the keyboard overlays the sheet's bottom edge (iOS, a mobile browser) the
|
|
2147
|
+
* sheet is lifted by the covered height (`translate`, its bottom safe-area padding dropped); while
|
|
2148
|
+
* the keyboard is up its height is capped at the keyboard's top edge minus the safe-area top minus
|
|
2149
|
+
* 8 px (a drag starts from that capped height), and the content region's `bfKeyboardAssist`
|
|
2150
|
+
* scrolls the focused control 24 px clear of the keyboard. The lift follows the keyboard (250 ms,
|
|
2151
|
+
* instant under `prefers-reduced-motion`). Hiding the keyboard restores the snap height at once
|
|
2152
|
+
* (the drop is instant, so the top edge stays on screen) and scrolls content left scrolled below
|
|
2153
|
+
* the top point back to its top. With two or more snap points the grabber is a button: a press,
|
|
2154
|
+
* `Enter` or `Space` moves one point up (from the top point back to the lowest), the arrow keys
|
|
2155
|
+
* step, `Home` and `End` jump; it is named `expand` or `collapse` (`BF_LABELS`) after the next
|
|
2156
|
+
* press, then `sheetPosition`, and every settle on another point announces `sheetPosition`
|
|
2157
|
+
* politely. A dismissible sheet starts with a visually hidden Close (`BF_LABELS.close`) that screen
|
|
2158
|
+
* readers reach and a keyboard user sees when focused. Not used directly in templates.
|
|
2159
|
+
*
|
|
2160
|
+
* @example
|
|
2161
|
+
* const ref = inject(BfSheetService).open(NewTaskComponent, { snapPoints: [0.5, 0.92] });
|
|
2162
|
+
* @summary Bottom sheet with snap points, drag to dismiss and a backdrop
|
|
2163
|
+
* @category Overlays
|
|
2164
|
+
* @since 0.2.0
|
|
2165
|
+
*/
|
|
2166
|
+
export declare class BfSheetComponent {
|
|
2167
|
+
private readonly config;
|
|
2168
|
+
private readonly host;
|
|
2169
|
+
private readonly document;
|
|
2170
|
+
private readonly keyboard;
|
|
2171
|
+
private readonly keyboardCover;
|
|
2172
|
+
private readonly contentElement;
|
|
2173
|
+
private readonly contentAssist;
|
|
2174
|
+
protected readonly template: TemplateRef<unknown> | null;
|
|
2175
|
+
protected readonly component: Type<unknown> | null;
|
|
2176
|
+
protected readonly contentInjector: import("@angular/core").DestroyableInjector;
|
|
2177
|
+
protected readonly templateContext: BfOverlayTemplateContext$1;
|
|
2178
|
+
private readonly lastIndex;
|
|
2179
|
+
protected readonly labels: import("@bitforgehq/ui").BfLabels;
|
|
2180
|
+
protected readonly dismissible: boolean;
|
|
2181
|
+
/** Two or more snap points: the grabber is a button that moves between them. */
|
|
2182
|
+
protected readonly adjustable: boolean;
|
|
2183
|
+
private readonly announcer;
|
|
2184
|
+
/**
|
|
2185
|
+
* What the next press does (collapse at the top point, else expand), then where the sheet is:
|
|
2186
|
+
* "Expand, Sheet at 1 of 2".
|
|
2187
|
+
*/
|
|
2188
|
+
protected readonly grabberLabel: import("@angular/core").Signal<string>;
|
|
2189
|
+
/** A drag that started on the grabber button ends without the click that may follow it. */
|
|
2190
|
+
private suppressGrabberClick;
|
|
2191
|
+
/**
|
|
2192
|
+
* The content scrolls at the top snap point and whenever the keyboard is up (the sheet may be
|
|
2193
|
+
* capped below its content); otherwise drags move the sheet.
|
|
2194
|
+
*/
|
|
2195
|
+
private readonly contentScrolls;
|
|
2196
|
+
protected readonly contentClass: import("@angular/core").Signal<string>;
|
|
2197
|
+
private index;
|
|
2198
|
+
/** Rendered height (px) and downward translation (px) below the lowest point. */
|
|
2199
|
+
private height;
|
|
2200
|
+
private offset;
|
|
2201
|
+
private gesture;
|
|
2202
|
+
private settleAnimation;
|
|
2203
|
+
constructor();
|
|
2204
|
+
/**
|
|
2205
|
+
* Lifts the sheet by the part of the viewport the keyboard covers and caps its height at the
|
|
2206
|
+
* keyboard's top edge; both go away with the keyboard, at once. Separate from
|
|
2207
|
+
* `--bf-sheet-height`, so drag and snap logic never see them.
|
|
2208
|
+
*/
|
|
2209
|
+
private applyKeyboard;
|
|
2210
|
+
/** The content's keyboard assist measured a sheet still sliding up: it measures once more. */
|
|
2211
|
+
private readonly onTransitionEnd;
|
|
2212
|
+
protected close(): void;
|
|
2213
|
+
/**
|
|
2214
|
+
* A press: one point higher, or from the top point back to the lowest. The click a pointer drag
|
|
2215
|
+
* may leave behind is swallowed; a keyboard or assistive-technology click (`detail` 0) never is.
|
|
2216
|
+
*/
|
|
2217
|
+
protected onGrabberClick(event: MouseEvent): void;
|
|
2218
|
+
/** Arrow keys step between points (never past the ends, never dismissing); Home and End jump. */
|
|
2219
|
+
protected onGrabberKeydown(event: KeyboardEvent): void;
|
|
2220
|
+
private snapTo;
|
|
2221
|
+
/** Viewport height with the keyboard hidden: the `100lvh` probe, else `innerHeight`. */
|
|
2222
|
+
private viewportHeight;
|
|
2223
|
+
private heights;
|
|
2224
|
+
private readonly onResize;
|
|
2225
|
+
private readonly onPointerDown;
|
|
2226
|
+
/**
|
|
2227
|
+
* Whether a content drag may move the sheet: always while the content does not scroll (below the
|
|
2228
|
+
* top snap point, keyboard hidden), and otherwise only downward while it is scrolled to 0.
|
|
2229
|
+
*/
|
|
2230
|
+
private contentMayDrag;
|
|
2231
|
+
/**
|
|
2232
|
+
* Non-passive `touchmove` guard, attached only while a press is tracked (the refresher's
|
|
2233
|
+
* pattern): keeps the browser from taking the drag as a pan, which would end the pointer stream
|
|
2234
|
+
* with `pointercancel`. Content drags the sheet does not want (upward at the top point,
|
|
2235
|
+
* horizontal) are left to scroll.
|
|
2236
|
+
*/
|
|
2237
|
+
private readonly touchMoveGuard;
|
|
2238
|
+
private readonly onPointerMove;
|
|
2239
|
+
/** Renders a proposed visible height: rubber-banded past the ends, translated below the lowest. */
|
|
2240
|
+
private show;
|
|
2241
|
+
private readonly onPointerUp;
|
|
2242
|
+
private readonly onPointerCancel;
|
|
2243
|
+
/** Only the host losing the capture it took ends the drag (a child's implicit capture bubbles). */
|
|
2244
|
+
private readonly onLostPointerCapture;
|
|
2245
|
+
/** Downward velocity (px/ms) over the last samples; 0 when they carry no elapsed time. */
|
|
2246
|
+
private velocity;
|
|
2247
|
+
private release;
|
|
2248
|
+
private nearest;
|
|
2249
|
+
/** Animates (instantly under reduced motion) to the snap point at `index`. */
|
|
2250
|
+
private settleTo;
|
|
2251
|
+
/**
|
|
2252
|
+
* The height the sheet shows: its snap height, or less while the keyboard caps it (`max-height`),
|
|
2253
|
+
* so a drag of a capped sheet moves it from the first pixel.
|
|
2254
|
+
*/
|
|
2255
|
+
private renderedHeight;
|
|
2256
|
+
/** A press during a settle continues from where the animation had got to. */
|
|
2257
|
+
private captureAnimatedHeight;
|
|
2258
|
+
private apply;
|
|
2259
|
+
private endGesture;
|
|
2260
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfSheetComponent, never>;
|
|
2261
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfSheetComponent, "bf-sheet", never, {}, {}, never, never, true, never>;
|
|
2262
|
+
}
|
|
2263
|
+
/**
|
|
2264
|
+
* Where focus goes when a sheet opens: the sheet itself (`panel`), so no soft keyboard comes up
|
|
2265
|
+
* and a screen reader starts reading at the sheet, or its first field (`first-field`): the element
|
|
2266
|
+
* marked `[autofocus]`/`[cdkFocusInitial]`, else the first focusable element of the content, which
|
|
2267
|
+
* raises the keyboard on Android when it is a text field.
|
|
2268
|
+
*
|
|
2269
|
+
* @summary Where focus lands when a sheet opens, the sheet itself or its first field
|
|
2270
|
+
* @since 0.3.0
|
|
2271
|
+
*/
|
|
2272
|
+
type BfSheetAutoFocus = 'panel' | 'first-field';
|
|
2273
|
+
/**
|
|
2274
|
+
* Options of `BfSheetService.open()`.
|
|
2275
|
+
*
|
|
2276
|
+
* @summary Options of a bottom sheet: where it rests, how it closes and its name
|
|
2277
|
+
* @since 0.2.0
|
|
2278
|
+
*/
|
|
2279
|
+
interface BfSheetOptions {
|
|
2280
|
+
/**
|
|
2281
|
+
* Heights the sheet rests at, as fractions of the viewport height (default `[0.5, 0.92]`).
|
|
2282
|
+
* @default [0.5, 0.92]
|
|
2283
|
+
*/
|
|
2284
|
+
snapPoints?: number[];
|
|
2285
|
+
/**
|
|
2286
|
+
* Index of the snap point the sheet opens at (default 0).
|
|
2287
|
+
* @default 0
|
|
2288
|
+
*/
|
|
2289
|
+
initial?: number;
|
|
2290
|
+
/**
|
|
2291
|
+
* The backdrop, `Escape`, the hardware back button and a downward drag close the sheet
|
|
2292
|
+
* (default true). When false only `close()` does, or a navigation (see `closeOnNavigation`).
|
|
2293
|
+
* @default true
|
|
2294
|
+
*/
|
|
2295
|
+
dismissible?: boolean;
|
|
2296
|
+
/** Injected into the content as `BF_OVERLAY_DATA`. */
|
|
2297
|
+
data?: unknown;
|
|
2298
|
+
/**
|
|
2299
|
+
* A navigation to another URL path (a pushed or popped page, a tab switch) closes the sheet with
|
|
2300
|
+
* no result (default true), also a non-dismissible one.
|
|
2301
|
+
* @default true
|
|
2302
|
+
*/
|
|
2303
|
+
closeOnNavigation?: boolean;
|
|
2304
|
+
/**
|
|
2305
|
+
* Accessible name of the sheet. Without it the sheet is named by the first heading in its
|
|
2306
|
+
* content (`aria-labelledby`), else by `provideBfLabels()`'s `sheet` ("Sheet").
|
|
2307
|
+
*/
|
|
2308
|
+
ariaLabel?: string;
|
|
2309
|
+
/**
|
|
2310
|
+
* Where focus goes on open: `panel` (default) focuses the sheet itself (a `role="dialog"` with a
|
|
2311
|
+
* name and `tabindex="-1"`), so a screen reader lands inside it and no soft keyboard hides it;
|
|
2312
|
+
* `first-field` focuses the element marked `[autofocus]`/`[cdkFocusInitial]`, else the first
|
|
2313
|
+
* focusable element of the content (never the sheet's own Close and grabber), which raises the
|
|
2314
|
+
* keyboard on Android when it is a text field.
|
|
2315
|
+
* @default 'panel'
|
|
2316
|
+
*/
|
|
2317
|
+
autoFocus?: BfSheetAutoFocus;
|
|
2318
|
+
/**
|
|
2319
|
+
* Injector the sheet resolves its labels (`BF_LABELS`) from and the parent of its content's
|
|
2320
|
+
* injector (default the root injector). Pass the opening component's `inject(Injector)` so a
|
|
2321
|
+
* feature-level `provideBfLabels()` and other feature providers reach it.
|
|
2322
|
+
*/
|
|
2323
|
+
injector?: Injector;
|
|
2324
|
+
}
|
|
2325
|
+
/**
|
|
2326
|
+
* Snap points used when none (or no valid ones) are given.
|
|
2327
|
+
*
|
|
2328
|
+
* @summary The snap points a bottom sheet rests at when none are given, half and full
|
|
2329
|
+
* @since 0.2.0
|
|
2330
|
+
*/
|
|
2331
|
+
export declare const BF_SHEET_DEFAULT_SNAP_POINTS: readonly number[];
|
|
2332
|
+
/**
|
|
2333
|
+
* Opens bottom sheets: a component or template in a `bf-sheet` container on the overlay core,
|
|
2334
|
+
* bottom-anchored over a backdrop, resting at snap points (fractions of the viewport height).
|
|
2335
|
+
* The content injects `BF_OVERLAY_DATA` and `BfSheetRef` (also as `BfOverlayRef`) to read its
|
|
2336
|
+
* data, move between snap points and close with a result. A dismissible sheet (the default)
|
|
2337
|
+
* closes on a backdrop tap, `Escape`, the hardware back button and a drag below its lowest
|
|
2338
|
+
* point; a non-dismissible one only through `close()`, and swallows the back button while open.
|
|
2339
|
+
* A navigation to another URL path closes either (`closeOnNavigation`). On open, focus goes to the
|
|
2340
|
+
* sheet itself, so no soft keyboard comes up (`autoFocus: 'first-field'` focuses the first field).
|
|
2341
|
+
*
|
|
2342
|
+
* @example
|
|
2343
|
+
* const ref = inject(BfSheetService).open<NewTaskComponent, Task>(NewTaskComponent, {
|
|
2344
|
+
* snapPoints: [0.5, 0.92],
|
|
2345
|
+
* data: { listId },
|
|
2346
|
+
* });
|
|
2347
|
+
* const task = await ref.afterClosed;
|
|
2348
|
+
* @since 0.2.0
|
|
2349
|
+
* @summary Opens bottom sheets that rest at snap points and close with a result
|
|
2350
|
+
*/
|
|
2351
|
+
export declare class BfSheetService {
|
|
2352
|
+
private readonly overlays;
|
|
2353
|
+
private readonly stack;
|
|
2354
|
+
private readonly backButton;
|
|
2355
|
+
private readonly injector;
|
|
2356
|
+
/**
|
|
2357
|
+
* Opens `content` (a component or a template) in a bottom sheet.
|
|
2358
|
+
* @param content The component or template to render in the sheet.
|
|
2359
|
+
* @param options Where the sheet rests, how it closes and its name.
|
|
2360
|
+
*/
|
|
2361
|
+
open<C, T = unknown>(content: Type<C> | TemplateRef<unknown>, options?: BfSheetOptions): BfSheetRef<T>;
|
|
2362
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfSheetService, never>;
|
|
2363
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2364
|
+
}
|
|
2365
|
+
/**
|
|
2366
|
+
* Where `bf-modal` sits: a page-sheet card, or edge to edge.
|
|
2367
|
+
*
|
|
2368
|
+
* @summary How a modal is presented: a page-sheet card over the stack, or fullscreen
|
|
2369
|
+
* @since 0.2.0
|
|
2370
|
+
*/
|
|
2371
|
+
type BfModalPresentation = 'sheet' | 'fullscreen';
|
|
2372
|
+
/** What `BfModalService` hands the `bf-modal` container (as its `BF_OVERLAY_DATA`); internal. */
|
|
2373
|
+
interface BfModalConfig {
|
|
2374
|
+
content: Type<unknown>;
|
|
2375
|
+
presentation: BfModalPresentation;
|
|
2376
|
+
/** The caller's data, re-provided to the content as `BF_OVERLAY_DATA`. */
|
|
2377
|
+
data: unknown;
|
|
2378
|
+
/** No `ariaLabel` was given: the panel is named by the content's first heading, if any. */
|
|
2379
|
+
labelledByHeading: boolean;
|
|
2380
|
+
}
|
|
2381
|
+
/**
|
|
2382
|
+
* The modal frame that `BfModalService.open()` renders on the overlay core, `position:
|
|
2383
|
+
* 'fullscreen'`: a `sheet` presentation (default) is a card whose top sits 10 px below the top
|
|
2384
|
+
* safe area (UIKit's page-sheet inset; `bg-bg rounded-t-card shadow-floating`) over the parked page stack, which scales down and
|
|
2385
|
+
* grows rounded corners behind it (`--bf-modal-depth`, written by `BfOverlayStack`, consumed by
|
|
2386
|
+
* `bf-stack-outlet`'s host rule); `fullscreen` covers the viewport edge to edge with no scale.
|
|
2387
|
+
* Like `bf-page`, it provides a fresh `BfPageContext` so the content's `bf-header` and
|
|
2388
|
+
* `bf-content` work inside it (with `mainLandmark` false, so its content is no `main` landmark,
|
|
2389
|
+
* and in the `sheet` presentation with `safeAreaTop` false, so the header adds no status-bar band
|
|
2390
|
+
* inside the card) — the content supplies its own header (typically a close
|
|
2391
|
+
* `bf-icon-button` in `start`) and content region. While the soft keyboard overlays the bottom of
|
|
2392
|
+
* a `sheet` card (iOS, a mobile browser), the card is padded at the bottom by the covered height,
|
|
2393
|
+
* so the content's `bf-content` ends at the keyboard's top edge and its keyboard assist reveals
|
|
2394
|
+
* the focused control there. Not used directly in templates.
|
|
2395
|
+
*
|
|
2396
|
+
* @example
|
|
2397
|
+
* const ref = inject(BfModalService).open(EditTaskComponent, { data: { taskId } });
|
|
2398
|
+
* @summary Modal overlay shown as an inset card over the scaled-down page, or full screen
|
|
2399
|
+
* @category Overlays
|
|
2400
|
+
* @since 0.2.0
|
|
2401
|
+
*/
|
|
2402
|
+
export declare class BfModalComponent {
|
|
2403
|
+
protected readonly config: BfModalConfig;
|
|
2404
|
+
private readonly outerRef;
|
|
2405
|
+
private readonly keyboardCover;
|
|
2406
|
+
protected readonly hostClasses: string;
|
|
2407
|
+
/** A sheet card ends at the keyboard's top edge; a fullscreen frame leaves it to `bf-content`. */
|
|
2408
|
+
protected readonly keyboardPadding: import("@angular/core").Signal<number | null>;
|
|
2409
|
+
protected readonly contentInjector: import("@angular/core").DestroyableInjector;
|
|
2410
|
+
constructor();
|
|
2411
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfModalComponent, never>;
|
|
2412
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfModalComponent, "bf-modal", never, {}, {}, never, never, true, never>;
|
|
2413
|
+
}
|
|
2414
|
+
/**
|
|
2415
|
+
* Options of `BfModalService.open()`.
|
|
2416
|
+
*
|
|
2417
|
+
* @summary Options of a modal: its data, presentation, dismissal and accessible name
|
|
2418
|
+
* @since 0.2.0
|
|
2419
|
+
*/
|
|
2420
|
+
interface BfModalOptions {
|
|
2421
|
+
/** Injected into the content as `BF_OVERLAY_DATA`. */
|
|
2422
|
+
data?: unknown;
|
|
2423
|
+
/**
|
|
2424
|
+
* A page-sheet card over the parked page stack (default), or a fullscreen frame.
|
|
2425
|
+
* @default 'sheet'
|
|
2426
|
+
*/
|
|
2427
|
+
presentation?: BfModalPresentation;
|
|
2428
|
+
/**
|
|
2429
|
+
* `Escape` and the hardware back button close the modal (default true); with false only the
|
|
2430
|
+
* content's own close control does, or a navigation (see `closeOnNavigation`), and back is
|
|
2431
|
+
* swallowed while the modal is open instead of
|
|
2432
|
+
* falling through to the page behind. There is no backdrop dismiss or drag-to-dismiss.
|
|
2433
|
+
* @default true
|
|
2434
|
+
*/
|
|
2435
|
+
dismissible?: boolean;
|
|
2436
|
+
/**
|
|
2437
|
+
* A navigation to another URL path closes the modal with no result (default true).
|
|
2438
|
+
* @default true
|
|
2439
|
+
*/
|
|
2440
|
+
closeOnNavigation?: boolean;
|
|
2441
|
+
/**
|
|
2442
|
+
* Accessible name of the modal panel. Without it the modal is named by the first heading in
|
|
2443
|
+
* its content (`aria-labelledby`, e.g. the `bf-header` title), else by `provideBfLabels()`'s
|
|
2444
|
+
* `modal` ("Modal").
|
|
2445
|
+
*/
|
|
2446
|
+
ariaLabel?: string;
|
|
2447
|
+
/**
|
|
2448
|
+
* Injector the modal resolves its labels (`BF_LABELS`) from and the parent of its content's
|
|
2449
|
+
* injector (default the root injector). Pass the opening component's `inject(Injector)` so a
|
|
2450
|
+
* feature-level `provideBfLabels()` and other feature providers reach it.
|
|
2451
|
+
*/
|
|
2452
|
+
injector?: Injector;
|
|
2453
|
+
}
|
|
2454
|
+
/**
|
|
2455
|
+
* Opens modals: a component in a `bf-modal` frame on the overlay core (`position: 'fullscreen'`,
|
|
2456
|
+
* no backdrop dismiss). `presentation: 'sheet'` (default) is a page-sheet card 10 px below the
|
|
2457
|
+
* top safe area over the parked page stack, which in iOS mode scales down and grows rounded corners
|
|
2458
|
+
* behind it (`countsAsModal: true`, driving `--bf-modal-depth` on the registered
|
|
2459
|
+
* `bf-stack-outlet` roots; Material mode leaves the page unscaled); `'fullscreen'` covers the
|
|
2460
|
+
* viewport edge to edge and does not count towards that depth. iOS mode
|
|
2461
|
+
* slides the card up and down; Material mode fades it up (and down) 16 px. The content supplies
|
|
2462
|
+
* its own `bf-header` (`largeTitle="false"`, typically a close `bf-icon-button` in `start`) and
|
|
2463
|
+
* `bf-content` — `bf-modal` provides a `BfPageContext` for them, like `bf-page`. It injects the
|
|
2464
|
+
* caller's `data` as `BF_OVERLAY_DATA` and closes itself with a result through the injected
|
|
2465
|
+
* `BfOverlayRef`, which `open()` also returns. A navigation to another URL path closes it with no
|
|
2466
|
+
* result (`closeOnNavigation`).
|
|
2467
|
+
*
|
|
2468
|
+
* @example
|
|
2469
|
+
* const ref = inject(BfModalService).open<EditTaskComponent, Task>(EditTaskComponent, {
|
|
2470
|
+
* data: { taskId },
|
|
2471
|
+
* });
|
|
2472
|
+
* const saved = await ref.afterClosed;
|
|
2473
|
+
* @since 0.2.0
|
|
2474
|
+
* @summary Opens a component as a modal page sheet over the stack, or fullscreen
|
|
2475
|
+
*/
|
|
2476
|
+
export declare class BfModalService {
|
|
2477
|
+
private readonly overlays;
|
|
2478
|
+
private readonly stack;
|
|
2479
|
+
private readonly backButton;
|
|
2480
|
+
private readonly platform;
|
|
2481
|
+
private readonly injector;
|
|
2482
|
+
private readonly config;
|
|
2483
|
+
/**
|
|
2484
|
+
* Opens `component` as a modal.
|
|
2485
|
+
* @param component The component to render; it injects `BfOverlayRef` and `BF_OVERLAY_DATA`.
|
|
2486
|
+
* @param options The modal's data, presentation, dismissal and name.
|
|
2487
|
+
*/
|
|
2488
|
+
open<C, T = unknown>(component: Type<C>, options?: BfModalOptions): BfOverlayRef$1<T>;
|
|
2489
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfModalService, never>;
|
|
2490
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2491
|
+
}
|
|
2492
|
+
/**
|
|
2493
|
+
* Where the toast pill anchors in the viewport.
|
|
2494
|
+
*
|
|
2495
|
+
* @summary Where a mobile toast pill anchors in the viewport, at the bottom or top
|
|
2496
|
+
* @since 0.2.0
|
|
2497
|
+
*/
|
|
2498
|
+
type BfToastPosition = 'bottom' | 'top';
|
|
2499
|
+
/** The action rendered as a real button inside the pill; internal. */
|
|
2500
|
+
interface BfToastActionConfig {
|
|
2501
|
+
label: string;
|
|
2502
|
+
run: () => void;
|
|
2503
|
+
}
|
|
2504
|
+
/** What holds a toast's timer: the pointer over it, or focus inside it; internal. */
|
|
2505
|
+
type BfToastHoldSource = 'pointer' | 'focus';
|
|
2506
|
+
/** What `BfToastService` hands the `bf-toast` container (as its `BF_OVERLAY_DATA`); internal. */
|
|
2507
|
+
interface BfToastConfig {
|
|
2508
|
+
message: string;
|
|
2509
|
+
action: BfToastActionConfig | null;
|
|
2510
|
+
position: BfToastPosition;
|
|
2511
|
+
/** Told when the pointer or focus enters (`held: true`) or leaves the pill; pauses the timer. */
|
|
2512
|
+
hold?: (source: BfToastHoldSource, held: boolean) => void;
|
|
2513
|
+
/** `Escape` pressed while focus is inside the pill; the service dismisses the toast. */
|
|
2514
|
+
escape?: () => void;
|
|
2515
|
+
}
|
|
2516
|
+
/**
|
|
2517
|
+
* The status pill that `BfToastService.show()` renders on the overlay core (`passive: true`, no
|
|
2518
|
+
* backdrop, no focus trap, no inert page and no back handler — it never steals focus): an ink
|
|
2519
|
+
* `bg-text text-bg rounded-full shadow-floating` pill holding the message (truncated to two lines)
|
|
2520
|
+
* and an optional action. The pill is not a live region: the service announces each toast once
|
|
2521
|
+
* through CDK `LiveAnnouncer`. The pointer over it or focus inside it pauses its timer, and
|
|
2522
|
+
* `Escape` with focus inside dismisses it. `position: 'bottom'` (default) sits 16 px above the
|
|
2523
|
+
* tab-bar inset (`--bf-tab-bar-inset-global`, published on `<html>` by `bf-tabs`, which leaves
|
|
2524
|
+
* 8 px above the floating bar, so the toast clears it by 24 px) and the soft keyboard
|
|
2525
|
+
* (`--bf-toast-keyboard` on the host: `BfKeyboardService.height()` where the keyboard overlays
|
|
2526
|
+
* the WebView — native iOS — and 0 where the WebView already shrinks); `position: 'top'` sits
|
|
2527
|
+
* 16 px below the status bar (a top margin of the safe-area inset plus 16 px, outside the pill)
|
|
2528
|
+
* instead. Not used directly in templates.
|
|
2529
|
+
*
|
|
2530
|
+
* @example
|
|
2531
|
+
* const ref = inject(BfToastService).show({ message: 'Saved' });
|
|
2532
|
+
* @summary Passive status pill with an optional action that never steals focus
|
|
2533
|
+
* @category Overlays
|
|
2534
|
+
* @since 0.2.0
|
|
2535
|
+
*/
|
|
2536
|
+
export declare class BfToastComponent {
|
|
2537
|
+
protected readonly config: BfToastConfig;
|
|
2538
|
+
private readonly host;
|
|
2539
|
+
private readonly keyboard;
|
|
2540
|
+
protected readonly classes: string;
|
|
2541
|
+
constructor();
|
|
2542
|
+
protected hold(source: BfToastHoldSource, held: boolean): void;
|
|
2543
|
+
/** Focus moving between elements inside the pill still holds it. */
|
|
2544
|
+
protected focusLeft(event: Event): void;
|
|
2545
|
+
/** `Escape` with focus inside dismisses the toast; claimed, so no overlay underneath sees it. */
|
|
2546
|
+
protected keydown(event: Event): void;
|
|
2547
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfToastComponent, never>;
|
|
2548
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfToastComponent, "bf-toast", never, {}, {}, never, never, true, never>;
|
|
2549
|
+
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Options of `BfToastService.show()`.
|
|
2552
|
+
*
|
|
2553
|
+
* @summary Options of a mobile toast: its message, an action, its duration and position
|
|
2554
|
+
* @since 0.2.0
|
|
2555
|
+
*/
|
|
2556
|
+
interface BfToastOptions {
|
|
2557
|
+
/** Text of the pill, truncated to two lines. */
|
|
2558
|
+
message: string;
|
|
2559
|
+
/** An optional action button. */
|
|
2560
|
+
action?: BfToastAction$1;
|
|
2561
|
+
/**
|
|
2562
|
+
* Milliseconds before the toast auto-dismisses, not counting time the pointer is over it or
|
|
2563
|
+
* focus is inside it; `0` keeps it until dismissed or its action fires (default 3000 without an
|
|
2564
|
+
* action, `0` with one).
|
|
2565
|
+
* @default 3000
|
|
2566
|
+
*/
|
|
2567
|
+
duration?: number;
|
|
2568
|
+
/**
|
|
2569
|
+
* Where the pill anchors (default `'bottom'`).
|
|
2570
|
+
* @default 'bottom'
|
|
2571
|
+
*/
|
|
2572
|
+
position?: BfToastPosition;
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* Queues status pills: `show(options)` renders `bf-toast` on the overlay core (`passive: true` —
|
|
2576
|
+
* no backdrop, no focus trap, the page stays interactive, and it never counts towards
|
|
2577
|
+
* `BfOverlayStack.count()`) and returns a `BfToastRef`. One toast is visible at a time; later
|
|
2578
|
+
* calls queue in order and show once the current one ends. A toast auto-dismisses after
|
|
2579
|
+
* `duration` ms (default 3000, resolving `'timeout'`); a toast with an action defaults to
|
|
2580
|
+
* `duration: 0`, which keeps it until `dismiss()`, `Escape` inside it (`'dismiss'`) or its action
|
|
2581
|
+
* button (`'action'`) ends it; such a persistent toast never blocks the queue — the next `show()`
|
|
2582
|
+
* replaces it (`'dismiss'`). The timer pauses while the pointer is over the toast or focus is
|
|
2583
|
+
* inside it and resumes with the remaining time. When a toast still holding focus closes, focus
|
|
2584
|
+
* returns to the element focused last outside it. Each toast is announced once, politely, through
|
|
2585
|
+
* CDK `LiveAnnouncer` as it shows. A navigation (a pushed or popped page, a tab switch) never
|
|
2586
|
+
* closes it.
|
|
2587
|
+
*
|
|
2588
|
+
* @example
|
|
2589
|
+
* const ref = inject(BfToastService).show({
|
|
2590
|
+
* message: 'Task deleted',
|
|
2591
|
+
* action: { label: 'Undo', handler: () => restore(task) },
|
|
2592
|
+
* });
|
|
2593
|
+
* const reason = await ref.afterDismissed;
|
|
2594
|
+
* @since 0.2.0
|
|
2595
|
+
* @summary Shows brief toast pills on phones, one at a time, queued in order
|
|
2596
|
+
*/
|
|
2597
|
+
export declare class BfToastService {
|
|
2598
|
+
private readonly overlays;
|
|
2599
|
+
private readonly queue;
|
|
2600
|
+
/**
|
|
2601
|
+
* Queues `options` as a toast; shows it now if none is visible, else once the current one ends.
|
|
2602
|
+
* A persistent toast (`duration` 0, the default with an action) never blocks the queue: a later
|
|
2603
|
+
* `show()` dismisses it (`'dismiss'`), whether it is visible or still waiting.
|
|
2604
|
+
* @param options The toast's message, action, duration and position.
|
|
2605
|
+
* @returns The toast's ref, to dismiss it or await why it ended.
|
|
2606
|
+
*/
|
|
2607
|
+
show(options: BfToastOptions): BfToastRef$1;
|
|
2608
|
+
/** Opens one passive overlay per toast, exactly as before the engine moved to `/overlay`. */
|
|
2609
|
+
private present;
|
|
2610
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfToastService, never>;
|
|
2611
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2612
|
+
}
|
|
2613
|
+
/**
|
|
2614
|
+
* The role of an action sheet row: `destructive` renders it in `text-danger`, `cancel` makes it the
|
|
2615
|
+
* separate cancel button.
|
|
2616
|
+
*
|
|
2617
|
+
* @summary The role of an action sheet row, a destructive action or the cancel button
|
|
2618
|
+
* @since 0.3.0
|
|
2619
|
+
*/
|
|
2620
|
+
type BfActionSheetActionRole = 'destructive' | 'cancel';
|
|
2621
|
+
/**
|
|
2622
|
+
* One row of an action sheet, or its cancel action when `role: 'cancel'`.
|
|
2623
|
+
*
|
|
2624
|
+
* @summary One row of an action sheet, or its cancel button, with its answer and role
|
|
2625
|
+
* @since 0.2.0
|
|
2626
|
+
*/
|
|
2627
|
+
interface BfActionSheetAction {
|
|
2628
|
+
/** What `open()` resolves with when the row is tapped (default `label`); keeps the answer
|
|
2629
|
+
* stable when the label is translated or two rows share a label. Ignored on the cancel action,
|
|
2630
|
+
* which always resolves `undefined`. */
|
|
2631
|
+
id?: string;
|
|
2632
|
+
/** Row text; also what `open()` resolves with when the row is tapped and has no `id`. */
|
|
2633
|
+
label: string;
|
|
2634
|
+
/** Icon rendered in the row's leading slot. */
|
|
2635
|
+
icon?: IconNode;
|
|
2636
|
+
/**
|
|
2637
|
+
* `destructive` renders the row's label in `text-danger`; `cancel` renders it as the separate
|
|
2638
|
+
* cancel button instead of a row (a plain row when omitted).
|
|
2639
|
+
*/
|
|
2640
|
+
role?: BfActionSheetActionRole;
|
|
2641
|
+
}
|
|
2642
|
+
/** What `BfActionSheetService` hands the `bf-action-sheet` container (as its `BF_OVERLAY_DATA`); internal. */
|
|
2643
|
+
interface BfActionSheetConfig {
|
|
2644
|
+
/** Heading above the rows, or `undefined` for none. */
|
|
2645
|
+
title: string | undefined;
|
|
2646
|
+
/** The caller's non-cancel actions, in order. */
|
|
2647
|
+
actions: BfActionSheetAction[];
|
|
2648
|
+
/** Label of the cancel button: the caller's `cancel`-role action, or "Cancel". */
|
|
2649
|
+
cancelLabel: string;
|
|
2650
|
+
}
|
|
2651
|
+
/**
|
|
2652
|
+
* The action sheet panel that `BfActionSheetService.open()` renders on the overlay core
|
|
2653
|
+
* (`position: 'bottom'`): an optional title above a `bf-list` of interactive rows for the
|
|
2654
|
+
* actions (destructive ones in `text-danger`, an icon in the leading slot) and a separate
|
|
2655
|
+
* `tonal` `bf-button` for the cancel action — rendered even when the caller passes none,
|
|
2656
|
+
* labelled "Cancel", which takes the initial focus. Tapping a row resolves the overlay with its
|
|
2657
|
+
* `id ?? label`; the cancel button, like
|
|
2658
|
+
* the backdrop, `Escape` and the hardware back button, resolves `undefined`. Not used directly
|
|
2659
|
+
* in templates.
|
|
2660
|
+
*
|
|
2661
|
+
* @example
|
|
2662
|
+
* const answer = await inject(BfActionSheetService).open({
|
|
2663
|
+
* title: 'Delete list?',
|
|
2664
|
+
* actions: [{ id: 'delete', label: 'Delete', role: 'destructive' }],
|
|
2665
|
+
* });
|
|
2666
|
+
* @summary Bottom panel of labelled actions with a separate cancel button, destructive ones shown in red
|
|
2667
|
+
* @category Overlays
|
|
2668
|
+
* @since 0.2.0
|
|
2669
|
+
*/
|
|
2670
|
+
export declare class BfActionSheetComponent {
|
|
2671
|
+
protected readonly config: BfActionSheetConfig;
|
|
2672
|
+
private readonly ref;
|
|
2673
|
+
protected select(action: BfActionSheetAction): void;
|
|
2674
|
+
protected cancel(): void;
|
|
2675
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfActionSheetComponent, never>;
|
|
2676
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfActionSheetComponent, "bf-action-sheet", never, {}, {}, never, never, true, never>;
|
|
2677
|
+
}
|
|
2678
|
+
/**
|
|
2679
|
+
* Options of `BfActionSheetService.open()`.
|
|
2680
|
+
*
|
|
2681
|
+
* @summary Options of an action sheet: its title, its rows and when it closes
|
|
2682
|
+
* @since 0.2.0
|
|
2683
|
+
*/
|
|
2684
|
+
interface BfActionSheetOptions {
|
|
2685
|
+
/** Heading above the rows; also the panel's accessible name (default `provideBfLabels()`'s
|
|
2686
|
+
* `actions`, "Actions"). */
|
|
2687
|
+
title?: string;
|
|
2688
|
+
/**
|
|
2689
|
+
* Rows, in order; a `cancel`-role entry becomes the separate cancel button instead of a row.
|
|
2690
|
+
* Only the first `cancel`-role entry is used; any further ones are ignored.
|
|
2691
|
+
*/
|
|
2692
|
+
actions: BfActionSheetAction[];
|
|
2693
|
+
/**
|
|
2694
|
+
* A navigation to another URL path closes the sheet, resolving `undefined` (default true).
|
|
2695
|
+
* @default true
|
|
2696
|
+
*/
|
|
2697
|
+
closeOnNavigation?: boolean;
|
|
2698
|
+
/**
|
|
2699
|
+
* Injector the action sheet resolves its labels (`BF_LABELS`) from and the parent of its content's
|
|
2700
|
+
* injector (default the root injector). Pass the opening component's `inject(Injector)` so a
|
|
2701
|
+
* feature-level `provideBfLabels()` and other feature providers reach it.
|
|
2702
|
+
*/
|
|
2703
|
+
injector?: Injector;
|
|
2704
|
+
}
|
|
2705
|
+
/**
|
|
2706
|
+
* Opens action sheets: a bottom-anchored list of actions on the overlay core (`position:
|
|
2707
|
+
* 'bottom'`, not counted as a modal). Renders `title` above a `bf-list` of the non-cancel
|
|
2708
|
+
* `actions` as interactive rows (destructive ones in `text-danger`, an icon in the leading slot
|
|
2709
|
+
* from `icon`), and a separate `tonal` `bf-button` for the cancel action — the caller's
|
|
2710
|
+
* first `cancel`-role entry if any (further ones are ignored), else a synthesized one labelled `provideBfLabels()`'s `cancel` ("Cancel").
|
|
2711
|
+
* Focus starts on the cancel button. `open()` resolves with the tapped row's `id ?? label`; the
|
|
2712
|
+
* cancel button, a backdrop tap, `Escape`, the hardware back button and a navigation to another
|
|
2713
|
+
* URL path all resolve `undefined`.
|
|
2714
|
+
*
|
|
2715
|
+
* @example
|
|
2716
|
+
* const answer = await inject(BfActionSheetService).open({
|
|
2717
|
+
* title: 'Delete list?',
|
|
2718
|
+
* actions: [
|
|
2719
|
+
* { id: 'delete', label: 'Delete', role: 'destructive' },
|
|
2720
|
+
* { id: 'rename', label: 'Rename' },
|
|
2721
|
+
* ],
|
|
2722
|
+
* });
|
|
2723
|
+
* @since 0.2.0
|
|
2724
|
+
* @summary Opens bottom action sheets that resolve with the row the user tapped
|
|
2725
|
+
*/
|
|
2726
|
+
export declare class BfActionSheetService {
|
|
2727
|
+
private readonly overlays;
|
|
2728
|
+
private readonly injector;
|
|
2729
|
+
/**
|
|
2730
|
+
* Opens the action sheet described by `options`; resolves with the tapped row's `id ?? label`,
|
|
2731
|
+
* or `undefined` when cancelled.
|
|
2732
|
+
* @param options The title and rows of the sheet.
|
|
2733
|
+
*/
|
|
2734
|
+
open(options: BfActionSheetOptions): Promise<string | undefined>;
|
|
2735
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfActionSheetService, never>;
|
|
2736
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2737
|
+
}
|
|
2738
|
+
/**
|
|
2739
|
+
* The role of an alert dialog button: `cancel` answers `Escape` and the hardware back button,
|
|
2740
|
+
* `destructive` renders `danger`.
|
|
2741
|
+
*
|
|
2742
|
+
* @summary The role of an alert dialog button, the cancel answer or a destructive action
|
|
2743
|
+
* @since 0.3.0
|
|
2744
|
+
*/
|
|
2745
|
+
type BfAlertDialogButtonRole = 'cancel' | 'destructive';
|
|
2746
|
+
/**
|
|
2747
|
+
* A button of `BfAlertDialogService.open()`.
|
|
2748
|
+
*
|
|
2749
|
+
* @summary One button of an alert dialog: its answer, its label and its role
|
|
2750
|
+
* @since 0.2.0
|
|
2751
|
+
*/
|
|
2752
|
+
interface BfAlertDialogButton {
|
|
2753
|
+
/** What `open()` resolves with when the button is tapped (default `label`); keeps the answer
|
|
2754
|
+
* stable when the label is translated or two buttons share a label. */
|
|
2755
|
+
id?: string;
|
|
2756
|
+
/** Button text; also the value `open()` resolves with when it is tapped and has no `id`. */
|
|
2757
|
+
label: string;
|
|
2758
|
+
/**
|
|
2759
|
+
* `cancel` renders as a `text` button, takes the initial focus and is what `Escape`/the
|
|
2760
|
+
* hardware back button answer with; `destructive` renders `danger` (a plain `primary`/`tonal` button when omitted).
|
|
2761
|
+
*/
|
|
2762
|
+
role?: BfAlertDialogButtonRole;
|
|
2763
|
+
}
|
|
2764
|
+
/**
|
|
2765
|
+
* Options of `BfAlertDialogService.open()`.
|
|
2766
|
+
*
|
|
2767
|
+
* @summary Options of an alert dialog: its title, message, buttons and when it closes
|
|
2768
|
+
* @since 0.2.0
|
|
2769
|
+
*/
|
|
2770
|
+
interface BfAlertDialogOptions {
|
|
2771
|
+
/** Dialog heading, rendered as the `h2` the panel's `aria-labelledby` points to. */
|
|
2772
|
+
title: string;
|
|
2773
|
+
/** Body text under the title. */
|
|
2774
|
+
message?: string;
|
|
2775
|
+
/** Buttons, left to right (default one button labelled `provideBfLabels()`'s `ok`, "OK"). */
|
|
2776
|
+
buttons?: BfAlertDialogButton[];
|
|
2777
|
+
/**
|
|
2778
|
+
* A navigation to another URL path closes the alert, resolving the cancel button's answer, or
|
|
2779
|
+
* `undefined` without one (default true).
|
|
2780
|
+
* @default true
|
|
2781
|
+
*/
|
|
2782
|
+
closeOnNavigation?: boolean;
|
|
2783
|
+
/**
|
|
2784
|
+
* Injector the dialog resolves its labels (`BF_LABELS`) from and the parent of its content's
|
|
2785
|
+
* injector (default the root injector). Pass the opening component's `inject(Injector)` so a
|
|
2786
|
+
* feature-level `provideBfLabels()` and other feature providers reach it.
|
|
2787
|
+
*/
|
|
2788
|
+
injector?: Injector;
|
|
2789
|
+
}
|
|
2790
|
+
/**
|
|
2791
|
+
* Opens alert dialogs: a centred, 300 px card on the overlay core (`position: 'center'`, no
|
|
2792
|
+
* backdrop dismiss). Renders `title` as an `h2`, an optional `message`, and `buttons` (default
|
|
2793
|
+
* one `ok` button from the app's `provideBfLabels()`, "OK") as a right-aligned row — `cancel`-role `text`, `destructive`-role
|
|
2794
|
+
* `danger`, the first plain button `primary`, further plain ones `tonal`. Focus starts on the
|
|
2795
|
+
* `cancel`-role button, else the first one. `open()` resolves with the tapped button's
|
|
2796
|
+
* `id ?? label`. `Escape` and the hardware back button resolve with the cancel button's answer
|
|
2797
|
+
* when `buttons` has one; with none, they are claimed and ignored — an alert
|
|
2798
|
+
* with no cancel button can only be answered by tapping a button, or closed by a navigation to
|
|
2799
|
+
* another URL path, which resolves the cancel button's answer, else `undefined`.
|
|
2800
|
+
*
|
|
2801
|
+
* @example
|
|
2802
|
+
* const answer = await inject(BfAlertDialogService).open({
|
|
2803
|
+
* title: 'Delete list?',
|
|
2804
|
+
* message: 'This cannot be undone.',
|
|
2805
|
+
* buttons: [
|
|
2806
|
+
* { id: 'cancel', label: 'Cancel', role: 'cancel' },
|
|
2807
|
+
* { id: 'delete', label: 'Delete', role: 'destructive' },
|
|
2808
|
+
* ],
|
|
2809
|
+
* });
|
|
2810
|
+
* @since 0.2.0
|
|
2811
|
+
* @summary Opens small centred alerts that resolve with the button the user tapped
|
|
2812
|
+
*/
|
|
2813
|
+
export declare class BfAlertDialogService {
|
|
2814
|
+
private readonly overlays;
|
|
2815
|
+
private readonly stack;
|
|
2816
|
+
private readonly backButton;
|
|
2817
|
+
private readonly injector;
|
|
2818
|
+
/**
|
|
2819
|
+
* Opens the alert described by `options`; resolves with the tapped button's `id ?? label`, or
|
|
2820
|
+
* `undefined` when a navigation closes an alert that has no cancel button.
|
|
2821
|
+
* @param options The title, message and buttons of the alert.
|
|
2822
|
+
*/
|
|
2823
|
+
open(options: BfAlertDialogOptions): Promise<string | undefined>;
|
|
2824
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfAlertDialogService, never>;
|
|
2825
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<any>;
|
|
2826
|
+
}
|
|
2827
|
+
/** A button of an alert dialog, with the variant `BfAlertDialogService` resolved for it. */
|
|
2828
|
+
interface BfAlertDialogButtonConfig {
|
|
2829
|
+
/** Button text. */
|
|
2830
|
+
label: string;
|
|
2831
|
+
/** What `open()` resolves with when it is tapped: the caller's `id ?? label`. */
|
|
2832
|
+
answer: string;
|
|
2833
|
+
/** `cancel` answers `Escape`/the hardware back button; `destructive` renders `danger`. */
|
|
2834
|
+
role?: BfAlertDialogButtonRole;
|
|
2835
|
+
variant: BfButtonVariant;
|
|
2836
|
+
/** Whether it takes the initial focus: the `cancel`-role button, else the first one. */
|
|
2837
|
+
initial: boolean;
|
|
2838
|
+
}
|
|
2839
|
+
/** What `BfAlertDialogService` hands the `bf-alert-dialog` container (as its `BF_OVERLAY_DATA`); internal. */
|
|
2840
|
+
interface BfAlertDialogConfig {
|
|
2841
|
+
title: string;
|
|
2842
|
+
message: string | undefined;
|
|
2843
|
+
/** Id of the `h2` title, referenced by the panel's `aria-labelledby`. */
|
|
2844
|
+
titleId: string;
|
|
2845
|
+
/** Id of the message `p`, referenced by the panel's `aria-describedby` when there is a message. */
|
|
2846
|
+
messageId: string;
|
|
2847
|
+
buttons: BfAlertDialogButtonConfig[];
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* The alert dialog card that `BfAlertDialogService.open()` renders on the overlay core
|
|
2851
|
+
* (`position: 'center'`): an `h2.text-heading` title, an optional `text-body text-text-secondary`
|
|
2852
|
+
* message, and a right-aligned row of `bf-button`s (`cancel`-role `text`, `destructive`-role
|
|
2853
|
+
* `danger`, the first plain button `primary`, further plain ones `tonal`). Focus starts on the
|
|
2854
|
+
* `cancel`-role button, else the first one. Tapping a button resolves the overlay with its
|
|
2855
|
+
* `id ?? label`. There is no backdrop dismiss; `Escape` and the hardware
|
|
2856
|
+
* back button are handled by `BfAlertDialogService` (the cancel button's answer, or claimed and
|
|
2857
|
+
* ignored when there is none). Not used directly in templates.
|
|
2858
|
+
*
|
|
2859
|
+
* @example
|
|
2860
|
+
* const answer = await inject(BfAlertDialogService).open({
|
|
2861
|
+
* title: 'Delete list?',
|
|
2862
|
+
* message: 'This cannot be undone.',
|
|
2863
|
+
* buttons: [
|
|
2864
|
+
* { id: 'cancel', label: 'Cancel', role: 'cancel' },
|
|
2865
|
+
* { id: 'delete', label: 'Delete', role: 'destructive' },
|
|
2866
|
+
* ],
|
|
2867
|
+
* });
|
|
2868
|
+
* @summary Centred confirmation dialog with a title, message and a row of role-styled buttons
|
|
2869
|
+
* @category Overlays
|
|
2870
|
+
* @since 0.2.0
|
|
2871
|
+
*/
|
|
2872
|
+
export declare class BfAlertDialogComponent {
|
|
2873
|
+
protected readonly config: BfAlertDialogConfig;
|
|
2874
|
+
private readonly ref;
|
|
2875
|
+
protected select(button: BfAlertDialogButtonConfig): void;
|
|
2876
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<BfAlertDialogComponent, never>;
|
|
2877
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<BfAlertDialogComponent, "bf-alert-dialog", never, {}, {}, never, never, true, never>;
|
|
2878
|
+
}
|
|
2879
|
+
/**
|
|
2880
|
+
* Options of `provideBfShellTesting()`.
|
|
2881
|
+
*
|
|
2882
|
+
* @summary Options of the shell test providers: the routes and the shell settings
|
|
2883
|
+
* @since 0.3.0
|
|
2884
|
+
*/
|
|
2885
|
+
interface BfShellTestingOptions {
|
|
2886
|
+
/**
|
|
2887
|
+
* The routes of the test router.
|
|
2888
|
+
* @default []
|
|
2889
|
+
*/
|
|
2890
|
+
routes?: Routes;
|
|
2891
|
+
/** Shell settings over the test defaults (`swipeBack: false`, `hapticsOnTabChange: false`). */
|
|
2892
|
+
config?: Partial<BfShellConfig>;
|
|
2893
|
+
}
|
|
2894
|
+
/**
|
|
2895
|
+
* Test providers for an app on the mobile shell: `provideRouter(routes ?? [],
|
|
2896
|
+
* withComponentInputBinding(), withBfShellRouting())` plus `provideBfShell({ swipeBack: false,
|
|
2897
|
+
* hapticsOnTabChange: false, ...config })`, an in-memory `BF_THEME_STORAGE` (so a theme change
|
|
2898
|
+
* never reaches `localStorage`), and the same document cleanup as `provideBfTesting()` from
|
|
2899
|
+
* `@bitforgehq/ui/testing` on teardown (`dark` and `cdk-global-scrollblock` on `<html>`, `inert` on
|
|
2900
|
+
* body children, stray overlay panes). Like that cleanup, it needs TestBed's default
|
|
2901
|
+
* `teardown: { destroyAfterEach: true }`. Use it instead of the app's own shell providers in
|
|
2902
|
+
* `TestBed.configureTestingModule()`.
|
|
2903
|
+
*
|
|
2904
|
+
* @example
|
|
2905
|
+
* TestBed.configureTestingModule({
|
|
2906
|
+
* providers: [provideBfShellTesting({ routes: [{ path: 'inbox', component: InboxPage }] })],
|
|
2907
|
+
* });
|
|
2908
|
+
* @param options The routes and the shell settings.
|
|
2909
|
+
* @returns The environment providers for `TestBed.configureTestingModule()`.
|
|
2910
|
+
* @summary Test providers for the mobile shell: router, shell, in-memory theme and cleanup
|
|
2911
|
+
* @since 0.3.0
|
|
2912
|
+
*/
|
|
2913
|
+
export declare function provideBfShellTesting(options?: BfShellTestingOptions): EnvironmentProviders;
|
|
2914
|
+
export { type BfActionSheetAction, type BfActionSheetActionRole, type BfActionSheetOptions, type BfAlertDialogButton, type BfAlertDialogButtonRole, type BfAlertDialogOptions, type BfBackAtRoot, type BfContentScrollEvent, type BfHapticsImpactStyle, type BfHapticsNotificationType, type BfKeyboardAssistBehavior, type BfKeyboardPhase, type BfModalOptions, type BfModalPresentation, type BfNavDirection, type BfNavTarget, type BfOverlayOptions, type BfOverlayPosition, type BfOverlayStackOptions, type BfOverlayTemplateContext, type BfPlatform, type BfRefresherRefreshEvent, type BfSheetAutoFocus, type BfSheetOptions, type BfShellConfig, type BfShellConfigMode, type BfShellDynamicType, type BfShellDynamicTypeLimit, type BfShellMode, type BfShellTestingOptions, type BfStackChange, type BfStackTransition, type BfStackTransitionEvent, type BfStackedOverlay, type BfTabContext, type BfTheme, type BfToastAction, type BfToastDismissReason, type BfToastOptions, type BfToastPosition, BfToastRef, type BfTransitionKind, type BfViewEvent, type BfViewState, prefersReducedMotion };
|