@bitforgehq/ui 0.4.0 → 0.5.0-next.4

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 (87) hide show
  1. package/CHANGELOG.md +350 -0
  2. package/README.md +12 -12
  3. package/ai/MANIFEST.index.json +74 -2
  4. package/ai/MANIFEST.json +3507 -1763
  5. package/ai/REFERENCE.index.json +189 -0
  6. package/ai/REFERENCE.json +1617 -139
  7. package/ai/UI_GUIDE.md +70 -20
  8. package/ai/components/app-frame.md +1 -1
  9. package/ai/components/badge.md +41 -1
  10. package/ai/components/chat-composer.md +357 -0
  11. package/ai/components/chat-message.md +251 -0
  12. package/ai/components/chat-thread.md +521 -0
  13. package/ai/components/checkbox.md +7 -0
  14. package/ai/components/combobox.md +12 -0
  15. package/ai/components/date-input.md +9 -0
  16. package/ai/components/datetime-input.md +2 -0
  17. package/ai/components/field.md +10 -0
  18. package/ai/components/file-input.md +498 -0
  19. package/ai/components/header.md +1 -1
  20. package/ai/components/image-input.md +368 -0
  21. package/ai/components/image-tile.md +452 -0
  22. package/ai/components/image-viewer.md +309 -0
  23. package/ai/components/media-card.md +478 -0
  24. package/ai/components/menu-button.md +67 -9
  25. package/ai/components/menu.md +10 -0
  26. package/ai/components/multi-combobox.md +7 -0
  27. package/ai/components/nav-group.md +10 -3
  28. package/ai/components/nav-item.md +11 -2
  29. package/ai/components/number-input.md +2 -7
  30. package/ai/components/pagination.md +59 -11
  31. package/ai/components/popover.md +13 -0
  32. package/ai/components/radio-group.md +6 -0
  33. package/ai/components/segmented.md +14 -2
  34. package/ai/components/select.md +100 -42
  35. package/ai/components/sidebar-toggle.md +16 -9
  36. package/ai/components/sidebar.md +41 -13
  37. package/ai/components/tab-group.md +18 -2
  38. package/ai/components/table.md +17 -2
  39. package/ai/components/theme-menu-button.md +1 -0
  40. package/ai/components/time-input.md +2 -0
  41. package/ai/components/toolbar.md +7 -18
  42. package/ai/reference/bf-chat-composer-harness.md +64 -0
  43. package/ai/reference/bf-chat-message-role.md +27 -0
  44. package/ai/reference/bf-chat-message-status.md +28 -0
  45. package/ai/reference/bf-fade-in-directive.md +18 -0
  46. package/ai/reference/bf-file-input-harness.md +67 -0
  47. package/ai/reference/bf-file-input-variant.md +27 -0
  48. package/ai/reference/bf-image-input-harness.md +67 -0
  49. package/ai/reference/bf-image-input-shape.md +27 -0
  50. package/ai/reference/bf-image-tile-aspect.md +28 -0
  51. package/ai/reference/bf-image-tile-caption-placement.md +27 -0
  52. package/ai/reference/bf-image-tile-harness.md +70 -0
  53. package/ai/reference/bf-image-viewer-actions-context.md +29 -0
  54. package/ai/reference/bf-image-viewer-harness.md +87 -0
  55. package/ai/reference/bf-image-viewer-image.md +25 -0
  56. package/ai/reference/bf-image-viewer-options.md +33 -0
  57. package/ai/reference/bf-image-viewer-origin.md +23 -0
  58. package/ai/reference/bf-image-viewer-ref.md +55 -0
  59. package/ai/reference/bf-image-viewer-service.md +32 -0
  60. package/ai/reference/bf-labels.md +107 -75
  61. package/ai/reference/bf-media-card-aspect.md +28 -0
  62. package/ai/reference/bf-media-card-harness.md +66 -0
  63. package/ai/reference/bf-motion-list-directive.md +22 -0
  64. package/ai/reference/bf-pagination-position-label.md +22 -0
  65. package/ai/reference/bf-prose-directive.md +16 -0
  66. package/ai/reference/bf-rejected-file-reason.md +28 -0
  67. package/ai/reference/bf-rejected-file.md +28 -0
  68. package/ai/reference/bf-select-harness.md +14 -5
  69. package/ai/reference/bf-select-option.md +2 -0
  70. package/ai/reference/bf-size.md +3 -0
  71. package/ai/reference/bf_table_sort_select.md +23 -0
  72. package/ai/reference/provide-bf-labels.md +11 -3
  73. package/ai/reference/provide-bf-select.md +20 -0
  74. package/bin/bf-ui.js +1 -0
  75. package/fesm2022/bitforgehq-ui-overlay.mjs +2660 -594
  76. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
  77. package/fesm2022/bitforgehq-ui-testing.mjs +414 -10
  78. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  79. package/fesm2022/bitforgehq-ui.mjs +8056 -3993
  80. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  81. package/llms-full.txt +4923 -132
  82. package/llms.txt +36 -1
  83. package/package.json +1 -1
  84. package/theme.css +60 -0
  85. package/types/bitforgehq-ui-overlay.d.ts +695 -7
  86. package/types/bitforgehq-ui-testing.d.ts +517 -6
  87. package/types/bitforgehq-ui.d.ts +1699 -181
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ComponentRef, DestroyRef, EnvironmentProviders, InjectionToken, Injector, Signal, StaticProvider, TemplateRef, Type } from "@angular/core";
3
3
  import { LiveAnnouncer } from "@angular/cdk/a11y";
4
- import { BfCalendarDisabledDate, BfColorScheme, BfCompareWith, BfSize } from "@bitforgehq/ui";
4
+ import { BfCalendarDisabledDate, BfColorScheme, BfCompareWith, BfSelectOption, BfSelectOption as BfSelectOption$1, BfSize } from "@bitforgehq/ui";
5
5
  import * as i1 from "@angular/cdk/menu";
6
6
  import { FormValueControl, ValidationError } from "@angular/forms/signals";
7
7
  /**
@@ -390,7 +390,6 @@ declare function firstTabbable(panel: HTMLElement): HTMLElement | null;
390
390
  * @since 0.2.0
391
391
  */
392
392
  export declare class BfOverlayService {
393
- private readonly overlay;
394
393
  private readonly injector;
395
394
  private readonly document;
396
395
  private readonly stack;
@@ -1162,7 +1161,6 @@ interface BfDesktopToastOptions {
1162
1161
  * @summary Shows brief desktop notifications in a stack at a corner of the viewport
1163
1162
  */
1164
1163
  export declare class BfDesktopToastService {
1165
- private readonly overlay;
1166
1164
  private readonly injector;
1167
1165
  private readonly document;
1168
1166
  private readonly config;
@@ -1244,6 +1242,7 @@ export declare class BfMenuComponent {
1244
1242
  readonly resolvedSize: import("@angular/core").Signal<BfSize>;
1245
1243
  private readonly triggerId;
1246
1244
  protected readonly labelledBy: import("@angular/core").Signal<string | null>;
1245
+ constructor();
1247
1246
  static ɵfac: i0.ɵɵFactoryDeclaration<BfMenuComponent, never>;
1248
1247
  static ɵcmp: i0.ɵɵComponentDeclaration<BfMenuComponent, "bf-menu", never, {
1249
1248
  "size": {
@@ -1440,6 +1439,11 @@ export declare class BfMenuTriggerDirective {
1440
1439
  * item, at the inline end, and ignores it. */
1441
1440
  readonly bfMenuPlacement: import("@angular/core").InputSignal<BfMenuPlacement>;
1442
1441
  constructor();
1442
+ /**
1443
+ * The trigger element, which the opening menu grows out of.
1444
+ * @internal
1445
+ */
1446
+ anchorElement(): HTMLElement;
1443
1447
  /** The trigger element's id (assigned when it has none), which names the menu it opens. It is
1444
1448
  * read when the menu opens: an `[id]` bound on the trigger that changes while the menu is open
1445
1449
  * names the menu from its next opening. */
@@ -1506,6 +1510,9 @@ export declare class BfMenuButtonComponent {
1506
1510
  readonly label: import("@angular/core").InputSignal<string>;
1507
1511
  /** Square button holding only the projected icon, like `bf-icon-button`; set `label`. */
1508
1512
  readonly iconOnly: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1513
+ /** Stretches the host and the button to the width of their container, as `bf-button`'s
1514
+ * `fullWidth`; the label and caret stay centred. Ignored with `iconOnly`. */
1515
+ readonly fullWidth: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1509
1516
  /** Disables the button; the menu cannot open. */
1510
1517
  readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1511
1518
  /** The menu opened. */
@@ -1514,6 +1521,9 @@ export declare class BfMenuButtonComponent {
1514
1521
  readonly closed: import("@angular/core").OutputEmitterRef<void>;
1515
1522
  /** The size in effect: `size`, else the app's `controlSize` default. */
1516
1523
  protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
1524
+ /** Full width (not icon-only): the host and the button fill the container. */
1525
+ private readonly stretched;
1526
+ protected readonly hostClasses: import("@angular/core").Signal<"inline-flex max-w-full w-full" | "inline-flex max-w-full">;
1517
1527
  protected readonly labelClasses: import("@angular/core").Signal<"contents" | "max-w-full min-w-0 truncate">;
1518
1528
  protected readonly classes: import("@angular/core").Signal<string>;
1519
1529
  static ɵfac: i0.ɵɵFactoryDeclaration<BfMenuButtonComponent, never>;
@@ -1548,6 +1558,11 @@ export declare class BfMenuButtonComponent {
1548
1558
  "required": false;
1549
1559
  "isSignal": true;
1550
1560
  };
1561
+ "fullWidth": {
1562
+ "alias": "fullWidth";
1563
+ "required": false;
1564
+ "isSignal": true;
1565
+ };
1551
1566
  "disabled": {
1552
1567
  "alias": "disabled";
1553
1568
  "required": false;
@@ -1694,6 +1709,158 @@ export declare class BfSidebarToggleComponent {
1694
1709
  };
1695
1710
  }, {}, never, ["[bfSlot=collapse-icon]", "[bfSlot=expand-icon]"], true, never>;
1696
1711
  }
1712
+ type BfChatComposerAction = 'send' | 'stop';
1713
+ /**
1714
+ * The input row of a chat: a `bf-textarea` that grows with the text (`autoResize`, up to
1715
+ * `maxRows`, then it scrolls), a start and an end slot for extra controls, and one button that
1716
+ * sends the text or, while a reply is `running`, stops it. `Enter` sends and `Shift+Enter`
1717
+ * starts a new line; nothing sends during IME composition or
1718
+ * when the text is only whitespace. After a send the text clears and focus stays in the field.
1719
+ * `disabled` with a `disabledReason` shows the reason as the button's tooltip and as the empty
1720
+ * field's placeholder.
1721
+ *
1722
+ * @example
1723
+ * <bf-chat-composer [(value)]="draft" [running]="replying()" (sent)="ask($event)" (stopped)="cancel()">
1724
+ * <bf-icon bfSlot="send-icon" [icon]="ArrowUp" />
1725
+ * <bf-icon bfSlot="stop-icon" [icon]="Square" />
1726
+ * </bf-chat-composer>
1727
+ * @summary Chat input that grows with the text and sends on Enter, or stops a reply
1728
+ * @category Forms
1729
+ * @since 0.5.0
1730
+ * @slot start Controls before the field, such as a preset picker or an attach button.
1731
+ * @slot end Controls between the field and the send button.
1732
+ * @slot send-icon The send button's icon; without one the button shows its text.
1733
+ * @slot stop-icon The stop button's icon; without one the button shows its text.
1734
+ */
1735
+ export declare class BfChatComposerComponent {
1736
+ private readonly defaults;
1737
+ private readonly labels;
1738
+ /** The text being written; two-way bindable. Cleared after a send. */
1739
+ readonly value: import("@angular/core").ModelSignal<string>;
1740
+ /** A reply is running: the button stops it (`stopped`) instead of sending. */
1741
+ readonly running: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1742
+ /** Nothing can be written or sent. */
1743
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
1744
+ /** Why it is disabled, shown as the button's tooltip and the empty field's placeholder. */
1745
+ readonly disabledReason: import("@angular/core").InputSignal<string>;
1746
+ /** Visible label above the field; usually left empty in a chat. */
1747
+ readonly label: import("@angular/core").InputSignal<string>;
1748
+ /** The field's accessible name without a visible label; empty uses the `chatComposer` label
1749
+ * ("Message"). */
1750
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
1751
+ /** Id(s) of the element(s) that name the field without a visible label. */
1752
+ readonly ariaLabelledby: import("@angular/core").InputSignal<string>;
1753
+ /** Example text shown while the field is empty. */
1754
+ readonly placeholder: import("@angular/core").InputSignal<string>;
1755
+ /** The lines the field grows to at most; past them it scrolls. */
1756
+ readonly maxRows: import("@angular/core").InputSignal<number>;
1757
+ /** Maximum number of characters (native `maxlength`). */
1758
+ readonly maxLength: import("@angular/core").InputSignal<number | undefined>;
1759
+ /** Native name attribute of the textarea. */
1760
+ readonly name: import("@angular/core").InputSignal<string>;
1761
+ /** Padding, type and button step: sm, md, lg; unset follows `provideBfDefaults()`
1762
+ * (`fieldSize`, `md` by default). */
1763
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
1764
+ /** Emitted with the new text right after the user changes it (each keystroke or paste). */
1765
+ readonly changed: import("@angular/core").OutputEmitterRef<string>;
1766
+ /** Emitted with the trimmed text when the user sends it (Enter or the send button). */
1767
+ readonly sent: import("@angular/core").OutputEmitterRef<string>;
1768
+ /** Emitted when the user presses the stop button while `running`. */
1769
+ readonly stopped: import("@angular/core").OutputEmitterRef<void>;
1770
+ private readonly field;
1771
+ protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
1772
+ /** The field's one-line height, matched to the button. */
1773
+ protected readonly fieldClasses: import("@angular/core").Signal<string>;
1774
+ protected readonly action: import("@angular/core").Signal<BfChatComposerAction>;
1775
+ /** Disabled with a reason: focusable, `aria-disabled`, with the reason as a tooltip. */
1776
+ protected readonly blocked: import("@angular/core").Signal<boolean>;
1777
+ /** Native `disabled`: disabled without a reason, or nothing to send yet. */
1778
+ protected readonly nativeDisabled: import("@angular/core").Signal<boolean>;
1779
+ protected readonly buttonName: import("@angular/core").Signal<string>;
1780
+ /** The field's `aria-label`: `ariaLabel`, else the label key while nothing else names it. */
1781
+ protected readonly fieldName: import("@angular/core").Signal<string>;
1782
+ protected readonly fieldPlaceholder: import("@angular/core").Signal<string>;
1783
+ protected readonly buttonClasses: import("@angular/core").Signal<string>;
1784
+ /** Sends the text: emits `sent` with it trimmed, clears the field and keeps focus in it. Does
1785
+ * nothing while disabled or running, or when the text is only whitespace. */
1786
+ send(): void;
1787
+ /** Focuses the text field. */
1788
+ focus(): void;
1789
+ /** @internal */
1790
+ onChanged(text: string): void;
1791
+ /** @internal */
1792
+ onButton(): void;
1793
+ /** @internal */
1794
+ onKeydown(event: KeyboardEvent): void;
1795
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfChatComposerComponent, never>;
1796
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfChatComposerComponent, "bf-chat-composer", never, {
1797
+ "value": {
1798
+ "alias": "value";
1799
+ "required": false;
1800
+ "isSignal": true;
1801
+ };
1802
+ "running": {
1803
+ "alias": "running";
1804
+ "required": false;
1805
+ "isSignal": true;
1806
+ };
1807
+ "disabled": {
1808
+ "alias": "disabled";
1809
+ "required": false;
1810
+ "isSignal": true;
1811
+ };
1812
+ "disabledReason": {
1813
+ "alias": "disabledReason";
1814
+ "required": false;
1815
+ "isSignal": true;
1816
+ };
1817
+ "label": {
1818
+ "alias": "label";
1819
+ "required": false;
1820
+ "isSignal": true;
1821
+ };
1822
+ "ariaLabel": {
1823
+ "alias": "ariaLabel";
1824
+ "required": false;
1825
+ "isSignal": true;
1826
+ };
1827
+ "ariaLabelledby": {
1828
+ "alias": "ariaLabelledby";
1829
+ "required": false;
1830
+ "isSignal": true;
1831
+ };
1832
+ "placeholder": {
1833
+ "alias": "placeholder";
1834
+ "required": false;
1835
+ "isSignal": true;
1836
+ };
1837
+ "maxRows": {
1838
+ "alias": "maxRows";
1839
+ "required": false;
1840
+ "isSignal": true;
1841
+ };
1842
+ "maxLength": {
1843
+ "alias": "maxLength";
1844
+ "required": false;
1845
+ "isSignal": true;
1846
+ };
1847
+ "name": {
1848
+ "alias": "name";
1849
+ "required": false;
1850
+ "isSignal": true;
1851
+ };
1852
+ "size": {
1853
+ "alias": "size";
1854
+ "required": false;
1855
+ "isSignal": true;
1856
+ };
1857
+ }, {
1858
+ "value": "valueChange";
1859
+ "changed": "changed";
1860
+ "sent": "sent";
1861
+ "stopped": "stopped";
1862
+ }, never, ["[bfSlot=start]", "[bfSlot=end]", "[bfSlot=send-icon]", "[bfSlot=stop-icon]"], true, never>;
1863
+ }
1697
1864
  /**
1698
1865
  * Layout of a side panel opened with `BfSidePanelService`: a title row with a close button, a
1699
1866
  * scrolling body and a footer of actions kept at the bottom. The panel is labelled by the title,
@@ -1932,7 +2099,7 @@ type BfTooltipPlacement = 'top' | 'bottom' | 'start' | 'end';
1932
2099
  * @since 0.3.1
1933
2100
  */
1934
2101
  export declare class BfTooltipDirective {
1935
- private readonly overlay;
2102
+ private readonly environment;
1936
2103
  private readonly document;
1937
2104
  private readonly injector;
1938
2105
  private readonly dir;
@@ -2037,7 +2204,7 @@ type BfPopoverPlacement = 'below-start' | 'below-end' | 'above-start' | 'above-e
2037
2204
  * @since 0.3.1
2038
2205
  */
2039
2206
  export declare class BfPopoverTriggerDirective {
2040
- private readonly overlay;
2207
+ private readonly environment;
2041
2208
  private readonly document;
2042
2209
  private readonly injector;
2043
2210
  private readonly viewContainer;
@@ -2060,6 +2227,7 @@ export declare class BfPopoverTriggerDirective {
2060
2227
  /** The id the `bf-popover` panel takes, which the trigger's `aria-controls` points at. */
2061
2228
  readonly panelId: string;
2062
2229
  private anchored;
2230
+ private readonly motion;
2063
2231
  private subscriptions;
2064
2232
  private stopNavigation;
2065
2233
  private stopHeading;
@@ -2089,6 +2257,10 @@ export declare class BfPopoverTriggerDirective {
2089
2257
  * the trigger.
2090
2258
  */
2091
2259
  private name;
2260
+ /**
2261
+ * Drops the listeners and closes the overlay: with its exit animation (it stays attached, inert,
2262
+ * until the exit has played), or at once when the directive is destroyed.
2263
+ */
2092
2264
  private teardown;
2093
2265
  static ɵfac: i0.ɵɵFactoryDeclaration<BfPopoverTriggerDirective, never>;
2094
2266
  static ɵdir: i0.ɵɵDirectiveDeclaration<BfPopoverTriggerDirective, "[bfPopoverTriggerFor]", ["bfPopoverTrigger"], {
@@ -2197,7 +2369,7 @@ interface ComboboxHost<T> {
2197
2369
  */
2198
2370
  declare class ComboboxCore<T> {
2199
2371
  readonly host: ComboboxHost<T>;
2200
- private readonly overlay;
2372
+ private readonly environment;
2201
2373
  private readonly injector;
2202
2374
  private readonly viewContainer;
2203
2375
  private readonly dir;
@@ -2220,6 +2392,9 @@ declare class ComboboxCore<T> {
2220
2392
  /** `aria-controls`: the listbox while it is rendered. */
2221
2393
  readonly controls: Signal<string | null>;
2222
2394
  private anchored;
2395
+ /** The listbox component's view, frozen while the panel plays its exit. */
2396
+ private panelView;
2397
+ private readonly motion;
2223
2398
  private subscriptions;
2224
2399
  constructor(host: ComboboxHost<T>);
2225
2400
  /**
@@ -2257,6 +2432,10 @@ declare class ComboboxCore<T> {
2257
2432
  /** Moves the active option by `step` through the enabled ones, wrapping at the ends. */
2258
2433
  private move;
2259
2434
  private firstEnabled;
2435
+ /**
2436
+ * Drops the listeners and closes the overlay: with its exit animation (the list frozen as it
2437
+ * was, so a reset query never reflows it while it fades), or at once on destroy.
2438
+ */
2260
2439
  private teardown;
2261
2440
  }
2262
2441
  /** Equality of an option's value and a picked value under `compareWith`, never for `null`. */
@@ -2777,6 +2956,271 @@ export declare class BfMultiComboboxComponent<T = string> implements FormValueCo
2777
2956
  "touch": "touch";
2778
2957
  }, never, never, true, never>;
2779
2958
  }
2959
+ /**
2960
+ * Single-choice dropdown styled like the text field, with a placeholder and Signal Forms binding.
2961
+ * Under a mouse it opens a styled list (the combobox's) that follows the select-only combobox
2962
+ * pattern: the arrow keys, `Home`, `End`, `PageUp`/`PageDown` and typeahead move through it,
2963
+ * `Enter`, `Space` or `Tab` pick. Under a coarse pointer (touch) it renders the platform's native
2964
+ * select instead. Generic over the option value (a string by default); `null` means nothing is
2965
+ * selected. Moved from `@bitforgehq/ui` to `@bitforgehq/ui/overlay` in 0.5.0.
2966
+ *
2967
+ * @example
2968
+ * <bf-select label="Project" placeholder="Pick a project" [options]="projects" [(value)]="projectId" />
2969
+ * <bf-select label="Team" placeholder="Pick a team" [options]="teams" [formField]="task.teamId" />
2970
+ * @summary Single-choice dropdown with a styled list, native under touch, with Signal Forms binding
2971
+ * @category Forms
2972
+ * @since 0.1.0
2973
+ */
2974
+ export declare class BfSelectComponent<T = string> implements FormValueControl<T | null> {
2975
+ /** The selected option's value, `null` while nothing is selected; two-way bindable and bound by
2976
+ * `[formField]`. */
2977
+ readonly value: import("@angular/core").ModelSignal<T | null>;
2978
+ /** The options to choose from. */
2979
+ readonly options: import("@angular/core").InputSignal<readonly BfSelectOption$1<T>[]>;
2980
+ /** Equality for matching `value` to an option (default `Object.is`); pass one for object values. */
2981
+ readonly compareWith: import("@angular/core").InputSignal<BfCompareWith<T>>;
2982
+ /** Height step: sm 32, md 40, lg 48 px; unset follows `provideBfDefaults()` (`fieldSize`, `md`
2983
+ * by default). */
2984
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
2985
+ /** Visible label above the control. */
2986
+ readonly label: import("@angular/core").InputSignal<string>;
2987
+ /**
2988
+ * Accessible name when no visible label is rendered (e.g. a table filter). Ignored when `label`
2989
+ * is set.
2990
+ */
2991
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
2992
+ /**
2993
+ * Id(s) of the element(s) that name the field when no visible label is rendered. Ignored when
2994
+ * `label` is set.
2995
+ */
2996
+ readonly ariaLabelledby: import("@angular/core").InputSignal<string>;
2997
+ /** Muted text shown while nothing is selected. */
2998
+ readonly placeholder: import("@angular/core").InputSignal<string>;
2999
+ /** Helper text under the control. */
3000
+ readonly helpText: import("@angular/core").InputSignal<string>;
3001
+ /** Explicit error text; takes precedence over Signal Forms errors. */
3002
+ readonly errorMessage: import("@angular/core").InputSignal<string>;
3003
+ /** Disables the control. */
3004
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3005
+ /** Shows the value but blocks changes; the select stays focusable and exposes `aria-readonly`. */
3006
+ readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3007
+ /** Marks the control required. */
3008
+ readonly required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3009
+ /** Field validity from Signal Forms. */
3010
+ readonly invalid: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3011
+ /** Whether the user has left the field. */
3012
+ readonly touched: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3013
+ /** Validation errors from Signal Forms. */
3014
+ readonly errors: import("@angular/core").InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
3015
+ /** Form name: of a hidden input carrying the selected option's key, or of the native select. */
3016
+ readonly name: import("@angular/core").InputSignal<string>;
3017
+ /** Control id; generated when not set. */
3018
+ readonly id: import("@angular/core").InputSignal<string>;
3019
+ /** Emitted with the chosen value after a user change (never `null`). */
3020
+ readonly changed: import("@angular/core").OutputEmitterRef<T>;
3021
+ /** Emitted when the control gains focus. */
3022
+ readonly focused: import("@angular/core").OutputEmitterRef<FocusEvent>;
3023
+ /** Emitted when the control loses focus. */
3024
+ readonly blurred: import("@angular/core").OutputEmitterRef<FocusEvent>;
3025
+ /** Emitted on blur so Signal Forms marks the field touched. */
3026
+ readonly touch: import("@angular/core").OutputEmitterRef<void>;
3027
+ private readonly fieldEl;
3028
+ private readonly anchorEl;
3029
+ private readonly nativeSelect;
3030
+ private readonly defaults;
3031
+ private readonly labels;
3032
+ private readonly document;
3033
+ /** Whether the primary pointer is coarse (touch), from `matchMedia`: the native mode. */
3034
+ protected readonly coarse: import("@angular/core").WritableSignal<boolean>;
3035
+ /** The size in effect: `size`, else the app's `fieldSize` default. */
3036
+ protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
3037
+ /** Index of the option matching `value`, `-1` while nothing (or `null`) is selected. */
3038
+ protected readonly selectedIndex: import("@angular/core").Signal<number>;
3039
+ /** The selected option's label, null while nothing is selected. */
3040
+ protected readonly selectedLabel: import("@angular/core").Signal<string | null>;
3041
+ /** The hidden input's value: the selected option's key (its index for an object), else `''`. */
3042
+ protected readonly formKey: import("@angular/core").Signal<string>;
3043
+ /** The options as the list shows them; the selected one is matched by identity. */
3044
+ private readonly listOptions;
3045
+ protected readonly core: ComboboxCore<T>;
3046
+ protected readonly errorText: import("@angular/core").Signal<string>;
3047
+ protected readonly showError: import("@angular/core").Signal<boolean>;
3048
+ protected readonly describedBy: import("@angular/core").Signal<string | null>;
3049
+ /** `aria-errormessage`: the error paragraph while `aria-invalid` is set. */
3050
+ protected readonly errorMessageId: import("@angular/core").Signal<string | null>;
3051
+ /**
3052
+ * `aria-label` value: only when there is no visible label, so the label stays the sole accessible
3053
+ * name.
3054
+ */
3055
+ protected readonly ariaLabelAttr: import("@angular/core").Signal<string | null>;
3056
+ /**
3057
+ * `aria-labelledby` value while there is no visible label; with one, the field points
3058
+ * `aria-labelledby` at the label's id instead (a `<label for>` cannot name a div).
3059
+ */
3060
+ protected readonly ariaLabelledbyAttr: import("@angular/core").Signal<string | null>;
3061
+ protected readonly wrapperClasses: import("@angular/core").Signal<string>;
3062
+ protected readonly classes: import("@angular/core").Signal<string>;
3063
+ /** The typed typeahead text and when its last key came. */
3064
+ private typeahead;
3065
+ private typedAt;
3066
+ constructor();
3067
+ /**
3068
+ * Focuses the field, or the native select under a coarse pointer; Signal Forms calls it from
3069
+ * `focusBoundControl()`.
3070
+ * @param options Passed on to the native `focus()`, such as `{ preventScroll: true }`.
3071
+ */
3072
+ focus(options?: FocusOptions): void;
3073
+ /**
3074
+ * A click on the label focuses the field (a label's `for` cannot name a div).
3075
+ * @internal
3076
+ */
3077
+ onHostClick(event: MouseEvent): void;
3078
+ /**
3079
+ * A click on the field opens or closes the list.
3080
+ * @internal
3081
+ */
3082
+ onClick(): void;
3083
+ /**
3084
+ * The select-only combobox keys: `Enter`, `Space` and the arrows open; while open the arrows,
3085
+ * `Home`, `End`, `PageUp` and `PageDown` move, `Enter`, `Space` and `Tab` pick; printable keys
3086
+ * search by label. `Escape` on an open list is the panel's: it closes it.
3087
+ * @internal
3088
+ */
3089
+ onKeydown(event: KeyboardEvent): void;
3090
+ /**
3091
+ * Leaving the field closes the list, emits `blurred` and marks the field touched. A press in the
3092
+ * list never moves the focus (the listbox cancels it), so this runs only when the field is left.
3093
+ * @internal
3094
+ */
3095
+ onBlur(event: FocusEvent): void;
3096
+ /** Opens the list with the selected option active, else the first enabled one. */
3097
+ private openList;
3098
+ /** Picks an option: the value and `changed` when it differs, and the list closes. */
3099
+ private pick;
3100
+ private pickActive;
3101
+ /** Moves the active option by `step` enabled options, stopping at the ends. */
3102
+ private page;
3103
+ /** Whether a typeahead search is still being typed. */
3104
+ private typing;
3105
+ /**
3106
+ * Adds a key to the typeahead search, opens the list and activates the next enabled option whose
3107
+ * label starts with the search, ignoring case and accents. One letter repeated cycles through the
3108
+ * options starting with it; a longer search keeps the active option while it still matches.
3109
+ */
3110
+ private search;
3111
+ /** The list's enabled options in list order. */
3112
+ private enabledItems;
3113
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfSelectComponent<any>, never>;
3114
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfSelectComponent<any>, "bf-select", never, {
3115
+ "value": {
3116
+ "alias": "value";
3117
+ "required": false;
3118
+ "isSignal": true;
3119
+ };
3120
+ "options": {
3121
+ "alias": "options";
3122
+ "required": true;
3123
+ "isSignal": true;
3124
+ };
3125
+ "compareWith": {
3126
+ "alias": "compareWith";
3127
+ "required": false;
3128
+ "isSignal": true;
3129
+ };
3130
+ "size": {
3131
+ "alias": "size";
3132
+ "required": false;
3133
+ "isSignal": true;
3134
+ };
3135
+ "label": {
3136
+ "alias": "label";
3137
+ "required": false;
3138
+ "isSignal": true;
3139
+ };
3140
+ "ariaLabel": {
3141
+ "alias": "ariaLabel";
3142
+ "required": false;
3143
+ "isSignal": true;
3144
+ };
3145
+ "ariaLabelledby": {
3146
+ "alias": "ariaLabelledby";
3147
+ "required": false;
3148
+ "isSignal": true;
3149
+ };
3150
+ "placeholder": {
3151
+ "alias": "placeholder";
3152
+ "required": false;
3153
+ "isSignal": true;
3154
+ };
3155
+ "helpText": {
3156
+ "alias": "helpText";
3157
+ "required": false;
3158
+ "isSignal": true;
3159
+ };
3160
+ "errorMessage": {
3161
+ "alias": "errorMessage";
3162
+ "required": false;
3163
+ "isSignal": true;
3164
+ };
3165
+ "disabled": {
3166
+ "alias": "disabled";
3167
+ "required": false;
3168
+ "isSignal": true;
3169
+ };
3170
+ "readonly": {
3171
+ "alias": "readonly";
3172
+ "required": false;
3173
+ "isSignal": true;
3174
+ };
3175
+ "required": {
3176
+ "alias": "required";
3177
+ "required": false;
3178
+ "isSignal": true;
3179
+ };
3180
+ "invalid": {
3181
+ "alias": "invalid";
3182
+ "required": false;
3183
+ "isSignal": true;
3184
+ };
3185
+ "touched": {
3186
+ "alias": "touched";
3187
+ "required": false;
3188
+ "isSignal": true;
3189
+ };
3190
+ "errors": {
3191
+ "alias": "errors";
3192
+ "required": false;
3193
+ "isSignal": true;
3194
+ };
3195
+ "name": {
3196
+ "alias": "name";
3197
+ "required": false;
3198
+ "isSignal": true;
3199
+ };
3200
+ "id": {
3201
+ "alias": "id";
3202
+ "required": false;
3203
+ "isSignal": true;
3204
+ };
3205
+ }, {
3206
+ "value": "valueChange";
3207
+ "changed": "changed";
3208
+ "focused": "focused";
3209
+ "blurred": "blurred";
3210
+ "touch": "touch";
3211
+ }, never, never, true, never>;
3212
+ }
3213
+ /**
3214
+ * Makes the library's built-in selects use the styled `bf-select`: a stacked `bf-table` then
3215
+ * renders its Sort by select as a `bf-select` (the native `<select>` under a coarse pointer, as
3216
+ * `bf-select` itself does) instead of the plain native one. Add it to
3217
+ * `ApplicationConfig.providers`.
3218
+ *
3219
+ * @returns The providers that fill `BF_TABLE_SORT_SELECT` with `BfSelectComponent`.
3220
+ * @summary Makes a stacked table's Sort by select the styled bf-select, app-wide
3221
+ * @since 0.5.0
3222
+ */
3223
+ export declare function provideBfSelect(): EnvironmentProviders;
2780
3224
  /**
2781
3225
  * How `bf-date-input` picks a date besides typing: `calendar` adds a button that opens a
2782
3226
  * `bf-calendar` in a popover, `none` keeps the field typed only.
@@ -3399,4 +3843,248 @@ export declare class BfDateTimeInputComponent implements FormValueControl<string
3399
3843
  "touch": "touch";
3400
3844
  }, never, never, true, never>;
3401
3845
  }
3402
- export { type BfComboboxFilter, type BfComboboxOption, type BfConfirmButton, type BfConfirmButtonRole, type BfConfirmOptions, type BfConfirmSize, type BfDateInputPicker, type BfDateTimeInputPicker, type BfDesktopToastConfig, type BfDesktopToastOptions, type BfDesktopToastPosition, type BfDialogConfig, type BfDialogRole, type BfDialogSize, type BfDialogTemplateContext, type BfMenuButtonVariant, type BfMenuPlacement, type BfOverlayAutoFocus, type BfOverlayController, type BfOverlayHost, type BfOverlayOptions, type BfOverlayPlacement, type BfOverlayPosition, type BfOverlayRole, type BfOverlayStackOptions, type BfOverlayTemplateContext, type BfPopoverPlacement, type BfSidePanelConfig, type BfSidePanelTemplateContext, type BfSidePanelWidth, type BfStackedOverlay, type BfTimeInputHourCycle, type BfTimeInputPicker, type BfToastAction, type BfToastController, type BfToastDismissReason, type BfTooltipPlacement, type ɵBfToastHandle, type ɵBfToastPresenter, type ɵBfToastQueueOptions, type ɵBfToastRequest, type ɵBfToastView, labelPanelByHeading as ɵlabelPanelByHeading, watchPanelHeading as ɵwatchPanelHeading };
3846
+ /**
3847
+ * One image of a `BfImageViewerService.open()` set.
3848
+ *
3849
+ * @summary One image the viewer shows: its URL, its name as alternative text and a caption
3850
+ * @since 0.5.0
3851
+ */
3852
+ interface BfImageViewerImage {
3853
+ /** URL of the full-size image. */
3854
+ src: string;
3855
+ /**
3856
+ * The image's name: its alternative text (`alt`), read when it shows and announced after a step
3857
+ * (required: the viewer shows nothing else that names it).
3858
+ */
3859
+ label: string;
3860
+ /** Text shown under the image; none shows no caption. */
3861
+ caption?: string;
3862
+ }
3863
+ /**
3864
+ * Handle to an open image viewer, returned by `BfImageViewerService.open()` and injectable in
3865
+ * its actions template (`inject(BfImageViewerRef)`). `index` is the shown image; `next()`,
3866
+ * `previous()` and `goTo()` step through the set (wrapping at both ends), `close()` plays the
3867
+ * exit motion and resolves `afterClosed`.
3868
+ *
3869
+ * @example
3870
+ * const ref = inject(BfImageViewerService).open({ images, index: 2, origin: thumb });
3871
+ * ref.next();
3872
+ * await ref.afterClosed;
3873
+ * @summary Handle on an open image viewer that steps through its images and closes it
3874
+ * @since 0.5.0
3875
+ */
3876
+ export declare class BfImageViewerRef {
3877
+ private readonly overlayRef;
3878
+ /** Unique id of the viewer (its overlay's `bf-overlay-N`). */
3879
+ readonly id: string;
3880
+ /** The images of the set, in order. */
3881
+ readonly images: readonly BfImageViewerImage[];
3882
+ /** Resolves once the viewer has closed and left the page. */
3883
+ readonly afterClosed: Promise<void>;
3884
+ /** True once the viewer has been detached. */
3885
+ readonly closed: Signal<boolean>;
3886
+ private readonly current;
3887
+ /** Index (0-based) of the image the viewer shows. */
3888
+ readonly index: Signal<number>;
3889
+ /** @internal Created by `BfImageViewerService`; apps never construct it. */
3890
+ constructor(overlayRef: BfOverlayRef<unknown>, images: readonly BfImageViewerImage[], start: number);
3891
+ /** Shows the next image; after the last one, the first. */
3892
+ next(): void;
3893
+ /** Shows the previous image; before the first one, the last. */
3894
+ previous(): void;
3895
+ /**
3896
+ * Shows the image at `index`, wrapped into the set (`-1` is the last one).
3897
+ * @param index The 0-based index of the image to show.
3898
+ */
3899
+ goTo(index: number): void;
3900
+ /** Closes the viewer: it zooms back into its thumbnail, or fades out. Ignored once closing. */
3901
+ close(): void;
3902
+ }
3903
+ /**
3904
+ * Where the viewer zooms from and back to: the thumbnail that was clicked, or a function that
3905
+ * returns the thumbnail of any image of the set (so closing after stepping zooms into the right
3906
+ * one), `null` for none.
3907
+ *
3908
+ * @summary The thumbnail an image viewer zooms from and back into, or a lookup per image
3909
+ * @since 0.5.0
3910
+ */
3911
+ type BfImageViewerOrigin = HTMLElement | ((index: number) => HTMLElement | null | undefined) | null;
3912
+ /**
3913
+ * Context of the `actions` template of `BfImageViewerService.open()`: `let-image`,
3914
+ * `let-index="index"` and `let-ref="ref"`.
3915
+ *
3916
+ * @summary What the viewer's actions template receives: the shown image, its index and the ref
3917
+ * @since 0.5.0
3918
+ */
3919
+ interface BfImageViewerActionsContext {
3920
+ /** The image the viewer shows (`let-image`). */
3921
+ $implicit: BfImageViewerImage;
3922
+ /** Its 0-based index in the set (`let-index="index"`). */
3923
+ index: number;
3924
+ /** The viewer's ref (`let-ref="ref"`), to close it or step. */
3925
+ ref: BfImageViewerRef;
3926
+ }
3927
+ /** @internal What `BfImageViewerService` hands the `bf-image-viewer` it opens. */
3928
+ interface BfImageViewerContext {
3929
+ readonly start: number;
3930
+ /** The viewer's accessible name. */
3931
+ readonly label: string;
3932
+ readonly origin: BfImageViewerOrigin;
3933
+ readonly actions: TemplateRef<BfImageViewerActionsContext> | null;
3934
+ /** Called by the viewer as it is created, so the overlay's enter and exit can run its motion. */
3935
+ readonly register: (motion: BfImageViewerMotion) => void;
3936
+ }
3937
+ /** @internal The open and close motion of a `bf-image-viewer`. */
3938
+ interface BfImageViewerMotion {
3939
+ enter(): Animation;
3940
+ exit(): Animation;
3941
+ }
3942
+ /** @internal Provided by `BfImageViewerService` to the viewer it opens. */
3943
+ declare const BF_IMAGE_VIEWER_CONTEXT: InjectionToken<BfImageViewerContext>;
3944
+ /** How far one image got. */
3945
+ type ImageStatus = 'pending' | 'loaded' | 'error';
3946
+ /**
3947
+ * The full-screen image viewer (lightbox) `BfImageViewerService.open()` renders: one image large
3948
+ * over a dark scrim, with a counter, previous and next buttons, a close button, an optional
3949
+ * caption and actions. It opens with a zoom out of the clicked thumbnail and steps with a
3950
+ * cross-fade. Apps do not place it in templates; open it with the service.
3951
+ *
3952
+ * @example
3953
+ * const ref = inject(BfImageViewerService).open({
3954
+ * images: [{ src: '/art/1.jpg', label: 'Neon skyline', caption: 'Concept 1' }],
3955
+ * index: 0,
3956
+ * origin: thumbnailElement,
3957
+ * });
3958
+ * @summary Full-screen image viewer that zooms from a thumbnail and steps through a set
3959
+ * @category Overlays
3960
+ * @since 0.5.0
3961
+ */
3962
+ export declare class BfImageViewerComponent implements BfImageViewerMotion {
3963
+ protected readonly labels: import("@bitforgehq/ui").BfLabels;
3964
+ protected readonly ref: BfImageViewerRef;
3965
+ protected readonly context: BfImageViewerContext;
3966
+ protected readonly injector: Injector;
3967
+ private readonly document;
3968
+ private readonly host;
3969
+ protected readonly closeIcon: import("lucide").IconNode;
3970
+ protected readonly previousIcon: import("lucide").IconNode;
3971
+ protected readonly nextIcon: import("lucide").IconNode;
3972
+ protected readonly previousClasses = "pointer-events-auto absolute top-1/2 -translate-y-1/2 start-3";
3973
+ protected readonly nextClasses = "pointer-events-auto absolute top-1/2 -translate-y-1/2 end-3";
3974
+ private readonly frame;
3975
+ private readonly scrim;
3976
+ private readonly top;
3977
+ private readonly bottom;
3978
+ /** The progress of every image shown so far, by index. */
3979
+ private readonly statuses;
3980
+ /** The aspect ratio (width / height) of every image that has loaded, by index. */
3981
+ private readonly ratios;
3982
+ protected readonly count: import("@angular/core").Signal<number>;
3983
+ protected readonly index: import("@angular/core").Signal<number>;
3984
+ protected readonly image: import("@angular/core").Signal<BfImageViewerImage>;
3985
+ protected readonly status: import("@angular/core").Signal<ImageStatus>;
3986
+ /** The shown image, keyed by index so a step replaces the element (and cross-fades); none
3987
+ * once it failed, so the failure message is not drawn over a broken-image box. */
3988
+ protected readonly shown: import("@angular/core").Signal<{
3989
+ index: number;
3990
+ image: BfImageViewerImage;
3991
+ }[]>;
3992
+ protected readonly counter: import("@angular/core").Signal<string>;
3993
+ /** Announced politely after each step (never on open, where the dialog itself is read). */
3994
+ private readonly stepped;
3995
+ protected readonly announcement: import("@angular/core").Signal<string>;
3996
+ /** The thumbnail of the shown image, under it until the large one arrives. */
3997
+ protected readonly placeholder: import("@angular/core").Signal<string | null>;
3998
+ /** Width / height of the shown image: once loaded its own, before that its thumbnail's. */
3999
+ protected readonly ratio: import("@angular/core").Signal<number | null>;
4000
+ protected readonly frameClasses: import("@angular/core").Signal<"relative max-h-full max-w-full aspect-(--bf-image-viewer-ratio) w-[min(100cqw,calc(100cqh*var(--bf-image-viewer-ratio)))]" | "relative max-h-full max-w-full size-full">;
4001
+ protected readonly actionsContext: import("@angular/core").Signal<BfImageViewerActionsContext>;
4002
+ constructor();
4003
+ /** @internal Plays the open motion; called by `BfImageViewerService` as the overlay's enter. */
4004
+ enter(): Animation;
4005
+ /** @internal Plays the close motion; called by `BfImageViewerService` as the overlay's exit. */
4006
+ exit(): Animation;
4007
+ /** @internal An image loaded: it shows, and the frame takes its aspect ratio. */
4008
+ imageLoaded(event: Event, index: number): void;
4009
+ /** @internal An image failed: the frame shows the failure message. */
4010
+ imageFailed(index: number): void;
4011
+ /** @internal Arrow keys step (mirrored under rtl), Home and End jump to the ends. */
4012
+ keydown(event: KeyboardEvent): void;
4013
+ /** @internal A click on the scrim or around the image closes the viewer. */
4014
+ clicked(event: MouseEvent): void;
4015
+ /** The thumbnail of image `index`, when the opener gave one. */
4016
+ private originFor;
4017
+ private parts;
4018
+ private reduced;
4019
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfImageViewerComponent, never>;
4020
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfImageViewerComponent, "bf-image-viewer", never, {}, {}, never, never, true, never>;
4021
+ }
4022
+ /**
4023
+ * Options of `BfImageViewerService.open()`.
4024
+ *
4025
+ * @summary Options of an image viewer: its images, the first one, its thumbnail and actions
4026
+ * @since 0.5.0
4027
+ */
4028
+ interface BfImageViewerOptions {
4029
+ /** The images to step through, in order; at least one. */
4030
+ images: readonly BfImageViewerImage[];
4031
+ /**
4032
+ * Index of the image shown first, wrapped into the set.
4033
+ * @default 0
4034
+ */
4035
+ index?: number;
4036
+ /**
4037
+ * The thumbnail the viewer zooms out of and back into (or a function returning the thumbnail
4038
+ * of an image by index); none fades the viewer in and out.
4039
+ */
4040
+ origin?: BfImageViewerOrigin;
4041
+ /**
4042
+ * Actions under the image, beside its caption (a download link, a "Use this one" button); its
4043
+ * context is `{ $implicit: image, index, ref }`.
4044
+ */
4045
+ actions?: TemplateRef<BfImageViewerActionsContext>;
4046
+ /** Accessible name of the viewer; empty uses `provideBfLabels()`'s `imageViewer`. */
4047
+ ariaLabel?: string;
4048
+ /**
4049
+ * A navigation to another URL path closes the viewer (default true).
4050
+ * @default true
4051
+ */
4052
+ closeOnNavigation?: boolean;
4053
+ /**
4054
+ * Parent of the viewer's injector and source of its labels (default the root injector). Pass
4055
+ * the opener's `inject(Injector)` so a feature-level `provideBfLabels()` reaches the viewer.
4056
+ */
4057
+ injector?: Injector;
4058
+ }
4059
+ /**
4060
+ * Opens a full-screen image viewer (a lightbox) on the overlay core: one image large over a dark
4061
+ * scrim, previous and next buttons, the arrow keys, Home and End to step through the set
4062
+ * (wrapping at both ends), a counter, the caption and optional actions. It zooms out of the
4063
+ * clicked thumbnail (`origin`) and back into it, cross-fades between images, and fades when there
4064
+ * is no thumbnail on screen; reduced motion only fades. It is a modal dialog: focus moves to its
4065
+ * close button and is trapped, `Escape`, the close button and a click on the scrim close it, the
4066
+ * page behind it is `inert` and does not scroll, and focus returns to the opener.
4067
+ *
4068
+ * @example
4069
+ * const ref = inject(BfImageViewerService).open({
4070
+ * images: shots.map((s) => ({ src: s.full, label: s.alt, caption: s.title })),
4071
+ * index: 2,
4072
+ * origin: (i) => thumbnails[i],
4073
+ * });
4074
+ * await ref.afterClosed;
4075
+ * @summary Opens a full-screen image viewer that zooms from a thumbnail and steps through a set
4076
+ * @since 0.5.0
4077
+ */
4078
+ export declare class BfImageViewerService {
4079
+ private readonly overlays;
4080
+ private readonly injector;
4081
+ /**
4082
+ * Opens the viewer on `options.images`, showing `options.index` first.
4083
+ * @param options The images, the first index, the thumbnail, the actions and the injector.
4084
+ * @returns The viewer's ref.
4085
+ */
4086
+ open(options: BfImageViewerOptions): BfImageViewerRef;
4087
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfImageViewerService, never>;
4088
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
4089
+ }
4090
+ export { type BfComboboxFilter, type BfComboboxOption, type BfConfirmButton, type BfConfirmButtonRole, type BfConfirmOptions, type BfConfirmSize, type BfDateInputPicker, type BfDateTimeInputPicker, type BfDesktopToastConfig, type BfDesktopToastOptions, type BfDesktopToastPosition, type BfDialogConfig, type BfDialogRole, type BfDialogSize, type BfDialogTemplateContext, type BfImageViewerActionsContext, type BfImageViewerImage, type BfImageViewerOptions, type BfImageViewerOrigin, type BfMenuButtonVariant, type BfMenuPlacement, type BfOverlayAutoFocus, type BfOverlayController, type BfOverlayHost, type BfOverlayOptions, type BfOverlayPlacement, type BfOverlayPosition, type BfOverlayRole, type BfOverlayStackOptions, type BfOverlayTemplateContext, type BfPopoverPlacement, type BfSelectOption, type BfSidePanelConfig, type BfSidePanelTemplateContext, type BfSidePanelWidth, type BfStackedOverlay, type BfTimeInputHourCycle, type BfTimeInputPicker, type BfToastAction, type BfToastController, type BfToastDismissReason, type BfTooltipPlacement, type ɵBfToastHandle, type ɵBfToastPresenter, type ɵBfToastQueueOptions, type ɵBfToastRequest, type ɵBfToastView, labelPanelByHeading as ɵlabelPanelByHeading, watchPanelHeading as ɵwatchPanelHeading };