@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.
Files changed (281) hide show
  1. package/CHANGELOG.md +3665 -0
  2. package/LICENSE +21 -0
  3. package/README.md +175 -0
  4. package/ai/MANIFEST.index.json +383 -0
  5. package/ai/MANIFEST.json +7528 -0
  6. package/ai/REFERENCE.index.json +1461 -0
  7. package/ai/REFERENCE.json +7213 -0
  8. package/ai/UI_GUIDE.md +1159 -0
  9. package/ai/components/action-bar.md +209 -0
  10. package/ai/components/action-sheet.md +526 -0
  11. package/ai/components/alert-dialog.md +509 -0
  12. package/ai/components/alert.md +376 -0
  13. package/ai/components/avatar.md +146 -0
  14. package/ai/components/back-button.md +286 -0
  15. package/ai/components/badge.md +171 -0
  16. package/ai/components/button.md +431 -0
  17. package/ai/components/card.md +303 -0
  18. package/ai/components/checkbox.md +418 -0
  19. package/ai/components/chip-group.md +205 -0
  20. package/ai/components/chip.md +300 -0
  21. package/ai/components/content.md +474 -0
  22. package/ai/components/desktop-toast.md +420 -0
  23. package/ai/components/dialog.md +962 -0
  24. package/ai/components/empty-state.md +146 -0
  25. package/ai/components/field.md +319 -0
  26. package/ai/components/header.md +809 -0
  27. package/ai/components/icon-button.md +221 -0
  28. package/ai/components/icon.md +176 -0
  29. package/ai/components/input.md +455 -0
  30. package/ai/components/list-item.md +326 -0
  31. package/ai/components/list.md +178 -0
  32. package/ai/components/menu-button.md +377 -0
  33. package/ai/components/menu.md +661 -0
  34. package/ai/components/modal.md +613 -0
  35. package/ai/components/number-input.md +423 -0
  36. package/ai/components/page.md +299 -0
  37. package/ai/components/progress.md +215 -0
  38. package/ai/components/radio-group.md +432 -0
  39. package/ai/components/refresher.md +377 -0
  40. package/ai/components/segmented.md +517 -0
  41. package/ai/components/select.md +510 -0
  42. package/ai/components/sheet.md +845 -0
  43. package/ai/components/spinner.md +171 -0
  44. package/ai/components/stack-outlet.md +661 -0
  45. package/ai/components/tab-bar.md +427 -0
  46. package/ai/components/tab.md +295 -0
  47. package/ai/components/tabs.md +408 -0
  48. package/ai/components/textarea.md +371 -0
  49. package/ai/components/toast.md +522 -0
  50. package/ai/components/toggle.md +387 -0
  51. package/ai/reference/bf-action-directive.md +21 -0
  52. package/ai/reference/bf-action-sheet-action-role.md +27 -0
  53. package/ai/reference/bf-action-sheet-action.md +28 -0
  54. package/ai/reference/bf-action-sheet-options.md +28 -0
  55. package/ai/reference/bf-action-sheet-service.md +33 -0
  56. package/ai/reference/bf-alert-dialog-button-role.md +27 -0
  57. package/ai/reference/bf-alert-dialog-button.md +27 -0
  58. package/ai/reference/bf-alert-dialog-options.md +29 -0
  59. package/ai/reference/bf-alert-dialog-service.md +34 -0
  60. package/ai/reference/bf-alert-variant.md +28 -0
  61. package/ai/reference/bf-autocapitalize.md +30 -0
  62. package/ai/reference/bf-avatar-size.md +27 -0
  63. package/ai/reference/bf-avatar-variant.md +28 -0
  64. package/ai/reference/bf-back-at-root.md +28 -0
  65. package/ai/reference/bf-back-button-service.md +40 -0
  66. package/ai/reference/bf-badge-variant.md +29 -0
  67. package/ai/reference/bf-button-size.md +29 -0
  68. package/ai/reference/bf-button-type.md +28 -0
  69. package/ai/reference/bf-button-variant.md +29 -0
  70. package/ai/reference/bf-card-padding.md +26 -0
  71. package/ai/reference/bf-card-variant.md +28 -0
  72. package/ai/reference/bf-chip-group-mode.md +27 -0
  73. package/ai/reference/bf-chip-variant.md +26 -0
  74. package/ai/reference/bf-compare-with.md +24 -0
  75. package/ai/reference/bf-component-overlay-ref.md +33 -0
  76. package/ai/reference/bf-confirm-button-role.md +26 -0
  77. package/ai/reference/bf-confirm-button.md +27 -0
  78. package/ai/reference/bf-confirm-options.md +31 -0
  79. package/ai/reference/bf-confirm-size.md +26 -0
  80. package/ai/reference/bf-content-scroll-event.md +21 -0
  81. package/ai/reference/bf-defaults-options.md +32 -0
  82. package/ai/reference/bf-defaults.md +28 -0
  83. package/ai/reference/bf-desktop-toast-config.md +28 -0
  84. package/ai/reference/bf-desktop-toast-harness.md +33 -0
  85. package/ai/reference/bf-desktop-toast-options.md +28 -0
  86. package/ai/reference/bf-desktop-toast-position.md +28 -0
  87. package/ai/reference/bf-desktop-toast-service.md +42 -0
  88. package/ai/reference/bf-dialog-config.md +44 -0
  89. package/ai/reference/bf-dialog-harness.md +52 -0
  90. package/ai/reference/bf-dialog-ref.md +44 -0
  91. package/ai/reference/bf-dialog-role.md +26 -0
  92. package/ai/reference/bf-dialog-service.md +55 -0
  93. package/ai/reference/bf-dialog-size.md +31 -0
  94. package/ai/reference/bf-dialog-template-context.md +32 -0
  95. package/ai/reference/bf-empty-state-heading-level.md +26 -0
  96. package/ai/reference/bf-enter-key-hint.md +31 -0
  97. package/ai/reference/bf-field-control-class.md +32 -0
  98. package/ai/reference/bf-field-control-state.md +28 -0
  99. package/ai/reference/bf-field-size.md +29 -0
  100. package/ai/reference/bf-haptics-impact-style.md +27 -0
  101. package/ai/reference/bf-haptics-notification-type.md +27 -0
  102. package/ai/reference/bf-haptics-service.md +41 -0
  103. package/ai/reference/bf-harness-filters.md +29 -0
  104. package/ai/reference/bf-horizontal-scroll-directive.md +129 -0
  105. package/ai/reference/bf-icon-button-variant.md +28 -0
  106. package/ai/reference/bf-icon-size.md +27 -0
  107. package/ai/reference/bf-input-autocapitalize.md +36 -0
  108. package/ai/reference/bf-input-enter-key-hint.md +38 -0
  109. package/ai/reference/bf-input-input-mode.md +38 -0
  110. package/ai/reference/bf-input-mode.md +32 -0
  111. package/ai/reference/bf-input-type.md +35 -0
  112. package/ai/reference/bf-jsdom-shim-options.md +22 -0
  113. package/ai/reference/bf-keyboard-assist-behavior.md +26 -0
  114. package/ai/reference/bf-keyboard-assist-directive.md +185 -0
  115. package/ai/reference/bf-keyboard-phase.md +30 -0
  116. package/ai/reference/bf-keyboard-service.md +50 -0
  117. package/ai/reference/bf-labels-overrides.md +26 -0
  118. package/ai/reference/bf-labels.md +44 -0
  119. package/ai/reference/bf-menu-button-harness.md +40 -0
  120. package/ai/reference/bf-menu-button-variant.md +27 -0
  121. package/ai/reference/bf-menu-divider-directive.md +13 -0
  122. package/ai/reference/bf-menu-group-directive.md +14 -0
  123. package/ai/reference/bf-menu-harness.md +55 -0
  124. package/ai/reference/bf-menu-item-checkbox-directive.md +31 -0
  125. package/ai/reference/bf-menu-item-directive.md +31 -0
  126. package/ai/reference/bf-menu-item-harness.md +52 -0
  127. package/ai/reference/bf-menu-item-radio-directive.md +29 -0
  128. package/ai/reference/bf-menu-placement.md +29 -0
  129. package/ai/reference/bf-menu-trigger-directive.md +46 -0
  130. package/ai/reference/bf-modal-options.md +30 -0
  131. package/ai/reference/bf-modal-presentation.md +26 -0
  132. package/ai/reference/bf-modal-service.md +38 -0
  133. package/ai/reference/bf-nav-controller.md +59 -0
  134. package/ai/reference/bf-nav-direction.md +23 -0
  135. package/ai/reference/bf-nav-target.md +21 -0
  136. package/ai/reference/bf-number-input-mode.md +28 -0
  137. package/ai/reference/bf-number-input-step.md +25 -0
  138. package/ai/reference/bf-overlay-auto-focus.md +29 -0
  139. package/ai/reference/bf-overlay-controller.md +22 -0
  140. package/ai/reference/bf-overlay-host.md +36 -0
  141. package/ai/reference/bf-overlay-options.md +53 -0
  142. package/ai/reference/bf-overlay-position.md +30 -0
  143. package/ai/reference/bf-overlay-ref.md +53 -0
  144. package/ai/reference/bf-overlay-role.md +27 -0
  145. package/ai/reference/bf-overlay-service.md +53 -0
  146. package/ai/reference/bf-overlay-stack-options.md +24 -0
  147. package/ai/reference/bf-overlay-stack.md +81 -0
  148. package/ai/reference/bf-overlay-template-context.md +24 -0
  149. package/ai/reference/bf-overscroll-stretch-directive.md +163 -0
  150. package/ai/reference/bf-page-context.md +24 -0
  151. package/ai/reference/bf-platform-service.md +53 -0
  152. package/ai/reference/bf-platform.md +28 -0
  153. package/ai/reference/bf-progress-size.md +26 -0
  154. package/ai/reference/bf-progress-tone.md +28 -0
  155. package/ai/reference/bf-radio-group-harness.md +49 -0
  156. package/ai/reference/bf-radio-group-orientation.md +26 -0
  157. package/ai/reference/bf-radio-option.md +30 -0
  158. package/ai/reference/bf-refresher-refresh-event.md +22 -0
  159. package/ai/reference/bf-segment-option.md +29 -0
  160. package/ai/reference/bf-segmented-harness.md +48 -0
  161. package/ai/reference/bf-segmented-size.md +29 -0
  162. package/ai/reference/bf-select-harness.md +70 -0
  163. package/ai/reference/bf-select-option.md +29 -0
  164. package/ai/reference/bf-sheet-auto-focus.md +29 -0
  165. package/ai/reference/bf-sheet-options.md +32 -0
  166. package/ai/reference/bf-sheet-ref.md +45 -0
  167. package/ai/reference/bf-sheet-service.md +34 -0
  168. package/ai/reference/bf-shell-config-mode.md +28 -0
  169. package/ai/reference/bf-shell-config.md +38 -0
  170. package/ai/reference/bf-shell-dynamic-type-limit.md +21 -0
  171. package/ai/reference/bf-shell-dynamic-type.md +25 -0
  172. package/ai/reference/bf-shell-mode.md +28 -0
  173. package/ai/reference/bf-shell-testing-options.md +26 -0
  174. package/ai/reference/bf-size.md +45 -0
  175. package/ai/reference/bf-spinner-size.md +27 -0
  176. package/ai/reference/bf-stack-change.md +22 -0
  177. package/ai/reference/bf-stack-reuse-strategy.md +32 -0
  178. package/ai/reference/bf-stack-transition-event.md +26 -0
  179. package/ai/reference/bf-stack-transition.md +26 -0
  180. package/ai/reference/bf-stacked-overlay.md +23 -0
  181. package/ai/reference/bf-system-bars-style.md +38 -0
  182. package/ai/reference/bf-tab-bar-controller.md +51 -0
  183. package/ai/reference/bf-tab-bar-host.md +52 -0
  184. package/ai/reference/bf-tab-context.md +32 -0
  185. package/ai/reference/bf-tab-links.md +37 -0
  186. package/ai/reference/bf-testing-options.md +27 -0
  187. package/ai/reference/bf-text-scale-service.md +35 -0
  188. package/ai/reference/bf-theme.md +27 -0
  189. package/ai/reference/bf-toast-action.md +25 -0
  190. package/ai/reference/bf-toast-controller.md +17 -0
  191. package/ai/reference/bf-toast-dismiss-reason.md +29 -0
  192. package/ai/reference/bf-toast-options.md +29 -0
  193. package/ai/reference/bf-toast-position.md +26 -0
  194. package/ai/reference/bf-toast-ref.md +41 -0
  195. package/ai/reference/bf-toast-service.md +39 -0
  196. package/ai/reference/bf-toggle-label-position.md +26 -0
  197. package/ai/reference/bf-transition-kind.md +28 -0
  198. package/ai/reference/bf-validation-message.md +31 -0
  199. package/ai/reference/bf-validation-messages.md +33 -0
  200. package/ai/reference/bf-view-event.md +28 -0
  201. package/ai/reference/bf-view-lifecycle.md +41 -0
  202. package/ai/reference/bf-view-state.md +28 -0
  203. package/ai/reference/bf_default_labels.md +21 -0
  204. package/ai/reference/bf_default_values.md +21 -0
  205. package/ai/reference/bf_defaults.md +21 -0
  206. package/ai/reference/bf_desktop_toast_defaults.md +21 -0
  207. package/ai/reference/bf_dialog_data.md +17 -0
  208. package/ai/reference/bf_labels.md +21 -0
  209. package/ai/reference/bf_overlay_data.md +19 -0
  210. package/ai/reference/bf_overlay_host.md +21 -0
  211. package/ai/reference/bf_sheet_default_snap_points.md +17 -0
  212. package/ai/reference/bf_shell_config.md +21 -0
  213. package/ai/reference/bf_shell_defaults.md +21 -0
  214. package/ai/reference/bf_tab_bar.md +21 -0
  215. package/ai/reference/bf_tab_bar_controller.md +21 -0
  216. package/ai/reference/bf_tab_context.md +21 -0
  217. package/ai/reference/bf_tab_links.md +21 -0
  218. package/ai/reference/bf_theme_storage.md +19 -0
  219. package/ai/reference/create-transition.md +36 -0
  220. package/ai/reference/duration_fast.md +17 -0
  221. package/ai/reference/duration_md.md +17 -0
  222. package/ai/reference/duration_overlay.md +17 -0
  223. package/ai/reference/duration_push.md +17 -0
  224. package/ai/reference/fade-down.md +26 -0
  225. package/ai/reference/fade-in.md +25 -0
  226. package/ai/reference/fade-out.md +25 -0
  227. package/ai/reference/fade-up.md +26 -0
  228. package/ai/reference/inject-shell-mode.md +23 -0
  229. package/ai/reference/install-bf-jsdom-shims.md +31 -0
  230. package/ai/reference/ios_duration.md +17 -0
  231. package/ai/reference/ios_easing.md +17 -0
  232. package/ai/reference/is-text-entry.md +25 -0
  233. package/ai/reference/max_complete_ms.md +17 -0
  234. package/ai/reference/md-transition.md +31 -0
  235. package/ai/reference/md_duration.md +17 -0
  236. package/ai/reference/md_easing.md +17 -0
  237. package/ai/reference/overlay_duration.md +21 -0
  238. package/ai/reference/overlay_easing.md +19 -0
  239. package/ai/reference/overlay_reduced_duration.md +17 -0
  240. package/ai/reference/pop-frames-at.md +25 -0
  241. package/ai/reference/prefers-reduced-motion.md +25 -0
  242. package/ai/reference/provide-bf-defaults.md +33 -0
  243. package/ai/reference/provide-bf-desktop-toast.md +28 -0
  244. package/ai/reference/provide-bf-labels.md +38 -0
  245. package/ai/reference/provide-bf-shell-testing.md +34 -0
  246. package/ai/reference/provide-bf-shell.md +41 -0
  247. package/ai/reference/provide-bf-testing.md +33 -0
  248. package/ai/reference/reduced-transition.md +28 -0
  249. package/ai/reference/reduced_duration.md +17 -0
  250. package/ai/reference/resolve-shell-mode.md +33 -0
  251. package/ai/reference/scale-in.md +25 -0
  252. package/ai/reference/settle-duration.md +25 -0
  253. package/ai/reference/settle-pop.md +33 -0
  254. package/ai/reference/settle_easing.md +17 -0
  255. package/ai/reference/should-complete-pop.md +26 -0
  256. package/ai/reference/slide-down.md +26 -0
  257. package/ai/reference/slide-up.md +26 -0
  258. package/ai/reference/with-bf-shell-routing.md +19 -0
  259. package/bin/bf-ui.js +81 -0
  260. package/fesm2022/bitforgehq-ui-icons.mjs +230 -0
  261. package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -0
  262. package/fesm2022/bitforgehq-ui-mobile.mjs +5530 -0
  263. package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -0
  264. package/fesm2022/bitforgehq-ui-number-input.mjs +680 -0
  265. package/fesm2022/bitforgehq-ui-number-input.mjs.map +1 -0
  266. package/fesm2022/bitforgehq-ui-overlay.mjs +2675 -0
  267. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -0
  268. package/fesm2022/bitforgehq-ui-testing.mjs +402 -0
  269. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -0
  270. package/fesm2022/bitforgehq-ui.mjs +7765 -0
  271. package/fesm2022/bitforgehq-ui.mjs.map +1 -0
  272. package/llms-full.txt +25394 -0
  273. package/llms.txt +329 -0
  274. package/package.json +94 -0
  275. package/theme.css +253 -0
  276. package/types/bitforgehq-ui-icons.d.ts +50 -0
  277. package/types/bitforgehq-ui-mobile.d.ts +2914 -0
  278. package/types/bitforgehq-ui-number-input.d.ts +282 -0
  279. package/types/bitforgehq-ui-overlay.d.ts +1514 -0
  280. package/types/bitforgehq-ui-testing.d.ts +495 -0
  281. package/types/bitforgehq-ui.d.ts +3499 -0
@@ -0,0 +1,2675 @@
1
+ import * as i0 from "@angular/core";
2
+ import { Component, DOCUMENT, DestroyRef, Directive, ElementRef, Injectable, InjectionToken, Injector, SimpleChange, TemplateRef, afterNextRender, booleanAttribute, computed, effect, inject, input, makeEnvironmentProviders, model, output, signal, viewChild } from "@angular/core";
3
+ import { FocusTrapFactory, LiveAnnouncer } from "@angular/cdk/a11y";
4
+ import { Overlay, OverlayConfig } from "@angular/cdk/overlay";
5
+ import { ComponentPortal } from "@angular/cdk/portal";
6
+ import { Location, NgTemplateOutlet } from "@angular/common";
7
+ import { BF_DEFAULTS, BF_LABELS, BfButtonComponent, BfIconButtonComponent, ɵBF_BUTTON_CLASSES, ɵBF_ICON_BUTTON_CLASSES, ɵPILL_HIT, ɵuniqueId } from "@bitforgehq/ui";
8
+ import { BfIconComponent } from "@bitforgehq/ui/icons";
9
+ import { X } from "lucide";
10
+ import { Directionality } from "@angular/cdk/bidi";
11
+ import * as i1 from "@angular/cdk/menu";
12
+ import { CDK_MENU, CdkMenu, CdkMenuGroup, CdkMenuItem, CdkMenuItemCheckbox, CdkMenuItemRadio, CdkMenuTrigger, CdkTargetMenuAim } from "@angular/cdk/menu";
13
+ const BF_OVERLAY_DATA = new InjectionToken("BF_OVERLAY_DATA");
14
+ let nextId = 0;
15
+ var BfOverlayRef = class {
16
+ controller;
17
+ id = `bf-overlay-${nextId++}`;
18
+ afterClosed;
19
+ closedState = signal(false, ...ngDevMode ? [{ debugName: "closedState" }] : /* istanbul ignore next */ []);
20
+ closed = this.closedState.asReadonly();
21
+ closing = false;
22
+ resolveClosed = () => void 0;
23
+ constructor(controller) {
24
+ this.controller = controller;
25
+ this.afterClosed = new Promise((resolve) => {
26
+ this.resolveClosed = resolve;
27
+ });
28
+ }
29
+ get isClosing() {
30
+ return this.closing;
31
+ }
32
+ close(result) {
33
+ if (this.closing) return;
34
+ this.closing = true;
35
+ this.controller.close().then(() => {
36
+ this.closedState.set(true);
37
+ this.resolveClosed(result);
38
+ });
39
+ }
40
+ updatePosition() {
41
+ this.controller.updatePosition();
42
+ }
43
+ };
44
+ var BfComponentOverlayRef = class extends BfOverlayRef {
45
+ ref = null;
46
+ get componentRef() {
47
+ if (!this.ref) throw new Error("BfComponentOverlayRef: the content component is not attached yet");
48
+ return this.ref;
49
+ }
50
+ setComponentRef(ref) {
51
+ this.ref = ref;
52
+ }
53
+ };
54
+ const BF_OVERLAY_HOST = new InjectionToken("BF_OVERLAY_HOST");
55
+ const OVERLAY_CONTAINER = ".cdk-overlay-container";
56
+ const KEEP_ACTIVE = [
57
+ "script",
58
+ "style",
59
+ "template",
60
+ "link",
61
+ ".cdk-live-announcer-element",
62
+ ".cdk-describedby-message-container",
63
+ "[data-bf-overlay-keep]"
64
+ ].join(", ");
65
+ var BfOverlayStack = class BfOverlayStack {
66
+ host = inject(BF_OVERLAY_HOST, { optional: true });
67
+ document = inject(DOCUMENT);
68
+ roots = /* @__PURE__ */ new Set();
69
+ inertBodyChildren = /* @__PURE__ */ new Set();
70
+ entries = signal([], ...ngDevMode ? [{ debugName: "entries" }] : /* istanbul ignore next */ []);
71
+ constructor() {
72
+ inject(DestroyRef).onDestroy(() => {
73
+ for (const el of this.inertBodyChildren) el.removeAttribute("inert");
74
+ this.inertBodyChildren.clear();
75
+ for (const root of this.roots) {
76
+ root.removeAttribute("inert");
77
+ root.style.removeProperty("--bf-modal-depth");
78
+ }
79
+ this.roots.clear();
80
+ });
81
+ }
82
+ count = computed(() => this.entries().length, ...ngDevMode ? [{ debugName: "count" }] : /* istanbul ignore next */ []);
83
+ depth = computed(() => this.entries().filter((e) => e.countsAsModal).length, ...ngDevMode ? [{ debugName: "depth" }] : /* istanbul ignore next */ []);
84
+ registerRoot(el) {
85
+ this.roots.add(el);
86
+ this.applyTo(el);
87
+ this.applyToBody();
88
+ return () => {
89
+ if (this.roots.delete(el)) {
90
+ el.removeAttribute("inert");
91
+ el.style.removeProperty("--bf-modal-depth");
92
+ this.applyToBody();
93
+ }
94
+ };
95
+ }
96
+ push(ref, options = {}) {
97
+ if (this.entries().some((e) => e.ref === ref)) return;
98
+ const unregisterBack = this.host?.registerBack(options.backPriority ?? 100, () => {
99
+ ref.close();
100
+ return true;
101
+ }) ?? (() => void 0);
102
+ this.entries.update((list) => [...list, {
103
+ ref,
104
+ countsAsModal: options.countsAsModal ?? false,
105
+ unregisterBack
106
+ }]);
107
+ this.apply();
108
+ }
109
+ pop(ref) {
110
+ const entry = this.entries().find((e) => e.ref === ref);
111
+ if (!entry) return;
112
+ entry.unregisterBack();
113
+ this.entries.update((list) => list.filter((e) => e !== entry));
114
+ this.apply();
115
+ }
116
+ isTop(ref) {
117
+ const list = this.entries();
118
+ return list.length > 0 && list[list.length - 1].ref === ref;
119
+ }
120
+ releaseBack(ref) {
121
+ this.entries().find((e) => e.ref === ref)?.unregisterBack();
122
+ }
123
+ apply() {
124
+ for (const root of this.roots) this.applyTo(root);
125
+ this.applyToBody();
126
+ }
127
+ applyToBody() {
128
+ if (this.count() === 0 || this.roots.size > 0) {
129
+ for (const el of this.inertBodyChildren) el.removeAttribute("inert");
130
+ this.inertBodyChildren.clear();
131
+ return;
132
+ }
133
+ const containers = Array.from(this.document.querySelectorAll(OVERLAY_CONTAINER));
134
+ for (const child of Array.from(this.document.body.children)) {
135
+ if (child.hasAttribute("inert") || containers.some((container) => child.contains(container)) || child.matches(KEEP_ACTIVE)) continue;
136
+ child.setAttribute("inert", "");
137
+ this.inertBodyChildren.add(child);
138
+ }
139
+ }
140
+ applyTo(root) {
141
+ if (this.count() > 0) root.setAttribute("inert", "");
142
+ else root.removeAttribute("inert");
143
+ const depth = this.depth();
144
+ if (depth > 0) root.style.setProperty("--bf-modal-depth", String(depth));
145
+ else root.style.removeProperty("--bf-modal-depth");
146
+ }
147
+ static ɵfac = i0.ɵɵngDeclareFactory({
148
+ minVersion: "12.0.0",
149
+ version: "22.1.7",
150
+ ngImport: i0,
151
+ type: BfOverlayStack,
152
+ deps: [],
153
+ target: i0.ɵɵFactoryTarget.Injectable
154
+ });
155
+ static ɵprov = i0.ɵɵngDeclareInjectable({
156
+ minVersion: "12.0.0",
157
+ version: "22.1.7",
158
+ ngImport: i0,
159
+ type: BfOverlayStack,
160
+ providedIn: "root"
161
+ });
162
+ };
163
+ i0.ɵɵngDeclareClassMetadata({
164
+ minVersion: "12.0.0",
165
+ version: "22.1.7",
166
+ ngImport: i0,
167
+ type: BfOverlayStack,
168
+ decorators: [{
169
+ type: Injectable,
170
+ args: [{ providedIn: "root" }]
171
+ }],
172
+ ctorParameters: () => []
173
+ });
174
+ const OVERLAY_DURATION = 260;
175
+ const OVERLAY_EASING = "cubic-bezier(0.32, 0.72, 0, 1)";
176
+ const OVERLAY_REDUCED_DURATION = 150;
177
+ function prefersReducedMotion(view) {
178
+ if (!view || typeof view.matchMedia !== "function") return false;
179
+ return view.matchMedia("(prefers-reduced-motion: reduce)").matches;
180
+ }
181
+ function urlPath(url) {
182
+ const end = url.search(/[?#]/);
183
+ return end === -1 ? url : url.slice(0, end);
184
+ }
185
+ function watchPathChange(location, onChange) {
186
+ let last = urlPath(location.path());
187
+ const stop = location.onUrlChange(() => {
188
+ const path = urlPath(location.path());
189
+ if (path === last) return;
190
+ last = path;
191
+ onChange();
192
+ });
193
+ let stopped = false;
194
+ return () => {
195
+ if (stopped) return;
196
+ stopped = true;
197
+ queueMicrotask(stop);
198
+ };
199
+ }
200
+ const TIMING_KEYS = /* @__PURE__ */ new Set([
201
+ "offset",
202
+ "easing",
203
+ "composite"
204
+ ]);
205
+ var BfFinishedAnimation = class extends EventTarget {
206
+ currentTime = null;
207
+ effect = null;
208
+ finished = Promise.resolve(this);
209
+ id = "";
210
+ oncancel = null;
211
+ onfinish = null;
212
+ onremove = null;
213
+ overallProgress = 1;
214
+ pending = false;
215
+ playState = "finished";
216
+ playbackRate = 1;
217
+ ready = Promise.resolve(this);
218
+ replaceState = "active";
219
+ startTime = null;
220
+ timeline = null;
221
+ cancel() {}
222
+ commitStyles() {}
223
+ finish() {}
224
+ pause() {}
225
+ persist() {}
226
+ play() {}
227
+ reverse() {}
228
+ updatePlaybackRate(rate) {
229
+ this.playbackRate = rate;
230
+ }
231
+ };
232
+ function animateOrSettle(el, frames, options) {
233
+ if (typeof el.animate === "function") return el.animate(frames, options);
234
+ const last = frames[frames.length - 1];
235
+ if (last && (options.fill === "forwards" || options.fill === "both")) {
236
+ for (const [key, value] of Object.entries(last)) if (!TIMING_KEYS.has(key) && value !== null && value !== void 0) el.style.setProperty(key.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`), String(value));
237
+ }
238
+ return new BfFinishedAnimation();
239
+ }
240
+ function run(el, frames, entering) {
241
+ if (prefersReducedMotion(el.ownerDocument.defaultView)) return animateOrSettle(el, entering ? [{ opacity: 0 }, { opacity: 1 }] : [{ opacity: 1 }, { opacity: 0 }], {
242
+ duration: 150,
243
+ easing: "linear",
244
+ fill: entering ? "backwards" : "forwards"
245
+ });
246
+ return animateOrSettle(el, frames, {
247
+ duration: 260,
248
+ easing: OVERLAY_EASING,
249
+ fill: entering ? "backwards" : "forwards"
250
+ });
251
+ }
252
+ function slideUp(el, distance = "100%") {
253
+ return run(el, [{ transform: `translate3d(0,${distance},0)` }, { transform: "translate3d(0,0,0)" }], true);
254
+ }
255
+ function slideDown(el, distance = "100%") {
256
+ return run(el, [{ transform: "translate3d(0,0,0)" }, { transform: `translate3d(0,${distance},0)` }], false);
257
+ }
258
+ function fadeIn(el) {
259
+ return run(el, [{ opacity: 0 }, { opacity: 1 }], true);
260
+ }
261
+ function fadeOut(el) {
262
+ return run(el, [{ opacity: 1 }, { opacity: 0 }], false);
263
+ }
264
+ function scaleIn(el) {
265
+ return run(el, [{
266
+ opacity: 0,
267
+ transform: "scale(0.92)"
268
+ }, {
269
+ opacity: 1,
270
+ transform: "scale(1)"
271
+ }], true);
272
+ }
273
+ function fadeUp(el, distance = "16px") {
274
+ return run(el, [{
275
+ opacity: 0,
276
+ transform: `translate3d(0,${distance},0)`
277
+ }, {
278
+ opacity: 1,
279
+ transform: "translate3d(0,0,0)"
280
+ }], true);
281
+ }
282
+ function fadeDown(el, distance = "16px") {
283
+ return run(el, [{
284
+ opacity: 1,
285
+ transform: "translate3d(0,0,0)"
286
+ }, {
287
+ opacity: 0,
288
+ transform: `translate3d(0,${distance},0)`
289
+ }], false);
290
+ }
291
+ var BfOverlayTemplateHostComponent = class BfOverlayTemplateHostComponent {
292
+ template = input.required(...ngDevMode ? [{ debugName: "template" }] : /* istanbul ignore next */ []);
293
+ context = input.required(...ngDevMode ? [{ debugName: "context" }] : /* istanbul ignore next */ []);
294
+ injector = input.required(...ngDevMode ? [{ debugName: "injector" }] : /* istanbul ignore next */ []);
295
+ static ɵfac = i0.ɵɵngDeclareFactory({
296
+ minVersion: "12.0.0",
297
+ version: "22.1.7",
298
+ ngImport: i0,
299
+ type: BfOverlayTemplateHostComponent,
300
+ deps: [],
301
+ target: i0.ɵɵFactoryTarget.Component
302
+ });
303
+ static ɵcmp = i0.ɵɵngDeclareComponent({
304
+ minVersion: "17.1.0",
305
+ version: "22.1.7",
306
+ type: BfOverlayTemplateHostComponent,
307
+ isStandalone: true,
308
+ selector: "bf-overlay-template-host",
309
+ inputs: {
310
+ template: {
311
+ classPropertyName: "template",
312
+ publicName: "template",
313
+ isSignal: true,
314
+ isRequired: true,
315
+ transformFunction: null
316
+ },
317
+ context: {
318
+ classPropertyName: "context",
319
+ publicName: "context",
320
+ isSignal: true,
321
+ isRequired: true,
322
+ transformFunction: null
323
+ },
324
+ injector: {
325
+ classPropertyName: "injector",
326
+ publicName: "injector",
327
+ isSignal: true,
328
+ isRequired: true,
329
+ transformFunction: null
330
+ }
331
+ },
332
+ host: { styleAttribute: "display: contents" },
333
+ ngImport: i0,
334
+ template: `<ng-container
335
+ [ngTemplateOutlet]="template()"
336
+ [ngTemplateOutletContext]="context()"
337
+ [ngTemplateOutletInjector]="injector()"
338
+ />`,
339
+ isInline: true,
340
+ dependencies: [{
341
+ kind: "directive",
342
+ type: NgTemplateOutlet,
343
+ selector: "[ngTemplateOutlet]",
344
+ inputs: [
345
+ "ngTemplateOutletContext",
346
+ "ngTemplateOutlet",
347
+ "ngTemplateOutletInjector"
348
+ ]
349
+ }]
350
+ });
351
+ };
352
+ i0.ɵɵngDeclareClassMetadata({
353
+ minVersion: "12.0.0",
354
+ version: "22.1.7",
355
+ ngImport: i0,
356
+ type: BfOverlayTemplateHostComponent,
357
+ decorators: [{
358
+ type: Component,
359
+ args: [{
360
+ selector: "bf-overlay-template-host",
361
+ imports: [NgTemplateOutlet],
362
+ host: { style: "display: contents" },
363
+ template: `<ng-container
364
+ [ngTemplateOutlet]="template()"
365
+ [ngTemplateOutletContext]="context()"
366
+ [ngTemplateOutletInjector]="injector()"
367
+ />`
368
+ }]
369
+ }],
370
+ propDecorators: {
371
+ template: [{
372
+ type: i0.Input,
373
+ args: [{
374
+ isSignal: true,
375
+ alias: "template",
376
+ required: true
377
+ }]
378
+ }],
379
+ context: [{
380
+ type: i0.Input,
381
+ args: [{
382
+ isSignal: true,
383
+ alias: "context",
384
+ required: true
385
+ }]
386
+ }],
387
+ injector: [{
388
+ type: i0.Input,
389
+ args: [{
390
+ isSignal: true,
391
+ alias: "injector",
392
+ required: true
393
+ }]
394
+ }]
395
+ }
396
+ });
397
+ const TABBABLE = [
398
+ "a[href]",
399
+ "button:not([disabled])",
400
+ "input:not([disabled]):not([type=\"hidden\"])",
401
+ "select:not([disabled])",
402
+ "textarea:not([disabled])",
403
+ "[tabindex]:not([tabindex=\"-1\"])",
404
+ "[contenteditable=\"true\"]"
405
+ ].join(",");
406
+ function firstTabbable(panel) {
407
+ const autofocus = panel.querySelector("[autofocus], [cdkFocusInitial]");
408
+ if (autofocus) {
409
+ if (autofocus.matches(TABBABLE) || autofocus.hasAttribute("tabindex")) return autofocus;
410
+ const inner = autofocus.querySelector(TABBABLE);
411
+ if (inner) return inner;
412
+ }
413
+ for (const el of Array.from(panel.querySelectorAll(TABBABLE))) if (!el.closest("[inert]") && !el.hidden && !el.hasAttribute("data-bf-overlay-chrome")) return el;
414
+ return null;
415
+ }
416
+ function isCloseWatcherConstructor(value) {
417
+ return typeof value === "function";
418
+ }
419
+ function closeWatcherOf(view) {
420
+ const constructor = view ? Reflect.get(view, "CloseWatcher") : void 0;
421
+ return isCloseWatcherConstructor(constructor) ? constructor : null;
422
+ }
423
+ function fromOtherPane(event, pane) {
424
+ for (const target of event.composedPath()) {
425
+ if (target === pane) return false;
426
+ if (target instanceof Element && target.classList.contains("cdk-overlay-pane")) return true;
427
+ }
428
+ return false;
429
+ }
430
+ var BfOverlayService = class BfOverlayService {
431
+ overlay = inject(Overlay);
432
+ injector = inject(Injector);
433
+ document = inject(DOCUMENT);
434
+ stack = inject(BfOverlayStack);
435
+ focusTrapFactory = inject(FocusTrapFactory);
436
+ location = inject(Location);
437
+ openPanels = /* @__PURE__ */ new Set();
438
+ host = inject(BF_OVERLAY_HOST, { optional: true });
439
+ documentScrolls = this.host?.documentScrolls !== false;
440
+ open(content, options = {}) {
441
+ const passive = options.passive ?? false;
442
+ const previouslyFocused = this.document.activeElement;
443
+ const hasBackdrop = !passive && (options.backdrop ?? true);
444
+ const position = options.position ?? "center";
445
+ const overlayRef = this.overlay.create(new OverlayConfig({
446
+ positionStrategy: this.positionStrategy(position),
447
+ scrollStrategy: passive || !this.documentScrolls ? this.overlay.scrollStrategies.noop() : this.overlay.scrollStrategies.block(),
448
+ hasBackdrop,
449
+ backdropClass: options.backdropClass ?? "bf-overlay-backdrop",
450
+ panelClass: ["bf-overlay-panel", ...options.panelClass ?? []],
451
+ ...position === "fullscreen" ? {
452
+ width: "100%",
453
+ height: "100%"
454
+ } : {}
455
+ }));
456
+ const panel = overlayRef.overlayElement;
457
+ const subscriptions = [];
458
+ let focusTrap = null;
459
+ let enterAnimation = null;
460
+ let stopNavigation = null;
461
+ let closeWatcher = null;
462
+ const controller = {
463
+ close: async () => {
464
+ stopNavigation?.();
465
+ closeWatcher?.destroy();
466
+ closeWatcher = null;
467
+ this.stack.releaseBack(ref);
468
+ subscriptions.forEach((s) => s.unsubscribe());
469
+ enterAnimation?.cancel();
470
+ this.fadeOutBackdrop(overlayRef.backdropElement);
471
+ try {
472
+ await (options.exit ?? fadeOut)(panel)?.finished;
473
+ } catch {}
474
+ focusTrap?.destroy();
475
+ overlayRef.dispose();
476
+ this.stack.pop(ref);
477
+ this.openPanels.delete(panel);
478
+ if (!passive && (options.restoreFocus ?? true)) {
479
+ const fallback = [...this.openPanels].at(-1);
480
+ if (previouslyFocused?.isConnected) previouslyFocused.focus({ preventScroll: true });
481
+ else if (fallback) fallback.focus({ preventScroll: true });
482
+ }
483
+ },
484
+ updatePosition: () => overlayRef.updatePosition()
485
+ };
486
+ const ref = content instanceof TemplateRef ? new BfOverlayRef(controller) : new BfComponentOverlayRef(controller);
487
+ const contentInjector = Injector.create({
488
+ parent: options.injector ?? this.injector,
489
+ providers: [
490
+ {
491
+ provide: BF_OVERLAY_DATA,
492
+ useValue: options.data
493
+ },
494
+ {
495
+ provide: BfOverlayRef,
496
+ useValue: ref
497
+ },
498
+ ...options.providers?.(ref) ?? []
499
+ ]
500
+ });
501
+ this.decoratePanel(panel, options, passive);
502
+ if (!passive) {
503
+ this.openPanels.add(panel);
504
+ this.stack.push(ref, {
505
+ backPriority: options.backPriority,
506
+ countsAsModal: options.countsAsModal
507
+ });
508
+ }
509
+ if (content instanceof TemplateRef) {
510
+ const host = overlayRef.attach(new ComponentPortal(BfOverlayTemplateHostComponent, null, contentInjector));
511
+ host.setInput("template", content);
512
+ host.setInput("context", {
513
+ $implicit: ref,
514
+ data: options.data
515
+ });
516
+ host.setInput("injector", contentInjector);
517
+ host.changeDetectorRef.detectChanges();
518
+ } else {
519
+ const componentRef = overlayRef.attach(new ComponentPortal(content, null, contentInjector));
520
+ componentRef.changeDetectorRef.detectChanges();
521
+ ref.setComponentRef(componentRef);
522
+ }
523
+ this.dropDanglingLabel(panel, options);
524
+ if (!passive) {
525
+ const dismissByEscape = () => {
526
+ if (options.onEscape) options.onEscape();
527
+ else if (options.dismissOnEscape ?? true) ref.close();
528
+ };
529
+ subscriptions.push(overlayRef.keydownEvents().subscribe((event) => {
530
+ if (event.key !== "Escape" || !this.stack.isTop(ref) || fromOtherPane(event, overlayRef.overlayElement)) return;
531
+ event.preventDefault();
532
+ dismissByEscape();
533
+ }));
534
+ const Watcher = this.host?.handlesSystemBack ? null : closeWatcherOf(this.document.defaultView);
535
+ const watch = () => {
536
+ if (!Watcher) return;
537
+ const watcher = new Watcher();
538
+ watcher.onclose = () => {
539
+ if (closeWatcher !== watcher) return;
540
+ closeWatcher = null;
541
+ if (ref.isClosing) return;
542
+ if (this.stack.isTop(ref)) dismissByEscape();
543
+ if (!ref.isClosing) watch();
544
+ };
545
+ closeWatcher = watcher;
546
+ };
547
+ watch();
548
+ overlayRef.backdropElement?.addEventListener("mousedown", (event) => event.preventDefault());
549
+ if (hasBackdrop && (options.dismissOnBackdrop ?? true)) subscriptions.push(overlayRef.backdropClick().subscribe(() => ref.close()));
550
+ if (options.trapFocus ?? true) focusTrap = this.focusTrapFactory.create(panel);
551
+ (options.autoFocus === "panel" ? panel : firstTabbable(panel) ?? panel).focus({ preventScroll: true });
552
+ }
553
+ if (options.closeOnNavigation ?? !passive) stopNavigation = watchPathChange(this.location, () => {
554
+ if (ref.isClosing) return;
555
+ if (options.onNavigation) options.onNavigation();
556
+ else ref.close();
557
+ });
558
+ enterAnimation = (options.enter ?? fadeIn)(panel);
559
+ return ref;
560
+ }
561
+ fadeOutBackdrop(backdrop) {
562
+ if (!backdrop) return;
563
+ if (prefersReducedMotion(this.document.defaultView)) {
564
+ backdrop.style.opacity = "0";
565
+ return;
566
+ }
567
+ const current = this.document.defaultView?.getComputedStyle(backdrop).opacity;
568
+ animateOrSettle(backdrop, [{ opacity: current === void 0 || current === "" ? "1" : current }, { opacity: 0 }], {
569
+ duration: 260,
570
+ easing: OVERLAY_EASING,
571
+ fill: "forwards"
572
+ });
573
+ }
574
+ dropDanglingLabel(panel, options) {
575
+ const id = options.ariaLabelledBy;
576
+ if (!id || options.ariaLabel) return;
577
+ const target = this.document.getElementById(id);
578
+ if (!target || !panel.contains(target)) panel.removeAttribute("aria-labelledby");
579
+ }
580
+ decoratePanel(panel, options, passive) {
581
+ const role = options.role ?? (passive ? null : "dialog");
582
+ if (role) panel.setAttribute("role", role);
583
+ panel.setAttribute("tabindex", "-1");
584
+ if (!passive) panel.setAttribute("aria-modal", "true");
585
+ if (options.ariaLabel) panel.setAttribute("aria-label", options.ariaLabel);
586
+ if (options.ariaLabelledBy) panel.setAttribute("aria-labelledby", options.ariaLabelledBy);
587
+ if (options.ariaDescribedBy) panel.setAttribute("aria-describedby", options.ariaDescribedBy);
588
+ }
589
+ positionStrategy(position) {
590
+ const global = this.overlay.position().global();
591
+ switch (position) {
592
+ case "bottom": return global.centerHorizontally().bottom("0");
593
+ case "top": return global.centerHorizontally().top("0");
594
+ case "fullscreen": return global.top("0").left("0");
595
+ default: return global.centerHorizontally().centerVertically();
596
+ }
597
+ }
598
+ static ɵfac = i0.ɵɵngDeclareFactory({
599
+ minVersion: "12.0.0",
600
+ version: "22.1.7",
601
+ ngImport: i0,
602
+ type: BfOverlayService,
603
+ deps: [],
604
+ target: i0.ɵɵFactoryTarget.Injectable
605
+ });
606
+ static ɵprov = i0.ɵɵngDeclareInjectable({
607
+ minVersion: "12.0.0",
608
+ version: "22.1.7",
609
+ ngImport: i0,
610
+ type: BfOverlayService,
611
+ providedIn: "root"
612
+ });
613
+ };
614
+ i0.ɵɵngDeclareClassMetadata({
615
+ minVersion: "12.0.0",
616
+ version: "22.1.7",
617
+ ngImport: i0,
618
+ type: BfOverlayService,
619
+ decorators: [{
620
+ type: Injectable,
621
+ args: [{ providedIn: "root" }]
622
+ }]
623
+ });
624
+ let nextTitleId = 0;
625
+ const HEADING = "h1, h2, h3, h4, h5, h6, [role=\"heading\"]";
626
+ function labelPanelByHeading(panel) {
627
+ const heading = Array.from(panel.querySelectorAll(HEADING)).find((element) => !element.closest("[aria-hidden=\"true\"], [hidden]"));
628
+ if (!heading) return false;
629
+ if (!heading.id) heading.id = `bf-overlay-title-${nextTitleId++}`;
630
+ panel.setAttribute("aria-labelledby", heading.id);
631
+ panel.removeAttribute("aria-label");
632
+ return true;
633
+ }
634
+ function watchPanelHeading(panel) {
635
+ if (labelPanelByHeading(panel)) return () => void 0;
636
+ const observer = new MutationObserver(() => {
637
+ if (labelPanelByHeading(panel)) observer.disconnect();
638
+ });
639
+ observer.observe(panel, {
640
+ childList: true,
641
+ subtree: true,
642
+ attributes: true,
643
+ attributeFilter: [
644
+ "role",
645
+ "aria-hidden",
646
+ "hidden"
647
+ ]
648
+ });
649
+ return () => observer.disconnect();
650
+ }
651
+ var BfToastRef = class {
652
+ controller;
653
+ afterDismissed;
654
+ constructor(controller, afterDismissed) {
655
+ this.controller = controller;
656
+ this.afterDismissed = afterDismissed;
657
+ }
658
+ dismiss() {
659
+ this.controller.dismiss();
660
+ }
661
+ };
662
+ const DEFAULT_DURATION = 3e3;
663
+ function announcement(message, action) {
664
+ if (!action) return message;
665
+ const separator = /[.!?…:;,]$/.test(message.trim()) ? " " : ". ";
666
+ return `${message.trim()}${separator}${action.label}`;
667
+ }
668
+ var ɵBfToastQueue = class {
669
+ presenter;
670
+ options;
671
+ waiting = [];
672
+ shown = /* @__PURE__ */ new Set();
673
+ destroyed = false;
674
+ constructor(presenter, options) {
675
+ this.presenter = presenter;
676
+ this.options = options;
677
+ options.destroyRef.onDestroy(() => {
678
+ this.destroyed = true;
679
+ for (const entry of [...this.waiting, ...this.shown]) this.dismissEntry(entry);
680
+ });
681
+ }
682
+ show(request) {
683
+ let resolve = () => void 0;
684
+ const afterDismissed = new Promise((res) => {
685
+ resolve = res;
686
+ });
687
+ const entry = {
688
+ request,
689
+ message: request.message,
690
+ action: request.action,
691
+ duration: request.duration ?? (request.action ? 0 : DEFAULT_DURATION),
692
+ resolve,
693
+ dismissed: false
694
+ };
695
+ const ref = new BfToastRef({ dismiss: () => this.dismissEntry(entry) }, afterDismissed);
696
+ if (this.destroyed) {
697
+ entry.dismissed = true;
698
+ resolve("dismiss");
699
+ return ref;
700
+ }
701
+ for (const stale of [...this.waiting, ...this.shown]) if (stale.duration <= 0) this.dismissEntry(stale);
702
+ this.waiting.push(entry);
703
+ this.pump();
704
+ return ref;
705
+ }
706
+ dismissEntry(entry) {
707
+ if (entry.dismissed) return;
708
+ if (entry.finish) {
709
+ entry.finish("dismiss");
710
+ return;
711
+ }
712
+ const index = this.waiting.indexOf(entry);
713
+ if (index >= 0) this.waiting.splice(index, 1);
714
+ entry.dismissed = true;
715
+ entry.resolve("dismiss");
716
+ }
717
+ pump() {
718
+ while (!this.destroyed && this.shown.size < this.options.maxVisible) {
719
+ const entry = this.waiting.shift();
720
+ if (!entry) return;
721
+ this.shown.add(entry);
722
+ this.present(entry);
723
+ }
724
+ }
725
+ present(entry) {
726
+ const doc = this.options.document;
727
+ let timer = null;
728
+ let remaining = entry.duration;
729
+ let startedAt = 0;
730
+ const holds = /* @__PURE__ */ new Set();
731
+ let handle = null;
732
+ let early = null;
733
+ let returnTo = this.focusedElement();
734
+ const inToast = (target) => target instanceof Node && (handle?.host?.contains(target) ?? false);
735
+ const onDocumentFocusIn = (event) => {
736
+ if (!inToast(event.target)) returnTo = event.target instanceof HTMLElement ? event.target : null;
737
+ };
738
+ const onDocumentFocusOut = (event) => {
739
+ if (!inToast(event.target) && event.relatedTarget === null) returnTo = null;
740
+ };
741
+ const pauseTimer = () => {
742
+ if (timer === null) return;
743
+ clearTimeout(timer);
744
+ timer = null;
745
+ remaining -= Date.now() - startedAt;
746
+ };
747
+ const startTimer = () => {
748
+ if (entry.duration <= 0 || entry.dismissed || timer !== null || holds.size > 0) return;
749
+ startedAt = Date.now();
750
+ timer = setTimeout(() => finish("timeout"), Math.max(0, remaining));
751
+ };
752
+ const close = (current, reason) => {
753
+ current.close(reason).then(() => {
754
+ entry.resolve(reason);
755
+ this.shown.delete(entry);
756
+ this.pump();
757
+ });
758
+ };
759
+ const finish = (reason) => {
760
+ if (entry.dismissed) return;
761
+ entry.dismissed = true;
762
+ pauseTimer();
763
+ doc.removeEventListener("focusin", onDocumentFocusIn, true);
764
+ doc.removeEventListener("focusout", onDocumentFocusOut, true);
765
+ if (inToast(doc.activeElement) && returnTo?.isConnected) returnTo.focus({ preventScroll: true });
766
+ if (handle) close(handle, reason);
767
+ else early = reason;
768
+ };
769
+ entry.finish = finish;
770
+ const view = {
771
+ message: entry.message,
772
+ action: entry.action ? {
773
+ label: entry.action.label,
774
+ run: () => {
775
+ if (entry.dismissed) return;
776
+ entry.action?.handler?.();
777
+ finish("action");
778
+ }
779
+ } : null,
780
+ hold: (source, held) => {
781
+ if (held) {
782
+ holds.add(source);
783
+ pauseTimer();
784
+ } else {
785
+ holds.delete(source);
786
+ startTimer();
787
+ }
788
+ },
789
+ escape: () => finish("dismiss")
790
+ };
791
+ handle = this.presenter.present(view, entry.request);
792
+ if (early) {
793
+ close(handle, early);
794
+ return;
795
+ }
796
+ doc.addEventListener("focusin", onDocumentFocusIn, true);
797
+ doc.addEventListener("focusout", onDocumentFocusOut, true);
798
+ this.options.announcer.announce(announcement(entry.message, entry.action), "polite");
799
+ startTimer();
800
+ }
801
+ focusedElement() {
802
+ const active = this.options.document.activeElement;
803
+ return active instanceof HTMLElement && active !== this.options.document.body ? active : null;
804
+ }
805
+ };
806
+ const BF_DIALOG_DATA = new InjectionToken("BF_DIALOG_DATA");
807
+ const BF_DIALOG_CONTEXT = new InjectionToken("BF_DIALOG_CONTEXT");
808
+ var BfDialogRef = class {
809
+ overlayRef;
810
+ instance;
811
+ id;
812
+ afterClosed;
813
+ closed;
814
+ constructor(overlayRef, instance = () => null) {
815
+ this.overlayRef = overlayRef;
816
+ this.instance = instance;
817
+ this.id = overlayRef.id;
818
+ this.afterClosed = overlayRef.afterClosed;
819
+ this.closed = overlayRef.closed;
820
+ }
821
+ get componentInstance() {
822
+ return this.instance();
823
+ }
824
+ close(result) {
825
+ this.overlayRef.close(result);
826
+ }
827
+ };
828
+ const HOST_BASE = "relative flex flex-col bg-surface text-text";
829
+ const CARD = "max-h-[calc(100dvh-2*var(--spacing-gutter))] rounded-card shadow-floating border border-transparent";
830
+ const SIZE$1 = {
831
+ sm: `w-[min(24rem,calc(100vw-2*var(--spacing-gutter)))] ${CARD}`,
832
+ md: `w-[min(32rem,calc(100vw-2*var(--spacing-gutter)))] ${CARD}`,
833
+ lg: `w-[min(48rem,calc(100vw-2*var(--spacing-gutter)))] ${CARD}`,
834
+ xl: `w-[min(64rem,calc(100vw-2*var(--spacing-gutter)))] ${CARD}`,
835
+ fullscreen: "h-full w-full"
836
+ };
837
+ const HEADER_BASE = "flex min-w-0 shrink-0 items-start gap-3 px-6 pt-6";
838
+ const HEADER = {
839
+ close: `${HEADER_BASE} min-h-14 pe-14`,
840
+ plain: `${HEADER_BASE} empty:hidden`
841
+ };
842
+ var BfDialogComponent = class BfDialogComponent {
843
+ labels = inject(BF_LABELS);
844
+ context = inject(BF_DIALOG_CONTEXT, { optional: true });
845
+ ref = inject(BfDialogRef, { optional: true });
846
+ title = input("", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
847
+ closeButton = input(true, {
848
+ ...ngDevMode ? { debugName: "closeButton" } : /* istanbul ignore next */ {},
849
+ transform: booleanAttribute
850
+ });
851
+ closeLabel = input("", ...ngDevMode ? [{ debugName: "closeLabel" }] : /* istanbul ignore next */ []);
852
+ overflowing = signal(false, ...ngDevMode ? [{ debugName: "overflowing" }] : /* istanbul ignore next */ []);
853
+ titleId = this.context?.titleId ?? ɵuniqueId("bf-dialog-title");
854
+ closeIcon = X;
855
+ size = this.context?.size ?? "md";
856
+ hostClasses = computed(() => `${HOST_BASE} ${SIZE$1[this.size]}`, ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
857
+ headerClasses = computed(() => HEADER[this.closeButton() ? "close" : "plain"], ...ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []);
858
+ closeName = computed(() => this.closeLabel() || this.labels.close, ...ngDevMode ? [{ debugName: "closeName" }] : /* istanbul ignore next */ []);
859
+ body = viewChild.required("body", ...ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []);
860
+ content = viewChild.required("content", ...ngDevMode ? [{ debugName: "content" }] : /* istanbul ignore next */ []);
861
+ constructor() {
862
+ let observer = null;
863
+ afterNextRender(() => {
864
+ const body = this.body().nativeElement;
865
+ const measure = () => this.overflowing.set(body.scrollHeight > body.clientHeight);
866
+ measure();
867
+ if (typeof ResizeObserver === "function") {
868
+ observer = new ResizeObserver(measure);
869
+ observer.observe(body);
870
+ observer.observe(this.content().nativeElement);
871
+ }
872
+ });
873
+ inject(DestroyRef).onDestroy(() => observer?.disconnect());
874
+ }
875
+ close() {
876
+ this.ref?.close();
877
+ }
878
+ static ɵfac = i0.ɵɵngDeclareFactory({
879
+ minVersion: "12.0.0",
880
+ version: "22.1.7",
881
+ ngImport: i0,
882
+ type: BfDialogComponent,
883
+ deps: [],
884
+ target: i0.ɵɵFactoryTarget.Component
885
+ });
886
+ static ɵcmp = i0.ɵɵngDeclareComponent({
887
+ minVersion: "17.0.0",
888
+ version: "22.1.7",
889
+ type: BfDialogComponent,
890
+ isStandalone: true,
891
+ selector: "bf-dialog",
892
+ inputs: {
893
+ title: {
894
+ classPropertyName: "title",
895
+ publicName: "title",
896
+ isSignal: true,
897
+ isRequired: false,
898
+ transformFunction: null
899
+ },
900
+ closeButton: {
901
+ classPropertyName: "closeButton",
902
+ publicName: "closeButton",
903
+ isSignal: true,
904
+ isRequired: false,
905
+ transformFunction: null
906
+ },
907
+ closeLabel: {
908
+ classPropertyName: "closeLabel",
909
+ publicName: "closeLabel",
910
+ isSignal: true,
911
+ isRequired: false,
912
+ transformFunction: null
913
+ }
914
+ },
915
+ host: { properties: {
916
+ "class": "hostClasses()",
917
+ "attr.data-bf-dialog-id": "titleId"
918
+ } },
919
+ viewQueries: [{
920
+ propertyName: "body",
921
+ first: true,
922
+ predicate: ["body"],
923
+ descendants: true,
924
+ isSignal: true
925
+ }, {
926
+ propertyName: "content",
927
+ first: true,
928
+ predicate: ["content"],
929
+ descendants: true,
930
+ isSignal: true
931
+ }],
932
+ ngImport: i0,
933
+ template: `
934
+ <div data-dialog-header [class]="headerClasses()">
935
+ @if (title()) {
936
+ <h2 [id]="titleId" class="text-heading min-w-0 flex-1 wrap-anywhere">{{ title() }}</h2>
937
+ }
938
+ <ng-content select="[bfSlot=header]" />
939
+ </div>
940
+ <div
941
+ #body
942
+ data-dialog-body
943
+ class="focus-visible:ring-ring min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4 focus-visible:ring-4 focus-visible:outline-hidden focus-visible:ring-inset"
944
+ [attr.tabindex]="overflowing() ? 0 : null"
945
+ [attr.role]="overflowing() && title() ? 'region' : null"
946
+ [attr.aria-labelledby]="overflowing() && title() ? titleId : null"
947
+ >
948
+ <div #content class="flex flex-col gap-4"><ng-content /></div>
949
+ </div>
950
+ <!-- A projected wrapper (<div bfSlot="footer">) lays out its buttons like the row itself. -->
951
+ <div
952
+ data-dialog-footer
953
+ class="flex shrink-0 flex-wrap justify-end gap-2 px-6 pb-6 *:flex *:min-w-0 *:flex-wrap *:justify-end *:gap-2 empty:hidden"
954
+ >
955
+ <ng-content select="[bfSlot=footer]" />
956
+ </div>
957
+ @if (closeButton()) {
958
+ <!-- Last in DOM order so first-tabbable focus lands on the content, not on the ×. -->
959
+ <bf-icon-button
960
+ data-dialog-close
961
+ class="absolute end-3 top-3"
962
+ variant="text"
963
+ size="sm"
964
+ [label]="closeName()"
965
+ (clicked)="close()"
966
+ >
967
+ <bf-icon [icon]="closeIcon" />
968
+ </bf-icon-button>
969
+ }
970
+ `,
971
+ isInline: true,
972
+ dependencies: [{
973
+ kind: "component",
974
+ type: BfIconButtonComponent,
975
+ selector: "bf-icon-button",
976
+ inputs: [
977
+ "variant",
978
+ "size",
979
+ "type",
980
+ "disabled",
981
+ "label"
982
+ ],
983
+ outputs: ["clicked"]
984
+ }, {
985
+ kind: "component",
986
+ type: BfIconComponent,
987
+ selector: "bf-icon",
988
+ inputs: [
989
+ "icon",
990
+ "size",
991
+ "label"
992
+ ]
993
+ }]
994
+ });
995
+ };
996
+ i0.ɵɵngDeclareClassMetadata({
997
+ minVersion: "12.0.0",
998
+ version: "22.1.7",
999
+ ngImport: i0,
1000
+ type: BfDialogComponent,
1001
+ decorators: [{
1002
+ type: Component,
1003
+ args: [{
1004
+ selector: "bf-dialog",
1005
+ imports: [BfIconButtonComponent, BfIconComponent],
1006
+ host: {
1007
+ "[class]": "hostClasses()",
1008
+ "[attr.data-bf-dialog-id]": "titleId"
1009
+ },
1010
+ template: `
1011
+ <div data-dialog-header [class]="headerClasses()">
1012
+ @if (title()) {
1013
+ <h2 [id]="titleId" class="text-heading min-w-0 flex-1 wrap-anywhere">{{ title() }}</h2>
1014
+ }
1015
+ <ng-content select="[bfSlot=header]" />
1016
+ </div>
1017
+ <div
1018
+ #body
1019
+ data-dialog-body
1020
+ class="focus-visible:ring-ring min-h-0 flex-1 overflow-y-auto overscroll-contain px-6 py-4 focus-visible:ring-4 focus-visible:outline-hidden focus-visible:ring-inset"
1021
+ [attr.tabindex]="overflowing() ? 0 : null"
1022
+ [attr.role]="overflowing() && title() ? 'region' : null"
1023
+ [attr.aria-labelledby]="overflowing() && title() ? titleId : null"
1024
+ >
1025
+ <div #content class="flex flex-col gap-4"><ng-content /></div>
1026
+ </div>
1027
+ <!-- A projected wrapper (<div bfSlot="footer">) lays out its buttons like the row itself. -->
1028
+ <div
1029
+ data-dialog-footer
1030
+ class="flex shrink-0 flex-wrap justify-end gap-2 px-6 pb-6 *:flex *:min-w-0 *:flex-wrap *:justify-end *:gap-2 empty:hidden"
1031
+ >
1032
+ <ng-content select="[bfSlot=footer]" />
1033
+ </div>
1034
+ @if (closeButton()) {
1035
+ <!-- Last in DOM order so first-tabbable focus lands on the content, not on the ×. -->
1036
+ <bf-icon-button
1037
+ data-dialog-close
1038
+ class="absolute end-3 top-3"
1039
+ variant="text"
1040
+ size="sm"
1041
+ [label]="closeName()"
1042
+ (clicked)="close()"
1043
+ >
1044
+ <bf-icon [icon]="closeIcon" />
1045
+ </bf-icon-button>
1046
+ }
1047
+ `
1048
+ }]
1049
+ }],
1050
+ ctorParameters: () => [],
1051
+ propDecorators: {
1052
+ title: [{
1053
+ type: i0.Input,
1054
+ args: [{
1055
+ isSignal: true,
1056
+ alias: "title",
1057
+ required: false
1058
+ }]
1059
+ }],
1060
+ closeButton: [{
1061
+ type: i0.Input,
1062
+ args: [{
1063
+ isSignal: true,
1064
+ alias: "closeButton",
1065
+ required: false
1066
+ }]
1067
+ }],
1068
+ closeLabel: [{
1069
+ type: i0.Input,
1070
+ args: [{
1071
+ isSignal: true,
1072
+ alias: "closeLabel",
1073
+ required: false
1074
+ }]
1075
+ }],
1076
+ body: [{
1077
+ type: i0.ViewChild,
1078
+ args: ["body", { isSignal: true }]
1079
+ }],
1080
+ content: [{
1081
+ type: i0.ViewChild,
1082
+ args: ["content", { isSignal: true }]
1083
+ }]
1084
+ }
1085
+ });
1086
+ const BF_DIALOG_TEMPLATE = new InjectionToken("BF_DIALOG_TEMPLATE");
1087
+ var BfDialogTemplateHostComponent = class BfDialogTemplateHostComponent {
1088
+ view = inject(BF_DIALOG_TEMPLATE);
1089
+ injector = inject(Injector);
1090
+ static ɵfac = i0.ɵɵngDeclareFactory({
1091
+ minVersion: "12.0.0",
1092
+ version: "22.1.7",
1093
+ ngImport: i0,
1094
+ type: BfDialogTemplateHostComponent,
1095
+ deps: [],
1096
+ target: i0.ɵɵFactoryTarget.Component
1097
+ });
1098
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1099
+ minVersion: "14.0.0",
1100
+ version: "22.1.7",
1101
+ type: BfDialogTemplateHostComponent,
1102
+ isStandalone: true,
1103
+ selector: "bf-dialog-template-host",
1104
+ host: { styleAttribute: "display: contents" },
1105
+ ngImport: i0,
1106
+ template: `<ng-container
1107
+ [ngTemplateOutlet]="view.template"
1108
+ [ngTemplateOutletContext]="view.context"
1109
+ [ngTemplateOutletInjector]="injector"
1110
+ />`,
1111
+ isInline: true,
1112
+ dependencies: [{
1113
+ kind: "directive",
1114
+ type: NgTemplateOutlet,
1115
+ selector: "[ngTemplateOutlet]",
1116
+ inputs: [
1117
+ "ngTemplateOutletContext",
1118
+ "ngTemplateOutlet",
1119
+ "ngTemplateOutletInjector"
1120
+ ]
1121
+ }]
1122
+ });
1123
+ };
1124
+ i0.ɵɵngDeclareClassMetadata({
1125
+ minVersion: "12.0.0",
1126
+ version: "22.1.7",
1127
+ ngImport: i0,
1128
+ type: BfDialogTemplateHostComponent,
1129
+ decorators: [{
1130
+ type: Component,
1131
+ args: [{
1132
+ selector: "bf-dialog-template-host",
1133
+ imports: [NgTemplateOutlet],
1134
+ host: { style: "display: contents" },
1135
+ template: `<ng-container
1136
+ [ngTemplateOutlet]="view.template"
1137
+ [ngTemplateOutletContext]="view.context"
1138
+ [ngTemplateOutletInjector]="injector"
1139
+ />`
1140
+ }]
1141
+ }]
1142
+ });
1143
+ var BfConfirmDialogComponent = class BfConfirmDialogComponent {
1144
+ data = inject(BF_DIALOG_DATA);
1145
+ ref = inject(BfDialogRef);
1146
+ static ɵfac = i0.ɵɵngDeclareFactory({
1147
+ minVersion: "12.0.0",
1148
+ version: "22.1.7",
1149
+ ngImport: i0,
1150
+ type: BfConfirmDialogComponent,
1151
+ deps: [],
1152
+ target: i0.ɵɵFactoryTarget.Component
1153
+ });
1154
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1155
+ minVersion: "17.0.0",
1156
+ version: "22.1.7",
1157
+ type: BfConfirmDialogComponent,
1158
+ isStandalone: true,
1159
+ selector: "bf-confirm-dialog",
1160
+ host: { styleAttribute: "display: contents" },
1161
+ ngImport: i0,
1162
+ template: `
1163
+ <bf-dialog [title]="data.title" [closeButton]="false">
1164
+ @if (data.message) {
1165
+ <p [id]="data.messageId" class="text-body text-text-secondary">{{ data.message }}</p>
1166
+ }
1167
+ <div bfSlot="footer">
1168
+ @for (button of data.buttons; track $index) {
1169
+ <bf-button
1170
+ [variant]="button.variant"
1171
+ [attr.cdkFocusInitial]="button.initial ? '' : null"
1172
+ (clicked)="ref.close(button.answer)"
1173
+ >
1174
+ {{ button.label }}
1175
+ </bf-button>
1176
+ }
1177
+ </div>
1178
+ </bf-dialog>
1179
+ `,
1180
+ isInline: true,
1181
+ dependencies: [{
1182
+ kind: "component",
1183
+ type: BfDialogComponent,
1184
+ selector: "bf-dialog",
1185
+ inputs: [
1186
+ "title",
1187
+ "closeButton",
1188
+ "closeLabel"
1189
+ ]
1190
+ }, {
1191
+ kind: "component",
1192
+ type: BfButtonComponent,
1193
+ selector: "bf-button, a[bfButton]",
1194
+ inputs: [
1195
+ "variant",
1196
+ "size",
1197
+ "type",
1198
+ "disabled",
1199
+ "loading",
1200
+ "fullWidth"
1201
+ ],
1202
+ outputs: ["clicked"]
1203
+ }]
1204
+ });
1205
+ };
1206
+ i0.ɵɵngDeclareClassMetadata({
1207
+ minVersion: "12.0.0",
1208
+ version: "22.1.7",
1209
+ ngImport: i0,
1210
+ type: BfConfirmDialogComponent,
1211
+ decorators: [{
1212
+ type: Component,
1213
+ args: [{
1214
+ selector: "bf-confirm-dialog",
1215
+ imports: [BfDialogComponent, BfButtonComponent],
1216
+ host: { style: "display: contents" },
1217
+ template: `
1218
+ <bf-dialog [title]="data.title" [closeButton]="false">
1219
+ @if (data.message) {
1220
+ <p [id]="data.messageId" class="text-body text-text-secondary">{{ data.message }}</p>
1221
+ }
1222
+ <div bfSlot="footer">
1223
+ @for (button of data.buttons; track $index) {
1224
+ <bf-button
1225
+ [variant]="button.variant"
1226
+ [attr.cdkFocusInitial]="button.initial ? '' : null"
1227
+ (clicked)="ref.close(button.answer)"
1228
+ >
1229
+ {{ button.label }}
1230
+ </bf-button>
1231
+ }
1232
+ </div>
1233
+ </bf-dialog>
1234
+ `
1235
+ }]
1236
+ }]
1237
+ });
1238
+ var BfDialogService = class BfDialogService {
1239
+ overlays = inject(BfOverlayService);
1240
+ injector = inject(Injector);
1241
+ open(content, config = {}) {
1242
+ return this.openDialog(content, config, {});
1243
+ }
1244
+ confirm(options) {
1245
+ const injector = options.injector ?? this.injector;
1246
+ const labels = injector.get(BF_LABELS);
1247
+ const buttons = options.buttons?.length ? options.buttons : [{
1248
+ id: "cancel",
1249
+ label: labels.cancel,
1250
+ role: "cancel"
1251
+ }, {
1252
+ id: "ok",
1253
+ label: labels.ok
1254
+ }];
1255
+ const cancelIndex = buttons.findIndex((button) => button.role === "cancel");
1256
+ const initialIndex = cancelIndex >= 0 ? cancelIndex : 0;
1257
+ let primaryAssigned = false;
1258
+ const views = buttons.map((button, index) => {
1259
+ let variant;
1260
+ if (button.role === "cancel") variant = "outline";
1261
+ else if (button.role === "destructive") variant = "danger";
1262
+ else if (!primaryAssigned) {
1263
+ variant = "primary";
1264
+ primaryAssigned = true;
1265
+ } else variant = "tonal";
1266
+ return {
1267
+ label: button.label,
1268
+ answer: button.id ?? button.label,
1269
+ variant,
1270
+ initial: index === initialIndex
1271
+ };
1272
+ });
1273
+ const messageId = ɵuniqueId("bf-confirm-message");
1274
+ const data = {
1275
+ title: options.title,
1276
+ message: options.message,
1277
+ messageId,
1278
+ buttons: views
1279
+ };
1280
+ const cancel = views[cancelIndex];
1281
+ const ref = this.openDialog(BfConfirmDialogComponent, {
1282
+ data,
1283
+ role: "alertdialog",
1284
+ size: options.size ?? "sm",
1285
+ ariaDescribedBy: options.message ? messageId : void 0,
1286
+ dismissOnBackdrop: false,
1287
+ closeOnNavigation: options.closeOnNavigation,
1288
+ injector
1289
+ }, {
1290
+ onEscape: () => {
1291
+ if (cancel) ref.close(cancel.answer);
1292
+ },
1293
+ onNavigation: () => ref.close(cancel?.answer)
1294
+ });
1295
+ return ref.afterClosed;
1296
+ }
1297
+ openDialog(content, config, handlers) {
1298
+ const size = config.size ?? "md";
1299
+ const role = config.role ?? "dialog";
1300
+ const injector = config.injector ?? this.injector;
1301
+ const titleId = ɵuniqueId("bf-dialog-title");
1302
+ let dialogRef = null;
1303
+ let instance = null;
1304
+ const providers = (ref) => {
1305
+ const created = new BfDialogRef(ref, () => instance);
1306
+ dialogRef = created;
1307
+ const list = [
1308
+ {
1309
+ provide: BfDialogRef,
1310
+ useValue: created
1311
+ },
1312
+ {
1313
+ provide: BF_DIALOG_DATA,
1314
+ useValue: config.data
1315
+ },
1316
+ {
1317
+ provide: BF_DIALOG_CONTEXT,
1318
+ useValue: {
1319
+ titleId,
1320
+ size
1321
+ }
1322
+ }
1323
+ ];
1324
+ if (content instanceof TemplateRef) {
1325
+ const view = {
1326
+ template: content,
1327
+ context: {
1328
+ $implicit: created,
1329
+ data: config.data
1330
+ }
1331
+ };
1332
+ list.push({
1333
+ provide: BF_DIALOG_TEMPLATE,
1334
+ useValue: view
1335
+ });
1336
+ }
1337
+ return list;
1338
+ };
1339
+ const options = {
1340
+ data: config.data,
1341
+ position: size === "fullscreen" ? "fullscreen" : "center",
1342
+ role,
1343
+ ariaLabel: config.ariaLabel,
1344
+ ariaLabelledBy: config.ariaLabel ? void 0 : titleId,
1345
+ ariaDescribedBy: config.ariaDescribedBy,
1346
+ dismissOnBackdrop: config.dismissOnBackdrop ?? role === "dialog",
1347
+ dismissOnEscape: config.dismissOnEscape ?? true,
1348
+ onEscape: handlers.onEscape,
1349
+ closeOnNavigation: config.closeOnNavigation,
1350
+ onNavigation: handlers.onNavigation,
1351
+ autoFocus: config.autoFocus,
1352
+ restoreFocus: config.restoreFocus,
1353
+ panelClass: ["bf-dialog-panel", ...config.panelClass ?? []],
1354
+ injector,
1355
+ providers,
1356
+ enter: size === "fullscreen" ? fadeIn : scaleIn,
1357
+ exit: fadeOut
1358
+ };
1359
+ let overlayRef;
1360
+ if (content instanceof TemplateRef) overlayRef = this.overlays.open(BfDialogTemplateHostComponent, options);
1361
+ else {
1362
+ const componentRef = this.overlays.open(content, options);
1363
+ instance = componentRef.componentRef.instance;
1364
+ overlayRef = componentRef;
1365
+ }
1366
+ if (!dialogRef) throw new Error("BfDialogService: the overlay core did not build the dialog providers");
1367
+ this.nameUnlabelledPanel(overlayRef.componentRef.location.nativeElement, overlayRef.afterClosed, config, injector);
1368
+ return dialogRef;
1369
+ }
1370
+ nameUnlabelledPanel(host, afterClosed, config, injector) {
1371
+ const panel = host instanceof HTMLElement ? host.closest(".bf-overlay-panel") : null;
1372
+ if (!panel || config.ariaLabel || panel.hasAttribute("aria-labelledby")) return;
1373
+ panel.setAttribute("aria-label", injector.get(BF_LABELS).dialog);
1374
+ const stop = watchPanelHeading(panel);
1375
+ afterClosed.then(stop);
1376
+ }
1377
+ static ɵfac = i0.ɵɵngDeclareFactory({
1378
+ minVersion: "12.0.0",
1379
+ version: "22.1.7",
1380
+ ngImport: i0,
1381
+ type: BfDialogService,
1382
+ deps: [],
1383
+ target: i0.ɵɵFactoryTarget.Injectable
1384
+ });
1385
+ static ɵprov = i0.ɵɵngDeclareInjectable({
1386
+ minVersion: "12.0.0",
1387
+ version: "22.1.7",
1388
+ ngImport: i0,
1389
+ type: BfDialogService,
1390
+ providedIn: "root"
1391
+ });
1392
+ };
1393
+ i0.ɵɵngDeclareClassMetadata({
1394
+ minVersion: "12.0.0",
1395
+ version: "22.1.7",
1396
+ ngImport: i0,
1397
+ type: BfDialogService,
1398
+ decorators: [{
1399
+ type: Injectable,
1400
+ args: [{ providedIn: "root" }]
1401
+ }]
1402
+ });
1403
+ var BfDesktopToastComponent = class BfDesktopToastComponent {
1404
+ message = input.required(...ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []);
1405
+ actionLabel = input("", ...ngDevMode ? [{ debugName: "actionLabel" }] : /* istanbul ignore next */ []);
1406
+ actionClicked = output();
1407
+ escaped = output();
1408
+ keydown(event) {
1409
+ if (!(event instanceof KeyboardEvent) || event.key !== "Escape") return;
1410
+ event.preventDefault();
1411
+ event.stopPropagation();
1412
+ this.escaped.emit();
1413
+ }
1414
+ static ɵfac = i0.ɵɵngDeclareFactory({
1415
+ minVersion: "12.0.0",
1416
+ version: "22.1.7",
1417
+ ngImport: i0,
1418
+ type: BfDesktopToastComponent,
1419
+ deps: [],
1420
+ target: i0.ɵɵFactoryTarget.Component
1421
+ });
1422
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1423
+ minVersion: "17.0.0",
1424
+ version: "22.1.7",
1425
+ type: BfDesktopToastComponent,
1426
+ isStandalone: true,
1427
+ selector: "bf-desktop-toast",
1428
+ inputs: {
1429
+ message: {
1430
+ classPropertyName: "message",
1431
+ publicName: "message",
1432
+ isSignal: true,
1433
+ isRequired: true,
1434
+ transformFunction: null
1435
+ },
1436
+ actionLabel: {
1437
+ classPropertyName: "actionLabel",
1438
+ publicName: "actionLabel",
1439
+ isSignal: true,
1440
+ isRequired: false,
1441
+ transformFunction: null
1442
+ }
1443
+ },
1444
+ outputs: {
1445
+ actionClicked: "actionClicked",
1446
+ escaped: "escaped"
1447
+ },
1448
+ host: {
1449
+ listeners: { "keydown": "keydown($event)" },
1450
+ classAttribute: "bg-surface text-text border border-border rounded-card shadow-floating px-4 py-3 text-body flex items-start gap-3 w-[min(24rem,calc(100vw-2*var(--spacing-gutter)))]"
1451
+ },
1452
+ ngImport: i0,
1453
+ template: `
1454
+ <span class="min-w-0 flex-1 wrap-anywhere">{{ message() }}</span>
1455
+ @if (actionLabel()) {
1456
+ <button
1457
+ type="button"
1458
+ class="text-primary-strong focus-visible:ring-ring rounded-tile -me-2 inline-flex min-h-6 shrink-0 cursor-pointer items-center px-2 font-bold hover:underline focus-visible:ring-4 focus-visible:outline-hidden"
1459
+ (click)="actionClicked.emit()"
1460
+ >
1461
+ {{ actionLabel() }}
1462
+ </button>
1463
+ }
1464
+ `,
1465
+ isInline: true
1466
+ });
1467
+ };
1468
+ i0.ɵɵngDeclareClassMetadata({
1469
+ minVersion: "12.0.0",
1470
+ version: "22.1.7",
1471
+ ngImport: i0,
1472
+ type: BfDesktopToastComponent,
1473
+ decorators: [{
1474
+ type: Component,
1475
+ args: [{
1476
+ selector: "bf-desktop-toast",
1477
+ host: {
1478
+ class: "bg-surface text-text border border-border rounded-card shadow-floating px-4 py-3 text-body flex items-start gap-3 w-[min(24rem,calc(100vw-2*var(--spacing-gutter)))]",
1479
+ "(keydown)": "keydown($event)"
1480
+ },
1481
+ template: `
1482
+ <span class="min-w-0 flex-1 wrap-anywhere">{{ message() }}</span>
1483
+ @if (actionLabel()) {
1484
+ <button
1485
+ type="button"
1486
+ class="text-primary-strong focus-visible:ring-ring rounded-tile -me-2 inline-flex min-h-6 shrink-0 cursor-pointer items-center px-2 font-bold hover:underline focus-visible:ring-4 focus-visible:outline-hidden"
1487
+ (click)="actionClicked.emit()"
1488
+ >
1489
+ {{ actionLabel() }}
1490
+ </button>
1491
+ }
1492
+ `
1493
+ }]
1494
+ }],
1495
+ propDecorators: {
1496
+ message: [{
1497
+ type: i0.Input,
1498
+ args: [{
1499
+ isSignal: true,
1500
+ alias: "message",
1501
+ required: true
1502
+ }]
1503
+ }],
1504
+ actionLabel: [{
1505
+ type: i0.Input,
1506
+ args: [{
1507
+ isSignal: true,
1508
+ alias: "actionLabel",
1509
+ required: false
1510
+ }]
1511
+ }],
1512
+ actionClicked: [{
1513
+ type: i0.Output,
1514
+ args: ["actionClicked"]
1515
+ }],
1516
+ escaped: [{
1517
+ type: i0.Output,
1518
+ args: ["escaped"]
1519
+ }]
1520
+ }
1521
+ });
1522
+ const BF_DESKTOP_TOAST_DEFAULTS = Object.freeze({
1523
+ position: "bottom-end",
1524
+ maxVisible: 3,
1525
+ ariaLabel: ""
1526
+ });
1527
+ const BF_DESKTOP_TOAST_CONFIG = new InjectionToken("BF_DESKTOP_TOAST_CONFIG", {
1528
+ providedIn: "root",
1529
+ factory: () => BF_DESKTOP_TOAST_DEFAULTS
1530
+ });
1531
+ function provideBfDesktopToast(config = {}) {
1532
+ return makeEnvironmentProviders([{
1533
+ provide: BF_DESKTOP_TOAST_CONFIG,
1534
+ useValue: Object.freeze({
1535
+ ...BF_DESKTOP_TOAST_DEFAULTS,
1536
+ ...config
1537
+ })
1538
+ }]);
1539
+ }
1540
+ var BfDesktopToastStackComponent = class BfDesktopToastStackComponent {
1541
+ label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
1542
+ items = input([], ...ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []);
1543
+ held = output();
1544
+ focusLeft(event) {
1545
+ const to = event.relatedTarget;
1546
+ const self = event.currentTarget;
1547
+ if (to instanceof Node && self instanceof Node && self.contains(to)) return;
1548
+ this.held.emit({
1549
+ source: "focus",
1550
+ held: false
1551
+ });
1552
+ }
1553
+ static ɵfac = i0.ɵɵngDeclareFactory({
1554
+ minVersion: "12.0.0",
1555
+ version: "22.1.7",
1556
+ ngImport: i0,
1557
+ type: BfDesktopToastStackComponent,
1558
+ deps: [],
1559
+ target: i0.ɵɵFactoryTarget.Component
1560
+ });
1561
+ static ɵcmp = i0.ɵɵngDeclareComponent({
1562
+ minVersion: "17.0.0",
1563
+ version: "22.1.7",
1564
+ type: BfDesktopToastStackComponent,
1565
+ isStandalone: true,
1566
+ selector: "bf-desktop-toast-stack",
1567
+ inputs: {
1568
+ label: {
1569
+ classPropertyName: "label",
1570
+ publicName: "label",
1571
+ isSignal: true,
1572
+ isRequired: false,
1573
+ transformFunction: null
1574
+ },
1575
+ items: {
1576
+ classPropertyName: "items",
1577
+ publicName: "items",
1578
+ isSignal: true,
1579
+ isRequired: false,
1580
+ transformFunction: null
1581
+ }
1582
+ },
1583
+ outputs: { held: "held" },
1584
+ host: {
1585
+ attributes: { "role": "region" },
1586
+ listeners: {
1587
+ "pointerenter": "held.emit({ source: 'pointer', held: true })",
1588
+ "pointerleave": "held.emit({ source: 'pointer', held: false })",
1589
+ "focusin": "held.emit({ source: 'focus', held: true })",
1590
+ "focusout": "focusLeft($event)"
1591
+ },
1592
+ properties: { "attr.aria-label": "label()" },
1593
+ classAttribute: "flex flex-col gap-2"
1594
+ },
1595
+ ngImport: i0,
1596
+ template: `
1597
+ @for (item of items(); track item.id) {
1598
+ <bf-desktop-toast
1599
+ [attr.data-bf-toast]="item.id"
1600
+ [message]="item.view.message"
1601
+ [actionLabel]="item.view.action?.label ?? ''"
1602
+ (actionClicked)="item.view.action?.run()"
1603
+ (escaped)="item.view.escape()"
1604
+ />
1605
+ }
1606
+ `,
1607
+ isInline: true,
1608
+ dependencies: [{
1609
+ kind: "component",
1610
+ type: BfDesktopToastComponent,
1611
+ selector: "bf-desktop-toast",
1612
+ inputs: ["message", "actionLabel"],
1613
+ outputs: ["actionClicked", "escaped"]
1614
+ }]
1615
+ });
1616
+ };
1617
+ i0.ɵɵngDeclareClassMetadata({
1618
+ minVersion: "12.0.0",
1619
+ version: "22.1.7",
1620
+ ngImport: i0,
1621
+ type: BfDesktopToastStackComponent,
1622
+ decorators: [{
1623
+ type: Component,
1624
+ args: [{
1625
+ selector: "bf-desktop-toast-stack",
1626
+ imports: [BfDesktopToastComponent],
1627
+ host: {
1628
+ role: "region",
1629
+ "[attr.aria-label]": "label()",
1630
+ class: "flex flex-col gap-2",
1631
+ "(pointerenter)": "held.emit({ source: 'pointer', held: true })",
1632
+ "(pointerleave)": "held.emit({ source: 'pointer', held: false })",
1633
+ "(focusin)": "held.emit({ source: 'focus', held: true })",
1634
+ "(focusout)": "focusLeft($event)"
1635
+ },
1636
+ template: `
1637
+ @for (item of items(); track item.id) {
1638
+ <bf-desktop-toast
1639
+ [attr.data-bf-toast]="item.id"
1640
+ [message]="item.view.message"
1641
+ [actionLabel]="item.view.action?.label ?? ''"
1642
+ (actionClicked)="item.view.action?.run()"
1643
+ (escaped)="item.view.escape()"
1644
+ />
1645
+ }
1646
+ `
1647
+ }]
1648
+ }],
1649
+ propDecorators: {
1650
+ label: [{
1651
+ type: i0.Input,
1652
+ args: [{
1653
+ isSignal: true,
1654
+ alias: "label",
1655
+ required: false
1656
+ }]
1657
+ }],
1658
+ items: [{
1659
+ type: i0.Input,
1660
+ args: [{
1661
+ isSignal: true,
1662
+ alias: "items",
1663
+ required: false
1664
+ }]
1665
+ }],
1666
+ held: [{
1667
+ type: i0.Output,
1668
+ args: ["held"]
1669
+ }]
1670
+ }
1671
+ });
1672
+ const INSET = {
1673
+ top: "calc(24px + var(--spacing-safe-top, 0px))",
1674
+ bottom: "calc(24px + var(--spacing-safe-bottom, 0px))",
1675
+ endLtr: "calc(24px + var(--spacing-safe-right, 0px))",
1676
+ endRtl: "calc(24px + var(--spacing-safe-left, 0px))"
1677
+ };
1678
+ var BfDesktopToastService = class BfDesktopToastService {
1679
+ overlay = inject(Overlay);
1680
+ injector = inject(Injector);
1681
+ document = inject(DOCUMENT);
1682
+ config = inject(BF_DESKTOP_TOAST_CONFIG);
1683
+ directionality = inject(Directionality);
1684
+ overlayStack = inject(BfOverlayStack);
1685
+ f6ReturnTo = null;
1686
+ onKeydown = (event) => this.keydown(event);
1687
+ items = [];
1688
+ holds = /* @__PURE__ */ new Set();
1689
+ pane = null;
1690
+ dirSubscription = null;
1691
+ nextId = 0;
1692
+ queue = new ɵBfToastQueue({ present: (view, options) => this.present(view, options) }, {
1693
+ maxVisible: Math.max(1, Math.floor(this.config.maxVisible)),
1694
+ announcer: inject(LiveAnnouncer),
1695
+ document: this.document,
1696
+ destroyRef: inject(DestroyRef)
1697
+ });
1698
+ constructor() {
1699
+ inject(DestroyRef).onDestroy(() => this.disposePane());
1700
+ }
1701
+ show(options) {
1702
+ return this.queue.show(options);
1703
+ }
1704
+ present(view, options) {
1705
+ const pane = this.ensurePane(options.injector ?? this.injector);
1706
+ const item = {
1707
+ id: this.nextId++,
1708
+ view
1709
+ };
1710
+ this.items = [...this.items, item];
1711
+ this.render();
1712
+ for (const source of this.holds) view.hold(source, true);
1713
+ const host = pane.overlayRef.overlayElement.querySelector(`[data-bf-toast="${item.id}"]`);
1714
+ if (host) fadeUp(host, this.anchoredTop() ? "-8px" : "8px");
1715
+ return {
1716
+ host,
1717
+ close: async () => {
1718
+ if (host) try {
1719
+ await fadeOut(host).finished;
1720
+ } catch {}
1721
+ this.remove(item);
1722
+ }
1723
+ };
1724
+ }
1725
+ remove(item) {
1726
+ if (!this.pane) return;
1727
+ this.items = this.items.filter((i) => i !== item);
1728
+ if (this.items.length === 0) {
1729
+ this.disposePane();
1730
+ return;
1731
+ }
1732
+ this.render();
1733
+ if (this.holds.has("focus") && !this.pane.overlayRef.overlayElement.contains(this.document.activeElement)) this.setHold("focus", false);
1734
+ }
1735
+ render() {
1736
+ const pane = this.pane;
1737
+ if (!pane) return;
1738
+ pane.stack.setInput("items", this.anchoredTop() ? [...this.items].reverse() : this.items);
1739
+ pane.stack.changeDetectorRef.detectChanges();
1740
+ }
1741
+ setHold(source, held) {
1742
+ if (held === this.holds.has(source)) return;
1743
+ if (held) this.holds.add(source);
1744
+ else this.holds.delete(source);
1745
+ for (const item of this.items) item.view.hold(source, held);
1746
+ }
1747
+ ensurePane(injector) {
1748
+ if (this.pane) return this.pane;
1749
+ const overlayRef = this.overlay.create({
1750
+ positionStrategy: this.positionStrategy(),
1751
+ scrollStrategy: this.overlay.scrollStrategies.noop(),
1752
+ hasBackdrop: false,
1753
+ panelClass: "bf-desktop-toast-pane"
1754
+ });
1755
+ const stack = overlayRef.attach(new ComponentPortal(BfDesktopToastStackComponent, null, injector));
1756
+ stack.setInput("label", this.config.ariaLabel || injector.get(BF_LABELS).notifications);
1757
+ stack.instance.held.subscribe(({ source, held }) => this.setHold(source, held));
1758
+ overlayRef.updatePosition();
1759
+ this.document.addEventListener("keydown", this.onKeydown);
1760
+ this.dirSubscription = this.directionality.change.subscribe((dir) => {
1761
+ overlayRef.setDirection(dir);
1762
+ overlayRef.updatePositionStrategy(this.positionStrategy());
1763
+ });
1764
+ this.pane = {
1765
+ overlayRef,
1766
+ stack
1767
+ };
1768
+ return this.pane;
1769
+ }
1770
+ disposePane() {
1771
+ if (this.pane) this.document.removeEventListener("keydown", this.onKeydown);
1772
+ this.dirSubscription?.unsubscribe();
1773
+ this.dirSubscription = null;
1774
+ this.pane?.overlayRef.dispose();
1775
+ this.pane = null;
1776
+ this.items = [];
1777
+ this.holds.clear();
1778
+ this.f6ReturnTo = null;
1779
+ }
1780
+ keydown(event) {
1781
+ const pane = this.pane;
1782
+ if (!pane || event.key !== "F6" || event.ctrlKey || event.altKey || event.metaKey) return;
1783
+ const active = this.document.activeElement;
1784
+ if (active instanceof Node && pane.overlayRef.overlayElement.contains(active)) {
1785
+ const back = this.f6ReturnTo;
1786
+ if (back?.isConnected) {
1787
+ event.preventDefault();
1788
+ this.f6ReturnTo = null;
1789
+ back.focus();
1790
+ }
1791
+ return;
1792
+ }
1793
+ if (this.overlayStack.count() > 0) return;
1794
+ const newest = [...this.items].reverse().find((item) => item.view.action);
1795
+ const button = newest ? pane.overlayRef.overlayElement.querySelector(`[data-bf-toast="${newest.id}"] button`) : null;
1796
+ if (!button) return;
1797
+ event.preventDefault();
1798
+ this.f6ReturnTo = active instanceof HTMLElement && active !== this.document.body ? active : null;
1799
+ button.focus();
1800
+ }
1801
+ anchoredTop() {
1802
+ return this.config.position.startsWith("top");
1803
+ }
1804
+ positionStrategy() {
1805
+ const global = this.overlay.position().global();
1806
+ const vertical = this.anchoredTop() ? global.top(INSET.top) : global.bottom(INSET.bottom);
1807
+ return this.config.position.endsWith("center") ? vertical.centerHorizontally() : vertical.end(this.directionality.value === "rtl" ? INSET.endRtl : INSET.endLtr);
1808
+ }
1809
+ static ɵfac = i0.ɵɵngDeclareFactory({
1810
+ minVersion: "12.0.0",
1811
+ version: "22.1.7",
1812
+ ngImport: i0,
1813
+ type: BfDesktopToastService,
1814
+ deps: [],
1815
+ target: i0.ɵɵFactoryTarget.Injectable
1816
+ });
1817
+ static ɵprov = i0.ɵɵngDeclareInjectable({
1818
+ minVersion: "12.0.0",
1819
+ version: "22.1.7",
1820
+ ngImport: i0,
1821
+ type: BfDesktopToastService,
1822
+ providedIn: "root"
1823
+ });
1824
+ };
1825
+ i0.ɵɵngDeclareClassMetadata({
1826
+ minVersion: "12.0.0",
1827
+ version: "22.1.7",
1828
+ ngImport: i0,
1829
+ type: BfDesktopToastService,
1830
+ decorators: [{
1831
+ type: Injectable,
1832
+ args: [{ providedIn: "root" }]
1833
+ }],
1834
+ ctorParameters: () => []
1835
+ });
1836
+ const GAP = 4;
1837
+ const BELOW_START = {
1838
+ originX: "start",
1839
+ originY: "bottom",
1840
+ overlayX: "start",
1841
+ overlayY: "top",
1842
+ offsetY: GAP
1843
+ };
1844
+ const BELOW_END = {
1845
+ originX: "end",
1846
+ originY: "bottom",
1847
+ overlayX: "end",
1848
+ overlayY: "top",
1849
+ offsetY: GAP
1850
+ };
1851
+ const ABOVE_START = {
1852
+ originX: "start",
1853
+ originY: "top",
1854
+ overlayX: "start",
1855
+ overlayY: "bottom",
1856
+ offsetY: -4
1857
+ };
1858
+ const ABOVE_END = {
1859
+ originX: "end",
1860
+ originY: "top",
1861
+ overlayX: "end",
1862
+ overlayY: "bottom",
1863
+ offsetY: -4
1864
+ };
1865
+ const POSITIONS = {
1866
+ "below-start": [
1867
+ BELOW_START,
1868
+ ABOVE_START,
1869
+ BELOW_END,
1870
+ ABOVE_END
1871
+ ],
1872
+ "below-end": [
1873
+ BELOW_END,
1874
+ ABOVE_END,
1875
+ BELOW_START,
1876
+ ABOVE_START
1877
+ ],
1878
+ "above-start": [
1879
+ ABOVE_START,
1880
+ BELOW_START,
1881
+ ABOVE_END,
1882
+ BELOW_END
1883
+ ],
1884
+ "above-end": [
1885
+ ABOVE_END,
1886
+ BELOW_END,
1887
+ ABOVE_START,
1888
+ BELOW_START
1889
+ ]
1890
+ };
1891
+ var BfMenuTriggerDirective = class BfMenuTriggerDirective {
1892
+ el = inject(ElementRef).nativeElement;
1893
+ bfMenuPlacement = input("below-start", ...ngDevMode ? [{ debugName: "bfMenuPlacement" }] : /* istanbul ignore next */ []);
1894
+ constructor() {
1895
+ const trigger = inject(CdkMenuTrigger, { self: true });
1896
+ if (inject(CDK_MENU, { optional: true }) !== null) return;
1897
+ const location = inject(Location);
1898
+ let stop = null;
1899
+ const unwatch = () => {
1900
+ stop?.();
1901
+ stop = null;
1902
+ };
1903
+ const opened = trigger.opened.subscribe(() => {
1904
+ unwatch();
1905
+ stop = watchPathChange(location, () => {
1906
+ if (trigger.isOpen()) trigger.close();
1907
+ });
1908
+ });
1909
+ const closed = trigger.closed.subscribe(unwatch);
1910
+ inject(DestroyRef).onDestroy(() => {
1911
+ opened.unsubscribe();
1912
+ closed.unsubscribe();
1913
+ unwatch();
1914
+ });
1915
+ let previous;
1916
+ effect(() => {
1917
+ const positions = POSITIONS[this.bfMenuPlacement()];
1918
+ trigger.menuPosition = positions;
1919
+ if (previous) trigger.ngOnChanges({ menuPosition: new SimpleChange(previous, positions, false) });
1920
+ previous = positions;
1921
+ });
1922
+ }
1923
+ labelId() {
1924
+ if (!this.el.id) this.el.id = ɵuniqueId("bf-menu-trigger");
1925
+ return this.el.id;
1926
+ }
1927
+ static ɵfac = i0.ɵɵngDeclareFactory({
1928
+ minVersion: "12.0.0",
1929
+ version: "22.1.7",
1930
+ ngImport: i0,
1931
+ type: BfMenuTriggerDirective,
1932
+ deps: [],
1933
+ target: i0.ɵɵFactoryTarget.Directive
1934
+ });
1935
+ static ɵdir = i0.ɵɵngDeclareDirective({
1936
+ minVersion: "17.1.0",
1937
+ version: "22.1.7",
1938
+ type: BfMenuTriggerDirective,
1939
+ isStandalone: true,
1940
+ selector: "[bfMenuTriggerFor]",
1941
+ inputs: { bfMenuPlacement: {
1942
+ classPropertyName: "bfMenuPlacement",
1943
+ publicName: "bfMenuPlacement",
1944
+ isSignal: true,
1945
+ isRequired: false,
1946
+ transformFunction: null
1947
+ } },
1948
+ hostDirectives: [{
1949
+ directive: i1.CdkMenuTrigger,
1950
+ inputs: [
1951
+ "cdkMenuTriggerFor",
1952
+ "bfMenuTriggerFor",
1953
+ "cdkMenuTriggerData",
1954
+ "bfMenuTriggerData"
1955
+ ],
1956
+ outputs: [
1957
+ "cdkMenuOpened",
1958
+ "bfMenuOpened",
1959
+ "cdkMenuClosed",
1960
+ "bfMenuClosed"
1961
+ ]
1962
+ }],
1963
+ ngImport: i0
1964
+ });
1965
+ };
1966
+ i0.ɵɵngDeclareClassMetadata({
1967
+ minVersion: "12.0.0",
1968
+ version: "22.1.7",
1969
+ ngImport: i0,
1970
+ type: BfMenuTriggerDirective,
1971
+ decorators: [{
1972
+ type: Directive,
1973
+ args: [{
1974
+ selector: "[bfMenuTriggerFor]",
1975
+ hostDirectives: [{
1976
+ directive: CdkMenuTrigger,
1977
+ inputs: ["cdkMenuTriggerFor: bfMenuTriggerFor", "cdkMenuTriggerData: bfMenuTriggerData"],
1978
+ outputs: ["cdkMenuOpened: bfMenuOpened", "cdkMenuClosed: bfMenuClosed"]
1979
+ }]
1980
+ }]
1981
+ }],
1982
+ ctorParameters: () => [],
1983
+ propDecorators: { bfMenuPlacement: [{
1984
+ type: i0.Input,
1985
+ args: [{
1986
+ isSignal: true,
1987
+ alias: "bfMenuPlacement",
1988
+ required: false
1989
+ }]
1990
+ }] }
1991
+ });
1992
+ var BfMenuComponent = class BfMenuComponent {
1993
+ defaults = inject(BF_DEFAULTS);
1994
+ trigger = inject(BfMenuTriggerDirective, { optional: true });
1995
+ size = input(void 0, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
1996
+ ariaLabel = input("", ...ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []);
1997
+ ariaLabelledby = input("", ...ngDevMode ? [{ debugName: "ariaLabelledby" }] : /* istanbul ignore next */ []);
1998
+ resolvedSize = computed(() => this.size() ?? this.defaults.controlSize, ...ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []);
1999
+ triggerId = this.trigger?.labelId() ?? null;
2000
+ labelledBy = computed(() => this.ariaLabelledby() || (this.ariaLabel() ? null : this.triggerId), ...ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []);
2001
+ static ɵfac = i0.ɵɵngDeclareFactory({
2002
+ minVersion: "12.0.0",
2003
+ version: "22.1.7",
2004
+ ngImport: i0,
2005
+ type: BfMenuComponent,
2006
+ deps: [],
2007
+ target: i0.ɵɵFactoryTarget.Component
2008
+ });
2009
+ static ɵcmp = i0.ɵɵngDeclareComponent({
2010
+ minVersion: "17.1.0",
2011
+ version: "22.1.7",
2012
+ type: BfMenuComponent,
2013
+ isStandalone: true,
2014
+ selector: "bf-menu",
2015
+ inputs: {
2016
+ size: {
2017
+ classPropertyName: "size",
2018
+ publicName: "size",
2019
+ isSignal: true,
2020
+ isRequired: false,
2021
+ transformFunction: null
2022
+ },
2023
+ ariaLabel: {
2024
+ classPropertyName: "ariaLabel",
2025
+ publicName: "ariaLabel",
2026
+ isSignal: true,
2027
+ isRequired: false,
2028
+ transformFunction: null
2029
+ },
2030
+ ariaLabelledby: {
2031
+ classPropertyName: "ariaLabelledby",
2032
+ publicName: "ariaLabelledby",
2033
+ isSignal: true,
2034
+ isRequired: false,
2035
+ transformFunction: null
2036
+ }
2037
+ },
2038
+ host: {
2039
+ properties: {
2040
+ "attr.aria-label": "ariaLabel() || null",
2041
+ "attr.aria-labelledby": "labelledBy()"
2042
+ },
2043
+ classAttribute: "flex flex-col bg-surface text-text border border-border rounded-card shadow-floating p-1 min-w-48 max-h-[min(24rem,calc(100dvh-2rem))] overflow-y-auto overscroll-contain"
2044
+ },
2045
+ hostDirectives: [{ directive: i1.CdkMenu }, { directive: i1.CdkTargetMenuAim }],
2046
+ ngImport: i0,
2047
+ template: "<ng-content />",
2048
+ isInline: true
2049
+ });
2050
+ };
2051
+ i0.ɵɵngDeclareClassMetadata({
2052
+ minVersion: "12.0.0",
2053
+ version: "22.1.7",
2054
+ ngImport: i0,
2055
+ type: BfMenuComponent,
2056
+ decorators: [{
2057
+ type: Component,
2058
+ args: [{
2059
+ selector: "bf-menu",
2060
+ hostDirectives: [CdkMenu, CdkTargetMenuAim],
2061
+ host: {
2062
+ class: "flex flex-col bg-surface text-text border border-border rounded-card shadow-floating p-1 min-w-48 max-h-[min(24rem,calc(100dvh-2rem))] overflow-y-auto overscroll-contain",
2063
+ "[attr.aria-label]": "ariaLabel() || null",
2064
+ "[attr.aria-labelledby]": "labelledBy()"
2065
+ },
2066
+ template: "<ng-content />"
2067
+ }]
2068
+ }],
2069
+ propDecorators: {
2070
+ size: [{
2071
+ type: i0.Input,
2072
+ args: [{
2073
+ isSignal: true,
2074
+ alias: "size",
2075
+ required: false
2076
+ }]
2077
+ }],
2078
+ ariaLabel: [{
2079
+ type: i0.Input,
2080
+ args: [{
2081
+ isSignal: true,
2082
+ alias: "ariaLabel",
2083
+ required: false
2084
+ }]
2085
+ }],
2086
+ ariaLabelledby: [{
2087
+ type: i0.Input,
2088
+ args: [{
2089
+ isSignal: true,
2090
+ alias: "ariaLabelledby",
2091
+ required: false
2092
+ }]
2093
+ }]
2094
+ }
2095
+ });
2096
+ const ITEM = "relative flex w-full items-center gap-3 px-3 text-text text-start rounded-field cursor-pointer select-none focus:outline-hidden no-underline! focus:bg-surface-muted not-aria-disabled:hover:bg-surface-muted focus-visible:ring-4 focus-visible:ring-ring focus-visible:ring-inset aria-disabled:text-text-disabled aria-disabled:cursor-not-allowed forced-colors:aria-disabled:text-[GrayText] forced-colors:focus:forced-color-adjust-none forced-colors:focus:bg-[Highlight] forced-colors:focus:text-[HighlightText] forced-colors:focus:aria-disabled:bg-[Canvas] forced-colors:focus:aria-disabled:text-[GrayText] forced-colors:focus:aria-disabled:outline-2 forced-colors:focus:aria-disabled:-outline-offset-2 forced-colors:focus:aria-disabled:outline-[Highlight]";
2097
+ const SIZE = {
2098
+ sm: "min-h-8 py-1 text-label-sm pointer-coarse:min-h-hit",
2099
+ md: "min-h-9 py-1.5 text-body pointer-coarse:min-h-hit",
2100
+ lg: "min-h-11 py-2 text-body"
2101
+ };
2102
+ const SUBMENU_CHEVRON = "aria-[haspopup=menu]:after:ms-auto aria-[haspopup=menu]:after:size-2 aria-[haspopup=menu]:after:shrink-0 aria-[haspopup=menu]:after:-translate-x-0.5 aria-[haspopup=menu]:after:rotate-45 rtl:aria-[haspopup=menu]:after:translate-x-0.5 rtl:aria-[haspopup=menu]:after:-rotate-135 aria-[haspopup=menu]:after:border-t-[1.5px] aria-[haspopup=menu]:after:border-r-[1.5px] aria-[haspopup=menu]:after:border-current aria-[haspopup=menu]:after:content-['']";
2103
+ const INDICATOR = {
2104
+ item: "",
2105
+ checkbox: "before:mx-[5px] before:h-[11px] before:w-[6px] before:shrink-0 before:-translate-y-px before:rotate-45 before:border-current aria-checked:before:border-r-2 aria-checked:before:border-b-2 before:content-['']",
2106
+ radio: "before:mx-1 before:size-2 before:shrink-0 before:rounded-full before:border-current aria-checked:before:border-4 before:content-['']"
2107
+ };
2108
+ function itemClasses(kind) {
2109
+ const menu = inject(BfMenuComponent, { optional: true });
2110
+ const defaults = inject(BF_DEFAULTS);
2111
+ return computed(() => {
2112
+ const size = menu?.resolvedSize() ?? defaults.controlSize;
2113
+ return [
2114
+ ITEM,
2115
+ SIZE[size],
2116
+ SUBMENU_CHEVRON,
2117
+ INDICATOR[kind]
2118
+ ].filter(Boolean).join(" ");
2119
+ });
2120
+ }
2121
+ function linkItemRules() {
2122
+ const el = inject(ElementRef).nativeElement;
2123
+ if (el.tagName !== "A") return;
2124
+ const disabled = () => el.getAttribute("aria-disabled") === "true";
2125
+ const block = (event) => {
2126
+ event.preventDefault();
2127
+ event.stopImmediatePropagation();
2128
+ };
2129
+ const onClick = (event) => {
2130
+ if (disabled()) block(event);
2131
+ };
2132
+ const onKeydown = (event) => {
2133
+ if (event.key === "Enter" && disabled()) {
2134
+ block(event);
2135
+ return;
2136
+ }
2137
+ if (event.key !== " " || event.altKey || event.ctrlKey || event.metaKey || event.shiftKey || disabled()) return;
2138
+ block(event);
2139
+ if (!event.repeat) el.click();
2140
+ };
2141
+ el.addEventListener("click", onClick, { capture: true });
2142
+ el.addEventListener("keydown", onKeydown, { capture: true });
2143
+ inject(DestroyRef).onDestroy(() => {
2144
+ el.removeEventListener("click", onClick, { capture: true });
2145
+ el.removeEventListener("keydown", onKeydown, { capture: true });
2146
+ });
2147
+ }
2148
+ var BfMenuItemDirective = class BfMenuItemDirective {
2149
+ classes = itemClasses("item");
2150
+ constructor() {
2151
+ linkItemRules();
2152
+ }
2153
+ static ɵfac = i0.ɵɵngDeclareFactory({
2154
+ minVersion: "12.0.0",
2155
+ version: "22.1.7",
2156
+ ngImport: i0,
2157
+ type: BfMenuItemDirective,
2158
+ deps: [],
2159
+ target: i0.ɵɵFactoryTarget.Directive
2160
+ });
2161
+ static ɵdir = i0.ɵɵngDeclareDirective({
2162
+ minVersion: "14.0.0",
2163
+ version: "22.1.7",
2164
+ type: BfMenuItemDirective,
2165
+ isStandalone: true,
2166
+ selector: "button[bfMenuItem], a[bfMenuItem]",
2167
+ host: { properties: { "class": "classes()" } },
2168
+ hostDirectives: [{
2169
+ directive: i1.CdkMenuItem,
2170
+ inputs: [
2171
+ "cdkMenuItemDisabled",
2172
+ "bfMenuItemDisabled",
2173
+ "cdkMenuitemTypeaheadLabel",
2174
+ "bfMenuItemTypeahead"
2175
+ ],
2176
+ outputs: ["cdkMenuItemTriggered", "triggered"]
2177
+ }],
2178
+ ngImport: i0
2179
+ });
2180
+ };
2181
+ i0.ɵɵngDeclareClassMetadata({
2182
+ minVersion: "12.0.0",
2183
+ version: "22.1.7",
2184
+ ngImport: i0,
2185
+ type: BfMenuItemDirective,
2186
+ decorators: [{
2187
+ type: Directive,
2188
+ args: [{
2189
+ selector: "button[bfMenuItem], a[bfMenuItem]",
2190
+ hostDirectives: [{
2191
+ directive: CdkMenuItem,
2192
+ inputs: ["cdkMenuItemDisabled: bfMenuItemDisabled", "cdkMenuitemTypeaheadLabel: bfMenuItemTypeahead"],
2193
+ outputs: ["cdkMenuItemTriggered: triggered"]
2194
+ }],
2195
+ host: { "[class]": "classes()" }
2196
+ }]
2197
+ }],
2198
+ ctorParameters: () => []
2199
+ });
2200
+ var BfMenuItemCheckboxDirective = class BfMenuItemCheckboxDirective {
2201
+ checked = model(false, ...ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []);
2202
+ changed = output();
2203
+ classes = itemClasses("checkbox");
2204
+ constructor() {
2205
+ const item = inject(CdkMenuItemCheckbox, { self: true });
2206
+ effect(() => {
2207
+ item.checked = this.checked();
2208
+ });
2209
+ const subscription = item.triggered.subscribe(() => {
2210
+ const next = !item.checked;
2211
+ this.checked.set(next);
2212
+ this.changed.emit(next);
2213
+ });
2214
+ inject(DestroyRef).onDestroy(() => subscription.unsubscribe());
2215
+ }
2216
+ static ɵfac = i0.ɵɵngDeclareFactory({
2217
+ minVersion: "12.0.0",
2218
+ version: "22.1.7",
2219
+ ngImport: i0,
2220
+ type: BfMenuItemCheckboxDirective,
2221
+ deps: [],
2222
+ target: i0.ɵɵFactoryTarget.Directive
2223
+ });
2224
+ static ɵdir = i0.ɵɵngDeclareDirective({
2225
+ minVersion: "17.1.0",
2226
+ version: "22.1.7",
2227
+ type: BfMenuItemCheckboxDirective,
2228
+ isStandalone: true,
2229
+ selector: "button[bfMenuItemCheckbox]",
2230
+ inputs: { checked: {
2231
+ classPropertyName: "checked",
2232
+ publicName: "checked",
2233
+ isSignal: true,
2234
+ isRequired: false,
2235
+ transformFunction: null
2236
+ } },
2237
+ outputs: {
2238
+ checked: "checkedChange",
2239
+ changed: "changed"
2240
+ },
2241
+ host: { properties: { "class": "classes()" } },
2242
+ hostDirectives: [{
2243
+ directive: i1.CdkMenuItemCheckbox,
2244
+ inputs: [
2245
+ "cdkMenuItemDisabled",
2246
+ "bfMenuItemDisabled",
2247
+ "cdkMenuitemTypeaheadLabel",
2248
+ "bfMenuItemTypeahead"
2249
+ ],
2250
+ outputs: ["cdkMenuItemTriggered", "triggered"]
2251
+ }],
2252
+ ngImport: i0
2253
+ });
2254
+ };
2255
+ i0.ɵɵngDeclareClassMetadata({
2256
+ minVersion: "12.0.0",
2257
+ version: "22.1.7",
2258
+ ngImport: i0,
2259
+ type: BfMenuItemCheckboxDirective,
2260
+ decorators: [{
2261
+ type: Directive,
2262
+ args: [{
2263
+ selector: "button[bfMenuItemCheckbox]",
2264
+ hostDirectives: [{
2265
+ directive: CdkMenuItemCheckbox,
2266
+ inputs: ["cdkMenuItemDisabled: bfMenuItemDisabled", "cdkMenuitemTypeaheadLabel: bfMenuItemTypeahead"],
2267
+ outputs: ["cdkMenuItemTriggered: triggered"]
2268
+ }],
2269
+ host: { "[class]": "classes()" }
2270
+ }]
2271
+ }],
2272
+ ctorParameters: () => [],
2273
+ propDecorators: {
2274
+ checked: [{
2275
+ type: i0.Input,
2276
+ args: [{
2277
+ isSignal: true,
2278
+ alias: "checked",
2279
+ required: false
2280
+ }]
2281
+ }, {
2282
+ type: i0.Output,
2283
+ args: ["checkedChange"]
2284
+ }],
2285
+ changed: [{
2286
+ type: i0.Output,
2287
+ args: ["changed"]
2288
+ }]
2289
+ }
2290
+ });
2291
+ var BfMenuItemRadioDirective = class BfMenuItemRadioDirective {
2292
+ classes = itemClasses("radio");
2293
+ static ɵfac = i0.ɵɵngDeclareFactory({
2294
+ minVersion: "12.0.0",
2295
+ version: "22.1.7",
2296
+ ngImport: i0,
2297
+ type: BfMenuItemRadioDirective,
2298
+ deps: [],
2299
+ target: i0.ɵɵFactoryTarget.Directive
2300
+ });
2301
+ static ɵdir = i0.ɵɵngDeclareDirective({
2302
+ minVersion: "14.0.0",
2303
+ version: "22.1.7",
2304
+ type: BfMenuItemRadioDirective,
2305
+ isStandalone: true,
2306
+ selector: "button[bfMenuItemRadio]",
2307
+ host: { properties: { "class": "classes()" } },
2308
+ hostDirectives: [{
2309
+ directive: i1.CdkMenuItemRadio,
2310
+ inputs: [
2311
+ "cdkMenuItemChecked",
2312
+ "checked",
2313
+ "cdkMenuItemDisabled",
2314
+ "bfMenuItemDisabled",
2315
+ "cdkMenuitemTypeaheadLabel",
2316
+ "bfMenuItemTypeahead"
2317
+ ],
2318
+ outputs: ["cdkMenuItemTriggered", "triggered"]
2319
+ }],
2320
+ ngImport: i0
2321
+ });
2322
+ };
2323
+ i0.ɵɵngDeclareClassMetadata({
2324
+ minVersion: "12.0.0",
2325
+ version: "22.1.7",
2326
+ ngImport: i0,
2327
+ type: BfMenuItemRadioDirective,
2328
+ decorators: [{
2329
+ type: Directive,
2330
+ args: [{
2331
+ selector: "button[bfMenuItemRadio]",
2332
+ hostDirectives: [{
2333
+ directive: CdkMenuItemRadio,
2334
+ inputs: [
2335
+ "cdkMenuItemChecked: checked",
2336
+ "cdkMenuItemDisabled: bfMenuItemDisabled",
2337
+ "cdkMenuitemTypeaheadLabel: bfMenuItemTypeahead"
2338
+ ],
2339
+ outputs: ["cdkMenuItemTriggered: triggered"]
2340
+ }],
2341
+ host: { "[class]": "classes()" }
2342
+ }]
2343
+ }]
2344
+ });
2345
+ var BfMenuGroupDirective = class BfMenuGroupDirective {
2346
+ static ɵfac = i0.ɵɵngDeclareFactory({
2347
+ minVersion: "12.0.0",
2348
+ version: "22.1.7",
2349
+ ngImport: i0,
2350
+ type: BfMenuGroupDirective,
2351
+ deps: [],
2352
+ target: i0.ɵɵFactoryTarget.Directive
2353
+ });
2354
+ static ɵdir = i0.ɵɵngDeclareDirective({
2355
+ minVersion: "14.0.0",
2356
+ version: "22.1.7",
2357
+ type: BfMenuGroupDirective,
2358
+ isStandalone: true,
2359
+ selector: "[bfMenuGroup]",
2360
+ host: { classAttribute: "flex flex-col" },
2361
+ hostDirectives: [{ directive: i1.CdkMenuGroup }],
2362
+ ngImport: i0
2363
+ });
2364
+ };
2365
+ i0.ɵɵngDeclareClassMetadata({
2366
+ minVersion: "12.0.0",
2367
+ version: "22.1.7",
2368
+ ngImport: i0,
2369
+ type: BfMenuGroupDirective,
2370
+ decorators: [{
2371
+ type: Directive,
2372
+ args: [{
2373
+ selector: "[bfMenuGroup]",
2374
+ hostDirectives: [CdkMenuGroup],
2375
+ host: { class: "flex flex-col" }
2376
+ }]
2377
+ }]
2378
+ });
2379
+ var BfMenuDividerDirective = class BfMenuDividerDirective {
2380
+ static ɵfac = i0.ɵɵngDeclareFactory({
2381
+ minVersion: "12.0.0",
2382
+ version: "22.1.7",
2383
+ ngImport: i0,
2384
+ type: BfMenuDividerDirective,
2385
+ deps: [],
2386
+ target: i0.ɵɵFactoryTarget.Directive
2387
+ });
2388
+ static ɵdir = i0.ɵɵngDeclareDirective({
2389
+ minVersion: "14.0.0",
2390
+ version: "22.1.7",
2391
+ type: BfMenuDividerDirective,
2392
+ isStandalone: true,
2393
+ selector: "[bfMenuDivider]",
2394
+ host: {
2395
+ attributes: { "role": "separator" },
2396
+ classAttribute: "my-1 block h-0 border-t border-border"
2397
+ },
2398
+ ngImport: i0
2399
+ });
2400
+ };
2401
+ i0.ɵɵngDeclareClassMetadata({
2402
+ minVersion: "12.0.0",
2403
+ version: "22.1.7",
2404
+ ngImport: i0,
2405
+ type: BfMenuDividerDirective,
2406
+ decorators: [{
2407
+ type: Directive,
2408
+ args: [{
2409
+ selector: "[bfMenuDivider]",
2410
+ host: {
2411
+ role: "separator",
2412
+ class: "my-1 block h-0 border-t border-border"
2413
+ }
2414
+ }]
2415
+ }]
2416
+ });
2417
+ const BUTTON = ɵBF_BUTTON_CLASSES;
2418
+ const ICON = ɵBF_ICON_BUTTON_CLASSES;
2419
+ const CARET_PADDING = {
2420
+ sm: "ps-3.5 pe-3",
2421
+ md: "ps-4.5 pe-4",
2422
+ lg: "ps-6 pe-5"
2423
+ };
2424
+ var BfMenuButtonComponent = class BfMenuButtonComponent {
2425
+ defaults = inject(BF_DEFAULTS);
2426
+ menu = input.required(...ngDevMode ? [{ debugName: "menu" }] : /* istanbul ignore next */ []);
2427
+ variant = input("outline", ...ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []);
2428
+ size = input(void 0, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
2429
+ placement = input("below-start", ...ngDevMode ? [{ debugName: "placement" }] : /* istanbul ignore next */ []);
2430
+ label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
2431
+ iconOnly = input(false, {
2432
+ ...ngDevMode ? { debugName: "iconOnly" } : /* istanbul ignore next */ {},
2433
+ transform: booleanAttribute
2434
+ });
2435
+ disabled = input(false, {
2436
+ ...ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {},
2437
+ transform: booleanAttribute
2438
+ });
2439
+ opened = output();
2440
+ closed = output();
2441
+ resolvedSize = computed(() => this.size() ?? this.defaults.controlSize, ...ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []);
2442
+ labelClasses = computed(() => this.iconOnly() ? "contents" : "max-w-full min-w-0 truncate", ...ngDevMode ? [{ debugName: "labelClasses" }] : /* istanbul ignore next */ []);
2443
+ classes = computed(() => {
2444
+ const size = this.resolvedSize();
2445
+ const variant = this.variant();
2446
+ const hit = ɵPILL_HIT[size][variant === "outline" ? "bordered" : "plain"];
2447
+ if (this.iconOnly()) {
2448
+ const pressed = this.disabled() ? "" : ICON.pressed[variant];
2449
+ return [
2450
+ ICON.base,
2451
+ ICON.variant[variant],
2452
+ pressed,
2453
+ ICON.size[size],
2454
+ hit
2455
+ ].filter(Boolean).join(" ");
2456
+ }
2457
+ const padding = variant === "text" ? BUTTON.textPadding[size] : CARET_PADDING[size];
2458
+ const pressed = this.disabled() ? "" : BUTTON.pressed[variant];
2459
+ return [
2460
+ BUTTON.base,
2461
+ "cursor-pointer",
2462
+ BUTTON.variant[variant],
2463
+ pressed,
2464
+ BUTTON.size[size],
2465
+ padding,
2466
+ hit
2467
+ ].filter(Boolean).join(" ");
2468
+ }, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
2469
+ static ɵfac = i0.ɵɵngDeclareFactory({
2470
+ minVersion: "12.0.0",
2471
+ version: "22.1.7",
2472
+ ngImport: i0,
2473
+ type: BfMenuButtonComponent,
2474
+ deps: [],
2475
+ target: i0.ɵɵFactoryTarget.Component
2476
+ });
2477
+ static ɵcmp = i0.ɵɵngDeclareComponent({
2478
+ minVersion: "17.0.0",
2479
+ version: "22.1.7",
2480
+ type: BfMenuButtonComponent,
2481
+ isStandalone: true,
2482
+ selector: "bf-menu-button",
2483
+ inputs: {
2484
+ menu: {
2485
+ classPropertyName: "menu",
2486
+ publicName: "menu",
2487
+ isSignal: true,
2488
+ isRequired: true,
2489
+ transformFunction: null
2490
+ },
2491
+ variant: {
2492
+ classPropertyName: "variant",
2493
+ publicName: "variant",
2494
+ isSignal: true,
2495
+ isRequired: false,
2496
+ transformFunction: null
2497
+ },
2498
+ size: {
2499
+ classPropertyName: "size",
2500
+ publicName: "size",
2501
+ isSignal: true,
2502
+ isRequired: false,
2503
+ transformFunction: null
2504
+ },
2505
+ placement: {
2506
+ classPropertyName: "placement",
2507
+ publicName: "placement",
2508
+ isSignal: true,
2509
+ isRequired: false,
2510
+ transformFunction: null
2511
+ },
2512
+ label: {
2513
+ classPropertyName: "label",
2514
+ publicName: "label",
2515
+ isSignal: true,
2516
+ isRequired: false,
2517
+ transformFunction: null
2518
+ },
2519
+ iconOnly: {
2520
+ classPropertyName: "iconOnly",
2521
+ publicName: "iconOnly",
2522
+ isSignal: true,
2523
+ isRequired: false,
2524
+ transformFunction: null
2525
+ },
2526
+ disabled: {
2527
+ classPropertyName: "disabled",
2528
+ publicName: "disabled",
2529
+ isSignal: true,
2530
+ isRequired: false,
2531
+ transformFunction: null
2532
+ }
2533
+ },
2534
+ outputs: {
2535
+ opened: "opened",
2536
+ closed: "closed"
2537
+ },
2538
+ host: { classAttribute: "inline-flex max-w-full" },
2539
+ ngImport: i0,
2540
+ template: `
2541
+ <button
2542
+ type="button"
2543
+ [bfMenuTriggerFor]="menu()"
2544
+ [bfMenuPlacement]="placement()"
2545
+ [disabled]="disabled()"
2546
+ [attr.aria-label]="label() || null"
2547
+ [class]="classes()"
2548
+ (bfMenuOpened)="opened.emit()"
2549
+ (bfMenuClosed)="closed.emit()"
2550
+ >
2551
+ <ng-content select="[bfSlot=icon-start]" />
2552
+ <span data-label [class]="labelClasses()"><ng-content /></span>
2553
+ @if (!iconOnly()) {
2554
+ <!-- A CSS caret pointing down in either direction (physical borders), in the text colour; nothing in the accessible name. -->
2555
+ <span
2556
+ data-caret
2557
+ class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-r-[1.5px] border-b-[1.5px] border-current"
2558
+ ></span>
2559
+ }
2560
+ </button>
2561
+ `,
2562
+ isInline: true,
2563
+ dependencies: [{
2564
+ kind: "directive",
2565
+ type: BfMenuTriggerDirective,
2566
+ selector: "[bfMenuTriggerFor]",
2567
+ inputs: ["bfMenuPlacement"]
2568
+ }]
2569
+ });
2570
+ };
2571
+ i0.ɵɵngDeclareClassMetadata({
2572
+ minVersion: "12.0.0",
2573
+ version: "22.1.7",
2574
+ ngImport: i0,
2575
+ type: BfMenuButtonComponent,
2576
+ decorators: [{
2577
+ type: Component,
2578
+ args: [{
2579
+ selector: "bf-menu-button",
2580
+ imports: [BfMenuTriggerDirective],
2581
+ host: { class: "inline-flex max-w-full" },
2582
+ template: `
2583
+ <button
2584
+ type="button"
2585
+ [bfMenuTriggerFor]="menu()"
2586
+ [bfMenuPlacement]="placement()"
2587
+ [disabled]="disabled()"
2588
+ [attr.aria-label]="label() || null"
2589
+ [class]="classes()"
2590
+ (bfMenuOpened)="opened.emit()"
2591
+ (bfMenuClosed)="closed.emit()"
2592
+ >
2593
+ <ng-content select="[bfSlot=icon-start]" />
2594
+ <span data-label [class]="labelClasses()"><ng-content /></span>
2595
+ @if (!iconOnly()) {
2596
+ <!-- A CSS caret pointing down in either direction (physical borders), in the text colour; nothing in the accessible name. -->
2597
+ <span
2598
+ data-caret
2599
+ class="size-2 shrink-0 -translate-y-0.5 rotate-45 border-r-[1.5px] border-b-[1.5px] border-current"
2600
+ ></span>
2601
+ }
2602
+ </button>
2603
+ `
2604
+ }]
2605
+ }],
2606
+ propDecorators: {
2607
+ menu: [{
2608
+ type: i0.Input,
2609
+ args: [{
2610
+ isSignal: true,
2611
+ alias: "menu",
2612
+ required: true
2613
+ }]
2614
+ }],
2615
+ variant: [{
2616
+ type: i0.Input,
2617
+ args: [{
2618
+ isSignal: true,
2619
+ alias: "variant",
2620
+ required: false
2621
+ }]
2622
+ }],
2623
+ size: [{
2624
+ type: i0.Input,
2625
+ args: [{
2626
+ isSignal: true,
2627
+ alias: "size",
2628
+ required: false
2629
+ }]
2630
+ }],
2631
+ placement: [{
2632
+ type: i0.Input,
2633
+ args: [{
2634
+ isSignal: true,
2635
+ alias: "placement",
2636
+ required: false
2637
+ }]
2638
+ }],
2639
+ label: [{
2640
+ type: i0.Input,
2641
+ args: [{
2642
+ isSignal: true,
2643
+ alias: "label",
2644
+ required: false
2645
+ }]
2646
+ }],
2647
+ iconOnly: [{
2648
+ type: i0.Input,
2649
+ args: [{
2650
+ isSignal: true,
2651
+ alias: "iconOnly",
2652
+ required: false
2653
+ }]
2654
+ }],
2655
+ disabled: [{
2656
+ type: i0.Input,
2657
+ args: [{
2658
+ isSignal: true,
2659
+ alias: "disabled",
2660
+ required: false
2661
+ }]
2662
+ }],
2663
+ opened: [{
2664
+ type: i0.Output,
2665
+ args: ["opened"]
2666
+ }],
2667
+ closed: [{
2668
+ type: i0.Output,
2669
+ args: ["closed"]
2670
+ }]
2671
+ }
2672
+ });
2673
+ export { BF_DESKTOP_TOAST_DEFAULTS, BF_DIALOG_DATA, BF_OVERLAY_DATA, BF_OVERLAY_HOST, BfComponentOverlayRef, BfDesktopToastComponent, BfDesktopToastService, BfDialogComponent, BfDialogRef, BfDialogService, BfMenuButtonComponent, BfMenuComponent, BfMenuDividerDirective, BfMenuGroupDirective, BfMenuItemCheckboxDirective, BfMenuItemDirective, BfMenuItemRadioDirective, BfMenuTriggerDirective, BfOverlayRef, BfOverlayService, BfOverlayStack, BfToastRef, OVERLAY_DURATION, OVERLAY_EASING, OVERLAY_REDUCED_DURATION, fadeDown, fadeIn, fadeOut, fadeUp, prefersReducedMotion, provideBfDesktopToast, scaleIn, slideDown, slideUp, ɵBfToastQueue, labelPanelByHeading as ɵlabelPanelByHeading, watchPanelHeading as ɵwatchPanelHeading };
2674
+
2675
+ //# sourceMappingURL=bitforgehq-ui-overlay.mjs.map