@bitforgehq/ui 0.3.0 → 0.3.1

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 (144) hide show
  1. package/CHANGELOG.md +482 -0
  2. package/README.md +17 -11
  3. package/ai/MANIFEST.index.json +288 -0
  4. package/ai/MANIFEST.json +8716 -3926
  5. package/ai/REFERENCE.index.json +413 -0
  6. package/ai/REFERENCE.json +4710 -2047
  7. package/ai/UI_GUIDE.md +185 -57
  8. package/ai/components/back-button.md +42 -2
  9. package/ai/components/badge.md +17 -7
  10. package/ai/components/bar-chart.md +188 -0
  11. package/ai/components/breadcrumb-item.md +121 -0
  12. package/ai/components/breadcrumb.md +277 -0
  13. package/ai/components/button.md +82 -15
  14. package/ai/components/calendar.md +300 -0
  15. package/ai/components/card.md +63 -2
  16. package/ai/components/chart-card.md +283 -0
  17. package/ai/components/combobox.md +411 -0
  18. package/ai/components/date-input.md +396 -0
  19. package/ai/components/datetime-input.md +215 -0
  20. package/ai/components/description-item.md +111 -0
  21. package/ai/components/description-list.md +160 -0
  22. package/ai/components/donut-chart.md +169 -0
  23. package/ai/components/header.md +67 -2
  24. package/ai/components/icon-button.md +74 -16
  25. package/ai/components/icon.md +63 -7
  26. package/ai/components/line-chart.md +234 -0
  27. package/ai/components/list.md +70 -6
  28. package/ai/components/menu.md +5 -0
  29. package/ai/components/multi-combobox.md +257 -0
  30. package/ai/components/nav-group.md +178 -0
  31. package/ai/components/nav-item.md +210 -0
  32. package/ai/components/page-header.md +237 -0
  33. package/ai/components/pagination.md +173 -0
  34. package/ai/components/popover.md +250 -0
  35. package/ai/components/side-panel.md +391 -0
  36. package/ai/components/sidebar.md +363 -0
  37. package/ai/components/skeleton.md +215 -0
  38. package/ai/components/sparkline.md +188 -0
  39. package/ai/components/stat.md +233 -0
  40. package/ai/components/tab-group.md +226 -0
  41. package/ai/components/tab-panel.md +163 -0
  42. package/ai/components/table.md +568 -0
  43. package/ai/components/tabs.md +42 -2
  44. package/ai/components/theme-menu-button.md +182 -0
  45. package/ai/components/theme-switch.md +170 -0
  46. package/ai/components/time-input.md +240 -0
  47. package/ai/components/toolbar.md +289 -0
  48. package/ai/components/tooltip.md +230 -0
  49. package/ai/components/top-nav.md +159 -0
  50. package/ai/reference/bf-badge-appearance.md +36 -0
  51. package/ai/reference/bf-badge-variant.md +1 -1
  52. package/ai/reference/bf-bar-chart-orientation.md +27 -0
  53. package/ai/reference/bf-button-appearance.md +36 -0
  54. package/ai/reference/bf-button-variant.md +1 -1
  55. package/ai/reference/bf-calendar-disabled-date.md +23 -0
  56. package/ai/reference/bf-calendar-harness.md +51 -0
  57. package/ai/reference/bf-calendar-weekday.md +31 -0
  58. package/ai/reference/bf-chart-card-heading-level.md +26 -0
  59. package/ai/reference/bf-chart-curve.md +28 -0
  60. package/ai/reference/bf-chart-harness.md +51 -0
  61. package/ai/reference/bf-chart-legend-position.md +30 -0
  62. package/ai/reference/bf-chart-series.md +23 -0
  63. package/ai/reference/bf-chart-value-format.md +23 -0
  64. package/ai/reference/bf-color-scheme-service.md +30 -0
  65. package/ai/reference/bf-color-scheme.md +31 -0
  66. package/ai/reference/bf-combobox-filter.md +27 -0
  67. package/ai/reference/bf-combobox-harness.md +89 -0
  68. package/ai/reference/bf-combobox-option.md +33 -0
  69. package/ai/reference/bf-compare-with.md +2 -0
  70. package/ai/reference/bf-date-input-harness.md +67 -0
  71. package/ai/reference/bf-date-input-picker.md +27 -0
  72. package/ai/reference/bf-date-time-input-harness.md +76 -0
  73. package/ai/reference/bf-date-time-input-picker.md +27 -0
  74. package/ai/reference/bf-description-list-layout.md +26 -0
  75. package/ai/reference/bf-donut-slice.md +22 -0
  76. package/ai/reference/bf-labels.md +67 -20
  77. package/ai/reference/bf-menu-button-variant.md +1 -0
  78. package/ai/reference/bf-menu-placement.md +1 -0
  79. package/ai/reference/bf-overlay-options.md +28 -27
  80. package/ai/reference/bf-overlay-placement.md +34 -0
  81. package/ai/reference/bf-overlay-position.md +1 -1
  82. package/ai/reference/bf-overlay-service.md +5 -3
  83. package/ai/reference/bf-page-header-heading-level.md +26 -0
  84. package/ai/reference/bf-pagination-harness.md +61 -0
  85. package/ai/reference/bf-platform-service.md +17 -15
  86. package/ai/reference/bf-popover-harness.md +42 -0
  87. package/ai/reference/bf-popover-placement.md +28 -0
  88. package/ai/reference/bf-popover-trigger-directive.md +56 -0
  89. package/ai/reference/bf-side-panel-config.md +35 -0
  90. package/ai/reference/bf-side-panel-harness.md +34 -0
  91. package/ai/reference/bf-side-panel-ref.md +44 -0
  92. package/ai/reference/bf-side-panel-service.md +43 -0
  93. package/ai/reference/bf-side-panel-template-context.md +32 -0
  94. package/ai/reference/bf-side-panel-width.md +28 -0
  95. package/ai/reference/bf-size.md +12 -0
  96. package/ai/reference/bf-skeleton-shape.md +28 -0
  97. package/ai/reference/bf-stat-trend-intent.md +27 -0
  98. package/ai/reference/bf-stat-trend.md +27 -0
  99. package/ai/reference/bf-stat-variant.md +26 -0
  100. package/ai/reference/bf-tab-group-harness.md +44 -0
  101. package/ai/reference/bf-table-align.md +26 -0
  102. package/ai/reference/bf-table-cell-context.md +24 -0
  103. package/ai/reference/bf-table-cell-directive.md +22 -0
  104. package/ai/reference/bf-table-column.md +28 -0
  105. package/ai/reference/bf-table-harness.md +77 -0
  106. package/ai/reference/bf-table-row-key.md +21 -0
  107. package/ai/reference/bf-table-sort-direction.md +26 -0
  108. package/ai/reference/bf-table-sort.md +27 -0
  109. package/ai/reference/bf-theme.md +5 -4
  110. package/ai/reference/bf-time-input-harness.md +67 -0
  111. package/ai/reference/bf-time-input-hour-cycle.md +27 -0
  112. package/ai/reference/bf-time-input-picker.md +27 -0
  113. package/ai/reference/bf-tooltip-directive.md +43 -0
  114. package/ai/reference/bf-tooltip-harness.md +43 -0
  115. package/ai/reference/bf-tooltip-placement.md +28 -0
  116. package/ai/reference/bf_color_scheme_storage.md +20 -0
  117. package/ai/reference/bf_side_panel_data.md +17 -0
  118. package/ai/reference/bf_theme_storage.md +3 -1
  119. package/ai/reference/provide-bf-color-scheme.md +20 -0
  120. package/ai/reference/provide-bf-labels.md +12 -4
  121. package/ai/reference/slide-in-from-end.md +24 -0
  122. package/ai/reference/slide-out-to-end.md +24 -0
  123. package/fesm2022/bitforgehq-ui-charts.mjs +3045 -0
  124. package/fesm2022/bitforgehq-ui-charts.mjs.map +1 -0
  125. package/fesm2022/bitforgehq-ui-icons.mjs +107 -3
  126. package/fesm2022/bitforgehq-ui-icons.mjs.map +1 -1
  127. package/fesm2022/bitforgehq-ui-mobile.mjs +14 -59
  128. package/fesm2022/bitforgehq-ui-mobile.mjs.map +1 -1
  129. package/fesm2022/bitforgehq-ui-overlay.mjs +6436 -33
  130. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
  131. package/fesm2022/bitforgehq-ui-testing.mjs +618 -1
  132. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  133. package/fesm2022/bitforgehq-ui.mjs +5092 -153
  134. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  135. package/llms-full.txt +25177 -14398
  136. package/llms.txt +95 -1
  137. package/package.json +7 -3
  138. package/theme.css +101 -0
  139. package/types/bitforgehq-ui-charts.d.ts +967 -0
  140. package/types/bitforgehq-ui-icons.d.ts +13 -1
  141. package/types/bitforgehq-ui-mobile.d.ts +25 -18
  142. package/types/bitforgehq-ui-overlay.d.ts +1844 -7
  143. package/types/bitforgehq-ui-testing.d.ts +748 -1
  144. package/types/bitforgehq-ui.d.ts +2136 -44
@@ -1,5 +1,5 @@
1
1
  import * as i0 from "@angular/core";
2
- import { ElementRef, EnvironmentProviders, InjectionToken, Provider, Signal } from "@angular/core";
2
+ import { ElementRef, EnvironmentProviders, InjectionToken, Provider, Signal, TemplateRef } from "@angular/core";
3
3
  import { FormCheckboxControl, FormValueControl, ValidationError } from "@angular/forms/signals";
4
4
  /**
5
5
  * The one control-height scale: sm 32 px, md 40 px, lg 48 px.
@@ -201,7 +201,7 @@ interface BfLabels {
201
201
  */
202
202
  readonly refreshing: string;
203
203
  /**
204
- * bf-dialog's close button, and bf-sheet's screen-reader Close.
204
+ * bf-dialog's and bf-side-panel's close button, and bf-sheet's screen-reader Close.
205
205
  * @default 'Close'
206
206
  */
207
207
  readonly close: string;
@@ -222,7 +222,7 @@ interface BfLabels {
222
222
  */
223
223
  readonly sheetPosition: (position: number, count: number) => string;
224
224
  /**
225
- * A dialog's name without an ariaLabel, a bf-dialog title or a heading.
225
+ * A dialog's or side panel's name without an ariaLabel, a title or a heading.
226
226
  * @default 'Dialog'
227
227
  */
228
228
  readonly dialog: string;
@@ -231,6 +231,252 @@ interface BfLabels {
231
231
  * @default 'Notifications'
232
232
  */
233
233
  readonly notifications: string;
234
+ /**
235
+ * bf-table's header checkbox, which selects or clears every row.
236
+ * @default 'Select all rows'
237
+ */
238
+ readonly tableSelectAll: string;
239
+ /**
240
+ * bf-theme-switch's and bf-theme-menu-button's name without a label.
241
+ * @default 'Theme'
242
+ */
243
+ readonly theme: string;
244
+ /**
245
+ * The theme choice that follows the system's colour scheme.
246
+ * @default 'System'
247
+ */
248
+ readonly themeSystem: string;
249
+ /**
250
+ * The theme choice that forces the light colour scheme.
251
+ * @default 'Light'
252
+ */
253
+ readonly themeLight: string;
254
+ /**
255
+ * The theme choice that forces the dark colour scheme.
256
+ * @default 'Dark'
257
+ */
258
+ readonly themeDark: string;
259
+ /**
260
+ * bf-breadcrumb's navigation name.
261
+ * @default 'Breadcrumb'
262
+ */
263
+ readonly breadcrumb: string;
264
+ /**
265
+ * bf-breadcrumb's ellipsis button, which shows the levels a `maxItems` trail hides.
266
+ * @default (count) => (count === 1 ? 'Show 1 more level' : `Show ${count} more levels`)
267
+ */
268
+ readonly breadcrumbExpand: (count: number) => string;
269
+ /**
270
+ * bf-sidebar's and bf-top-nav's navigation name.
271
+ * @default 'Main'
272
+ */
273
+ readonly navigation: string;
274
+ /**
275
+ * a[bfNavItem]'s announcement of its count badge.
276
+ * @default (count) => `${count} new`
277
+ */
278
+ readonly navBadge: (count: number) => string;
279
+ /**
280
+ * bf-pagination's navigation name.
281
+ * @default 'Pagination'
282
+ */
283
+ readonly pagination: string;
284
+ /**
285
+ * bf-pagination's button to the previous page.
286
+ * @default 'Previous page'
287
+ */
288
+ readonly previousPage: string;
289
+ /**
290
+ * bf-pagination's button to the next page.
291
+ * @default 'Next page'
292
+ */
293
+ readonly nextPage: string;
294
+ /**
295
+ * bf-pagination's compact position text, such as "Page 3 of 12".
296
+ * @default (page, count) => `Page ${page} of ${count}`
297
+ */
298
+ readonly pageOf: (page: number, count: number) => string;
299
+ /**
300
+ * bf-pagination's name of one page button, such as "Page 3".
301
+ * @default (page) => `Page ${page}`
302
+ */
303
+ readonly goToPage: (page: number) => string;
304
+ /**
305
+ * bf-tab-group's tablist name.
306
+ * @default 'Tabs'
307
+ */
308
+ readonly tabGroup: string;
309
+ /**
310
+ * bf-calendar's button that shows the previous month.
311
+ * @default 'Previous month'
312
+ */
313
+ readonly calendarPreviousMonth: string;
314
+ /**
315
+ * bf-calendar's button that shows the next month.
316
+ * @default 'Next month'
317
+ */
318
+ readonly calendarNextMonth: string;
319
+ /**
320
+ * bf-calendar's title button in the day view, which opens the month view; read after the
321
+ * visible month and year.
322
+ * @default 'Choose month'
323
+ */
324
+ readonly calendarChooseMonth: string;
325
+ /**
326
+ * bf-calendar's title button in the month view, which opens the year view; read after the
327
+ * visible year.
328
+ * @default 'Choose year'
329
+ */
330
+ readonly calendarChooseYear: string;
331
+ /**
332
+ * bf-stat's hidden direction word before an upward delta, so colour is never the only signal.
333
+ * @default 'Up'
334
+ */
335
+ readonly statTrendUp: string;
336
+ /**
337
+ * bf-stat's hidden direction word before a downward delta.
338
+ * @default 'Down'
339
+ */
340
+ readonly statTrendDown: string;
341
+ /**
342
+ * bf-stat's hidden direction word before an unchanged (flat) delta.
343
+ * @default 'No change'
344
+ */
345
+ readonly statTrendFlat: string;
346
+ /**
347
+ * bf-combobox's and bf-multi-combobox's list row when no option matches the typed text.
348
+ * @default 'No results'
349
+ */
350
+ readonly comboboxEmpty: string;
351
+ /**
352
+ * bf-multi-combobox's remove button on a picked value's tag.
353
+ * @default (label) => `Remove ${label}`
354
+ */
355
+ readonly comboboxRemove: (label: string) => string;
356
+ /**
357
+ * The day part of bf-date-input and bf-datetime-input; its first letter is the part's
358
+ * placeholder ("dd").
359
+ * @default 'Day'
360
+ */
361
+ readonly dateInputDay: string;
362
+ /**
363
+ * The month part of bf-date-input and bf-datetime-input; its first letter is the part's
364
+ * placeholder ("mm").
365
+ * @default 'Month'
366
+ */
367
+ readonly dateInputMonth: string;
368
+ /**
369
+ * The year part of bf-date-input and bf-datetime-input; its first letter is the part's
370
+ * placeholder ("yyyy").
371
+ * @default 'Year'
372
+ */
373
+ readonly dateInputYear: string;
374
+ /**
375
+ * The button of bf-date-input and bf-datetime-input that opens the calendar, and the panel's name.
376
+ * @default 'Choose date'
377
+ */
378
+ readonly dateInputOpenCalendar: string;
379
+ /**
380
+ * The error of bf-date-input and bf-datetime-input while the date is incomplete or does not
381
+ * exist (31 February).
382
+ * @default 'Enter a valid date'
383
+ */
384
+ readonly dateInputInvalid: string;
385
+ /**
386
+ * The error of bf-date-input and bf-datetime-input for a typed date that `disabledDate` rules out.
387
+ * @default 'This date is not available'
388
+ */
389
+ readonly dateInputUnavailable: string;
390
+ /**
391
+ * The hour part of bf-time-input and bf-datetime-input; its first letter is the part's
392
+ * placeholder ("hh").
393
+ * @default 'Hour'
394
+ */
395
+ readonly timeInputHour: string;
396
+ /**
397
+ * The minute part of bf-time-input and bf-datetime-input; its first letter is the part's
398
+ * placeholder ("mm").
399
+ * @default 'Minute'
400
+ */
401
+ readonly timeInputMinute: string;
402
+ /**
403
+ * The second part of bf-time-input with `seconds`; its first letter is the part's placeholder
404
+ * ("ss").
405
+ * @default 'Second'
406
+ */
407
+ readonly timeInputSecond: string;
408
+ /**
409
+ * The AM/PM part of bf-time-input and bf-datetime-input under a 12-hour clock.
410
+ * @default 'AM/PM'
411
+ */
412
+ readonly timeInputDayPeriod: string;
413
+ /**
414
+ * The button of bf-time-input that opens the list of times, and the list's name.
415
+ * @default 'Choose time'
416
+ */
417
+ readonly timeInputOpenList: string;
418
+ /**
419
+ * The error of bf-time-input and bf-datetime-input while the time is incomplete.
420
+ * @default 'Enter a valid time'
421
+ */
422
+ readonly timeInputInvalid: string;
423
+ /**
424
+ * The error of bf-time-input and bf-datetime-input below `min`, given the limit as the locale
425
+ * writes it.
426
+ * @default (time) => `Pick ${time} or later`
427
+ */
428
+ readonly timeInputMin: (time: string) => string;
429
+ /**
430
+ * The error of bf-time-input and bf-datetime-input above `max`, given the limit as the locale
431
+ * writes it.
432
+ * @default (time) => `Pick ${time} or earlier`
433
+ */
434
+ readonly timeInputMax: (time: string) => string;
435
+ /**
436
+ * The name of a chart from `@bitforgehq/ui/charts` that has no `label` (and no `bf-chart-card` title).
437
+ * @default 'Chart'
438
+ */
439
+ readonly chart: string;
440
+ /**
441
+ * The name of a chart's legend, the group of buttons that show and hide its series.
442
+ * @default 'Legend'
443
+ */
444
+ readonly chartLegend: string;
445
+ /**
446
+ * The name of a chart's plot, the focusable area whose arrow keys move between the values.
447
+ * @default 'Data points, arrow keys move between them'
448
+ */
449
+ readonly chartValues: string;
450
+ /**
451
+ * A chart's button that shows its data as a table.
452
+ * @default 'Show data'
453
+ */
454
+ readonly chartShowData: string;
455
+ /**
456
+ * A chart's button that hides its data table again.
457
+ * @default 'Hide data'
458
+ */
459
+ readonly chartHideData: string;
460
+ /**
461
+ * The first column header of a chart's data table.
462
+ * @default 'Category'
463
+ */
464
+ readonly chartCategory: string;
465
+ /**
466
+ * The value column header of a bf-donut-chart's data table.
467
+ * @default 'Value'
468
+ */
469
+ readonly chartValue: string;
470
+ /**
471
+ * bf-chart-card's text when it has no data and no `empty` slot.
472
+ * @default 'No data to show'
473
+ */
474
+ readonly chartEmpty: string;
475
+ /**
476
+ * bf-chart-card's text when its data failed to load and it has no `error` slot.
477
+ * @default 'The data could not be loaded'
478
+ */
479
+ readonly chartError: string;
234
480
  /** Default error text per validator kind (see `BfValidationMessages`). */
235
481
  readonly validation: BfValidationMessages;
236
482
  }
@@ -261,10 +507,18 @@ export declare const BF_LABELS: InjectionToken<BfLabels>;
261
507
  * Replaces built-in strings, merged over the parent's (validation merged key by key); a key left
262
508
  * out or set to `undefined` keeps the parent's string. In `ApplicationConfig.providers` it covers
263
509
  * every string. In a component's `providers` it covers that sub-tree's widgets and form controls
264
- * (`loading`, `dismiss`, `tabBar`, `tabBadge`, `back`, `refreshing`, `validation`); the overlay
265
- * services (`ok`, `cancel`, `actions`, `sheet`, `modal`, `close`, `expand`, `collapse`,
266
- * `sheetPosition`, `dialog`, `notifications`) are
267
- * root singletons and pick it up only when the caller passes its injector:
510
+ * (`loading`, `dismiss`, `tabBar`, `tabBadge`, `back`, `refreshing`, `tableSelectAll`, `theme`,
511
+ * `themeSystem`, `themeLight`, `themeDark`, `breadcrumb`, `breadcrumbExpand`, `navigation`,
512
+ * `navBadge`, `pagination`, `previousPage`, `nextPage`, `pageOf`, `goToPage`, `tabGroup`,
513
+ * `calendarPreviousMonth`, `calendarNextMonth`, `calendarChooseMonth`, `calendarChooseYear`,
514
+ * `statTrendUp`, `statTrendDown`, `statTrendFlat`, `comboboxEmpty`, `comboboxRemove`,
515
+ * `dateInputDay`, `dateInputMonth`, `dateInputYear`, `dateInputOpenCalendar`, `dateInputInvalid`,
516
+ * `dateInputUnavailable`, `timeInputHour`, `timeInputMinute`, `timeInputSecond`,
517
+ * `timeInputDayPeriod`, `timeInputOpenList`, `timeInputInvalid`, `timeInputMin`, `timeInputMax`,
518
+ * `chart`, `chartLegend`, `chartValues`, `chartShowData`, `chartHideData`, `chartCategory`,
519
+ * `chartValue`, `chartEmpty`, `chartError`, `validation`); the overlay services (`ok`, `cancel`,
520
+ * `actions`, `sheet`, `modal`, `close`, `expand`, `collapse`, `sheetPosition`, `dialog`,
521
+ * `notifications`) are root singletons and pick it up only when the caller passes its injector:
268
522
  * `open(…, { injector: inject(Injector) })`.
269
523
  *
270
524
  * @param overrides The strings to replace; any key left out keeps the parent's.
@@ -273,6 +527,87 @@ export declare const BF_LABELS: InjectionToken<BfLabels>;
273
527
  * @since 0.3.0
274
528
  */
275
529
  export declare function provideBfLabels(overrides: BfLabelsOverrides): Provider;
530
+ /**
531
+ * The app's colour scheme choice: follow the system, or force light or dark.
532
+ *
533
+ * @summary The colour scheme choice, following the system or forcing light or dark
534
+ * @since 0.3.1
535
+ */
536
+ type BfColorScheme = 'system' | 'light' | 'dark';
537
+ /** The key-value store the choice is kept in: `getItem`/`setItem` of the Web Storage API. */
538
+ type BfColorSchemeStorage = Pick<Storage, 'getItem' | 'setItem'>;
539
+ /**
540
+ * A store in memory, gone with the app: where `localStorage` is unavailable, and in tests.
541
+ * Internal: `provideBfShellTesting()` (`@bitforgehq/ui/mobile`) uses it through
542
+ * `ɵcreateMemoryColorSchemeStorage`.
543
+ */
544
+ declare function createMemoryColorSchemeStorage(): BfColorSchemeStorage;
545
+ /**
546
+ * Where `BfColorSchemeService` keeps the colour scheme choice (the key `bf-theme`): `localStorage`
547
+ * when it is available, otherwise an in-memory map. Provide another store (a native preferences
548
+ * plugin, or an in-memory one in tests) to keep the choice elsewhere. `BF_THEME_STORAGE` from
549
+ * `@bitforgehq/ui/mobile` is this same token.
550
+ *
551
+ * @example
552
+ * providers: [{ provide: BF_COLOR_SCHEME_STORAGE, useValue: sessionStorage }]
553
+ * @summary Injection token for the store that keeps the colour scheme choice between visits
554
+ * @since 0.3.1
555
+ */
556
+ export declare const BF_COLOR_SCHEME_STORAGE: InjectionToken<Pick<Storage, "getItem" | "setItem">>;
557
+ /**
558
+ * The app's colour scheme: the user's choice (system, light, dark), kept in
559
+ * `BF_COLOR_SCHEME_STORAGE` under `bf-theme`, and whether the app is dark now. With
560
+ * `provideBfColorScheme()` (or `provideBfShell()` in a Capacitor app) it toggles the `dark` class
561
+ * on `<html>` and stores every change; `prefers-color-scheme` is the source under `system` and is
562
+ * followed live. Without either, the signals still compute but nothing is written, so a page that
563
+ * merely injects the service never fights the host page's own theme. Storage and the media query are read in the browser only, so a server render
564
+ * starts at `system`, light, and writes nothing. No Capacitor: a desktop web app uses it as is,
565
+ * and the shell's `BfPlatformService.theme` and `dark` are these same signals.
566
+ *
567
+ * @example
568
+ * private readonly colorScheme = inject(BfColorSchemeService);
569
+ * toggle(): void { this.colorScheme.scheme.set(this.colorScheme.dark() ? 'light' : 'dark'); }
570
+ * @summary The app colour scheme choice and dark state, applied to html and stored
571
+ * @since 0.3.1
572
+ */
573
+ export declare class BfColorSchemeService {
574
+ private readonly document;
575
+ private readonly storage;
576
+ private readonly injector;
577
+ private readonly browser;
578
+ /** The user's choice, stored when `provideBfColorScheme()` is provided; set it with
579
+ * `scheme.set(…)`. */
580
+ readonly scheme: import("@angular/core").WritableSignal<BfColorScheme>;
581
+ private readonly prefersDark;
582
+ /** Whether the system prefers dark (`prefers-color-scheme: dark`), followed live. */
583
+ readonly systemDark: Signal<boolean>;
584
+ /** Whether the app is dark now: the choice, or the system's under `system`. */
585
+ readonly dark: Signal<boolean>;
586
+ private claimed;
587
+ constructor();
588
+ /**
589
+ * Makes this service own `<html>` and the store, once: called by `provideBfColorScheme()` and
590
+ * by the shell's `BfPlatformService`. Nothing is written on the server.
591
+ * @internal
592
+ */
593
+ claimDocument(): void;
594
+ private followSystem;
595
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfColorSchemeService, never>;
596
+ static ɵprov: i0.ɵɵInjectableDeclaration<any>;
597
+ }
598
+ /**
599
+ * Lets `BfColorSchemeService` own the app's colour scheme: it toggles `dark` on `<html>`, follows
600
+ * `prefers-color-scheme` under `system` and stores the choice (key `bf-theme`). For a desktop web
601
+ * app; a Capacitor app gets it from `provideBfShell()`. Add it to `ApplicationConfig.providers`
602
+ * and switch with `inject(BfColorSchemeService).scheme.set('dark')`.
603
+ *
604
+ * @example
605
+ * export const appConfig: ApplicationConfig = { providers: [provideBfColorScheme()] };
606
+ * @returns The providers that make the service own `<html>` and start it with the app.
607
+ * @summary Applies the stored colour scheme choice to html, for desktop web apps
608
+ * @since 0.3.1
609
+ */
610
+ export declare function provideBfColorScheme(): EnvironmentProviders;
276
611
  /**
277
612
  * The diameter of a `bf-spinner`: sm, md or lg.
278
613
  *
@@ -333,6 +668,15 @@ export declare class BfSpinnerComponent {
333
668
  * @since 0.1.0
334
669
  */
335
670
  type BfButtonVariant = 'primary' | 'tonal' | 'outline' | 'text' | 'danger';
671
+ /**
672
+ * Every value the `variant` input of a `bf-button` takes: the five `BfButtonVariant` styles plus
673
+ * `ghost`, the quiet neutral one. A new type, so `Record`s and exhaustive switches over
674
+ * `BfButtonVariant` keep compiling.
675
+ *
676
+ * @summary Every button style, the five variants plus the quiet neutral ghost
677
+ * @since 0.3.1
678
+ */
679
+ type BfButtonAppearance = BfButtonVariant | 'ghost';
336
680
  /**
337
681
  * The height step of a `bf-button`; the same scale as every sized widget.
338
682
  *
@@ -352,14 +696,15 @@ type BfButtonType = 'button' | 'submit' | 'reset';
352
696
  * the internal `ɵBF_BUTTON_CLASSES` export so the two never drift. */
353
697
  declare const BUTTON_CLASSES: {
354
698
  readonly base: string;
355
- readonly variant: Record<BfButtonVariant, string>;
356
- readonly pressed: Record<BfButtonVariant, string>;
699
+ readonly variant: Record<BfButtonAppearance, string>;
700
+ readonly pressed: Record<BfButtonAppearance, string>;
701
+ readonly current: Record<BfButtonAppearance, string>;
357
702
  readonly size: Record<BfSize, string>;
358
703
  readonly padding: Record<BfSize, string>;
359
704
  readonly textPadding: Record<BfSize, string>;
360
705
  };
361
706
  /**
362
- * Pill-shaped action button with five variants, three sizes, a loading state and icon slots. Put
707
+ * Pill-shaped action button with six variants, three sizes, a loading state and icon slots. Put
363
708
  * the label in the default slot and icons in the `icon-start` / `icon-end` slots; never place a
364
709
  * `bf-button` inside another interactive element. For navigation, put `bfButton` on your own `<a>`
365
710
  * (with `href` or `routerLink`): it renders as a real link that looks like the button.
@@ -371,6 +716,7 @@ declare const BUTTON_CLASSES: {
371
716
  * New task
372
717
  * </bf-button>
373
718
  * <a bfButton variant="outline" routerLink="/projects">All projects</a>
719
+ * <a bfButton variant="ghost" routerLink="/inbox" routerLinkActive ariaCurrentWhenActive="page">Inbox</a>
374
720
  * @summary Pill-shaped action button with five variants, three sizes and a loading state
375
721
  * @category Actions
376
722
  * @since 0.1.0
@@ -379,8 +725,9 @@ declare const BUTTON_CLASSES: {
379
725
  * @slot icon-end An icon after the label.
380
726
  */
381
727
  export declare class BfButtonComponent {
382
- /** Visual style: primary (filled), tonal (soft tint), outline, text, danger. */
383
- readonly variant: import("@angular/core").InputSignal<BfButtonVariant>;
728
+ /** Visual style: primary (filled), tonal (soft tint), outline, text, danger, or ghost (quiet
729
+ * neutral). On `a[bfButton]`, `ghost`, `text` and `outline` also show `aria-current="page"`. */
730
+ readonly variant: import("@angular/core").InputSignal<BfButtonAppearance>;
384
731
  /** Height step: sm 32, md 40, lg 48 px; unset follows `provideBfDefaults()` (`controlSize`,
385
732
  * `md` by default). */
386
733
  readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
@@ -471,12 +818,17 @@ declare const ICON_BUTTON_CLASSES: {
471
818
  };
472
819
  /**
473
820
  * Round button that holds a single icon, for toolbars, headers and list rows. The `label` is
474
- * required because the icon alone gives assistive tech no name.
821
+ * required because the icon alone gives assistive tech no name. For navigation, put
822
+ * `bfIconButton` on your own `<a>` (with `href` or `routerLink`): it renders as a real link that
823
+ * looks like the icon button.
475
824
  *
476
825
  * @example
477
826
  * <bf-icon-button label="Search" (clicked)="openSearch()">
478
827
  * <bf-icon [icon]="Search" />
479
828
  * </bf-icon-button>
829
+ * <a bfIconButton label="Edit project" routerLink="/projects/atlas/edit">
830
+ * <bf-icon [icon]="Pencil" />
831
+ * </a>
480
832
  * @summary Round icon-only button for toolbars and rows, with a required accessible label
481
833
  * @category Actions
482
834
  * @since 0.1.0
@@ -488,25 +840,39 @@ export declare class BfIconButtonComponent {
488
840
  /** Height step: sm 32, md 40, lg 48 px (square); unset follows `provideBfDefaults()`
489
841
  * (`controlSize`, `md` by default). */
490
842
  readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
491
- /** Native button type. */
843
+ /** Native button type. Ignored on `a[bfIconButton]`. */
492
844
  readonly type: import("@angular/core").InputSignal<BfButtonType>;
493
- /** Disables the control and swallows clicks. */
845
+ /** Disables the control and swallows clicks. Ignored on `a[bfIconButton]`: a link is never
846
+ * disabled; render a disabled `bf-icon-button` instead. */
494
847
  readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
495
- /** Accessible name announced instead of the icon. */
848
+ /** Accessible name announced instead of the icon; on `a[bfIconButton]`, the link's
849
+ * `aria-label`. */
496
850
  readonly label: import("@angular/core").InputSignal<string>;
497
- /** Emitted on click while enabled. */
851
+ /** Emitted on click while enabled; on `a[bfIconButton]`, on every click (the link still
852
+ * navigates). */
498
853
  readonly clicked: import("@angular/core").OutputEmitterRef<Event>;
499
854
  private readonly defaults;
855
+ /** Whether the host is the consumer's `<a>` (`a[bfIconButton]`) rather than a
856
+ * `bf-icon-button` element. */
857
+ protected readonly isLink: boolean;
500
858
  /** The size in effect: `size`, else the app's `controlSize` default. */
501
859
  protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
502
860
  readonly classes: import("@angular/core").Signal<string>;
861
+ /** The host's classes: the whole icon button on a link (with `no-underline!`, so an unlayered
862
+ * global link rule cannot underline it), else the wrapper's display. */
863
+ readonly hostClasses: import("@angular/core").Signal<string>;
864
+ /**
865
+ * A click on `a[bfIconButton]` emits `clicked`; the browser (or `routerLink`) still follows it.
866
+ * @internal
867
+ */
868
+ onHostClick(event: Event): void;
503
869
  /**
504
870
  * The inner button's click: emits `clicked` unless disabled.
505
871
  * @internal
506
872
  */
507
873
  onClick(event: Event): void;
508
874
  static ɵfac: i0.ɵɵFactoryDeclaration<BfIconButtonComponent, never>;
509
- static ɵcmp: i0.ɵɵComponentDeclaration<BfIconButtonComponent, "bf-icon-button", never, {
875
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfIconButtonComponent, "bf-icon-button, a[bfIconButton]", never, {
510
876
  "variant": {
511
877
  "alias": "variant";
512
878
  "required": false;
@@ -543,6 +909,15 @@ export declare class BfIconButtonComponent {
543
909
  * @since 0.1.0
544
910
  */
545
911
  type BfBadgeVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'danger';
912
+ /**
913
+ * Every tone the `variant` input of a `bf-badge` takes: the five `BfBadgeVariant` tones plus
914
+ * `info`, for an informational label such as a category. A new type, so `Record`s and exhaustive
915
+ * switches over `BfBadgeVariant` keep compiling.
916
+ *
917
+ * @summary Every badge tone, the five variants plus the informational info tone
918
+ * @since 0.3.1
919
+ */
920
+ type BfBadgeAppearance = BfBadgeVariant | 'info';
546
921
  /**
547
922
  * Status label ("On track", "At risk") or, with `count`, a compact numeric pill for unread counts.
548
923
  *
@@ -555,8 +930,9 @@ type BfBadgeVariant = 'neutral' | 'primary' | 'success' | 'warning' | 'danger';
555
930
  * @slot default The badge text, shown when no `count` is set.
556
931
  */
557
932
  export declare class BfBadgeComponent {
558
- /** Tint for the label style. Ignored when `count` is set. */
559
- readonly variant: import("@angular/core").InputSignal<BfBadgeVariant>;
933
+ /** Tint for the label style: neutral, primary, success, warning, danger or info. Ignored when
934
+ * `count` is set. */
935
+ readonly variant: import("@angular/core").InputSignal<BfBadgeAppearance>;
560
936
  /** Switches to the count pill; values above 99 render as "99+". */
561
937
  readonly count: import("@angular/core").InputSignal<number | undefined>;
562
938
  /** What the count counts ("unread messages"), read by assistive tech after the number ("99+
@@ -2592,6 +2968,68 @@ export declare class BfSegmentedComponent<T = string> implements FormValueContro
2592
2968
  "touch": "touch";
2593
2969
  }, never, never, true, never>;
2594
2970
  }
2971
+ /**
2972
+ * The colour scheme switch: System, Light and Dark as a three-option segmented control. It holds
2973
+ * a `BfColorScheme` and injects no service, so the app binds its own state, usually
2974
+ * `BfColorSchemeService.scheme` (`provideBfColorScheme()` on desktop, `provideBfShell()` in a
2975
+ * Capacitor app, where `BfPlatformService.theme` is the same signal).
2976
+ *
2977
+ * @example
2978
+ * <bf-theme-switch [(value)]="colorScheme.scheme" />
2979
+ * @summary Segmented System, Light and Dark switch bound two-way to the app colour scheme
2980
+ * @category Forms
2981
+ * @since 0.3.1
2982
+ */
2983
+ export declare class BfThemeSwitchComponent implements FormValueControl<BfColorScheme> {
2984
+ private readonly labels;
2985
+ /** The colour scheme choice; bind it two-way, usually to `BfColorSchemeService.scheme`, or
2986
+ * with `[formField]`. */
2987
+ readonly value: import("@angular/core").ModelSignal<BfColorScheme>;
2988
+ /** Accessible name of the switch (not shown); empty falls back to the `theme` label. */
2989
+ readonly label: import("@angular/core").InputSignal<string>;
2990
+ /** Height step: sm 32, md 40, lg 48 px; unset follows `provideBfDefaults()` (`controlSize`,
2991
+ * `md` by default). */
2992
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
2993
+ /** Stretch the switch and share the width between the three segments. */
2994
+ readonly fullWidth: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2995
+ /** Emitted with the new choice right after the user picks another segment. */
2996
+ readonly changed: import("@angular/core").OutputEmitterRef<BfColorScheme>;
2997
+ /** The three segments, labelled by `themeSystem`, `themeLight` and `themeDark`. */
2998
+ protected readonly options: readonly BfSegmentOption<BfColorScheme>[];
2999
+ /** The group's accessible name: `label`, else the `theme` label. */
3000
+ protected readonly resolvedLabel: import("@angular/core").Signal<string>;
3001
+ /**
3002
+ * Takes the segment the user picked.
3003
+ * @internal
3004
+ */
3005
+ select(next: BfColorScheme): void;
3006
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfThemeSwitchComponent, never>;
3007
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfThemeSwitchComponent, "bf-theme-switch", never, {
3008
+ "value": {
3009
+ "alias": "value";
3010
+ "required": false;
3011
+ "isSignal": true;
3012
+ };
3013
+ "label": {
3014
+ "alias": "label";
3015
+ "required": false;
3016
+ "isSignal": true;
3017
+ };
3018
+ "size": {
3019
+ "alias": "size";
3020
+ "required": false;
3021
+ "isSignal": true;
3022
+ };
3023
+ "fullWidth": {
3024
+ "alias": "fullWidth";
3025
+ "required": false;
3026
+ "isSignal": true;
3027
+ };
3028
+ }, {
3029
+ "value": "valueChange";
3030
+ "changed": "changed";
3031
+ }, never, never, true, never>;
3032
+ }
2595
3033
  /**
2596
3034
  * Container for `bf-list-item` rows. The inset style (default) wraps the rows in the warm
2597
3035
  * background with rounded corners, as in the design's grouped lists.
@@ -2600,6 +3038,11 @@ export declare class BfSegmentedComponent<T = string> implements FormValueContro
2600
3038
  * <bf-list>
2601
3039
  * <bf-list-item title="Notifications" subtitle="Every Monday at 8:00" />
2602
3040
  * </bf-list>
3041
+ * <bf-card>
3042
+ * <bf-list [inset]="false" divided class="-mx-card">
3043
+ * <bf-list-item title="Atlas rebrand" subtitle="Due Friday" />
3044
+ * </bf-list>
3045
+ * </bf-card>
2603
3046
  * @summary Container for list rows, inset by default with rounded corners on a warm background
2604
3047
  * @category Data display
2605
3048
  * @since 0.1.0
@@ -2608,7 +3051,10 @@ export declare class BfSegmentedComponent<T = string> implements FormValueContro
2608
3051
  export declare class BfListComponent {
2609
3052
  /** Grouped look with the warm container; false renders rows on the page background. */
2610
3053
  readonly inset: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
2611
- readonly classes: import("@angular/core").Signal<"flex flex-col gap-1 rounded-card bg-bg p-1.5" | "flex flex-col gap-2 bg-transparent p-0">;
3054
+ /** Separates the rows with a `border` line instead of a gap, with square rows whose hover
3055
+ * reaches the list's edges. Off by default. */
3056
+ readonly divided: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3057
+ readonly classes: import("@angular/core").Signal<string>;
2612
3058
  static ɵfac: i0.ɵɵFactoryDeclaration<BfListComponent, never>;
2613
3059
  static ɵcmp: i0.ɵɵComponentDeclaration<BfListComponent, "bf-list", never, {
2614
3060
  "inset": {
@@ -2616,6 +3062,11 @@ export declare class BfListComponent {
2616
3062
  "required": false;
2617
3063
  "isSignal": true;
2618
3064
  };
3065
+ "divided": {
3066
+ "alias": "divided";
3067
+ "required": false;
3068
+ "isSignal": true;
3069
+ };
2619
3070
  }, {}, never, ["*"], true, never>;
2620
3071
  }
2621
3072
  /**
@@ -2745,7 +3196,7 @@ type BfCardPadding = 'md' | 'lg';
2745
3196
  * @since 0.1.0
2746
3197
  * @slot header Content above the body, such as a title row.
2747
3198
  * @slot default The card body.
2748
- * @slot footer Content below the body, such as its actions.
3199
+ * @slot footer Content below the body, such as its actions; it sits on the card's bottom edge.
2749
3200
  */
2750
3201
  export declare class BfCardComponent implements BfActionHost {
2751
3202
  /** Surface treatment: raised (default), tint, ink, flat. */
@@ -3454,32 +3905,1673 @@ export declare class BfActionDirective {
3454
3905
  static ɵfac: i0.ɵɵFactoryDeclaration<BfActionDirective, never>;
3455
3906
  static ɵdir: i0.ɵɵDirectiveDeclaration<BfActionDirective, "a[bfAction], button[bfAction]", never, {}, {}, never, never, true, never>;
3456
3907
  }
3457
- /** An error as a field reads it: its kind and optional message; limit fields (`minLength`,
3458
- * `context.requiredLength`, …) are read through type guards by `bfValidationMessage`. */
3459
- type FieldErrorLike = Pick<ValidationError, 'kind' | 'message'>;
3460
- /**
3461
- * Explicit error message wins; otherwise, once the field was touched, the first form error's text:
3462
- * its own `message`, else the default for its kind from `messages` (`BF_LABELS.validation`).
3463
- */
3464
- declare function fieldErrorText(errorMessage: string, touched: boolean, errors: readonly FieldErrorLike[], messages: BfValidationMessages): string;
3465
- /** The visual error state: any error text, or a field the form marked invalid after it was touched. */
3466
- declare function fieldShowsError(errorText: string, invalid: boolean, touched: boolean): boolean;
3908
+ /** What a `bf-tab-panel` reads from its `bf-tab-group`; a token so the two files never import each
3909
+ * other. Internal: not exported from the package. */
3910
+ interface BfTabGroupHost {
3911
+ /** The value of the panel the group shows: `selected`, else the first enabled panel's. */
3912
+ readonly current: Signal<string>;
3913
+ }
3914
+ /** The enclosing `bf-tab-group`, as its panels inject it. */
3915
+ declare const BF_TAB_GROUP: InjectionToken<BfTabGroupHost>;
3467
3916
  /**
3468
- * `aria-describedby` targets: the help paragraph and the error paragraph under it, each while it
3469
- * is rendered (`"<id>-help <id>-error"`, `"<id>-help"`, `"<id>-error"`), else none.
3917
+ * One tab of a `bf-tab-group` and the content it shows: `label` is the tab's text, `value` the
3918
+ * key the group's `selected` holds. Put the content in an `ng-template` inside the panel and it is
3919
+ * created only while the panel is selected (`keepAlive` keeps it once visited); plain content
3920
+ * renders at once and is only hidden. An icon in `bfSlot="icon"` shows in the tab before the label.
3921
+ *
3922
+ * @example
3923
+ * <bf-tab-panel value="activity" label="Activity" [badge]="3">
3924
+ * <bf-icon bfSlot="icon" [icon]="Activity" />
3925
+ * <ng-template><app-activity-feed /></ng-template>
3926
+ * </bf-tab-panel>
3927
+ * @summary One tab of a tab group with its label, badge, icon and lazy content
3928
+ * @category Navigation
3929
+ * @since 0.3.1
3930
+ * @slot icon An icon in the tab before the label, a `bf-icon`.
3931
+ * @slot default Content rendered at once and hidden while another tab is selected; put it in an
3932
+ * `ng-template` instead to create it only when the panel is shown.
3470
3933
  */
3471
- declare function fieldDescribedBy(id: string, errorText: string, helpText: string): string | null;
3472
- /** `aria-errormessage` target: the error paragraph while the control is invalid, else none. */
3473
- declare function fieldErrorMessageId(id: string, errorText: string, showError: boolean): string | null;
3934
+ export declare class BfTabPanelComponent {
3935
+ /** The key of this panel; the group's `selected` holds it while the panel is shown. */
3936
+ readonly value: import("@angular/core").InputSignal<string>;
3937
+ /** The tab's visible text, also its accessible name. */
3938
+ readonly label: import("@angular/core").InputSignal<string>;
3939
+ /** Disables the tab: it cannot be clicked and the arrow keys skip it. */
3940
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3941
+ /** A count shown as a pill after the tab's label, announced with `provideBfLabels()`'s
3942
+ * `tabBadge(count)` ("3 new"); `null` shows none. */
3943
+ readonly badge: import("@angular/core").InputSignal<number | null>;
3944
+ /** Keeps the content of an `ng-template` in the DOM, hidden, once the panel has been shown, so
3945
+ * its state (scroll, form input) survives switching tabs. */
3946
+ readonly keepAlive: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
3947
+ private readonly group;
3948
+ /** The panel's DOM id, which its tab's `aria-controls` names. */
3949
+ readonly panelId: string;
3950
+ /** The DOM id of this panel's tab, which the panel's `aria-labelledby` names. */
3951
+ readonly tabId: string;
3952
+ /** The icon slot as a template, for the group to render inside the tab. */
3953
+ readonly icon: import("@angular/core").Signal<TemplateRef<unknown> | undefined>;
3954
+ /** The consumer's lazy content, if any. */
3955
+ protected readonly content: import("@angular/core").Signal<TemplateRef<any> | undefined>;
3956
+ /** Whether the group shows this panel. */
3957
+ readonly isSelected: import("@angular/core").Signal<boolean>;
3958
+ /** Latches once the panel has been shown. */
3959
+ private readonly visited;
3960
+ /** Whether the `ng-template` content exists: while selected, or once visited with `keepAlive`.
3961
+ * `visited` is read first on every run, so the latch sees each selection. */
3962
+ protected readonly rendered: import("@angular/core").Signal<boolean>;
3963
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfTabPanelComponent, never>;
3964
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfTabPanelComponent, "bf-tab-panel", never, {
3965
+ "value": {
3966
+ "alias": "value";
3967
+ "required": true;
3968
+ "isSignal": true;
3969
+ };
3970
+ "label": {
3971
+ "alias": "label";
3972
+ "required": true;
3973
+ "isSignal": true;
3974
+ };
3975
+ "disabled": {
3976
+ "alias": "disabled";
3977
+ "required": false;
3978
+ "isSignal": true;
3979
+ };
3980
+ "badge": {
3981
+ "alias": "badge";
3982
+ "required": false;
3983
+ "isSignal": true;
3984
+ };
3985
+ "keepAlive": {
3986
+ "alias": "keepAlive";
3987
+ "required": false;
3988
+ "isSignal": true;
3989
+ };
3990
+ }, {}, ["content"], ["[bfSlot=icon]", "*"], true, never>;
3991
+ }
3474
3992
  /**
3475
- * Returns a document-unique id such as `bf-input-3`, for associating labels and hints with controls.
3993
+ * In-page tabs: a row of tabs over the content they switch, one `bf-tab-panel` per tab. The
3994
+ * `selected` model holds the shown panel's `value`; unset or unknown, the first enabled panel
3995
+ * shows. Selection follows focus: the arrow keys (mirrored under `dir="rtl"`), Home and End move
3996
+ * to a tab and show its panel. When the tabs do not fit, the row scrolls sideways.
3476
3997
  *
3477
- * The ids come from this module-level counter, so a server render and the client (or two server
3478
- * renders in one process) number them differently: `@bitforgehq/ui` 0.x is client-rendered only,
3479
- * and SSR, hydration and prerendering of pages that render its components are not supported.
3480
- * Hydration-stable ids are decided before 1.0.
3998
+ * @example
3999
+ * <bf-tab-group label="Project" [(selected)]="tab">
4000
+ * <bf-tab-panel value="overview" label="Overview">…</bf-tab-panel>
4001
+ * <bf-tab-panel value="activity" label="Activity" [badge]="3">…</bf-tab-panel>
4002
+ * </bf-tab-group>
4003
+ * @summary In-page tabs that switch between content panels, with keyboard navigation and badges
4004
+ * @category Navigation
4005
+ * @since 0.3.1
4006
+ * @slot default The panels, each a `bf-tab-panel`.
3481
4007
  */
3482
- declare function uniqueId(prefix: string): string;
4008
+ export declare class BfTabGroupComponent implements BfTabGroupHost {
4009
+ /** The shown panel's `value`; two-way bindable. Unset or unknown shows the first enabled panel
4010
+ * (the model keeps its value until the user picks a tab). */
4011
+ readonly selected: import("@angular/core").ModelSignal<string>;
4012
+ /** Accessible name of the tablist; empty falls back to `provideBfLabels()`'s `tabGroup`
4013
+ * ("Tabs"). */
4014
+ readonly label: import("@angular/core").InputSignal<string>;
4015
+ /** Height step of the tabs: sm 32, md 40, lg 48 px (at least 44 px under a coarse pointer);
4016
+ * unset follows `provideBfDefaults()` (`controlSize`, `md` by default). */
4017
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
4018
+ /** Stretches the tabs to share the group's width. */
4019
+ readonly fitted: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
4020
+ /** Emitted with the newly selected panel's `value` after a user change. */
4021
+ readonly changed: import("@angular/core").OutputEmitterRef<string>;
4022
+ /** The `bf-tab-panel` children, in document order. */
4023
+ readonly panels: import("@angular/core").Signal<readonly BfTabPanelComponent[]>;
4024
+ private readonly tabs;
4025
+ private readonly labels;
4026
+ private readonly defaults;
4027
+ /** The size in effect: `size`, else the app's `controlSize` default. */
4028
+ private readonly resolvedSize;
4029
+ /** The tablist's accessible name: `label`, else the `tabGroup` label. */
4030
+ readonly name: import("@angular/core").Signal<string>;
4031
+ /** The panel shown: the one whose `value` is `selected`, else the first enabled panel (else the
4032
+ * first panel). */
4033
+ private readonly currentPanel;
4034
+ /** The value of the panel shown; what each panel compares its own `value` with. */
4035
+ readonly current: import("@angular/core").Signal<string>;
4036
+ /** The panel whose tab owns the roving tab stop: the shown one, else (it is disabled) the first
4037
+ * enabled one. */
4038
+ protected readonly tabStop: import("@angular/core").Signal<BfTabPanelComponent | undefined>;
4039
+ protected readonly scrollerClasses = "-m-1 overflow-x-auto p-1";
4040
+ protected readonly listClasses = "flex w-max min-w-full border-b border-border";
4041
+ protected readonly badgeClasses = "flex h-5 min-w-5 shrink-0 items-center justify-center rounded-control bg-primary px-1.5 text-micro font-bold text-on-primary";
4042
+ /**
4043
+ * The classes of a panel's tab.
4044
+ * @internal
4045
+ */
4046
+ tabClasses(panel: BfTabPanelComponent): string;
4047
+ /**
4048
+ * The badge as screen readers hear it after the label.
4049
+ * @internal
4050
+ */
4051
+ badgeAnnouncement(count: number): string;
4052
+ /**
4053
+ * Shows `panel` and emits `changed`, unless it is disabled or already shown.
4054
+ * @internal
4055
+ */
4056
+ select(panel: BfTabPanelComponent): void;
4057
+ /**
4058
+ * Arrow keys (mirrored under `dir="rtl"`), Home and End move focus and selection.
4059
+ * @internal
4060
+ */
4061
+ onKeydown(event: KeyboardEvent): void;
4062
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfTabGroupComponent, never>;
4063
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfTabGroupComponent, "bf-tab-group", never, {
4064
+ "selected": {
4065
+ "alias": "selected";
4066
+ "required": false;
4067
+ "isSignal": true;
4068
+ };
4069
+ "label": {
4070
+ "alias": "label";
4071
+ "required": false;
4072
+ "isSignal": true;
4073
+ };
4074
+ "size": {
4075
+ "alias": "size";
4076
+ "required": false;
4077
+ "isSignal": true;
4078
+ };
4079
+ "fitted": {
4080
+ "alias": "fitted";
4081
+ "required": false;
4082
+ "isSignal": true;
4083
+ };
4084
+ }, {
4085
+ "selected": "selectedChange";
4086
+ "changed": "changed";
4087
+ }, ["panels"], ["*"], true, never>;
4088
+ }
4089
+ /**
4090
+ * The heading level of a `bf-page-header` title: `1` for the page, `2` for a section header.
4091
+ *
4092
+ * @summary The heading level of a page header title, one for a page or two
4093
+ * @since 0.3.1
4094
+ */
4095
+ type BfPageHeaderHeadingLevel = 1 | 2;
4096
+ /**
4097
+ * The top of a desktop page: a breadcrumb above, then the page title with its subtitle and
4098
+ * badges, and the page's actions at the inline end, wrapping under the title in a narrow window.
4099
+ *
4100
+ * @example
4101
+ * <bf-page-header title="Atlas rebrand" subtitle="12 of 18 tasks done">
4102
+ * <bf-badge bfSlot="meta" variant="success">On track</bf-badge>
4103
+ * <bf-button bfSlot="actions" (clicked)="create()">New task</bf-button>
4104
+ * </bf-page-header>
4105
+ * @summary Desktop page header with breadcrumb, title, subtitle, badges and a row of actions
4106
+ * @category Navigation
4107
+ * @since 0.3.1
4108
+ * @slot breadcrumb The trail above the title, such as `bf-breadcrumb`.
4109
+ * @slot title Rich title content inside the heading, when the `title` input is empty.
4110
+ * @slot meta Badges beside the title, wrapping under it when they do not fit.
4111
+ * @slot actions The page's buttons and menu buttons at the inline end.
4112
+ */
4113
+ export declare class BfPageHeaderComponent {
4114
+ /** The page title, rendered as the heading; empty to use the `title` slot instead. */
4115
+ readonly title: import("@angular/core").InputSignal<string>;
4116
+ /** One line under the title, such as a status or a count. */
4117
+ readonly subtitle: import("@angular/core").InputSignal<string>;
4118
+ /** Heading level of the title so the header fits the page outline. */
4119
+ readonly headingLevel: import("@angular/core").InputSignal<BfPageHeaderHeadingLevel>;
4120
+ protected readonly headingClasses = "text-title text-text min-w-0 wrap-break-word";
4121
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfPageHeaderComponent, never>;
4122
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfPageHeaderComponent, "bf-page-header", never, {
4123
+ "title": {
4124
+ "alias": "title";
4125
+ "required": false;
4126
+ "isSignal": true;
4127
+ };
4128
+ "subtitle": {
4129
+ "alias": "subtitle";
4130
+ "required": false;
4131
+ "isSignal": true;
4132
+ };
4133
+ "headingLevel": {
4134
+ "alias": "headingLevel";
4135
+ "required": false;
4136
+ "isSignal": true;
4137
+ };
4138
+ }, {}, never, ["[bfSlot=breadcrumb]", "[bfSlot=meta]", "[bfSlot=actions]", "[bfSlot=title]"], true, never>;
4139
+ }
4140
+ /**
4141
+ * Row of search, filters, a view switch and trailing actions above a list or table. Every
4142
+ * control projected into it is `sm` unless it sets `size` itself.
4143
+ *
4144
+ * @example
4145
+ * <bf-toolbar label="Project filters" [status]="results().length + ' results'">
4146
+ * <bf-input type="search" ariaLabel="Search projects" [(value)]="query" />
4147
+ * <bf-select ariaLabel="Status" [options]="statuses" [(value)]="status" />
4148
+ * <bf-segmented bfSlot="view" label="View" [options]="views" [(value)]="view" />
4149
+ * <bf-button bfSlot="actions" (clicked)="create()">New project</bf-button>
4150
+ * </bf-toolbar>
4151
+ * @summary Dense row of search, filters, view switch, result count and actions
4152
+ * @category Actions
4153
+ * @since 0.3.1
4154
+ * @slot default The search field and the filters (bf-input, bf-select, bf-chip-group), in order.
4155
+ * @slot view A view switch after the filters, such as a bf-segmented of list and grid.
4156
+ * @slot actions The trailing actions, kept together at the inline end of the row.
4157
+ */
4158
+ export declare class BfToolbarComponent {
4159
+ /** The group's accessible name, such as "Project filters"; unnamed when empty. */
4160
+ readonly label: import("@angular/core").InputSignal<string>;
4161
+ /** The result count or a short state, such as "24 results", announced politely on change. */
4162
+ readonly status: import("@angular/core").InputSignal<string>;
4163
+ readonly statusClasses: import("@angular/core").Signal<string>;
4164
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfToolbarComponent, never>;
4165
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfToolbarComponent, "bf-toolbar", never, {
4166
+ "label": {
4167
+ "alias": "label";
4168
+ "required": false;
4169
+ "isSignal": true;
4170
+ };
4171
+ "status": {
4172
+ "alias": "status";
4173
+ "required": false;
4174
+ "isSignal": true;
4175
+ };
4176
+ }, {}, never, ["*", "[bfSlot=view]", "[bfSlot=actions]"], true, never>;
4177
+ }
4178
+ /**
4179
+ * What a `bf-table` cell template receives: the row (`let-row`) and its position in `rows`.
4180
+ *
4181
+ * @summary The row and its index that a custom table cell template receives
4182
+ * @since 0.3.1
4183
+ */
4184
+ interface BfTableCellContext<T> {
4185
+ /** The row the cell belongs to (`let-row`). */
4186
+ $implicit: T;
4187
+ /** The row's position in the table's `rows` (`let-index="index"`). */
4188
+ index: number;
4189
+ }
4190
+ /**
4191
+ * Replaces the default text of one `bf-table` column with a template, such as a badge, an avatar
4192
+ * or a link. `bfTableCell` names the column's `key`; bind `bfTableCellOf` to the table's rows so
4193
+ * `let-row` is typed as one of them (it is `unknown` otherwise).
4194
+ *
4195
+ * @example
4196
+ * <bf-table [rows]="tasks()" [columns]="columns">
4197
+ * <ng-template bfTableCell="status" [bfTableCellOf]="tasks()" let-task>
4198
+ * <bf-badge [variant]="task.done ? 'success' : 'neutral'">{{ task.status }}</bf-badge>
4199
+ * </ng-template>
4200
+ * </bf-table>
4201
+ * @summary Custom template for the cells of one table column, with the row typed
4202
+ * @since 0.3.1
4203
+ */
4204
+ export declare class BfTableCellDirective<T = unknown> {
4205
+ /** The `key` of the column whose cells this template renders. */
4206
+ readonly bfTableCell: import("@angular/core").InputSignal<string>;
4207
+ /** The table's rows; only types `let-row`, the table never reads it. */
4208
+ readonly bfTableCellOf: import("@angular/core").InputSignal<readonly T[]>;
4209
+ /**
4210
+ * The cell template the table renders for each row.
4211
+ * @internal
4212
+ */
4213
+ readonly template: TemplateRef<BfTableCellContext<T>>;
4214
+ /**
4215
+ * Types the template's context for the template type checker.
4216
+ * @internal
4217
+ * @param _directive The directive instance (unused).
4218
+ * @param _context The template's context.
4219
+ * @returns Always true.
4220
+ */
4221
+ static ngTemplateContextGuard<T>(_directive: BfTableCellDirective<T>, _context: unknown): _context is BfTableCellContext<T>;
4222
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfTableCellDirective<any>, never>;
4223
+ static ɵdir: i0.ɵɵDirectiveDeclaration<BfTableCellDirective<any>, "ng-template[bfTableCell]", never, {
4224
+ "bfTableCell": {
4225
+ "alias": "bfTableCell";
4226
+ "required": true;
4227
+ "isSignal": true;
4228
+ };
4229
+ "bfTableCellOf": {
4230
+ "alias": "bfTableCellOf";
4231
+ "required": false;
4232
+ "isSignal": true;
4233
+ };
4234
+ }, {}, never, never, true, never>;
4235
+ }
4236
+ /**
4237
+ * Where a `bf-table` column lines up its header and cells: `start` for text, `end` for numbers.
4238
+ *
4239
+ * @summary The inline alignment of a table column, start for text or end for numbers
4240
+ * @since 0.3.1
4241
+ */
4242
+ type BfTableAlign = 'start' | 'end';
4243
+ /**
4244
+ * The direction of a sorted `bf-table` column, as `aria-sort` names it.
4245
+ *
4246
+ * @summary The direction a sorted table column is in, ascending or descending
4247
+ * @since 0.3.1
4248
+ */
4249
+ type BfTableSortDirection = 'ascending' | 'descending';
4250
+ /**
4251
+ * One column of a `bf-table`: the row property it shows, its header and how it behaves.
4252
+ *
4253
+ * @summary One table column with its row key, header label, sorting and alignment
4254
+ * @since 0.3.1
4255
+ */
4256
+ interface BfTableColumn {
4257
+ /** The row property the default cell shows; also the key a `bfTableCell` template names. */
4258
+ key: string;
4259
+ /** The header text. */
4260
+ label: string;
4261
+ /**
4262
+ * Whether the header is a button that sets the table's `sort`.
4263
+ * @default false
4264
+ */
4265
+ sortable?: boolean;
4266
+ /**
4267
+ * The inline alignment of the header and cells; `end` also sets tabular figures.
4268
+ * @default 'start'
4269
+ */
4270
+ align?: BfTableAlign;
4271
+ }
4272
+ /**
4273
+ * The column a `bf-table` is sorted by and the direction; the consumer sorts the rows.
4274
+ *
4275
+ * @summary The column key and direction a table is sorted by, set by its headers
4276
+ * @since 0.3.1
4277
+ */
4278
+ interface BfTableSort {
4279
+ /** The `key` of the sorted column. */
4280
+ column: string;
4281
+ /** The sort direction. */
4282
+ direction: BfTableSortDirection;
4283
+ }
4284
+ /**
4285
+ * Returns the string that identifies a `bf-table` row in `selection` and in the `@for` track.
4286
+ *
4287
+ * @summary Function that returns the unique string key of one table row
4288
+ * @since 0.3.1
4289
+ */
4290
+ type BfTableRowKey<T> = (row: T) => string;
4291
+ interface BfTableEntry<T> {
4292
+ row: T;
4293
+ key: string;
4294
+ index: number;
4295
+ }
4296
+ /**
4297
+ * Data table for desktop: column headers that set a sort, optional row selection with
4298
+ * checkboxes, custom cells from `bfTableCell` templates and an empty slot. It never sorts or
4299
+ * filters itself; the consumer sorts the rows in a `computed()` from `sort`.
4300
+ *
4301
+ * @example
4302
+ * <bf-table label="Tasks" [rows]="sorted()" [columns]="columns" [(sort)]="sort" selectable [(selection)]="selected">
4303
+ * <ng-template bfTableCell="title" [bfTableCellOf]="sorted()" let-task>{{ task.title }}</ng-template>
4304
+ * <bf-empty-state bfSlot="empty" title="No tasks" />
4305
+ * </bf-table>
4306
+ * @summary Desktop data table with sortable headers, row selection, custom cells and an empty slot
4307
+ * @category Data display
4308
+ * @since 0.3.1
4309
+ * @slot empty Shown in one full-width row while `rows` is empty, such as a `bf-empty-state`.
4310
+ */
4311
+ export declare class BfTableComponent<T = unknown> {
4312
+ /** The rows to show, already sorted and filtered by the consumer. */
4313
+ readonly rows: import("@angular/core").InputSignal<readonly T[]>;
4314
+ /** The columns, in order. */
4315
+ readonly columns: import("@angular/core").InputSignal<readonly BfTableColumn[]>;
4316
+ /** The unique string key of a row, used for `selection` and to track rows; by default the
4317
+ * row's `id` (a string or a number), else its index. */
4318
+ readonly rowKey: import("@angular/core").InputSignal<BfTableRowKey<T>>;
4319
+ /** The table's name, rendered as a visually hidden `caption`. */
4320
+ readonly label: import("@angular/core").InputSignal<string>;
4321
+ /** The sorted column and direction, `null` while unsorted; two-way bindable. A sortable header
4322
+ * sets it, and the consumer sorts `rows` from it. */
4323
+ readonly sort: import("@angular/core").ModelSignal<BfTableSort | null>;
4324
+ /** Adds a first column of checkboxes that select rows. */
4325
+ readonly selectable: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
4326
+ /** The keys (`rowKey`) of the selected rows; two-way bindable. */
4327
+ readonly selection: import("@angular/core").ModelSignal<readonly string[]>;
4328
+ /** Accessible name of the header checkbox; empty falls back to `provideBfLabels()`'s
4329
+ * `tableSelectAll` ("Select all rows"). */
4330
+ readonly selectAllLabel: import("@angular/core").InputSignal<string>;
4331
+ /** Row height step: sm 40, md 48, lg 56 px (the header 32/40/48; at least 44 px under a coarse
4332
+ * pointer); unset follows `provideBfDefaults()` (`controlSize`, `md` by default). */
4333
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
4334
+ private readonly labels;
4335
+ private readonly defaults;
4336
+ private readonly table;
4337
+ private readonly cells;
4338
+ private readonly id;
4339
+ /** The size in effect: `size`, else the app's `controlSize` default. */
4340
+ protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
4341
+ /** The header checkbox's name: `selectAllLabel`, else the `tableSelectAll` label. */
4342
+ protected readonly selectAllName: import("@angular/core").Signal<string>;
4343
+ /** Each row with its key (the `rowKey`, else its index) and its index. */
4344
+ protected readonly entries: import("@angular/core").Signal<BfTableEntry<T>[]>;
4345
+ /** The custom cell template of each column key. */
4346
+ protected readonly templates: import("@angular/core").Signal<Map<string, TemplateRef<BfTableCellContext<unknown>>>>;
4347
+ protected readonly selectedKeys: import("@angular/core").Signal<Set<string>>;
4348
+ /** Whether every row is selected (and there is at least one). */
4349
+ protected readonly allSelected: import("@angular/core").Signal<boolean>;
4350
+ /** Whether some rows, but not all, are selected: the header checkbox is mixed. */
4351
+ protected readonly someSelected: import("@angular/core").Signal<boolean>;
4352
+ /** The number of columns, the selection column included: the empty row's `colspan`. */
4353
+ protected readonly columnCount: import("@angular/core").Signal<number>;
4354
+ protected readonly sortButton: string;
4355
+ protected readonly selectHeadClasses: import("@angular/core").Signal<string>;
4356
+ protected readonly selectBodyClasses: import("@angular/core").Signal<string>;
4357
+ /**
4358
+ * The classes of a column's header cell.
4359
+ * @internal
4360
+ */
4361
+ headClasses(column: BfTableColumn): string;
4362
+ /**
4363
+ * The classes of a column's body cell.
4364
+ * @internal
4365
+ */
4366
+ bodyClasses(column: BfTableColumn): string;
4367
+ /**
4368
+ * The classes of the body row with this key.
4369
+ * @internal
4370
+ */
4371
+ rowClasses(key: string): string;
4372
+ /**
4373
+ * The classes of a sortable header's arrow mark.
4374
+ * @internal
4375
+ */
4376
+ arrowClasses(key: string): string;
4377
+ /**
4378
+ * The `aria-sort` of a column's header: its direction while sorted, else none.
4379
+ * @internal
4380
+ */
4381
+ ariaSort(key: string): BfTableSortDirection | null;
4382
+ /**
4383
+ * The id of a row's first data cell, which names the row's checkbox.
4384
+ * @internal
4385
+ */
4386
+ cellId(index: number): string;
4387
+ /**
4388
+ * The default text of a cell: the row's property `key` when it is a string, number or boolean,
4389
+ * else empty (render an object, such as a date, with a `bfTableCell` template).
4390
+ * @internal
4391
+ */
4392
+ cellText(row: T, key: string): string;
4393
+ /**
4394
+ * Sorts by the column with this key: ascending first, then descending and ascending again.
4395
+ * @param key The column's `key`.
4396
+ */
4397
+ sortBy(key: string): void;
4398
+ /**
4399
+ * Selects or clears every row; keys of rows not shown stay as they are.
4400
+ * @param selected True to select every row, false to clear them.
4401
+ */
4402
+ selectAll(selected: boolean): void;
4403
+ /**
4404
+ * Selects or clears one row.
4405
+ * @param key The row's key.
4406
+ * @param selected True to select it, false to clear it.
4407
+ */
4408
+ selectRow(key: string, selected: boolean): void;
4409
+ /**
4410
+ * ArrowUp / ArrowDown on a button, link or checkbox in a row move focus to the control at the
4411
+ * same place in the nearest row above or below that has one.
4412
+ * @internal
4413
+ */
4414
+ onKeydown(event: KeyboardEvent): void;
4415
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfTableComponent<any>, never>;
4416
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfTableComponent<any>, "bf-table", never, {
4417
+ "rows": {
4418
+ "alias": "rows";
4419
+ "required": true;
4420
+ "isSignal": true;
4421
+ };
4422
+ "columns": {
4423
+ "alias": "columns";
4424
+ "required": true;
4425
+ "isSignal": true;
4426
+ };
4427
+ "rowKey": {
4428
+ "alias": "rowKey";
4429
+ "required": false;
4430
+ "isSignal": true;
4431
+ };
4432
+ "label": {
4433
+ "alias": "label";
4434
+ "required": false;
4435
+ "isSignal": true;
4436
+ };
4437
+ "sort": {
4438
+ "alias": "sort";
4439
+ "required": false;
4440
+ "isSignal": true;
4441
+ };
4442
+ "selectable": {
4443
+ "alias": "selectable";
4444
+ "required": false;
4445
+ "isSignal": true;
4446
+ };
4447
+ "selection": {
4448
+ "alias": "selection";
4449
+ "required": false;
4450
+ "isSignal": true;
4451
+ };
4452
+ "selectAllLabel": {
4453
+ "alias": "selectAllLabel";
4454
+ "required": false;
4455
+ "isSignal": true;
4456
+ };
4457
+ "size": {
4458
+ "alias": "size";
4459
+ "required": false;
4460
+ "isSignal": true;
4461
+ };
4462
+ }, {
4463
+ "sort": "sortChange";
4464
+ "selection": "selectionChange";
4465
+ }, ["cells"], ["[bfSlot=empty]"], true, never>;
4466
+ }
4467
+ /**
4468
+ * The layout of a `bf-description-list`: `rows` (label beside value, divided) or `grid` (tiles).
4469
+ *
4470
+ * @summary The two description list layouts, divided label-value rows or a grid of tiles
4471
+ * @since 0.3.1
4472
+ */
4473
+ type BfDescriptionListLayout = 'rows' | 'grid';
4474
+ /** What a `div[bfDescriptionItem]` reads from its `bf-description-list`. */
4475
+ interface BfDescriptionListHost {
4476
+ /** The list's layout. */
4477
+ readonly layout: Signal<BfDescriptionListLayout>;
4478
+ }
4479
+ /**
4480
+ * Provided by `bf-description-list` so each `div[bfDescriptionItem]` styles itself for the list's
4481
+ * layout, without `description-item.component.ts` importing `description-list.component.ts`.
4482
+ */
4483
+ declare const BF_DESCRIPTION_LIST: InjectionToken<BfDescriptionListHost>;
4484
+ /**
4485
+ * A list of label-value pairs, such as a record's details: a native `dl` around
4486
+ * `div[bfDescriptionItem]`s, as divided rows (label beside value) or a grid of tiles.
4487
+ *
4488
+ * @example
4489
+ * <bf-description-list>
4490
+ * <div bfDescriptionItem label="Cuisine">Italian</div>
4491
+ * <div bfDescriptionItem label="Difficulty"><bf-badge variant="success">Easy</bf-badge></div>
4492
+ * </bf-description-list>
4493
+ * @summary Native description list of label-value pairs, as divided rows or a tile grid
4494
+ * @category Data display
4495
+ * @since 0.3.1
4496
+ * @slot default The pairs, each a `div[bfDescriptionItem]`.
4497
+ */
4498
+ export declare class BfDescriptionListComponent implements BfDescriptionListHost {
4499
+ /** `rows` (default): label beside value, divided, stacked in a narrow list; `grid`: tiles with the label over the value. */
4500
+ readonly layout: import("@angular/core").InputSignal<BfDescriptionListLayout>;
4501
+ readonly classes: import("@angular/core").Signal<string>;
4502
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfDescriptionListComponent, never>;
4503
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfDescriptionListComponent, "bf-description-list", never, {
4504
+ "layout": {
4505
+ "alias": "layout";
4506
+ "required": false;
4507
+ "isSignal": true;
4508
+ };
4509
+ }, {}, never, ["*"], true, never>;
4510
+ }
4511
+ /**
4512
+ * One label-value pair of a `bf-description-list`: the `label` becomes the `dt`, the content the
4513
+ * `dd`. Put it on a `div` inside the list.
4514
+ *
4515
+ * @example
4516
+ * <bf-description-list>
4517
+ * <div bfDescriptionItem label="Servings">4</div>
4518
+ * </bf-description-list>
4519
+ * @summary One label and value pair of a description list, label as term, content as value
4520
+ * @category Data display
4521
+ * @since 0.3.1
4522
+ * @slot default The value: text or rich content such as a badge or a link.
4523
+ */
4524
+ export declare class BfDescriptionItemComponent {
4525
+ /** The term, shown as the pair's label. */
4526
+ readonly label: import("@angular/core").InputSignal<string>;
4527
+ /** The enclosing list, which sets the layout; `rows` outside a list. */
4528
+ private readonly list;
4529
+ readonly classes: import("@angular/core").Signal<string>;
4530
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfDescriptionItemComponent, never>;
4531
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfDescriptionItemComponent, "div[bfDescriptionItem]", never, {
4532
+ "label": {
4533
+ "alias": "label";
4534
+ "required": true;
4535
+ "isSignal": true;
4536
+ };
4537
+ }, {}, never, ["*"], true, never>;
4538
+ }
4539
+ /**
4540
+ * The surface of a `bf-stat`: plain (on whatever holds it) or card (its own outlined tile).
4541
+ *
4542
+ * @summary The two stat surfaces, plain on its container or an outlined card tile
4543
+ * @since 0.3.1
4544
+ */
4545
+ type BfStatVariant = 'plain' | 'card';
4546
+ /**
4547
+ * The direction of a `bf-stat` delta: up, down or flat (no change).
4548
+ *
4549
+ * @summary The three directions of a stat's delta pill, up, down or no change
4550
+ * @since 0.3.1
4551
+ */
4552
+ type BfStatTrend = 'up' | 'down' | 'flat';
4553
+ /**
4554
+ * Which direction of a `bf-stat` delta is good: positive (up is good, such as revenue) or
4555
+ * negative (down is good, such as costs or churn).
4556
+ *
4557
+ * @summary Whether a rising or a falling figure is the good news for a stat
4558
+ * @since 0.3.1
4559
+ */
4560
+ type BfStatTrendIntent = 'positive' | 'negative';
4561
+ /**
4562
+ * One figure with its label, such as a count, a duration or a total: a native `dl` pair with the
4563
+ * value set large, an optional icon tile at the start and a supporting line under the value.
4564
+ *
4565
+ * A `delta` with a `trend` adds a pill beside the value, toned by `trendIntent`.
4566
+ *
4567
+ * @example
4568
+ * <bf-stat label="Revenue" value="€48,200" delta="+12%" trend="up" />
4569
+ * <bf-stat label="Cook time" value="30 min" variant="card">
4570
+ * <bf-icon bfSlot="icon" [icon]="Flame" />
4571
+ * Oven at 200 °C
4572
+ * </bf-stat>
4573
+ * @summary One labelled figure with an optional icon tile and a supporting line
4574
+ * @category Data display
4575
+ * @since 0.3.1
4576
+ * @slot icon The icon in the tile at the start.
4577
+ * @slot default A supporting line under the value, such as a trend or a badge.
4578
+ */
4579
+ export declare class BfStatComponent {
4580
+ /** What the figure measures, shown above it. */
4581
+ readonly label: import("@angular/core").InputSignal<string>;
4582
+ /** The figure, already formatted (`45 min`, `1,204`, `98%`). */
4583
+ readonly value: import("@angular/core").InputSignal<string>;
4584
+ /** Surface: plain (default) on its container, or card, an outlined tile of its own. */
4585
+ readonly variant: import("@angular/core").InputSignal<BfStatVariant>;
4586
+ /** A change shown in a pill beside the value, already formatted (`+12%`); empty shows none. */
4587
+ readonly delta: import("@angular/core").InputSignal<string>;
4588
+ /** The delta's direction: an arrow mark and a hidden word; left unset, the pill is neutral. */
4589
+ readonly trend: import("@angular/core").InputSignal<BfStatTrend | undefined>;
4590
+ /** Whether up is good (positive, default) or down is good (negative, such as costs). */
4591
+ readonly trendIntent: import("@angular/core").InputSignal<BfStatTrendIntent>;
4592
+ private readonly labels;
4593
+ readonly classes: import("@angular/core").Signal<string>;
4594
+ /** @internal */
4595
+ readonly deltaClasses: import("@angular/core").Signal<string>;
4596
+ /** @internal */
4597
+ readonly markClasses: import("@angular/core").Signal<string>;
4598
+ /** @internal The direction read before the delta, so colour is never the only signal. */
4599
+ readonly trendWord: import("@angular/core").Signal<string>;
4600
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfStatComponent, never>;
4601
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfStatComponent, "bf-stat", never, {
4602
+ "label": {
4603
+ "alias": "label";
4604
+ "required": true;
4605
+ "isSignal": true;
4606
+ };
4607
+ "value": {
4608
+ "alias": "value";
4609
+ "required": true;
4610
+ "isSignal": true;
4611
+ };
4612
+ "variant": {
4613
+ "alias": "variant";
4614
+ "required": false;
4615
+ "isSignal": true;
4616
+ };
4617
+ "delta": {
4618
+ "alias": "delta";
4619
+ "required": false;
4620
+ "isSignal": true;
4621
+ };
4622
+ "trend": {
4623
+ "alias": "trend";
4624
+ "required": false;
4625
+ "isSignal": true;
4626
+ };
4627
+ "trendIntent": {
4628
+ "alias": "trendIntent";
4629
+ "required": false;
4630
+ "isSignal": true;
4631
+ };
4632
+ }, {}, never, ["[bfSlot=icon]", "*"], true, never>;
4633
+ }
4634
+ /**
4635
+ * What a `li[bfBreadcrumbItem]` reads from its enclosing `bf-breadcrumb`, provided through an
4636
+ * injection token so `breadcrumb.component.ts` and `breadcrumb-item.component.ts` never import each
4637
+ * other. Both methods read signals, so an item calls them in a `computed()`.
4638
+ */
4639
+ interface BfBreadcrumbTrail {
4640
+ /**
4641
+ * Whether `item` is the last item of the trail: the current page.
4642
+ * @param item The item asking.
4643
+ */
4644
+ isCurrent(item: object): boolean;
4645
+ /**
4646
+ * Whether `item` is one of the middle items a collapsed trail hides behind its ellipsis.
4647
+ * @param item The item asking.
4648
+ */
4649
+ isHidden(item: object): boolean;
4650
+ }
4651
+ /** Provided by `bf-breadcrumb` for the items projected into it. */
4652
+ declare const BF_BREADCRUMB: InjectionToken<BfBreadcrumbTrail>;
4653
+ /**
4654
+ * Desktop breadcrumb trail: a `nav` named "Breadcrumb" around an ordered list of
4655
+ * `li[bfBreadcrumbItem]` levels, the last one the current page, a CSS chevron between them. With
4656
+ * `maxItems` set and a longer trail it keeps the first level and the last `maxItems - 1`, and hides
4657
+ * the middle ones behind an ellipsis button that shows them in place, or behind the consumer's own
4658
+ * `bfSlot="overflow"` content (a menu button of the hidden levels).
4659
+ *
4660
+ * @example
4661
+ * <bf-breadcrumb [maxItems]="3">
4662
+ * <li bfBreadcrumbItem><a routerLink="/">Home</a></li>
4663
+ * <li bfBreadcrumbItem><a routerLink="/projects">Projects</a></li>
4664
+ * <li bfBreadcrumbItem><a routerLink="/projects/atlas">Atlas</a></li>
4665
+ * <li bfBreadcrumbItem>Settings</li>
4666
+ * </bf-breadcrumb>
4667
+ * @summary Desktop breadcrumb trail of links to the current page, with optional collapsing
4668
+ * @category Navigation
4669
+ * @since 0.3.1
4670
+ * @slot default The levels, each a `li[bfBreadcrumbItem]`, the current page last.
4671
+ * @slot overflow Replaces the ellipsis button of a collapsed trail, e.g. a menu of the hidden levels.
4672
+ */
4673
+ export declare class BfBreadcrumbComponent implements BfBreadcrumbTrail {
4674
+ private readonly labels;
4675
+ private readonly injector;
4676
+ /** Accessible name of the navigation; empty falls back to `provideBfLabels()`'s `breadcrumb`
4677
+ * ("Breadcrumb"). */
4678
+ readonly label: import("@angular/core").InputSignal<string>;
4679
+ /**
4680
+ * Collapse a trail longer than this: keep the first level and the last `maxItems - 1` and hide
4681
+ * the middle ones behind an ellipsis. `0` never collapses; values below 2 act as 2, so the
4682
+ * current page always stays.
4683
+ */
4684
+ readonly maxItems: import("@angular/core").InputSignalWithTransform<number, unknown>;
4685
+ /** The rendered navigation name: `label`, else the `breadcrumb` label. */
4686
+ protected readonly name: import("@angular/core").Signal<string>;
4687
+ private readonly items;
4688
+ private readonly itemElements;
4689
+ private readonly more;
4690
+ private readonly expanded;
4691
+ /** How many middle levels the trail hides right now; 0 when it shows all of them. */
4692
+ readonly hiddenCount: import("@angular/core").Signal<number>;
4693
+ protected readonly expandLabel: import("@angular/core").Signal<string>;
4694
+ protected readonly expandClasses: string;
4695
+ protected readonly separator = "size-1.5 shrink-0 rotate-45 border-t-[1.5px] border-r-[1.5px] border-text-subtle rtl:-rotate-135";
4696
+ constructor();
4697
+ /**
4698
+ * Whether `item` is the last level, the current page.
4699
+ * @internal
4700
+ */
4701
+ isCurrent(item: object): boolean;
4702
+ /**
4703
+ * Whether `item` is one of the middle levels the collapsed trail hides.
4704
+ * @internal
4705
+ */
4706
+ isHidden(item: object): boolean;
4707
+ /**
4708
+ * Shows every level in place and moves focus to the first one it revealed (its link).
4709
+ * @internal
4710
+ */
4711
+ expand(): void;
4712
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfBreadcrumbComponent, never>;
4713
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfBreadcrumbComponent, "bf-breadcrumb", never, {
4714
+ "label": {
4715
+ "alias": "label";
4716
+ "required": false;
4717
+ "isSignal": true;
4718
+ };
4719
+ "maxItems": {
4720
+ "alias": "maxItems";
4721
+ "required": false;
4722
+ "isSignal": true;
4723
+ };
4724
+ }, {}, ["items", "itemElements"], ["[bfSlot=overflow]", "*"], true, never>;
4725
+ }
4726
+ declare const BREADCRUMB_SEPARATOR = "size-1.5 shrink-0 rotate-45 border-t-[1.5px] border-r-[1.5px] border-text-subtle rtl:-rotate-135";
4727
+ /**
4728
+ * One level of a `bf-breadcrumb` trail, on the consumer's own `<li>` so the list stays `ol > li`.
4729
+ * Project an `<a routerLink>` for an ancestor page, or plain text for the current page; the last
4730
+ * item is the current page (`aria-current="page"`, no link look, no separator), every other one is
4731
+ * followed by a chevron.
4732
+ *
4733
+ * @example
4734
+ * <li bfBreadcrumbItem><a routerLink="/projects">Projects</a></li>
4735
+ * <li bfBreadcrumbItem>Atlas</li>
4736
+ * @summary One level of a breadcrumb trail: a link, or the current page as text
4737
+ * @category Navigation
4738
+ * @since 0.3.1
4739
+ * @slot default The level: an `<a>` link to the page, or plain text for the current page.
4740
+ */
4741
+ export declare class BfBreadcrumbItemComponent {
4742
+ private readonly trail;
4743
+ private readonly host;
4744
+ /** Whether this item is the last of the trail, the current page. */
4745
+ readonly current: import("@angular/core").Signal<boolean>;
4746
+ /** Whether a collapsed trail hides this item behind its ellipsis. */
4747
+ readonly hidden: import("@angular/core").Signal<boolean>;
4748
+ protected readonly classes: import("@angular/core").Signal<string>;
4749
+ protected readonly separator = "size-1.5 shrink-0 rotate-45 border-t-[1.5px] border-r-[1.5px] border-text-subtle rtl:-rotate-135";
4750
+ /**
4751
+ * Moves keyboard focus to the item's link (or other focusable content); an item without one
4752
+ * takes focus itself through `tabindex="-1"`. Called by `bf-breadcrumb` after the ellipsis
4753
+ * reveals the hidden levels.
4754
+ * @internal
4755
+ */
4756
+ focus(): void;
4757
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfBreadcrumbItemComponent, never>;
4758
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfBreadcrumbItemComponent, "li[bfBreadcrumbItem]", never, {}, {}, never, ["*"], true, never>;
4759
+ }
4760
+ /**
4761
+ * The vertical navigation of a desktop app: a `nav` landmark with a `header` slot (the brand),
4762
+ * the destinations (`a[bfNavItem]` links, optionally in `bf-nav-group`s) and a `footer` slot.
4763
+ * `collapsed` turns it into an icon rail; the consumer owns the toggle button and binds
4764
+ * `[(collapsed)]`. Below a breakpoint hide it (`class="hidden md:flex"`) and drive a
4765
+ * `bf-menu-button` from the same routes.
4766
+ *
4767
+ * @example
4768
+ * <bf-sidebar label="Main" [(collapsed)]="collapsed" class="hidden md:flex">
4769
+ * <a bfSlot="header" routerLink="/">Atlas</a>
4770
+ * <bf-nav-group label="Workspace">
4771
+ * <a bfNavItem routerLink="/inbox" routerLinkActive ariaCurrentWhenActive="page">
4772
+ * <bf-icon bfSlot="icon" [icon]="Inbox" />
4773
+ * Inbox
4774
+ * </a>
4775
+ * </bf-nav-group>
4776
+ * </bf-sidebar>
4777
+ * @summary Vertical app navigation with brand, grouped links, footer and an icon rail mode
4778
+ * @category Navigation
4779
+ * @since 0.3.1
4780
+ * @slot header The brand or app switcher above the destinations.
4781
+ * @slot default The destinations: `a[bfNavItem]` links and `bf-nav-group`s.
4782
+ * @slot footer Content under the destinations, such as settings or the account.
4783
+ */
4784
+ export declare class BfSidebarComponent {
4785
+ /** Accessible name of the navigation; empty falls back to `provideBfLabels()`'s `navigation`
4786
+ * ("Main"). Name each landmark differently when a page has more than one. */
4787
+ readonly label: import("@angular/core").InputSignal<string>;
4788
+ /** Collapses the sidebar to an icon rail: items show their icon only, their label stays for
4789
+ * screen readers and becomes a tooltip. Bind `[(collapsed)]` to your own toggle button. */
4790
+ readonly collapsed: import("@angular/core").ModelSignal<boolean>;
4791
+ private readonly labels;
4792
+ /** The rendered navigation name: `label`, else the `navigation` label. */
4793
+ protected readonly name: import("@angular/core").Signal<string>;
4794
+ private readonly width;
4795
+ readonly hostClasses: import("@angular/core").Signal<string>;
4796
+ protected readonly regionClasses: import("@angular/core").Signal<string>;
4797
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfSidebarComponent, never>;
4798
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfSidebarComponent, "bf-sidebar", never, {
4799
+ "label": {
4800
+ "alias": "label";
4801
+ "required": false;
4802
+ "isSignal": true;
4803
+ };
4804
+ "collapsed": {
4805
+ "alias": "collapsed";
4806
+ "required": false;
4807
+ "isSignal": true;
4808
+ };
4809
+ }, {
4810
+ "collapsed": "collapsedChange";
4811
+ }, never, ["[bfSlot=header]", "*", "[bfSlot=footer]"], true, never>;
4812
+ }
4813
+ /**
4814
+ * The horizontal navigation of a desktop app with few sections: a `nav` landmark holding a row
4815
+ * of `a[bfNavItem]` links that wraps onto more lines in a narrow container. Each link marks the
4816
+ * current page from `aria-current="page"`, as in `bf-sidebar`.
4817
+ *
4818
+ * @example
4819
+ * <bf-top-nav label="Sections">
4820
+ * <a bfNavItem routerLink="/overview" routerLinkActive ariaCurrentWhenActive="page">Overview</a>
4821
+ * <a bfNavItem routerLink="/reports" routerLinkActive ariaCurrentWhenActive="page">Reports</a>
4822
+ * </bf-top-nav>
4823
+ * @summary Horizontal app navigation, a wrapping row of links for apps with few sections
4824
+ * @category Navigation
4825
+ * @since 0.3.1
4826
+ * @slot default The destinations, `a[bfNavItem]` links.
4827
+ */
4828
+ export declare class BfTopNavComponent {
4829
+ /** Accessible name of the navigation; empty falls back to `provideBfLabels()`'s `navigation`
4830
+ * ("Main"). Name each landmark differently when a page has more than one. */
4831
+ readonly label: import("@angular/core").InputSignal<string>;
4832
+ private readonly labels;
4833
+ /** The rendered navigation name: `label`, else the `navigation` label. */
4834
+ protected readonly name: import("@angular/core").Signal<string>;
4835
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfTopNavComponent, never>;
4836
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfTopNavComponent, "bf-top-nav", never, {
4837
+ "label": {
4838
+ "alias": "label";
4839
+ "required": false;
4840
+ "isSignal": true;
4841
+ };
4842
+ }, {}, never, ["*"], true, never>;
4843
+ }
4844
+ /**
4845
+ * A titled group of `a[bfNavItem]` links inside a `bf-sidebar`: `label` is shown as a small
4846
+ * heading above them and names the group (`role="group"`) for screen readers, also while the
4847
+ * sidebar is collapsed and the heading is hidden.
4848
+ *
4849
+ * @example
4850
+ * <bf-nav-group label="Workspace">
4851
+ * <a bfNavItem routerLink="/inbox" routerLinkActive ariaCurrentWhenActive="page">Inbox</a>
4852
+ * <a bfNavItem routerLink="/projects" routerLinkActive ariaCurrentWhenActive="page">Projects</a>
4853
+ * </bf-nav-group>
4854
+ * @summary A titled group of sidebar links with a small heading that names it
4855
+ * @category Navigation
4856
+ * @since 0.3.1
4857
+ * @slot default The group's `a[bfNavItem]` links.
4858
+ */
4859
+ export declare class BfNavGroupComponent {
4860
+ /** The group's heading and accessible name, such as "Workspace". */
4861
+ readonly label: import("@angular/core").InputSignal<string>;
4862
+ private readonly nav;
4863
+ /** The heading's id, referenced by the group's `aria-labelledby`. */
4864
+ protected readonly headingId: string;
4865
+ private readonly form;
4866
+ readonly hostClasses: import("@angular/core").Signal<string>;
4867
+ protected readonly headingClasses: import("@angular/core").Signal<string>;
4868
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfNavGroupComponent, never>;
4869
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfNavGroupComponent, "bf-nav-group", never, {
4870
+ "label": {
4871
+ "alias": "label";
4872
+ "required": true;
4873
+ "isSignal": true;
4874
+ };
4875
+ }, {}, never, ["*"], true, never>;
4876
+ }
4877
+ /**
4878
+ * One destination of a `bf-sidebar` or `bf-top-nav`: put `bfNavItem` on your own `<a>` with
4879
+ * `routerLink`, `routerLinkActive` and `ariaCurrentWhenActive="page"`, and the item shows the
4880
+ * current page from `aria-current`. An icon goes in the `icon` slot, the label in the default
4881
+ * slot; `badge` adds a count. In a collapsed sidebar only the icon shows, the label stays for
4882
+ * screen readers and becomes the `title` tooltip.
4883
+ *
4884
+ * @example
4885
+ * <a bfNavItem routerLink="/inbox" routerLinkActive ariaCurrentWhenActive="page" [badge]="3">
4886
+ * <bf-icon bfSlot="icon" [icon]="Inbox" />
4887
+ * Inbox
4888
+ * </a>
4889
+ * @summary Navigation link for a sidebar or top nav, with icon, label and count
4890
+ * @category Navigation
4891
+ * @since 0.3.1
4892
+ * @slot icon An icon before the label, a `bf-icon`; the only thing shown while collapsed.
4893
+ * @slot default The label.
4894
+ */
4895
+ export declare class BfNavItemComponent {
4896
+ /** Height step: sm 32, md 40, lg 48 px (44 px at least under a coarse pointer); unset follows
4897
+ * `provideBfDefaults()` (`controlSize`, `md` by default). */
4898
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
4899
+ /** A count shown as a pill at the inline end (a dot while collapsed), announced with
4900
+ * `provideBfLabels()`'s `navBadge(count)` ("3 new"); `null` shows none. */
4901
+ readonly badge: import("@angular/core").InputSignal<number | null>;
4902
+ private readonly defaults;
4903
+ private readonly labels;
4904
+ private readonly nav;
4905
+ /** The consumer's own `title`, kept while the item shows its label. */
4906
+ private readonly ownTitle;
4907
+ private readonly label;
4908
+ /** The projected label's text, for the collapsed `title`. */
4909
+ private readonly labelText;
4910
+ /** True while the enclosing sidebar is collapsed to an icon rail. */
4911
+ protected readonly collapsed: import("@angular/core").Signal<boolean>;
4912
+ private readonly form;
4913
+ /** The size in effect: `size`, else the app's `controlSize` default. */
4914
+ private readonly resolvedSize;
4915
+ readonly classes: import("@angular/core").Signal<string>;
4916
+ protected readonly labelClasses: import("@angular/core").Signal<string>;
4917
+ protected readonly badgeClasses: import("@angular/core").Signal<string>;
4918
+ /** The badge as screen readers hear it after the label. */
4919
+ protected readonly badgeAnnouncement: import("@angular/core").Signal<string>;
4920
+ /** Collapsed, the label as the pointer tooltip; else the consumer's own `title`, if any. */
4921
+ protected readonly hoverTitle: import("@angular/core").Signal<string | null>;
4922
+ constructor();
4923
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfNavItemComponent, never>;
4924
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfNavItemComponent, "a[bfNavItem]", never, {
4925
+ "size": {
4926
+ "alias": "size";
4927
+ "required": false;
4928
+ "isSignal": true;
4929
+ };
4930
+ "badge": {
4931
+ "alias": "badge";
4932
+ "required": false;
4933
+ "isSignal": true;
4934
+ };
4935
+ }, {}, never, ["[bfSlot=icon]", "*"], true, never>;
4936
+ }
4937
+ /**
4938
+ * The shape of a `bf-skeleton`: text lines, a rectangle (an image, a chart, a field) or a circle
4939
+ * (an avatar).
4940
+ *
4941
+ * @summary The three skeleton shapes, text lines, a rectangle or a circle
4942
+ * @since 0.3.1
4943
+ */
4944
+ type BfSkeletonShape = 'text' | 'rect' | 'circle';
4945
+ /**
4946
+ * Loading placeholder in the shape of the content to come: text lines, a rectangle or a circle,
4947
+ * on the sunken surface with a shimmer. It is hidden from assistive technology; mark the region it
4948
+ * stands in for with `aria-busy="true"` while it loads.
4949
+ *
4950
+ * @example
4951
+ * <div aria-busy="true">
4952
+ * <bf-skeleton shape="circle" />
4953
+ * <bf-skeleton [lines]="3" />
4954
+ * <bf-skeleton shape="rect" height="8rem" />
4955
+ * </div>
4956
+ * @summary Loading placeholder shaped as text lines, a rectangle or a circle, with a shimmer
4957
+ * @category Feedback
4958
+ * @since 0.3.1
4959
+ */
4960
+ export declare class BfSkeletonComponent {
4961
+ /** What it stands in for: `text` lines (default), a `rect` (an image, a chart) or a `circle`
4962
+ * (an avatar). */
4963
+ readonly shape: import("@angular/core").InputSignal<BfSkeletonShape>;
4964
+ /** How many lines a `text` skeleton draws, the last one shorter when there are several;
4965
+ * ignored by the other shapes. */
4966
+ readonly lines: import("@angular/core").InputSignalWithTransform<number, unknown>;
4967
+ /** Width as a CSS length (`12rem`, `60%`); empty fills the container, a circle is 40 px. A
4968
+ * circle's height follows its width. */
4969
+ readonly width: import("@angular/core").InputSignal<string>;
4970
+ /** Height as a CSS length: of each line of `text` (default `0.75rem`) or of the `rect`
4971
+ * (default `6rem`); a circle ignores it. */
4972
+ readonly height: import("@angular/core").InputSignal<string>;
4973
+ protected readonly lineClasses = "relative overflow-hidden bg-surface-sunken after:absolute after:inset-0 after:bg-linear-to-r after:from-transparent after:via-surface/70 after:to-transparent after:content-[''] after:animate-skeleton-shimmer rtl:after:animate-skeleton-shimmer-rtl motion-reduce:after:hidden forced-colors:border forced-colors:border-[GrayText] block h-[var(--bf-skeleton-height,0.75rem)] w-full rounded-full";
4974
+ protected readonly lastLineClasses = "relative overflow-hidden bg-surface-sunken after:absolute after:inset-0 after:bg-linear-to-r after:from-transparent after:via-surface/70 after:to-transparent after:content-[''] after:animate-skeleton-shimmer rtl:after:animate-skeleton-shimmer-rtl motion-reduce:after:hidden forced-colors:border forced-colors:border-[GrayText] block h-[var(--bf-skeleton-height,0.75rem)] w-3/5 rounded-full";
4975
+ /** The line numbers 1…n of a text skeleton; `lines` below 1 draws one. */
4976
+ protected readonly lineList: import("@angular/core").Signal<number[]>;
4977
+ protected readonly hostClasses: import("@angular/core").Signal<string>;
4978
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfSkeletonComponent, never>;
4979
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfSkeletonComponent, "bf-skeleton", never, {
4980
+ "shape": {
4981
+ "alias": "shape";
4982
+ "required": false;
4983
+ "isSignal": true;
4984
+ };
4985
+ "lines": {
4986
+ "alias": "lines";
4987
+ "required": false;
4988
+ "isSignal": true;
4989
+ };
4990
+ "width": {
4991
+ "alias": "width";
4992
+ "required": false;
4993
+ "isSignal": true;
4994
+ };
4995
+ "height": {
4996
+ "alias": "height";
4997
+ "required": false;
4998
+ "isSignal": true;
4999
+ };
5000
+ }, {}, never, never, true, never>;
5001
+ }
5002
+ /** One slot of the page row: a page number, or a gap before or after the current page's run. */
5003
+ type BfPaginationItem = number | 'gap-start' | 'gap-end';
5004
+ type BfPaginationDirection = 'previous' | 'next';
5005
+ /**
5006
+ * Page navigation for a long list or table: Previous and Next buttons around the page numbers,
5007
+ * the current one marked, the hidden runs shown as an ellipsis. `compact` shows "Page 3 of 12"
5008
+ * between the arrows instead, for narrow screens. The page count comes from `pageCount`, or from
5009
+ * `total` and `pageSize`; the consumer shows the rows of `page`.
5010
+ *
5011
+ * @example
5012
+ * <bf-pagination [(page)]="page" [pageCount]="12" />
5013
+ * <bf-pagination [(page)]="page" [total]="invoices().length" [pageSize]="10" compact />
5014
+ * @summary Previous, next and numbered page buttons for a long list or table
5015
+ * @category Navigation
5016
+ * @since 0.3.1
5017
+ */
5018
+ export declare class BfPaginationComponent {
5019
+ /** The current page, 1-based; two-way bindable. The buttons set it; show the rows of this page. */
5020
+ readonly page: import("@angular/core").ModelSignal<number>;
5021
+ /** The number of pages; wins over `total` and `pageSize` when above 0. */
5022
+ readonly pageCount: import("@angular/core").InputSignalWithTransform<number, unknown>;
5023
+ /** The number of items, used with `pageSize` while `pageCount` is 0. */
5024
+ readonly total: import("@angular/core").InputSignalWithTransform<number, unknown>;
5025
+ /** Items per page, used with `total` while `pageCount` is 0. */
5026
+ readonly pageSize: import("@angular/core").InputSignalWithTransform<number, unknown>;
5027
+ /** How many pages to show on each side of the current one. */
5028
+ readonly siblings: import("@angular/core").InputSignalWithTransform<number, unknown>;
5029
+ /** Shows "Page 3 of 12" between the arrows instead of the page buttons, for narrow screens. */
5030
+ readonly compact: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5031
+ /** Button height step: sm 32, md 40, lg 48 px (44 px hit area under a coarse pointer); unset
5032
+ * follows `provideBfDefaults()` (`controlSize`, `md` by default). */
5033
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
5034
+ /** Accessible name of the navigation; empty falls back to `provideBfLabels()`'s `pagination`
5035
+ * ("Pagination"). */
5036
+ readonly label: import("@angular/core").InputSignal<string>;
5037
+ protected readonly labels: import("@bitforgehq/ui").BfLabels;
5038
+ private readonly defaults;
5039
+ /** The size in effect: `size`, else the app's `controlSize` default. */
5040
+ protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
5041
+ /** The navigation's name: `label`, else the `pagination` label. */
5042
+ protected readonly name: import("@angular/core").Signal<string>;
5043
+ /** The page count in effect, at least 1: `pageCount`, else `total` over `pageSize`. */
5044
+ protected readonly count: import("@angular/core").Signal<number>;
5045
+ /** The page shown as current: `page`, clamped to 1…count. */
5046
+ protected readonly current: import("@angular/core").Signal<number>;
5047
+ protected readonly items: import("@angular/core").Signal<BfPaginationItem[]>;
5048
+ protected readonly chevron: Record<BfPaginationDirection, string>;
5049
+ protected readonly pageClasses: import("@angular/core").Signal<string>;
5050
+ protected readonly gapClasses: import("@angular/core").Signal<string>;
5051
+ protected readonly statusClasses: import("@angular/core").Signal<string>;
5052
+ /**
5053
+ * The classes of the previous or next button.
5054
+ * @internal
5055
+ */
5056
+ arrowClasses(disabled: boolean): string;
5057
+ /**
5058
+ * Goes to a page: sets `page` when it is another page within 1…count; else does nothing.
5059
+ * @param target The 1-based page to go to.
5060
+ */
5061
+ go(target: number): void;
5062
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfPaginationComponent, never>;
5063
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfPaginationComponent, "bf-pagination", never, {
5064
+ "page": {
5065
+ "alias": "page";
5066
+ "required": false;
5067
+ "isSignal": true;
5068
+ };
5069
+ "pageCount": {
5070
+ "alias": "pageCount";
5071
+ "required": false;
5072
+ "isSignal": true;
5073
+ };
5074
+ "total": {
5075
+ "alias": "total";
5076
+ "required": false;
5077
+ "isSignal": true;
5078
+ };
5079
+ "pageSize": {
5080
+ "alias": "pageSize";
5081
+ "required": false;
5082
+ "isSignal": true;
5083
+ };
5084
+ "siblings": {
5085
+ "alias": "siblings";
5086
+ "required": false;
5087
+ "isSignal": true;
5088
+ };
5089
+ "compact": {
5090
+ "alias": "compact";
5091
+ "required": false;
5092
+ "isSignal": true;
5093
+ };
5094
+ "size": {
5095
+ "alias": "size";
5096
+ "required": false;
5097
+ "isSignal": true;
5098
+ };
5099
+ "label": {
5100
+ "alias": "label";
5101
+ "required": false;
5102
+ "isSignal": true;
5103
+ };
5104
+ }, {
5105
+ "page": "pageChange";
5106
+ }, never, never, true, never>;
5107
+ }
5108
+ /**
5109
+ * A weekday as `Date.getDay()` counts it: 0 Sunday, 1 Monday … 6 Saturday.
5110
+ *
5111
+ * @summary A weekday number from 0 for Sunday to 6 for Saturday, as Date counts
5112
+ * @since 0.3.1
5113
+ */
5114
+ type BfCalendarWeekday = 0 | 1 | 2 | 3 | 4 | 5 | 6;
5115
+ /**
5116
+ * Tells `bf-calendar` which dates cannot be picked, such as weekends or booked days.
5117
+ *
5118
+ * @summary A function that marks an ISO date as not pickable in a calendar
5119
+ * @since 0.3.1
5120
+ */
5121
+ type BfCalendarDisabledDate = (iso: string) => boolean;
5122
+ /** The day grid, or one of the two jump views the title button opens. */
5123
+ type CalendarView = 'day' | 'month' | 'year';
5124
+ /** One cell of a calendar grid, as the template renders it. */
5125
+ interface CalendarCell {
5126
+ /** The ISO date, month or year the cell stands for. */
5127
+ readonly key: string;
5128
+ /** The visible text. */
5129
+ readonly text: string;
5130
+ /** The accessible name, when the visible text alone is too short. */
5131
+ readonly name: string | null;
5132
+ readonly disabled: boolean;
5133
+ readonly selected: boolean;
5134
+ readonly current: boolean;
5135
+ readonly tabStop: boolean;
5136
+ }
5137
+ /** One weekday column header: the short name shown, the full name in `abbr`. */
5138
+ interface CalendarWeekday {
5139
+ readonly short: string;
5140
+ readonly long: string;
5141
+ }
5142
+ /**
5143
+ * Inline month calendar for picking one date, an ARIA grid with full keyboard support. The value
5144
+ * is a plain ISO date string ('YYYY-MM-DD', never a Date with a time zone) or `null`; month and
5145
+ * weekday names come from `Intl` in the calendar's `locale`; implements the Signal Forms value
5146
+ * contract.
5147
+ *
5148
+ * @example
5149
+ * <bf-calendar label="Due date" min="2026-01-01" [(value)]="due" />
5150
+ * @summary Inline month calendar for picking one date, with month and year jumps
5151
+ * @category Forms
5152
+ * @since 0.3.1
5153
+ */
5154
+ export declare class BfCalendarComponent implements FormValueControl<string | null> {
5155
+ private readonly defaults;
5156
+ private readonly document;
5157
+ private readonly injector;
5158
+ /** The strings in effect; the template reads the button names from them. */
5159
+ protected readonly labels: import("@bitforgehq/ui").BfLabels;
5160
+ /** The picked date as an ISO string ('YYYY-MM-DD'), `null` while none is picked; two-way
5161
+ * bindable and bound by `[formField]`. */
5162
+ readonly value: import("@angular/core").ModelSignal<string | null>;
5163
+ /** The month on show ('YYYY-MM'), two-way bindable; `null` shows the value's month, else
5164
+ * today's. The previous/next buttons, the month and year views and the keyboard set it. */
5165
+ readonly month: import("@angular/core").ModelSignal<string | null>;
5166
+ /** The earliest date that can be picked (ISO); earlier dates show disabled. */
5167
+ readonly min: import("@angular/core").InputSignal<string | undefined>;
5168
+ /** The latest date that can be picked (ISO); later dates show disabled. */
5169
+ readonly max: import("@angular/core").InputSignal<string | undefined>;
5170
+ /** Marks more dates as not pickable (weekends, booked days); called with each ISO date. */
5171
+ readonly disabledDate: import("@angular/core").InputSignal<BfCalendarDisabledDate | null>;
5172
+ /** The first column's weekday, 0 Sunday to 6 Saturday; unset follows the locale's week (else
5173
+ * Monday). */
5174
+ readonly firstDayOfWeek: import("@angular/core").InputSignal<BfCalendarWeekday | undefined>;
5175
+ /** BCP 47 locale of the month and weekday names and of the week; empty follows the
5176
+ * document's `lang`, else English. */
5177
+ readonly locale: import("@angular/core").InputSignal<string>;
5178
+ /** The date marked as today (ISO); unset is the device's local date. */
5179
+ readonly today: import("@angular/core").InputSignal<string | undefined>;
5180
+ /** Cell size: sm 32, md 40, lg 48 px (44 px under a coarse pointer); unset follows
5181
+ * `provideBfDefaults()` (`controlSize`, `md` by default). */
5182
+ readonly size: import("@angular/core").InputSignal<BfSize | undefined>;
5183
+ /** Disables the whole calendar: nothing is focusable or pickable. */
5184
+ readonly disabled: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5185
+ /** Shows the value and lets the user browse the months, but blocks picking. */
5186
+ readonly readonly: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5187
+ /** Marks the date required (`aria-required` on the day grid). */
5188
+ readonly required: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5189
+ /** Field validity from Signal Forms. */
5190
+ readonly invalid: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5191
+ /** Whether the user has left the calendar; errors show only once touched. */
5192
+ readonly touched: import("@angular/core").InputSignalWithTransform<boolean, unknown>;
5193
+ /** Validation errors from Signal Forms; the first message is shown once touched. */
5194
+ readonly errors: import("@angular/core").InputSignal<readonly ValidationError.WithOptionalFieldTree[]>;
5195
+ /** Explicit error text; takes precedence over Signal Forms errors. */
5196
+ readonly errorMessage: import("@angular/core").InputSignal<string>;
5197
+ /** Accessible name of the calendar (not rendered visibly), such as "Due date". */
5198
+ readonly label: import("@angular/core").InputSignal<string>;
5199
+ /** Accessible name when `label` is not set. */
5200
+ readonly ariaLabel: import("@angular/core").InputSignal<string>;
5201
+ /** Id(s) of the element(s) that name the calendar (a visible heading) when `label` is not
5202
+ * set. */
5203
+ readonly ariaLabelledby: import("@angular/core").InputSignal<string>;
5204
+ /** Name of the bound field. Not rendered (the calendar has no native form element); kept so
5205
+ * Signal Forms can bind it. */
5206
+ readonly name: import("@angular/core").InputSignal<string>;
5207
+ /** The calendar's id; generated when not set. */
5208
+ readonly id: import("@angular/core").InputSignal<string>;
5209
+ /** Emitted with the new date right after the user picks a different one. */
5210
+ readonly changed: import("@angular/core").OutputEmitterRef<string>;
5211
+ /** Emitted with the date the user picked (click, Enter or Space), also when it already was
5212
+ * the value, so a popover around the calendar can close. */
5213
+ readonly picked: import("@angular/core").OutputEmitterRef<string>;
5214
+ /** Emitted when focus leaves the calendar, so Signal Forms marks the field touched. */
5215
+ readonly touch: import("@angular/core").OutputEmitterRef<void>;
5216
+ private readonly root;
5217
+ /** Which grid is on show: the days, or the month or year jump view. */
5218
+ protected readonly view: import("@angular/core").WritableSignal<CalendarView>;
5219
+ /** The day the keyboard last moved to; the tab stop while it is in the shown month. */
5220
+ private readonly activeDate;
5221
+ /** The month the month view's tab stop is on (its year is the view's year). */
5222
+ private readonly activeMonth;
5223
+ /** The year the year view's tab stop is on. */
5224
+ private readonly activeYear;
5225
+ protected readonly resolvedSize: import("@angular/core").Signal<BfSize>;
5226
+ /** The locale in effect: `locale`, else the document's `lang`, else English. */
5227
+ readonly resolvedLocale: import("@angular/core").Signal<string>;
5228
+ /** The first column's weekday: `firstDayOfWeek`, else the locale's, else Monday. */
5229
+ readonly firstDay: import("@angular/core").Signal<number>;
5230
+ private readonly minDate;
5231
+ private readonly maxDate;
5232
+ private readonly todayDate;
5233
+ private readonly selectedDate;
5234
+ /** The month on show: `month`, else the value's month, else today's (kept inside min/max). */
5235
+ readonly shownMonth: import("@angular/core").Signal<string>;
5236
+ private readonly formats;
5237
+ /** The shown month and year, such as "October 2026". */
5238
+ protected readonly monthTitle: import("@angular/core").Signal<string>;
5239
+ /** The header's title: the month and year, the month view's year or the year view's year. */
5240
+ protected readonly title: import("@angular/core").Signal<string>;
5241
+ /** What the title button does, read after its text. */
5242
+ protected readonly titleAction: import("@angular/core").Signal<string>;
5243
+ protected readonly titleId: import("@angular/core").Signal<string>;
5244
+ /** Whether the previous month lies wholly before `min`. */
5245
+ protected readonly atStart: import("@angular/core").Signal<boolean>;
5246
+ /** Whether the next month lies wholly after `max`. */
5247
+ protected readonly atEnd: import("@angular/core").Signal<boolean>;
5248
+ /** The weekday column headers, from the first day of the week on. */
5249
+ protected readonly weekdays: import("@angular/core").Signal<CalendarWeekday[]>;
5250
+ /** The day that owns the grid's tab stop: the active day while it is in the shown month, else
5251
+ * the value, else today, else the first pickable-by-range day of the month. */
5252
+ readonly tabStopDate: import("@angular/core").Signal<string>;
5253
+ /** The day grid: weeks of seven cells, `null` for the neighbouring months' days. */
5254
+ protected readonly dayRows: import("@angular/core").Signal<(CalendarCell | null)[][]>;
5255
+ /** The month view: the twelve months of the active month's year, three to a row. */
5256
+ protected readonly monthRows: import("@angular/core").Signal<CalendarCell[][]>;
5257
+ /** The first and last year the year view lists: `min`'s and `max`'s, else 100 years around. */
5258
+ private readonly yearRange;
5259
+ /** The year view: the years of `yearRange`, four to a row. */
5260
+ protected readonly yearRows: import("@angular/core").Signal<CalendarCell[][]>;
5261
+ readonly errorText: import("@angular/core").Signal<string>;
5262
+ readonly showError: import("@angular/core").Signal<boolean>;
5263
+ /** The error paragraph: `errorText`, visually hidden while a press elsewhere (that blurred
5264
+ * this calendar) holds the layout, so it never moves under the pointer. */
5265
+ protected readonly message: HeldMessage;
5266
+ /** The id of the error paragraph while there is an error, else null. */
5267
+ protected readonly errorId: import("@angular/core").Signal<string | null>;
5268
+ /** `aria-label` of the group: the `label`, else `ariaLabel`. */
5269
+ readonly ariaLabelAttr: import("@angular/core").Signal<string | null>;
5270
+ /** `aria-labelledby` of the group: only while no `label` names it. */
5271
+ readonly ariaLabelledbyAttr: import("@angular/core").Signal<string | null>;
5272
+ protected readonly frameClasses: import("@angular/core").Signal<string>;
5273
+ protected readonly bodyClasses: import("@angular/core").Signal<string>;
5274
+ protected readonly titleClasses: import("@angular/core").Signal<string>;
5275
+ protected readonly emptyCellClasses: import("@angular/core").Signal<string>;
5276
+ protected readonly weekdayClasses = "h-8 p-0 text-center align-middle text-label-xs font-normal text-text-muted";
5277
+ /**
5278
+ * The classes of the previous or next month button.
5279
+ * @internal
5280
+ */
5281
+ navClasses(direction: 'previous' | 'next'): string;
5282
+ /**
5283
+ * The classes of a day cell.
5284
+ * @internal
5285
+ */
5286
+ cellClasses(cell: CalendarCell): string;
5287
+ /**
5288
+ * The classes of a month or year cell: a little padding between the pills.
5289
+ * @internal
5290
+ */
5291
+ pickCellClasses(cell: CalendarCell): string;
5292
+ /**
5293
+ * The classes of the mark inside a cell.
5294
+ * @internal
5295
+ */
5296
+ markClasses(cell: CalendarCell, kind: 'day' | 'pick'): string;
5297
+ /**
5298
+ * Whether a date cannot be picked: it is outside `min`…`max` or `disabledDate` rules it out.
5299
+ * @param iso The ISO date to check.
5300
+ * @returns True when the date shows disabled.
5301
+ */
5302
+ isDateDisabled(iso: string): boolean;
5303
+ /**
5304
+ * Focuses the cell that owns the tab stop of the grid on show; Signal Forms calls it from
5305
+ * `focusBoundControl()`.
5306
+ * @param options Passed on to the native `focus()`, such as `{ preventScroll: true }`.
5307
+ */
5308
+ focus(options?: FocusOptions): void;
5309
+ /**
5310
+ * Picks `iso` as a click on its day would: ignored while disabled or read-only, and for an
5311
+ * invalid or disabled date. Shows its month.
5312
+ * @param iso The ISO date to pick.
5313
+ */
5314
+ select(iso: string): void;
5315
+ /**
5316
+ * Shows the month `offset` months away (the previous/next buttons); ignored past `min`/`max`.
5317
+ * @internal
5318
+ */
5319
+ showMonth(offset: number): void;
5320
+ /**
5321
+ * The title button: the day view opens the month view, the month view the year view.
5322
+ * @internal
5323
+ */
5324
+ openNextView(): void;
5325
+ /**
5326
+ * A click on a day.
5327
+ * @internal
5328
+ */
5329
+ pick(cell: CalendarCell): void;
5330
+ /**
5331
+ * A click (or Enter, Space) on a month of the month view: shows it in the day view.
5332
+ * @internal
5333
+ */
5334
+ pickMonth(cell: CalendarCell): void;
5335
+ /**
5336
+ * A click (or Enter, Space) on a year of the year view: opens that year's month view.
5337
+ * @internal
5338
+ */
5339
+ pickYear(cell: CalendarCell): void;
5340
+ /**
5341
+ * Escape in the month or year view returns to the day view (and stops there, so a popover
5342
+ * around the calendar stays open).
5343
+ * @internal
5344
+ */
5345
+ onKeydown(event: KeyboardEvent): void;
5346
+ /**
5347
+ * Marks the field touched once focus leaves the calendar (not on moves between its cells).
5348
+ * @internal
5349
+ */
5350
+ onFocusout(event: FocusEvent): void;
5351
+ /**
5352
+ * The day grid's keys: arrows by day and week (mirrored under RTL), Page Up/Down by month
5353
+ * (with Shift by year), Home/End to the week's ends, Enter/Space picks.
5354
+ * @internal
5355
+ */
5356
+ onDayKeydown(event: KeyboardEvent): void;
5357
+ /**
5358
+ * The month view's keys: arrows by one month and by a row of three, Home/End to the row's
5359
+ * ends, Page Up/Down by a year, Enter/Space shows the month.
5360
+ * @internal
5361
+ */
5362
+ onMonthKeydown(event: KeyboardEvent): void;
5363
+ /**
5364
+ * The year view's keys: arrows by one year and by a row of four, Home/End to the row's ends,
5365
+ * Page Up/Down by five rows, Enter/Space opens the year's months.
5366
+ * @internal
5367
+ */
5368
+ onYearKeydown(event: KeyboardEvent): void;
5369
+ /** Moves the day grid's tab stop (and focus) to `iso`, showing its month. */
5370
+ private moveTo;
5371
+ /** +1 when ArrowRight moves forward, -1 under `dir="rtl"`, where the days run right to left. */
5372
+ private inlineStep;
5373
+ private cellMode;
5374
+ /** After the next render, focuses the tab stop of the grid on show; in the scrolling year view
5375
+ * it first scrolls the cell into the middle of the box (`center`, on opening) or just into view
5376
+ * (`nearest`, on a key move). */
5377
+ private focusAfterRender;
5378
+ static ɵfac: i0.ɵɵFactoryDeclaration<BfCalendarComponent, never>;
5379
+ static ɵcmp: i0.ɵɵComponentDeclaration<BfCalendarComponent, "bf-calendar", never, {
5380
+ "value": {
5381
+ "alias": "value";
5382
+ "required": false;
5383
+ "isSignal": true;
5384
+ };
5385
+ "month": {
5386
+ "alias": "month";
5387
+ "required": false;
5388
+ "isSignal": true;
5389
+ };
5390
+ "min": {
5391
+ "alias": "min";
5392
+ "required": false;
5393
+ "isSignal": true;
5394
+ };
5395
+ "max": {
5396
+ "alias": "max";
5397
+ "required": false;
5398
+ "isSignal": true;
5399
+ };
5400
+ "disabledDate": {
5401
+ "alias": "disabledDate";
5402
+ "required": false;
5403
+ "isSignal": true;
5404
+ };
5405
+ "firstDayOfWeek": {
5406
+ "alias": "firstDayOfWeek";
5407
+ "required": false;
5408
+ "isSignal": true;
5409
+ };
5410
+ "locale": {
5411
+ "alias": "locale";
5412
+ "required": false;
5413
+ "isSignal": true;
5414
+ };
5415
+ "today": {
5416
+ "alias": "today";
5417
+ "required": false;
5418
+ "isSignal": true;
5419
+ };
5420
+ "size": {
5421
+ "alias": "size";
5422
+ "required": false;
5423
+ "isSignal": true;
5424
+ };
5425
+ "disabled": {
5426
+ "alias": "disabled";
5427
+ "required": false;
5428
+ "isSignal": true;
5429
+ };
5430
+ "readonly": {
5431
+ "alias": "readonly";
5432
+ "required": false;
5433
+ "isSignal": true;
5434
+ };
5435
+ "required": {
5436
+ "alias": "required";
5437
+ "required": false;
5438
+ "isSignal": true;
5439
+ };
5440
+ "invalid": {
5441
+ "alias": "invalid";
5442
+ "required": false;
5443
+ "isSignal": true;
5444
+ };
5445
+ "touched": {
5446
+ "alias": "touched";
5447
+ "required": false;
5448
+ "isSignal": true;
5449
+ };
5450
+ "errors": {
5451
+ "alias": "errors";
5452
+ "required": false;
5453
+ "isSignal": true;
5454
+ };
5455
+ "errorMessage": {
5456
+ "alias": "errorMessage";
5457
+ "required": false;
5458
+ "isSignal": true;
5459
+ };
5460
+ "label": {
5461
+ "alias": "label";
5462
+ "required": false;
5463
+ "isSignal": true;
5464
+ };
5465
+ "ariaLabel": {
5466
+ "alias": "ariaLabel";
5467
+ "required": false;
5468
+ "isSignal": true;
5469
+ };
5470
+ "ariaLabelledby": {
5471
+ "alias": "ariaLabelledby";
5472
+ "required": false;
5473
+ "isSignal": true;
5474
+ };
5475
+ "name": {
5476
+ "alias": "name";
5477
+ "required": false;
5478
+ "isSignal": true;
5479
+ };
5480
+ "id": {
5481
+ "alias": "id";
5482
+ "required": false;
5483
+ "isSignal": true;
5484
+ };
5485
+ }, {
5486
+ "value": "valueChange";
5487
+ "month": "monthChange";
5488
+ "changed": "changed";
5489
+ "picked": "picked";
5490
+ "touch": "touch";
5491
+ }, never, never, true, never>;
5492
+ }
5493
+ /** An error as a field reads it: its kind and optional message; limit fields (`minLength`,
5494
+ * `context.requiredLength`, …) are read through type guards by `bfValidationMessage`. */
5495
+ type FieldErrorLike = Pick<ValidationError, 'kind' | 'message'>;
5496
+ /**
5497
+ * Explicit error message wins; otherwise, once the field was touched, the first form error's text:
5498
+ * its own `message`, else the default for its kind from `messages` (`BF_LABELS.validation`).
5499
+ */
5500
+ declare function fieldErrorText(errorMessage: string, touched: boolean, errors: readonly FieldErrorLike[], messages: BfValidationMessages): string;
5501
+ /** The visual error state: any error text, or a field the form marked invalid after it was touched. */
5502
+ declare function fieldShowsError(errorText: string, invalid: boolean, touched: boolean): boolean;
5503
+ /**
5504
+ * `aria-describedby` targets: the help paragraph and the error paragraph under it, each while it
5505
+ * is rendered (`"<id>-help <id>-error"`, `"<id>-help"`, `"<id>-error"`), else none.
5506
+ */
5507
+ declare function fieldDescribedBy(id: string, errorText: string, helpText: string): string | null;
5508
+ /** `aria-errormessage` target: the error paragraph while the control is invalid, else none. */
5509
+ declare function fieldErrorMessageId(id: string, errorText: string, showError: boolean): string | null;
5510
+ /**
5511
+ * Returns a document-unique id such as `bf-input-3`, for associating labels and hints with controls.
5512
+ *
5513
+ * The ids come from this module-level counter, so a server render and the client (or two server
5514
+ * renders in one process) number them differently: `@bitforgehq/ui` 0.x is client-rendered only,
5515
+ * and SSR, hydration and prerendering of pages that render its components are not supported.
5516
+ * Hydration-stable ids are decided before 1.0.
5517
+ */
5518
+ declare function uniqueId(prefix: string): string;
5519
+ /** One plain date's parts; `month` is 1–12. */
5520
+ interface CalendarDate {
5521
+ readonly year: number;
5522
+ readonly month: number;
5523
+ readonly day: number;
5524
+ }
5525
+ /** One calendar month's parts; `month` is 1–12. */
5526
+ interface CalendarMonth {
5527
+ readonly year: number;
5528
+ readonly month: number;
5529
+ }
5530
+ /** The number of days in `month` (1–12) of `year`, leap years included. */
5531
+ declare function daysInMonth(year: number, month: number): number;
5532
+ /** The parts of an ISO date 'YYYY-MM-DD', or `null` for anything else (a wrong day, a time). */
5533
+ declare function parseIsoDate(value: string | null | undefined): CalendarDate | null;
5534
+ /** The parts of an ISO month 'YYYY-MM', or `null` for anything else. */
5535
+ declare function parseIsoMonth(value: string | null | undefined): CalendarMonth | null;
5536
+ /** The ISO date of the parts: '2026-03-07'. */
5537
+ declare function formatIsoDate({ year, month, day }: CalendarDate): string;
5538
+ /** The ISO month of the parts: '2026-03'. */
5539
+ declare function formatIsoMonth({ year, month }: CalendarMonth): string;
5540
+ /** `iso` itself when it is a valid ISO date, else `null`. */
5541
+ declare function validIsoDate(iso: string | null | undefined): string | null;
5542
+ /** The month 'YYYY-MM' an ISO date falls in. */
5543
+ declare function isoMonthOf(iso: string): string;
5544
+ /** The first day of an ISO month. */
5545
+ declare function firstOfMonth(isoMonth: string): string;
5546
+ /** The last day of an ISO month. */
5547
+ declare function lastOfMonth(isoMonth: string): string;
5548
+ /** A Date at UTC midnight of the parts, for Intl.DateTimeFormat with `timeZone: 'UTC'`. */
5549
+ declare function toUtcDate({ year, month, day }: CalendarDate): Date;
5550
+ /** `iso` moved by `days` (negative goes back); an invalid `iso` is returned as it is. */
5551
+ declare function addDays(iso: string, days: number): string;
5552
+ /** `iso` moved by `months`, the day clamped to the target month's length (Jan 31 + 1 → Feb 28). */
5553
+ declare function addMonths(iso: string, months: number): string;
5554
+ /** `iso` moved by `years`, Feb 29 clamped to Feb 28 in a common year. */
5555
+ declare function addYears(iso: string, years: number): string;
5556
+ /** An ISO month moved by `months`. */
5557
+ declare function addIsoMonths(isoMonth: string, months: number): string;
5558
+ /** The weekday of an ISO date: 0 Sunday … 6 Saturday, as `Date.getDay()` counts. */
5559
+ declare function weekdayOf(iso: string): number;
5560
+ /** The first day of the week `iso` is in, for weeks starting on `firstDay` (0 Sunday … 6). */
5561
+ declare function startOfWeek(iso: string, firstDay: number): string;
5562
+ /** The last day of the week `iso` is in, for weeks starting on `firstDay`. */
5563
+ declare function endOfWeek(iso: string, firstDay: number): string;
5564
+ /**
5565
+ * The weeks of a month as rows of seven ISO dates from `firstDay` on, `null` for the days of the
5566
+ * neighbouring months: four to six rows.
5567
+ */
5568
+ declare function monthWeeks(isoMonth: string, firstDay: number): (string | null)[][];
5569
+ /** -1, 0 or 1 as ISO date (or month) `a` falls before, on or after `b`. */
5570
+ declare function compareIso(a: string, b: string): number;
5571
+ /** `iso` kept inside `min`…`max` (either bound may be missing). */
5572
+ declare function clampIso(iso: string, min: string | null, max: string | null): string;
5573
+ /** The device's local calendar date of `now` (the day the user sees on their clock). */
5574
+ declare function localIsoDate(now?: Date): string;
3483
5575
  /** The positioned, empty ::after that carries the extension; add one inset class beside it. */
3484
5576
  declare const COARSE_HIT_BASE = "pointer-coarse:after:absolute pointer-coarse:after:inset-x-0 pointer-coarse:after:content-['']";
3485
5577
  /**
@@ -3496,4 +5588,4 @@ declare const PILL_HIT: Record<BfSize, Record<'plain' | 'bordered', string>>;
3496
5588
  declare function resetBfDocument(document: Document): void;
3497
5589
  /** Runs `resetBfDocument()` when the environment injector that holds it is destroyed. Internal. */
3498
5590
  declare function provideBfDocumentReset(): EnvironmentProviders;
3499
- export { type BfAlertVariant, type BfAutocapitalize, type BfAvatarSize, type BfAvatarVariant, type BfBadgeVariant, type BfButtonSize, type BfButtonType, type BfButtonVariant, type BfCardPadding, type BfCardVariant, type BfChipGroupMode, type BfChipVariant, type BfCompareWith, type BfDefaults, type BfDefaultsOptions, type BfEmptyStateHeadingLevel, type BfEnterKeyHint, type BfFieldControlState, type BfFieldSize, type BfIconButtonVariant, type BfInputAutocapitalize, type BfInputEnterKeyHint, type BfInputInputMode, type BfInputMode, type BfInputType, type BfLabels, type BfLabelsOverrides, type BfProgressSize, type BfProgressTone, type BfRadioGroupOrientation, type BfRadioOption, type BfSegmentOption, type BfSegmentedSize, type BfSelectOption, type BfSize, type BfSpinnerSize, type BfTabBarController, type BfTabBarHost, type BfTabLinks, type BfToggleLabelPosition, type BfValidationMessages, BUTTON_CLASSES as ɵBF_BUTTON_CLASSES, ICON_BUTTON_CLASSES as ɵBF_ICON_BUTTON_CLASSES, FIELD_BOX as ɵFIELD_BOX, FIELD_ICON_END as ɵFIELD_ICON_END, FIELD_ICON_START as ɵFIELD_ICON_START, FIELD_PADDING_END as ɵFIELD_PADDING_END, FIELD_PADDING_START as ɵFIELD_PADDING_START, PILL_HIT as ɵPILL_HIT, fieldDescribedBy as ɵfieldDescribedBy, fieldErrorMessageId as ɵfieldErrorMessageId, fieldErrorText as ɵfieldErrorText, fieldShowsError as ɵfieldShowsError, provideBfDocumentReset as ɵprovideBfDocumentReset, uniqueId as ɵuniqueId };
5591
+ export { type BfAlertVariant, type BfAutocapitalize, type BfAvatarSize, type BfAvatarVariant, type BfBadgeAppearance, type BfBadgeVariant, type BfButtonAppearance, type BfButtonSize, type BfButtonType, type BfButtonVariant, type BfCalendarDisabledDate, type BfCalendarWeekday, type BfCardPadding, type BfCardVariant, type BfChipGroupMode, type BfChipVariant, type BfColorScheme, type BfCompareWith, type BfDefaults, type BfDefaultsOptions, type BfDescriptionListLayout, type BfEmptyStateHeadingLevel, type BfEnterKeyHint, type BfFieldControlState, type BfFieldSize, type BfIconButtonVariant, type BfInputAutocapitalize, type BfInputEnterKeyHint, type BfInputInputMode, type BfInputMode, type BfInputType, type BfLabels, type BfLabelsOverrides, type BfPageHeaderHeadingLevel, type BfProgressSize, type BfProgressTone, type BfRadioGroupOrientation, type BfRadioOption, type BfSegmentOption, type BfSegmentedSize, type BfSelectOption, type BfSize, type BfSkeletonShape, type BfSpinnerSize, type BfStatTrend, type BfStatTrendIntent, type BfStatVariant, type BfTabBarController, type BfTabBarHost, type BfTabLinks, type BfTableAlign, type BfTableCellContext, type BfTableColumn, type BfTableRowKey, type BfTableSort, type BfTableSortDirection, type BfToggleLabelPosition, type BfValidationMessages, BUTTON_CLASSES as ɵBF_BUTTON_CLASSES, ICON_BUTTON_CLASSES as ɵBF_ICON_BUTTON_CLASSES, FIELD_BOX as ɵFIELD_BOX, FIELD_ICON_END as ɵFIELD_ICON_END, FIELD_ICON_START as ɵFIELD_ICON_START, FIELD_PADDING_END as ɵFIELD_PADDING_END, FIELD_PADDING_START as ɵFIELD_PADDING_START, PILL_HIT as ɵPILL_HIT, compareIso as ɵcompareIso, createMemoryColorSchemeStorage as ɵcreateMemoryColorSchemeStorage, daysInMonth as ɵdaysInMonth, fieldDescribedBy as ɵfieldDescribedBy, fieldErrorMessageId as ɵfieldErrorMessageId, fieldErrorText as ɵfieldErrorText, fieldShowsError as ɵfieldShowsError, formatIsoDate as ɵformatIsoDate, localIsoDate as ɵlocalIsoDate, parseIsoDate as ɵparseIsoDate, provideBfDocumentReset as ɵprovideBfDocumentReset, uniqueId as ɵuniqueId, validIsoDate as ɵvalidIsoDate };