@bitforgehq/ui 0.3.1 → 0.3.2

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 (45) hide show
  1. package/CHANGELOG.md +116 -0
  2. package/README.md +9 -8
  3. package/ai/MANIFEST.index.json +18 -0
  4. package/ai/MANIFEST.json +368 -31
  5. package/ai/REFERENCE.index.json +63 -0
  6. package/ai/REFERENCE.json +247 -5
  7. package/ai/UI_GUIDE.md +59 -33
  8. package/ai/components/app-frame.md +328 -0
  9. package/ai/components/card.md +56 -2
  10. package/ai/components/empty-state.md +99 -6
  11. package/ai/components/header.md +5 -1
  12. package/ai/components/sidebar-toggle.md +287 -0
  13. package/ai/components/sidebar.md +188 -10
  14. package/ai/components/stat.md +74 -10
  15. package/ai/components/table.md +134 -5
  16. package/ai/components/tabs.md +5 -1
  17. package/ai/components/toolbar.md +69 -4
  18. package/ai/reference/bf-app-frame-breakpoint.md +27 -0
  19. package/ai/reference/bf-app-frame-content-width.md +29 -0
  20. package/ai/reference/bf-empty-state-heading-level.md +1 -1
  21. package/ai/reference/bf-empty-state-heading.md +33 -0
  22. package/ai/reference/bf-labels.md +6 -0
  23. package/ai/reference/bf-sidebar-state-service.md +21 -0
  24. package/ai/reference/bf-sidebar-toggle-harness.md +32 -0
  25. package/ai/reference/bf-size.md +1 -0
  26. package/ai/reference/bf-stat-appearance.md +33 -0
  27. package/ai/reference/bf-stat-variant.md +1 -1
  28. package/ai/reference/bf-table-harness.md +1 -1
  29. package/ai/reference/bf-table-stack.md +29 -0
  30. package/ai/reference/bf_sidebar_state_storage.md +20 -0
  31. package/ai/reference/provide-bf-labels.md +4 -3
  32. package/ai/reference/provide-bf-sidebar-state.md +20 -0
  33. package/bin/bf-ui.js +433 -3
  34. package/fesm2022/bitforgehq-ui-overlay.mjs +571 -446
  35. package/fesm2022/bitforgehq-ui-overlay.mjs.map +1 -1
  36. package/fesm2022/bitforgehq-ui-testing.mjs +18 -2
  37. package/fesm2022/bitforgehq-ui-testing.mjs.map +1 -1
  38. package/fesm2022/bitforgehq-ui.mjs +759 -127
  39. package/fesm2022/bitforgehq-ui.mjs.map +1 -1
  40. package/llms-full.txt +1560 -43
  41. package/llms.txt +11 -0
  42. package/package.json +1 -1
  43. package/types/bitforgehq-ui-overlay.d.ts +51 -0
  44. package/types/bitforgehq-ui-testing.d.ts +35 -1
  45. package/types/bitforgehq-ui.d.ts +276 -20
@@ -43,6 +43,9 @@ const BF_DEFAULT_LABELS = {
43
43
  dialog: "Dialog",
44
44
  notifications: "Notifications",
45
45
  tableSelectAll: "Select all rows",
46
+ tableSortBy: "Sort by",
47
+ tableSortAscending: (column) => `${column}, ascending`,
48
+ tableSortDescending: (column) => `${column}, descending`,
46
49
  theme: "Theme",
47
50
  themeSystem: "System",
48
51
  themeLight: "Light",
@@ -51,6 +54,9 @@ const BF_DEFAULT_LABELS = {
51
54
  breadcrumbExpand: (count) => count === 1 ? "Show 1 more level" : `Show ${count} more levels`,
52
55
  navigation: "Main",
53
56
  navBadge: (count) => `${count} new`,
57
+ sidebarCollapse: "Collapse sidebar",
58
+ sidebarExpand: "Expand sidebar",
59
+ skipToContent: "Skip to main content",
54
60
  pagination: "Pagination",
55
61
  previousPage: "Previous page",
56
62
  nextPage: "Next page",
@@ -138,6 +144,9 @@ function mergeLabels(parent, o) {
138
144
  dialog: o.dialog ?? parent.dialog,
139
145
  notifications: o.notifications ?? parent.notifications,
140
146
  tableSelectAll: o.tableSelectAll ?? parent.tableSelectAll,
147
+ tableSortBy: o.tableSortBy ?? parent.tableSortBy,
148
+ tableSortAscending: o.tableSortAscending ?? parent.tableSortAscending,
149
+ tableSortDescending: o.tableSortDescending ?? parent.tableSortDescending,
141
150
  theme: o.theme ?? parent.theme,
142
151
  themeSystem: o.themeSystem ?? parent.themeSystem,
143
152
  themeLight: o.themeLight ?? parent.themeLight,
@@ -146,6 +155,9 @@ function mergeLabels(parent, o) {
146
155
  breadcrumbExpand: o.breadcrumbExpand ?? parent.breadcrumbExpand,
147
156
  navigation: o.navigation ?? parent.navigation,
148
157
  navBadge: o.navBadge ?? parent.navBadge,
158
+ sidebarCollapse: o.sidebarCollapse ?? parent.sidebarCollapse,
159
+ sidebarExpand: o.sidebarExpand ?? parent.sidebarExpand,
160
+ skipToContent: o.skipToContent ?? parent.skipToContent,
149
161
  pagination: o.pagination ?? parent.pagination,
150
162
  previousPage: o.previousPage ?? parent.previousPage,
151
163
  nextPage: o.nextPage ?? parent.nextPage,
@@ -199,7 +211,7 @@ function mergeLabels(parent, o) {
199
211
  }
200
212
  };
201
213
  }
202
- const STORAGE_KEY = "bf-theme";
214
+ const STORAGE_KEY$1 = "bf-theme";
203
215
  const DARK_QUERY = "(prefers-color-scheme: dark)";
204
216
  function createMemoryColorSchemeStorage() {
205
217
  const values = /* @__PURE__ */ new Map();
@@ -221,17 +233,17 @@ const BF_COLOR_SCHEME_STORAGE = new InjectionToken("BF_COLOR_SCHEME_STORAGE", {
221
233
  providedIn: "root",
222
234
  factory: () => browserStorage() ?? createMemoryColorSchemeStorage()
223
235
  });
224
- function readStored(storage) {
236
+ function readStored$1(storage) {
225
237
  try {
226
- const stored = storage.getItem(STORAGE_KEY);
238
+ const stored = storage.getItem(STORAGE_KEY$1);
227
239
  return stored === "light" || stored === "dark" || stored === "system" ? stored : "system";
228
240
  } catch {
229
241
  return "system";
230
242
  }
231
243
  }
232
- function persist(storage, scheme) {
244
+ function persist$1(storage, scheme) {
233
245
  try {
234
- storage.setItem(STORAGE_KEY, scheme);
246
+ storage.setItem(STORAGE_KEY$1, scheme);
235
247
  } catch {}
236
248
  }
237
249
  var BfColorSchemeService = class BfColorSchemeService {
@@ -239,7 +251,7 @@ var BfColorSchemeService = class BfColorSchemeService {
239
251
  storage = inject(BF_COLOR_SCHEME_STORAGE);
240
252
  injector = inject(Injector);
241
253
  browser = isPlatformBrowser(inject(PLATFORM_ID));
242
- scheme = signal(this.browser ? readStored(this.storage) : "system", ...ngDevMode ? [{ debugName: "scheme" }] : /* istanbul ignore next */ []);
254
+ scheme = signal(this.browser ? readStored$1(this.storage) : "system", ...ngDevMode ? [{ debugName: "scheme" }] : /* istanbul ignore next */ []);
243
255
  prefersDark = signal(false, ...ngDevMode ? [{ debugName: "prefersDark" }] : /* istanbul ignore next */ []);
244
256
  systemDark = this.prefersDark.asReadonly();
245
257
  dark = computed(() => this.scheme() === "system" ? this.prefersDark() : this.scheme() === "dark", ...ngDevMode ? [{ debugName: "dark" }] : /* istanbul ignore next */ []);
@@ -252,10 +264,10 @@ var BfColorSchemeService = class BfColorSchemeService {
252
264
  this.claimed = true;
253
265
  const html = this.document.documentElement;
254
266
  html.classList.toggle("dark", this.dark());
255
- persist(this.storage, this.scheme());
267
+ persist$1(this.storage, this.scheme());
256
268
  effect(() => {
257
269
  html.classList.toggle("dark", this.dark());
258
- persist(this.storage, this.scheme());
270
+ persist$1(this.storage, this.scheme());
259
271
  }, { injector: this.injector });
260
272
  }
261
273
  followSystem() {
@@ -299,6 +311,68 @@ function provideBfColorScheme() {
299
311
  inject(BfColorSchemeService).claimDocument();
300
312
  })]);
301
313
  }
314
+ const STORAGE_KEY = "bf-sidebar-collapsed";
315
+ const BF_SIDEBAR_STATE_STORAGE = new InjectionToken("BF_SIDEBAR_STATE_STORAGE", {
316
+ providedIn: "root",
317
+ factory: () => browserStorage() ?? createMemoryColorSchemeStorage()
318
+ });
319
+ function readStored(storage) {
320
+ try {
321
+ return storage.getItem(STORAGE_KEY) === "true";
322
+ } catch {
323
+ return false;
324
+ }
325
+ }
326
+ function persist(storage, collapsed) {
327
+ try {
328
+ storage.setItem(STORAGE_KEY, String(collapsed));
329
+ } catch {}
330
+ }
331
+ var BfSidebarStateService = class BfSidebarStateService {
332
+ storage = inject(BF_SIDEBAR_STATE_STORAGE);
333
+ injector = inject(Injector);
334
+ browser = isPlatformBrowser(inject(PLATFORM_ID));
335
+ collapsed = signal(this.browser ? readStored(this.storage) : false, ...ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []);
336
+ claimed = false;
337
+ claimStorage() {
338
+ if (this.claimed || !this.browser) return;
339
+ this.claimed = true;
340
+ effect(() => {
341
+ const collapsed = this.collapsed();
342
+ persist(this.storage, collapsed);
343
+ }, { injector: this.injector });
344
+ }
345
+ static ɵfac = i0.ɵɵngDeclareFactory({
346
+ minVersion: "12.0.0",
347
+ version: "22.1.7",
348
+ ngImport: i0,
349
+ type: BfSidebarStateService,
350
+ deps: [],
351
+ target: i0.ɵɵFactoryTarget.Injectable
352
+ });
353
+ static ɵprov = i0.ɵɵngDeclareInjectable({
354
+ minVersion: "12.0.0",
355
+ version: "22.1.7",
356
+ ngImport: i0,
357
+ type: BfSidebarStateService,
358
+ providedIn: "root"
359
+ });
360
+ };
361
+ i0.ɵɵngDeclareClassMetadata({
362
+ minVersion: "12.0.0",
363
+ version: "22.1.7",
364
+ ngImport: i0,
365
+ type: BfSidebarStateService,
366
+ decorators: [{
367
+ type: Injectable,
368
+ args: [{ providedIn: "root" }]
369
+ }]
370
+ });
371
+ function provideBfSidebarState() {
372
+ return makeEnvironmentProviders([provideEnvironmentInitializer(() => {
373
+ inject(BfSidebarStateService).claimStorage();
374
+ })]);
375
+ }
302
376
  function isRecord(value) {
303
377
  return typeof value === "object" && value !== null;
304
378
  }
@@ -527,7 +601,7 @@ const SIZE$5 = {
527
601
  md: "h-10 text-label-sm",
528
602
  lg: "h-12 text-label"
529
603
  };
530
- const PADDING$2 = {
604
+ const PADDING$3 = {
531
605
  sm: "px-3.5",
532
606
  md: "px-4.5",
533
607
  lg: "px-6"
@@ -543,7 +617,7 @@ const BUTTON_CLASSES = {
543
617
  pressed: PRESSED$2.button,
544
618
  current: CURRENT,
545
619
  size: SIZE$5,
546
- padding: PADDING$2,
620
+ padding: PADDING$3,
547
621
  textPadding: TEXT_PADDING
548
622
  };
549
623
  var BfButtonComponent = class BfButtonComponent {
@@ -569,7 +643,7 @@ var BfButtonComponent = class BfButtonComponent {
569
643
  classes = computed(() => {
570
644
  const size = this.resolvedSize();
571
645
  const variant = this.variant();
572
- const padding = variant === "text" || variant === "ghost" ? TEXT_PADDING[size] : PADDING$2[size];
646
+ const padding = variant === "text" || variant === "ghost" ? TEXT_PADDING[size] : PADDING$3[size];
573
647
  const hit = PILL_HIT[size][variant === "outline" ? "bordered" : "plain"];
574
648
  const width = this.fullWidth() ? "w-full" : "";
575
649
  const state = this.loading() && !this.isLink ? "loading" : "idle";
@@ -6641,7 +6715,7 @@ const VARIANT$3 = {
6641
6715
  ink: "bg-text text-bg",
6642
6716
  flat: "bg-surface text-text border-[1.5px] border-border-strong"
6643
6717
  };
6644
- const PADDING$1 = {
6718
+ const PADDING$2 = {
6645
6719
  md: "p-card",
6646
6720
  lg: "p-card-lg"
6647
6721
  };
@@ -6664,7 +6738,7 @@ var BfCardComponent = class BfCardComponent {
6664
6738
  classes = computed(() => [
6665
6739
  BASE$4,
6666
6740
  VARIANT$3[this.variant()],
6667
- PADDING$1[this.padding()],
6741
+ PADDING$2[this.padding()],
6668
6742
  this.interactive() ? INTERACTIVE : ACTION[this.actionState()]
6669
6743
  ].filter(Boolean).join(" "), ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
6670
6744
  actionState = computed(() => {
@@ -7438,10 +7512,16 @@ var BfEmptyStateComponent = class BfEmptyStateComponent {
7438
7512
  >
7439
7513
  <ng-content select="[bfSlot=icon]" />
7440
7514
  </div>
7441
- @if (headingLevel() === 3) {
7442
- <h3 class="text-heading text-text">{{ title() }}</h3>
7443
- } @else {
7444
- <h2 class="text-heading text-text">{{ title() }}</h2>
7515
+ @switch (headingLevel()) {
7516
+ @case (1) {
7517
+ <h1 class="text-heading text-text">{{ title() }}</h1>
7518
+ }
7519
+ @case (3) {
7520
+ <h3 class="text-heading text-text">{{ title() }}</h3>
7521
+ }
7522
+ @default {
7523
+ <h2 class="text-heading text-text">{{ title() }}</h2>
7524
+ }
7445
7525
  }
7446
7526
  @if (description()) {
7447
7527
  <p class="text-body text-text-muted max-w-sm">{{ description() }}</p>
@@ -7472,10 +7552,16 @@ i0.ɵɵngDeclareClassMetadata({
7472
7552
  >
7473
7553
  <ng-content select="[bfSlot=icon]" />
7474
7554
  </div>
7475
- @if (headingLevel() === 3) {
7476
- <h3 class="text-heading text-text">{{ title() }}</h3>
7477
- } @else {
7478
- <h2 class="text-heading text-text">{{ title() }}</h2>
7555
+ @switch (headingLevel()) {
7556
+ @case (1) {
7557
+ <h1 class="text-heading text-text">{{ title() }}</h1>
7558
+ }
7559
+ @case (3) {
7560
+ <h3 class="text-heading text-text">{{ title() }}</h3>
7561
+ }
7562
+ @default {
7563
+ <h2 class="text-heading text-text">{{ title() }}</h2>
7564
+ }
7479
7565
  }
7480
7566
  @if (description()) {
7481
7567
  <p class="text-body text-text-muted max-w-sm">{{ description() }}</p>
@@ -8966,10 +9052,19 @@ var BfToolbarComponent = class BfToolbarComponent {
8966
9052
  template: `
8967
9053
  <ng-content />
8968
9054
  <ng-content select="[bfSlot=view]" />
8969
- <span role="status" [class]="statusClasses()">{{ status() }}</span>
8970
- <!-- One flex item, so the actions wrap onto the next row together, never one by one. -->
8971
- <div class="ms-auto flex max-w-full flex-wrap items-center gap-2 empty:hidden">
8972
- <ng-content select="[bfSlot=actions]" />
9055
+ <!-- The status and the actions are one flex item that takes the rest of the row: on a narrow
9056
+ row they wrap together, the status at the start and the actions at the inline end, so the
9057
+ actions never sit alone on a row. With no actions the group dissolves (display: contents)
9058
+ and the status is a plain item of the row. -->
9059
+ <div
9060
+ data-end
9061
+ class="flex max-w-full grow flex-wrap items-center gap-2 has-[>div:empty]:contents"
9062
+ >
9063
+ <span role="status" [class]="statusClasses()">{{ status() }}</span>
9064
+ <!-- One flex item, so the actions wrap together, never one by one. -->
9065
+ <div class="ms-auto flex max-w-full flex-wrap items-center gap-2 empty:hidden">
9066
+ <ng-content select="[bfSlot=actions]" />
9067
+ </div>
8973
9068
  </div>
8974
9069
  `,
8975
9070
  isInline: true
@@ -8993,10 +9088,19 @@ i0.ɵɵngDeclareClassMetadata({
8993
9088
  template: `
8994
9089
  <ng-content />
8995
9090
  <ng-content select="[bfSlot=view]" />
8996
- <span role="status" [class]="statusClasses()">{{ status() }}</span>
8997
- <!-- One flex item, so the actions wrap onto the next row together, never one by one. -->
8998
- <div class="ms-auto flex max-w-full flex-wrap items-center gap-2 empty:hidden">
8999
- <ng-content select="[bfSlot=actions]" />
9091
+ <!-- The status and the actions are one flex item that takes the rest of the row: on a narrow
9092
+ row they wrap together, the status at the start and the actions at the inline end, so the
9093
+ actions never sit alone on a row. With no actions the group dissolves (display: contents)
9094
+ and the status is a plain item of the row. -->
9095
+ <div
9096
+ data-end
9097
+ class="flex max-w-full grow flex-wrap items-center gap-2 has-[>div:empty]:contents"
9098
+ >
9099
+ <span role="status" [class]="statusClasses()">{{ status() }}</span>
9100
+ <!-- One flex item, so the actions wrap together, never one by one. -->
9101
+ <div class="ms-auto flex max-w-full flex-wrap items-center gap-2 empty:hidden">
9102
+ <ng-content select="[bfSlot=actions]" />
9103
+ </div>
9000
9104
  </div>
9001
9105
  `
9002
9106
  }]
@@ -9102,10 +9206,15 @@ const HEAD_CELL = {
9102
9206
  lg: "h-12"
9103
9207
  };
9104
9208
  const BODY_CELL = {
9105
- sm: "h-10 py-1 text-label-sm pointer-coarse:h-hit",
9209
+ sm: "h-10 py-1 text-label-sm",
9106
9210
  md: "h-12 py-1 text-body",
9107
9211
  lg: "h-14 py-1 text-body"
9108
9212
  };
9213
+ const BODY_TOUCH = {
9214
+ never: "pointer-coarse:h-hit",
9215
+ narrow: "@min-xl:pointer-coarse:h-hit",
9216
+ coarse: ""
9217
+ };
9109
9218
  const ALIGN = {
9110
9219
  start: "text-start",
9111
9220
  end: "text-end tabular-nums"
@@ -9135,6 +9244,76 @@ const OWN_ARROWS = /* @__PURE__ */ new Set([
9135
9244
  "menu",
9136
9245
  "tab"
9137
9246
  ]);
9247
+ const STACK_HOST = {
9248
+ never: "block",
9249
+ narrow: "block @container",
9250
+ coarse: "block"
9251
+ };
9252
+ const STACK_BAR = {
9253
+ never: "hidden",
9254
+ narrow: "hidden @max-xl:flex",
9255
+ coarse: "hidden pointer-coarse:flex"
9256
+ };
9257
+ const STACK_TABLE = {
9258
+ never: "",
9259
+ narrow: "@max-xl:block",
9260
+ coarse: "pointer-coarse:block"
9261
+ };
9262
+ const STACK_HEAD = {
9263
+ never: "",
9264
+ narrow: "@max-xl:sr-only",
9265
+ coarse: "pointer-coarse:sr-only"
9266
+ };
9267
+ const STACK_ONLY = {
9268
+ never: "hidden",
9269
+ narrow: "hidden @max-xl:inline",
9270
+ coarse: "hidden pointer-coarse:inline"
9271
+ };
9272
+ const STACK_NEVER = {
9273
+ never: "",
9274
+ narrow: "@max-xl:hidden",
9275
+ coarse: "pointer-coarse:hidden"
9276
+ };
9277
+ const STACK_BODY = {
9278
+ never: "",
9279
+ narrow: "@max-xl:flex @max-xl:flex-col @max-xl:gap-2 @max-xl:divide-y-0",
9280
+ coarse: "pointer-coarse:flex pointer-coarse:flex-col pointer-coarse:gap-2 pointer-coarse:divide-y-0"
9281
+ };
9282
+ const STACK_ROW = {
9283
+ never: "",
9284
+ narrow: "@max-xl:grid @max-xl:items-center @max-xl:gap-x-3 @max-xl:rounded-tile @max-xl:px-3 @max-xl:py-2",
9285
+ coarse: "pointer-coarse:grid pointer-coarse:items-center pointer-coarse:gap-x-3 pointer-coarse:rounded-tile pointer-coarse:px-3 pointer-coarse:py-2"
9286
+ };
9287
+ const STACK_ROW_SELECTABLE = {
9288
+ never: "",
9289
+ narrow: "@max-xl:grid-cols-[auto_minmax(0,1fr)]",
9290
+ coarse: "pointer-coarse:grid-cols-[auto_minmax(0,1fr)]"
9291
+ };
9292
+ const STACK_ROW_FILL = {
9293
+ never: "",
9294
+ narrow: "@max-xl:bg-surface-sunken",
9295
+ coarse: "pointer-coarse:bg-surface-sunken"
9296
+ };
9297
+ const STACK_SELECT_CELL = {
9298
+ never: "",
9299
+ narrow: "@max-xl:flex @max-xl:h-auto @max-xl:w-auto @max-xl:p-0",
9300
+ coarse: "pointer-coarse:flex pointer-coarse:h-auto pointer-coarse:w-auto pointer-coarse:p-0"
9301
+ };
9302
+ const STACK_FIRST_CELL = {
9303
+ never: "",
9304
+ narrow: "@max-xl:block @max-xl:h-auto @max-xl:px-0 @max-xl:py-1 @max-xl:text-start @max-xl:font-bold",
9305
+ coarse: "pointer-coarse:block pointer-coarse:h-auto pointer-coarse:px-0 pointer-coarse:py-1 pointer-coarse:text-start pointer-coarse:font-bold"
9306
+ };
9307
+ const STACK_CELL = {
9308
+ never: "",
9309
+ narrow: "@max-xl:col-span-full @max-xl:flex @max-xl:h-auto @max-xl:items-baseline @max-xl:justify-between @max-xl:gap-3 @max-xl:px-0 @max-xl:py-1 @max-xl:text-end @max-xl:before:shrink-0 @max-xl:before:text-start @max-xl:before:text-label-xs @max-xl:before:font-bold @max-xl:before:text-text-muted @max-xl:before:content-[attr(data-label)_/_\"\"]",
9310
+ coarse: "pointer-coarse:col-span-full pointer-coarse:flex pointer-coarse:h-auto pointer-coarse:items-baseline pointer-coarse:justify-between pointer-coarse:gap-3 pointer-coarse:px-0 pointer-coarse:py-1 pointer-coarse:text-end pointer-coarse:before:shrink-0 pointer-coarse:before:text-start pointer-coarse:before:text-label-xs pointer-coarse:before:font-bold pointer-coarse:before:text-text-muted pointer-coarse:before:content-[attr(data-label)_/_\"\"]"
9311
+ };
9312
+ const STACK_EMPTY = {
9313
+ never: "",
9314
+ narrow: "@max-xl:block",
9315
+ coarse: "pointer-coarse:block"
9316
+ };
9138
9317
  var BfTableComponent = class BfTableComponent {
9139
9318
  rows = input.required(...ngDevMode ? [{ debugName: "rows" }] : /* istanbul ignore next */ []);
9140
9319
  columns = input.required(...ngDevMode ? [{ debugName: "columns" }] : /* istanbul ignore next */ []);
@@ -9148,11 +9327,13 @@ var BfTableComponent = class BfTableComponent {
9148
9327
  selection = model([], ...ngDevMode ? [{ debugName: "selection" }] : /* istanbul ignore next */ []);
9149
9328
  selectAllLabel = input("", ...ngDevMode ? [{ debugName: "selectAllLabel" }] : /* istanbul ignore next */ []);
9150
9329
  size = input(void 0, ...ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []);
9330
+ stack = input("never", ...ngDevMode ? [{ debugName: "stack" }] : /* istanbul ignore next */ []);
9151
9331
  labels = inject(BF_LABELS);
9152
9332
  defaults = inject(BF_DEFAULTS);
9153
9333
  table = viewChild.required("table", ...ngDevMode ? [{ debugName: "table" }] : /* istanbul ignore next */ []);
9154
9334
  cells = contentChildren(BfTableCellDirective, ...ngDevMode ? [{ debugName: "cells" }] : /* istanbul ignore next */ []);
9155
9335
  id = uniqueId("bf-table");
9336
+ captionId = `${this.id}-caption`;
9156
9337
  resolvedSize = computed(() => this.size() ?? this.defaults.controlSize, ...ngDevMode ? [{ debugName: "resolvedSize" }] : /* istanbul ignore next */ []);
9157
9338
  selectAllName = computed(() => this.selectAllLabel() || this.labels.tableSelectAll, ...ngDevMode ? [{ debugName: "selectAllName" }] : /* istanbul ignore next */ []);
9158
9339
  entries = computed(() => {
@@ -9175,18 +9356,50 @@ var BfTableComponent = class BfTableComponent {
9175
9356
  return !this.allSelected() && this.entries().some((entry) => selected.has(entry.key));
9176
9357
  }, ...ngDevMode ? [{ debugName: "someSelected" }] : /* istanbul ignore next */ []);
9177
9358
  columnCount = computed(() => this.columns().length + (this.selectable() ? 1 : 0), ...ngDevMode ? [{ debugName: "columnCount" }] : /* istanbul ignore next */ []);
9178
- sortButton = SORT_BUTTON;
9359
+ stacks = computed(() => this.stack() !== "never", ...ngDevMode ? [{ debugName: "stacks" }] : /* istanbul ignore next */ []);
9360
+ sortOptions = computed(() => this.columns().filter((column) => column.sortable).flatMap((column) => [{
9361
+ value: `${column.key}:ascending`,
9362
+ label: this.labels.tableSortAscending(column.label)
9363
+ }, {
9364
+ value: `${column.key}:descending`,
9365
+ label: this.labels.tableSortDescending(column.label)
9366
+ }]), ...ngDevMode ? [{ debugName: "sortOptions" }] : /* istanbul ignore next */ []);
9367
+ sortValue = computed(() => {
9368
+ const sort = this.sort();
9369
+ return sort ? `${sort.column}:${sort.direction}` : null;
9370
+ }, ...ngDevMode ? [{ debugName: "sortValue" }] : /* istanbul ignore next */ []);
9371
+ hostClasses = computed(() => STACK_HOST[this.stack()], ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
9372
+ stackBarClasses = computed(() => `${STACK_BAR[this.stack()]} flex-wrap items-end justify-between gap-x-4 gap-y-2 pb-3`, ...ngDevMode ? [{ debugName: "stackBarClasses" }] : /* istanbul ignore next */ []);
9373
+ tableClasses = computed(() => `w-full border-collapse ${STACK_TABLE[this.stack()]}`, ...ngDevMode ? [{ debugName: "tableClasses" }] : /* istanbul ignore next */ []);
9374
+ headClasses = computed(() => STACK_HEAD[this.stack()], ...ngDevMode ? [{ debugName: "headClasses" }] : /* istanbul ignore next */ []);
9375
+ bodyGroupClasses = computed(() => `divide-border divide-y ${STACK_BODY[this.stack()]}`, ...ngDevMode ? [{ debugName: "bodyGroupClasses" }] : /* istanbul ignore next */ []);
9376
+ sortButtonClasses = computed(() => `${SORT_BUTTON} ${STACK_NEVER[this.stack()]}`, ...ngDevMode ? [{ debugName: "sortButtonClasses" }] : /* istanbul ignore next */ []);
9377
+ notStackedClasses = computed(() => STACK_NEVER[this.stack()], ...ngDevMode ? [{ debugName: "notStackedClasses" }] : /* istanbul ignore next */ []);
9378
+ stackedOnlyClasses = computed(() => STACK_ONLY[this.stack()], ...ngDevMode ? [{ debugName: "stackedOnlyClasses" }] : /* istanbul ignore next */ []);
9379
+ stackEmptyClasses = computed(() => STACK_EMPTY[this.stack()], ...ngDevMode ? [{ debugName: "stackEmptyClasses" }] : /* istanbul ignore next */ []);
9179
9380
  selectHeadClasses = computed(() => `${HEAD_BASE} ${HEAD_CELL[this.resolvedSize()]} ${SELECT_CELL}`, ...ngDevMode ? [{ debugName: "selectHeadClasses" }] : /* istanbul ignore next */ []);
9180
- selectBodyClasses = computed(() => `${BODY_BASE} ${BODY_CELL[this.resolvedSize()]} ${SELECT_CELL}`, ...ngDevMode ? [{ debugName: "selectBodyClasses" }] : /* istanbul ignore next */ []);
9181
- headClasses(column) {
9381
+ selectBodyClasses = computed(() => `${BODY_BASE} ${this.bodyHeight()} ${SELECT_CELL} ${STACK_SELECT_CELL[this.stack()]}`, ...ngDevMode ? [{ debugName: "selectBodyClasses" }] : /* istanbul ignore next */ []);
9382
+ bodyHeight = computed(() => {
9383
+ const size = this.resolvedSize();
9384
+ const touch = size === "sm" ? BODY_TOUCH[this.stack()] : "";
9385
+ return touch ? `${BODY_CELL[size]} ${touch}` : BODY_CELL[size];
9386
+ }, ...ngDevMode ? [{ debugName: "bodyHeight" }] : /* istanbul ignore next */ []);
9387
+ headCellClasses(column) {
9182
9388
  return `${HEAD_BASE} ${HEAD_CELL[this.resolvedSize()]} ${ALIGN[column.align ?? "start"]}`;
9183
9389
  }
9184
- bodyClasses(column) {
9185
- return `${BODY_BASE} ${BODY_CELL[this.resolvedSize()]} ${ALIGN[column.align ?? "start"]}`;
9390
+ bodyClasses(column, first) {
9391
+ const stacked = (first ? STACK_FIRST_CELL : STACK_CELL)[this.stack()];
9392
+ return `${BODY_BASE} ${this.bodyHeight()} ${ALIGN[column.align ?? "start"]} ${stacked}`.trim();
9186
9393
  }
9187
9394
  rowClasses(key) {
9188
9395
  const state = this.selectedKeys().has(key) ? "selected" : this.selectable() ? "selectable" : "static";
9189
- return `transition-colors ${ROW[state]}`;
9396
+ const stack = this.stack();
9397
+ const tile = [
9398
+ STACK_ROW[stack],
9399
+ this.selectable() ? STACK_ROW_SELECTABLE[stack] : "",
9400
+ state === "selected" ? "" : STACK_ROW_FILL[stack]
9401
+ ].filter(Boolean).join(" ");
9402
+ return `transition-colors ${ROW[state]} ${tile}`.trim();
9190
9403
  }
9191
9404
  arrowClasses(key) {
9192
9405
  const sort = this.sort();
@@ -9211,6 +9424,14 @@ var BfTableComponent = class BfTableComponent {
9211
9424
  direction
9212
9425
  });
9213
9426
  }
9427
+ sortFromOption(value) {
9428
+ const at = value.lastIndexOf(":");
9429
+ const direction = value.slice(at + 1);
9430
+ if (at > 0 && (direction === "ascending" || direction === "descending")) this.sort.set({
9431
+ column: value.slice(0, at),
9432
+ direction
9433
+ });
9434
+ }
9214
9435
  selectAll(selected) {
9215
9436
  const keys = this.entries().map((entry) => entry.key);
9216
9437
  const shown = new Set(keys);
@@ -9238,7 +9459,7 @@ var BfTableComponent = class BfTableComponent {
9238
9459
  for (let i = rows.indexOf(row) + step; i >= 0 && i < rows.length; i += step) {
9239
9460
  const controls = [...rows[i]?.cells[cell.cellIndex]?.querySelectorAll(FOCUSABLE) ?? []];
9240
9461
  const next = controls[Math.min(position, controls.length - 1)];
9241
- if (next instanceof HTMLElement) {
9462
+ if (next instanceof HTMLElement && next.checkVisibility?.() !== false) {
9242
9463
  event.preventDefault();
9243
9464
  next.focus();
9244
9465
  return;
@@ -9322,6 +9543,13 @@ var BfTableComponent = class BfTableComponent {
9322
9543
  isSignal: true,
9323
9544
  isRequired: false,
9324
9545
  transformFunction: null
9546
+ },
9547
+ stack: {
9548
+ classPropertyName: "stack",
9549
+ publicName: "stack",
9550
+ isSignal: true,
9551
+ isRequired: false,
9552
+ transformFunction: null
9325
9553
  }
9326
9554
  },
9327
9555
  outputs: {
@@ -9330,7 +9558,7 @@ var BfTableComponent = class BfTableComponent {
9330
9558
  },
9331
9559
  host: {
9332
9560
  listeners: { "keydown": "onKeydown($event)" },
9333
- classAttribute: "block"
9561
+ properties: { "class": "hostClasses()" }
9334
9562
  },
9335
9563
  queries: [{
9336
9564
  propertyName: "cells",
@@ -9346,20 +9574,53 @@ var BfTableComponent = class BfTableComponent {
9346
9574
  }],
9347
9575
  ngImport: i0,
9348
9576
  template: `
9577
+ @if (stacks() && (selectable() || sortOptions().length > 0)) {
9578
+ <div data-bf-table-stack-bar [class]="stackBarClasses()">
9579
+ @if (selectable()) {
9580
+ <bf-checkbox
9581
+ [size]="resolvedSize()"
9582
+ [label]="selectAllName()"
9583
+ [checked]="allSelected()"
9584
+ [indeterminate]="someSelected()"
9585
+ [disabled]="entries().length === 0"
9586
+ (changed)="selectAll($event)"
9587
+ />
9588
+ }
9589
+ @if (sortOptions().length > 0) {
9590
+ <bf-select
9591
+ class="min-w-0 flex-1 basis-36"
9592
+ [label]="labels.tableSortBy"
9593
+ [options]="sortOptions()"
9594
+ [value]="sortValue()"
9595
+ (changed)="sortFromOption($event)"
9596
+ />
9597
+ }
9598
+ </div>
9599
+ }
9349
9600
  <div data-bf-table-scroller class="max-w-full overflow-x-auto">
9350
- <table #table class="w-full border-collapse">
9601
+ <table
9602
+ #table
9603
+ [attr.role]="stacks() ? 'table' : null"
9604
+ [attr.aria-labelledby]="stacks() && label() ? captionId : null"
9605
+ [class]="tableClasses()"
9606
+ >
9351
9607
  @if (label()) {
9352
- <caption class="sr-only">
9608
+ <caption class="sr-only" [attr.id]="stacks() ? captionId : null">
9353
9609
  {{
9354
9610
  label()
9355
9611
  }}
9356
9612
  </caption>
9357
9613
  }
9358
- <thead>
9359
- <tr class="border-border border-b">
9614
+ <thead [attr.role]="stacks() ? 'rowgroup' : null" [class]="headClasses()">
9615
+ <tr class="border-border border-b" [attr.role]="stacks() ? 'row' : null">
9360
9616
  @if (selectable()) {
9361
- <th scope="col" [class]="selectHeadClasses()">
9617
+ <th
9618
+ scope="col"
9619
+ [attr.role]="stacks() ? 'columnheader' : null"
9620
+ [class]="selectHeadClasses()"
9621
+ >
9362
9622
  <bf-checkbox
9623
+ [class]="notStackedClasses()"
9363
9624
  [size]="resolvedSize()"
9364
9625
  [checked]="allSelected()"
9365
9626
  [indeterminate]="someSelected()"
@@ -9372,15 +9633,21 @@ var BfTableComponent = class BfTableComponent {
9372
9633
  @for (column of columns(); track column.key) {
9373
9634
  <th
9374
9635
  scope="col"
9636
+ [attr.role]="stacks() ? 'columnheader' : null"
9375
9637
  [attr.data-bf-column]="column.key"
9376
9638
  [attr.aria-sort]="ariaSort(column.key)"
9377
- [class]="headClasses(column)"
9639
+ [class]="headCellClasses(column)"
9378
9640
  >
9379
9641
  @if (column.sortable) {
9380
- <button type="button" [class]="sortButton" (click)="sortBy(column.key)">
9642
+ <button type="button" [class]="sortButtonClasses()" (click)="sortBy(column.key)">
9381
9643
  {{ column.label }}
9382
9644
  <span aria-hidden="true" [class]="arrowClasses(column.key)"></span>
9383
9645
  </button>
9646
+ @if (stacks()) {
9647
+ <span data-bf-stacked-label [class]="stackedOnlyClasses()">{{
9648
+ column.label
9649
+ }}</span>
9650
+ }
9384
9651
  } @else {
9385
9652
  {{ column.label }}
9386
9653
  }
@@ -9388,11 +9655,15 @@ var BfTableComponent = class BfTableComponent {
9388
9655
  }
9389
9656
  </tr>
9390
9657
  </thead>
9391
- <tbody class="divide-border divide-y">
9658
+ <tbody [attr.role]="stacks() ? 'rowgroup' : null" [class]="bodyGroupClasses()">
9392
9659
  @for (entry of entries(); track entry.key) {
9393
- <tr data-bf-table-row [class]="rowClasses(entry.key)">
9660
+ <tr
9661
+ data-bf-table-row
9662
+ [attr.role]="stacks() ? 'row' : null"
9663
+ [class]="rowClasses(entry.key)"
9664
+ >
9394
9665
  @if (selectable()) {
9395
- <td [class]="selectBodyClasses()">
9666
+ <td [attr.role]="stacks() ? 'cell' : null" [class]="selectBodyClasses()">
9396
9667
  <bf-checkbox
9397
9668
  [size]="resolvedSize()"
9398
9669
  [checked]="selectedKeys().has(entry.key)"
@@ -9404,8 +9675,10 @@ var BfTableComponent = class BfTableComponent {
9404
9675
  @for (column of columns(); track column.key; let first = $first) {
9405
9676
  <td
9406
9677
  data-bf-cell
9678
+ [attr.role]="stacks() ? 'cell' : null"
9407
9679
  [attr.id]="first ? cellId(entry.index) : null"
9408
- [class]="bodyClasses(column)"
9680
+ [attr.data-label]="stacks() && !first ? column.label : null"
9681
+ [class]="bodyClasses(column, first)"
9409
9682
  >
9410
9683
  @if (templates().get(column.key); as template) {
9411
9684
  <ng-container
@@ -9421,8 +9694,18 @@ var BfTableComponent = class BfTableComponent {
9421
9694
  }
9422
9695
  </tr>
9423
9696
  } @empty {
9424
- <tr data-bf-table-empty>
9425
- <td [attr.colspan]="columnCount()"><ng-content select="[bfSlot=empty]" /></td>
9697
+ <tr
9698
+ data-bf-table-empty
9699
+ [attr.role]="stacks() ? 'row' : null"
9700
+ [class]="stackEmptyClasses()"
9701
+ >
9702
+ <td
9703
+ [attr.role]="stacks() ? 'cell' : null"
9704
+ [attr.colspan]="columnCount()"
9705
+ [class]="stackEmptyClasses()"
9706
+ >
9707
+ <ng-content select="[bfSlot=empty]" />
9708
+ </td>
9426
9709
  </tr>
9427
9710
  }
9428
9711
  </tbody>
@@ -9430,43 +9713,78 @@ var BfTableComponent = class BfTableComponent {
9430
9713
  </div>
9431
9714
  `,
9432
9715
  isInline: true,
9433
- dependencies: [{
9434
- kind: "directive",
9435
- type: NgTemplateOutlet,
9436
- selector: "[ngTemplateOutlet]",
9437
- inputs: [
9438
- "ngTemplateOutletContext",
9439
- "ngTemplateOutlet",
9440
- "ngTemplateOutletInjector"
9441
- ]
9442
- }, {
9443
- kind: "component",
9444
- type: BfCheckboxComponent,
9445
- selector: "bf-checkbox",
9446
- inputs: [
9447
- "checked",
9448
- "label",
9449
- "ariaLabel",
9450
- "ariaLabelledby",
9451
- "size",
9452
- "indeterminate",
9453
- "disabled",
9454
- "readonly",
9455
- "required",
9456
- "invalid",
9457
- "touched",
9458
- "errors",
9459
- "errorMessage",
9460
- "name",
9461
- "id"
9462
- ],
9463
- outputs: [
9464
- "checkedChange",
9465
- "indeterminateChange",
9466
- "changed",
9467
- "touch"
9468
- ]
9469
- }]
9716
+ dependencies: [
9717
+ {
9718
+ kind: "directive",
9719
+ type: NgTemplateOutlet,
9720
+ selector: "[ngTemplateOutlet]",
9721
+ inputs: [
9722
+ "ngTemplateOutletContext",
9723
+ "ngTemplateOutlet",
9724
+ "ngTemplateOutletInjector"
9725
+ ]
9726
+ },
9727
+ {
9728
+ kind: "component",
9729
+ type: BfCheckboxComponent,
9730
+ selector: "bf-checkbox",
9731
+ inputs: [
9732
+ "checked",
9733
+ "label",
9734
+ "ariaLabel",
9735
+ "ariaLabelledby",
9736
+ "size",
9737
+ "indeterminate",
9738
+ "disabled",
9739
+ "readonly",
9740
+ "required",
9741
+ "invalid",
9742
+ "touched",
9743
+ "errors",
9744
+ "errorMessage",
9745
+ "name",
9746
+ "id"
9747
+ ],
9748
+ outputs: [
9749
+ "checkedChange",
9750
+ "indeterminateChange",
9751
+ "changed",
9752
+ "touch"
9753
+ ]
9754
+ },
9755
+ {
9756
+ kind: "component",
9757
+ type: BfSelectComponent,
9758
+ selector: "bf-select",
9759
+ inputs: [
9760
+ "value",
9761
+ "options",
9762
+ "compareWith",
9763
+ "size",
9764
+ "label",
9765
+ "ariaLabel",
9766
+ "ariaLabelledby",
9767
+ "placeholder",
9768
+ "helpText",
9769
+ "errorMessage",
9770
+ "disabled",
9771
+ "readonly",
9772
+ "required",
9773
+ "invalid",
9774
+ "touched",
9775
+ "errors",
9776
+ "name",
9777
+ "id"
9778
+ ],
9779
+ outputs: [
9780
+ "valueChange",
9781
+ "changed",
9782
+ "focused",
9783
+ "blurred",
9784
+ "touch"
9785
+ ]
9786
+ }
9787
+ ]
9470
9788
  });
9471
9789
  };
9472
9790
  i0.ɵɵngDeclareClassMetadata({
@@ -9479,25 +9797,62 @@ i0.ɵɵngDeclareClassMetadata({
9479
9797
  args: [{
9480
9798
  selector: "bf-table",
9481
9799
  host: {
9482
- class: "block",
9800
+ "[class]": "hostClasses()",
9483
9801
  "(keydown)": "onKeydown($event)"
9484
9802
  },
9485
- imports: [NgTemplateOutlet, BfCheckboxComponent],
9803
+ imports: [
9804
+ NgTemplateOutlet,
9805
+ BfCheckboxComponent,
9806
+ BfSelectComponent
9807
+ ],
9486
9808
  template: `
9809
+ @if (stacks() && (selectable() || sortOptions().length > 0)) {
9810
+ <div data-bf-table-stack-bar [class]="stackBarClasses()">
9811
+ @if (selectable()) {
9812
+ <bf-checkbox
9813
+ [size]="resolvedSize()"
9814
+ [label]="selectAllName()"
9815
+ [checked]="allSelected()"
9816
+ [indeterminate]="someSelected()"
9817
+ [disabled]="entries().length === 0"
9818
+ (changed)="selectAll($event)"
9819
+ />
9820
+ }
9821
+ @if (sortOptions().length > 0) {
9822
+ <bf-select
9823
+ class="min-w-0 flex-1 basis-36"
9824
+ [label]="labels.tableSortBy"
9825
+ [options]="sortOptions()"
9826
+ [value]="sortValue()"
9827
+ (changed)="sortFromOption($event)"
9828
+ />
9829
+ }
9830
+ </div>
9831
+ }
9487
9832
  <div data-bf-table-scroller class="max-w-full overflow-x-auto">
9488
- <table #table class="w-full border-collapse">
9833
+ <table
9834
+ #table
9835
+ [attr.role]="stacks() ? 'table' : null"
9836
+ [attr.aria-labelledby]="stacks() && label() ? captionId : null"
9837
+ [class]="tableClasses()"
9838
+ >
9489
9839
  @if (label()) {
9490
- <caption class="sr-only">
9840
+ <caption class="sr-only" [attr.id]="stacks() ? captionId : null">
9491
9841
  {{
9492
9842
  label()
9493
9843
  }}
9494
9844
  </caption>
9495
9845
  }
9496
- <thead>
9497
- <tr class="border-border border-b">
9846
+ <thead [attr.role]="stacks() ? 'rowgroup' : null" [class]="headClasses()">
9847
+ <tr class="border-border border-b" [attr.role]="stacks() ? 'row' : null">
9498
9848
  @if (selectable()) {
9499
- <th scope="col" [class]="selectHeadClasses()">
9849
+ <th
9850
+ scope="col"
9851
+ [attr.role]="stacks() ? 'columnheader' : null"
9852
+ [class]="selectHeadClasses()"
9853
+ >
9500
9854
  <bf-checkbox
9855
+ [class]="notStackedClasses()"
9501
9856
  [size]="resolvedSize()"
9502
9857
  [checked]="allSelected()"
9503
9858
  [indeterminate]="someSelected()"
@@ -9510,15 +9865,21 @@ i0.ɵɵngDeclareClassMetadata({
9510
9865
  @for (column of columns(); track column.key) {
9511
9866
  <th
9512
9867
  scope="col"
9868
+ [attr.role]="stacks() ? 'columnheader' : null"
9513
9869
  [attr.data-bf-column]="column.key"
9514
9870
  [attr.aria-sort]="ariaSort(column.key)"
9515
- [class]="headClasses(column)"
9871
+ [class]="headCellClasses(column)"
9516
9872
  >
9517
9873
  @if (column.sortable) {
9518
- <button type="button" [class]="sortButton" (click)="sortBy(column.key)">
9874
+ <button type="button" [class]="sortButtonClasses()" (click)="sortBy(column.key)">
9519
9875
  {{ column.label }}
9520
9876
  <span aria-hidden="true" [class]="arrowClasses(column.key)"></span>
9521
9877
  </button>
9878
+ @if (stacks()) {
9879
+ <span data-bf-stacked-label [class]="stackedOnlyClasses()">{{
9880
+ column.label
9881
+ }}</span>
9882
+ }
9522
9883
  } @else {
9523
9884
  {{ column.label }}
9524
9885
  }
@@ -9526,11 +9887,15 @@ i0.ɵɵngDeclareClassMetadata({
9526
9887
  }
9527
9888
  </tr>
9528
9889
  </thead>
9529
- <tbody class="divide-border divide-y">
9890
+ <tbody [attr.role]="stacks() ? 'rowgroup' : null" [class]="bodyGroupClasses()">
9530
9891
  @for (entry of entries(); track entry.key) {
9531
- <tr data-bf-table-row [class]="rowClasses(entry.key)">
9892
+ <tr
9893
+ data-bf-table-row
9894
+ [attr.role]="stacks() ? 'row' : null"
9895
+ [class]="rowClasses(entry.key)"
9896
+ >
9532
9897
  @if (selectable()) {
9533
- <td [class]="selectBodyClasses()">
9898
+ <td [attr.role]="stacks() ? 'cell' : null" [class]="selectBodyClasses()">
9534
9899
  <bf-checkbox
9535
9900
  [size]="resolvedSize()"
9536
9901
  [checked]="selectedKeys().has(entry.key)"
@@ -9542,8 +9907,10 @@ i0.ɵɵngDeclareClassMetadata({
9542
9907
  @for (column of columns(); track column.key; let first = $first) {
9543
9908
  <td
9544
9909
  data-bf-cell
9910
+ [attr.role]="stacks() ? 'cell' : null"
9545
9911
  [attr.id]="first ? cellId(entry.index) : null"
9546
- [class]="bodyClasses(column)"
9912
+ [attr.data-label]="stacks() && !first ? column.label : null"
9913
+ [class]="bodyClasses(column, first)"
9547
9914
  >
9548
9915
  @if (templates().get(column.key); as template) {
9549
9916
  <ng-container
@@ -9559,8 +9926,18 @@ i0.ɵɵngDeclareClassMetadata({
9559
9926
  }
9560
9927
  </tr>
9561
9928
  } @empty {
9562
- <tr data-bf-table-empty>
9563
- <td [attr.colspan]="columnCount()"><ng-content select="[bfSlot=empty]" /></td>
9929
+ <tr
9930
+ data-bf-table-empty
9931
+ [attr.role]="stacks() ? 'row' : null"
9932
+ [class]="stackEmptyClasses()"
9933
+ >
9934
+ <td
9935
+ [attr.role]="stacks() ? 'cell' : null"
9936
+ [attr.colspan]="columnCount()"
9937
+ [class]="stackEmptyClasses()"
9938
+ >
9939
+ <ng-content select="[bfSlot=empty]" />
9940
+ </td>
9564
9941
  </tr>
9565
9942
  }
9566
9943
  </tbody>
@@ -9648,6 +10025,14 @@ i0.ɵɵngDeclareClassMetadata({
9648
10025
  required: false
9649
10026
  }]
9650
10027
  }],
10028
+ stack: [{
10029
+ type: i0.Input,
10030
+ args: [{
10031
+ isSignal: true,
10032
+ alias: "stack",
10033
+ required: false
10034
+ }]
10035
+ }],
9651
10036
  table: [{
9652
10037
  type: i0.ViewChild,
9653
10038
  args: ["table", { isSignal: true }]
@@ -9789,7 +10174,14 @@ i0.ɵɵngDeclareClassMetadata({
9789
10174
  const BASE$1 = "flex h-full items-start gap-3 text-start";
9790
10175
  const VARIANT = {
9791
10176
  plain: "",
9792
- card: "rounded-card bg-surface p-card border-[1.5px] border-border-strong"
10177
+ card: "rounded-card bg-surface p-card border-[1.5px] border-border-strong",
10178
+ tile: "rounded-card bg-surface-sunken p-card"
10179
+ };
10180
+ const ICON_TILE = "rounded-tile text-text-muted flex size-10 shrink-0 items-center justify-center empty:hidden";
10181
+ const ICON_TILE_SURFACE = {
10182
+ plain: "bg-surface-sunken",
10183
+ card: "bg-surface-sunken",
10184
+ tile: "bg-surface"
9793
10185
  };
9794
10186
  const DELTA_BASE = "inline-flex items-center gap-1 rounded-control px-2 py-1 text-micro font-bold leading-none tabular-nums";
9795
10187
  const DELTA_TONE = {
@@ -9811,6 +10203,7 @@ var BfStatComponent = class BfStatComponent {
9811
10203
  trendIntent = input("positive", ...ngDevMode ? [{ debugName: "trendIntent" }] : /* istanbul ignore next */ []);
9812
10204
  labels = inject(BF_LABELS);
9813
10205
  classes = computed(() => [BASE$1, VARIANT[this.variant()]].filter(Boolean).join(" "), ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
10206
+ iconTileClasses = computed(() => `${ICON_TILE} ${ICON_TILE_SURFACE[this.variant()]}`, ...ngDevMode ? [{ debugName: "iconTileClasses" }] : /* istanbul ignore next */ []);
9814
10207
  deltaClasses = computed(() => {
9815
10208
  const trend = this.trend();
9816
10209
  const tone = trend === void 0 || trend === "flat" ? "neutral" : trend === "up" === (this.trendIntent() === "positive") ? "good" : "bad";
@@ -9891,11 +10284,7 @@ var BfStatComponent = class BfStatComponent {
9891
10284
  ngImport: i0,
9892
10285
  template: `
9893
10286
  <div [class]="classes()">
9894
- <span
9895
- data-tile
9896
- class="rounded-tile bg-surface-sunken text-text-muted flex size-10 shrink-0 items-center justify-center empty:hidden"
9897
- ><ng-content select="[bfSlot=icon]"
9898
- /></span>
10287
+ <span data-tile [class]="iconTileClasses()"><ng-content select="[bfSlot=icon]" /></span>
9899
10288
  <dl class="flex min-w-0 flex-col gap-1">
9900
10289
  <dt class="text-caption text-text-muted">{{ label() }}</dt>
9901
10290
  <dd
@@ -9931,11 +10320,7 @@ i0.ɵɵngDeclareClassMetadata({
9931
10320
  host: { class: "block" },
9932
10321
  template: `
9933
10322
  <div [class]="classes()">
9934
- <span
9935
- data-tile
9936
- class="rounded-tile bg-surface-sunken text-text-muted flex size-10 shrink-0 items-center justify-center empty:hidden"
9937
- ><ng-content select="[bfSlot=icon]"
9938
- /></span>
10323
+ <span data-tile [class]="iconTileClasses()"><ng-content select="[bfSlot=icon]" /></span>
9939
10324
  <dl class="flex min-w-0 flex-col gap-1">
9940
10325
  <dt class="text-caption text-text-muted">{{ label() }}</dt>
9941
10326
  <dd
@@ -10303,6 +10688,7 @@ var BfSidebarComponent = class BfSidebarComponent {
10303
10688
  label = input("", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
10304
10689
  collapsed = model(false, ...ngDevMode ? [{ debugName: "collapsed" }] : /* istanbul ignore next */ []);
10305
10690
  labels = inject(BF_LABELS);
10691
+ navId = uniqueId("bf-sidebar");
10306
10692
  name = computed(() => this.label() || this.labels.navigation, ...ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []);
10307
10693
  width = computed(() => this.collapsed() ? "collapsed" : "expanded", ...ngDevMode ? [{ debugName: "width" }] : /* istanbul ignore next */ []);
10308
10694
  hostClasses = computed(() => HOST$2[this.width()], ...ngDevMode ? [{ debugName: "hostClasses" }] : /* istanbul ignore next */ []);
@@ -10344,14 +10730,20 @@ var BfSidebarComponent = class BfSidebarComponent {
10344
10730
  } },
10345
10731
  providers: [{
10346
10732
  provide: BF_NAV,
10347
- useFactory: () => ({
10348
- layout: "sidebar",
10349
- collapsed: inject(BfSidebarComponent).collapsed
10350
- })
10733
+ useFactory: () => {
10734
+ const sidebar = inject(BfSidebarComponent);
10735
+ return {
10736
+ layout: "sidebar",
10737
+ collapsed: sidebar.collapsed,
10738
+ navId: sidebar.navId,
10739
+ setCollapsed: (collapsed) => sidebar.collapsed.set(collapsed)
10740
+ };
10741
+ }
10351
10742
  }],
10352
10743
  ngImport: i0,
10353
10744
  template: `
10354
10745
  <nav
10746
+ [id]="navId"
10355
10747
  [attr.aria-label]="name()"
10356
10748
  class="border-border bg-surface flex min-h-0 flex-1 flex-col gap-6 border-e p-3"
10357
10749
  >
@@ -10387,13 +10779,19 @@ i0.ɵɵngDeclareClassMetadata({
10387
10779
  },
10388
10780
  providers: [{
10389
10781
  provide: BF_NAV,
10390
- useFactory: () => ({
10391
- layout: "sidebar",
10392
- collapsed: inject(BfSidebarComponent).collapsed
10393
- })
10782
+ useFactory: () => {
10783
+ const sidebar = inject(BfSidebarComponent);
10784
+ return {
10785
+ layout: "sidebar",
10786
+ collapsed: sidebar.collapsed,
10787
+ navId: sidebar.navId,
10788
+ setCollapsed: (collapsed) => sidebar.collapsed.set(collapsed)
10789
+ };
10790
+ }
10394
10791
  }],
10395
10792
  template: `
10396
10793
  <nav
10794
+ [id]="navId"
10397
10795
  [attr.aria-label]="name()"
10398
10796
  class="border-border bg-surface flex min-h-0 flex-1 flex-col gap-6 border-e p-3"
10399
10797
  >
@@ -10465,7 +10863,9 @@ var BfTopNavComponent = class BfTopNavComponent {
10465
10863
  provide: BF_NAV,
10466
10864
  useFactory: () => ({
10467
10865
  layout: "top",
10468
- collapsed: signal(false).asReadonly()
10866
+ collapsed: signal(false).asReadonly(),
10867
+ navId: null,
10868
+ setCollapsed: () => void 0
10469
10869
  })
10470
10870
  }],
10471
10871
  ngImport: i0,
@@ -10491,7 +10891,9 @@ i0.ɵɵngDeclareClassMetadata({
10491
10891
  provide: BF_NAV,
10492
10892
  useFactory: () => ({
10493
10893
  layout: "top",
10494
- collapsed: signal(false).asReadonly()
10894
+ collapsed: signal(false).asReadonly(),
10895
+ navId: null,
10896
+ setCollapsed: () => void 0
10495
10897
  })
10496
10898
  }],
10497
10899
  template: `
@@ -10596,7 +10998,7 @@ const HEIGHT = {
10596
10998
  md: "min-h-10 gap-3 text-label-sm pointer-coarse:min-h-hit",
10597
10999
  lg: "min-h-12 gap-3 text-label pointer-coarse:min-h-hit"
10598
11000
  };
10599
- const PADDING = {
11001
+ const PADDING$1 = {
10600
11002
  sm: "px-3",
10601
11003
  md: "px-3",
10602
11004
  lg: "px-4"
@@ -10638,7 +11040,7 @@ var BfNavItemComponent = class BfNavItemComponent {
10638
11040
  return [
10639
11041
  BASE,
10640
11042
  HEIGHT[size],
10641
- form === "collapsed" ? SQUARE[size] : PADDING[size],
11043
+ form === "collapsed" ? SQUARE[size] : PADDING$1[size],
10642
11044
  FORM[form]
10643
11045
  ].join(" ");
10644
11046
  }, ...ngDevMode ? [{ debugName: "classes" }] : /* istanbul ignore next */ []);
@@ -10768,6 +11170,236 @@ i0.ɵɵngDeclareClassMetadata({
10768
11170
  }]
10769
11171
  }
10770
11172
  });
11173
+ const SIDEBAR = {
11174
+ md: "hidden md:flex",
11175
+ lg: "hidden lg:flex"
11176
+ };
11177
+ const HEADER = {
11178
+ md: "flex md:hidden",
11179
+ lg: "flex lg:hidden"
11180
+ };
11181
+ const PADDING = {
11182
+ md: "p-4 md:p-8",
11183
+ lg: "p-4 lg:p-8"
11184
+ };
11185
+ const WIDTH = {
11186
+ md: "max-w-3xl",
11187
+ lg: "max-w-5xl",
11188
+ xl: "max-w-7xl",
11189
+ full: "max-w-none"
11190
+ };
11191
+ var BfAppFrameComponent = class BfAppFrameComponent {
11192
+ breakpoint = input("md", ...ngDevMode ? [{ debugName: "breakpoint" }] : /* istanbul ignore next */ []);
11193
+ contentWidth = input("xl", ...ngDevMode ? [{ debugName: "contentWidth" }] : /* istanbul ignore next */ []);
11194
+ mainId = input(uniqueId("bf-app-frame-main"), ...ngDevMode ? [{ debugName: "mainId" }] : /* istanbul ignore next */ []);
11195
+ labels = inject(BF_LABELS);
11196
+ host = inject(ElementRef);
11197
+ main = viewChild.required("main", ...ngDevMode ? [{ debugName: "main" }] : /* istanbul ignore next */ []);
11198
+ nested = signal(false, ...ngDevMode ? [{ debugName: "nested" }] : /* istanbul ignore next */ []);
11199
+ sidebarClasses = computed(() => SIDEBAR[this.breakpoint()], ...ngDevMode ? [{ debugName: "sidebarClasses" }] : /* istanbul ignore next */ []);
11200
+ headerClasses = computed(() => HEADER[this.breakpoint()], ...ngDevMode ? [{ debugName: "headerClasses" }] : /* istanbul ignore next */ []);
11201
+ paddingClasses = computed(() => PADDING[this.breakpoint()], ...ngDevMode ? [{ debugName: "paddingClasses" }] : /* istanbul ignore next */ []);
11202
+ widthClasses = computed(() => WIDTH[this.contentWidth()], ...ngDevMode ? [{ debugName: "widthClasses" }] : /* istanbul ignore next */ []);
11203
+ constructor() {
11204
+ afterNextRender({ read: () => this.nested.set(this.host.nativeElement.parentElement?.closest("main, [role=\"main\"]") != null) });
11205
+ }
11206
+ skip(event) {
11207
+ event.preventDefault();
11208
+ this.main().nativeElement.focus();
11209
+ }
11210
+ static ɵfac = i0.ɵɵngDeclareFactory({
11211
+ minVersion: "12.0.0",
11212
+ version: "22.1.7",
11213
+ ngImport: i0,
11214
+ type: BfAppFrameComponent,
11215
+ deps: [],
11216
+ target: i0.ɵɵFactoryTarget.Component
11217
+ });
11218
+ static ɵcmp = i0.ɵɵngDeclareComponent({
11219
+ minVersion: "17.2.0",
11220
+ version: "22.1.7",
11221
+ type: BfAppFrameComponent,
11222
+ isStandalone: true,
11223
+ selector: "bf-app-frame",
11224
+ inputs: {
11225
+ breakpoint: {
11226
+ classPropertyName: "breakpoint",
11227
+ publicName: "breakpoint",
11228
+ isSignal: true,
11229
+ isRequired: false,
11230
+ transformFunction: null
11231
+ },
11232
+ contentWidth: {
11233
+ classPropertyName: "contentWidth",
11234
+ publicName: "contentWidth",
11235
+ isSignal: true,
11236
+ isRequired: false,
11237
+ transformFunction: null
11238
+ },
11239
+ mainId: {
11240
+ classPropertyName: "mainId",
11241
+ publicName: "mainId",
11242
+ isSignal: true,
11243
+ isRequired: false,
11244
+ transformFunction: null
11245
+ }
11246
+ },
11247
+ host: { classAttribute: "bg-bg text-text relative flex" },
11248
+ viewQueries: [{
11249
+ propertyName: "main",
11250
+ first: true,
11251
+ predicate: ["main"],
11252
+ descendants: true,
11253
+ isSignal: true
11254
+ }],
11255
+ ngImport: i0,
11256
+ template: `
11257
+ <!-- The skip link focuses the content by script: under <base href="/"> a bare "#id" link
11258
+ resolves against the base, so following it would load the root URL instead of moving
11259
+ focus. The href stays for its link semantics and a copied or middle-clicked URL. -->
11260
+ <a
11261
+ data-skip-link
11262
+ [href]="'#' + mainId()"
11263
+ class="bg-surface text-text text-label-sm shadow-floating rounded-control focus-visible:ring-ring absolute start-4 top-4 z-50 px-4 py-2 font-bold not-focus:sr-only focus-visible:ring-4 focus-visible:outline-hidden"
11264
+ (click)="skip($event)"
11265
+ >{{ labels.skipToContent }}</a
11266
+ >
11267
+ <!-- From the breakpoint up the sidebar column sticks to the viewport at its full height (or
11268
+ the frame's, when a consumer gives it one); the bf-sidebar stretches to fill it and
11269
+ scrolls its own destinations. -->
11270
+ <div data-sidebar class="sticky top-0 h-dvh max-h-full shrink-0 {{ sidebarClasses() }}">
11271
+ <ng-content select="[bfSlot=sidebar]" />
11272
+ </div>
11273
+ <div data-column class="flex min-w-0 flex-1 flex-col">
11274
+ <header
11275
+ data-bar
11276
+ class="bg-surface border-border sticky top-0 z-10 min-h-14 items-center gap-3 border-b px-4 py-2 {{
11277
+ headerClasses()
11278
+ }}"
11279
+ >
11280
+ <div data-brand class="flex min-w-0 items-center empty:hidden">
11281
+ <ng-content select="[bfSlot=brand]" />
11282
+ </div>
11283
+ <div data-menu class="flex items-center empty:hidden">
11284
+ <ng-content select="[bfSlot=menu]" />
11285
+ </div>
11286
+ <div data-actions class="ms-auto flex items-center gap-2 empty:hidden">
11287
+ <ng-content select="[bfSlot=actions]" />
11288
+ </div>
11289
+ </header>
11290
+ <!-- A div with the main role rather than <main>: nested inside another page's main (a docs
11291
+ preview) it drops the role, so the document keeps exactly one main landmark. -->
11292
+ <div
11293
+ #main
11294
+ data-main
11295
+ [id]="mainId()"
11296
+ tabindex="-1"
11297
+ [attr.role]="nested() ? null : 'main'"
11298
+ class="min-w-0 flex-1 outline-hidden {{ paddingClasses() }}"
11299
+ >
11300
+ <div data-content class="mx-auto w-full {{ widthClasses() }}">
11301
+ <ng-content />
11302
+ </div>
11303
+ </div>
11304
+ </div>
11305
+ `,
11306
+ isInline: true
11307
+ });
11308
+ };
11309
+ i0.ɵɵngDeclareClassMetadata({
11310
+ minVersion: "12.0.0",
11311
+ version: "22.1.7",
11312
+ ngImport: i0,
11313
+ type: BfAppFrameComponent,
11314
+ decorators: [{
11315
+ type: Component,
11316
+ args: [{
11317
+ selector: "bf-app-frame",
11318
+ host: { class: "bg-bg text-text relative flex" },
11319
+ template: `
11320
+ <!-- The skip link focuses the content by script: under <base href="/"> a bare "#id" link
11321
+ resolves against the base, so following it would load the root URL instead of moving
11322
+ focus. The href stays for its link semantics and a copied or middle-clicked URL. -->
11323
+ <a
11324
+ data-skip-link
11325
+ [href]="'#' + mainId()"
11326
+ class="bg-surface text-text text-label-sm shadow-floating rounded-control focus-visible:ring-ring absolute start-4 top-4 z-50 px-4 py-2 font-bold not-focus:sr-only focus-visible:ring-4 focus-visible:outline-hidden"
11327
+ (click)="skip($event)"
11328
+ >{{ labels.skipToContent }}</a
11329
+ >
11330
+ <!-- From the breakpoint up the sidebar column sticks to the viewport at its full height (or
11331
+ the frame's, when a consumer gives it one); the bf-sidebar stretches to fill it and
11332
+ scrolls its own destinations. -->
11333
+ <div data-sidebar class="sticky top-0 h-dvh max-h-full shrink-0 {{ sidebarClasses() }}">
11334
+ <ng-content select="[bfSlot=sidebar]" />
11335
+ </div>
11336
+ <div data-column class="flex min-w-0 flex-1 flex-col">
11337
+ <header
11338
+ data-bar
11339
+ class="bg-surface border-border sticky top-0 z-10 min-h-14 items-center gap-3 border-b px-4 py-2 {{
11340
+ headerClasses()
11341
+ }}"
11342
+ >
11343
+ <div data-brand class="flex min-w-0 items-center empty:hidden">
11344
+ <ng-content select="[bfSlot=brand]" />
11345
+ </div>
11346
+ <div data-menu class="flex items-center empty:hidden">
11347
+ <ng-content select="[bfSlot=menu]" />
11348
+ </div>
11349
+ <div data-actions class="ms-auto flex items-center gap-2 empty:hidden">
11350
+ <ng-content select="[bfSlot=actions]" />
11351
+ </div>
11352
+ </header>
11353
+ <!-- A div with the main role rather than <main>: nested inside another page's main (a docs
11354
+ preview) it drops the role, so the document keeps exactly one main landmark. -->
11355
+ <div
11356
+ #main
11357
+ data-main
11358
+ [id]="mainId()"
11359
+ tabindex="-1"
11360
+ [attr.role]="nested() ? null : 'main'"
11361
+ class="min-w-0 flex-1 outline-hidden {{ paddingClasses() }}"
11362
+ >
11363
+ <div data-content class="mx-auto w-full {{ widthClasses() }}">
11364
+ <ng-content />
11365
+ </div>
11366
+ </div>
11367
+ </div>
11368
+ `
11369
+ }]
11370
+ }],
11371
+ ctorParameters: () => [],
11372
+ propDecorators: {
11373
+ breakpoint: [{
11374
+ type: i0.Input,
11375
+ args: [{
11376
+ isSignal: true,
11377
+ alias: "breakpoint",
11378
+ required: false
11379
+ }]
11380
+ }],
11381
+ contentWidth: [{
11382
+ type: i0.Input,
11383
+ args: [{
11384
+ isSignal: true,
11385
+ alias: "contentWidth",
11386
+ required: false
11387
+ }]
11388
+ }],
11389
+ mainId: [{
11390
+ type: i0.Input,
11391
+ args: [{
11392
+ isSignal: true,
11393
+ alias: "mainId",
11394
+ required: false
11395
+ }]
11396
+ }],
11397
+ main: [{
11398
+ type: i0.ViewChild,
11399
+ args: ["main", { isSignal: true }]
11400
+ }]
11401
+ }
11402
+ });
10771
11403
  const BAR = "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]";
10772
11404
  const HOST = {
10773
11405
  text: "flex flex-col gap-2",
@@ -12699,6 +13331,6 @@ function provideBfDocumentReset() {
12699
13331
  inject(DestroyRef).onDestroy(() => resetBfDocument(document));
12700
13332
  });
12701
13333
  }
12702
- export { BF_COLOR_SCHEME_STORAGE, BF_DEFAULTS, BF_DEFAULT_LABELS, BF_DEFAULT_VALUES, BF_LABELS, BF_TAB_BAR, BF_TAB_BAR_CONTROLLER, BF_TAB_LINKS, BfActionBarComponent, BfActionDirective, BfAlertComponent, BfAvatarComponent, BfBadgeComponent, BfBreadcrumbComponent, BfBreadcrumbItemComponent, BfButtonComponent, BfCalendarComponent, BfCardComponent, BfCheckboxComponent, BfChipComponent, BfChipGroupComponent, BfColorSchemeService, BfDescriptionItemComponent, BfDescriptionListComponent, BfEmptyStateComponent, BfFieldComponent, BfIconButtonComponent, BfInputComponent, BfListComponent, BfListItemComponent, BfNavGroupComponent, BfNavItemComponent, BfPageHeaderComponent, BfPaginationComponent, BfProgressComponent, BfRadioGroupComponent, BfSegmentedComponent, BfSelectComponent, BfSidebarComponent, BfSkeletonComponent, BfSpinnerComponent, BfStatComponent, BfTabBarComponent, BfTabComponent, BfTabGroupComponent, BfTabPanelComponent, BfTableCellDirective, BfTableComponent, BfTextareaComponent, BfThemeSwitchComponent, BfToggleComponent, BfToolbarComponent, BfTopNavComponent, bfFieldControlClass, bfValidationMessage, provideBfColorScheme, provideBfDefaults, provideBfLabels, 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 };
13334
+ export { BF_COLOR_SCHEME_STORAGE, BF_DEFAULTS, BF_DEFAULT_LABELS, BF_DEFAULT_VALUES, BF_LABELS, BF_SIDEBAR_STATE_STORAGE, BF_TAB_BAR, BF_TAB_BAR_CONTROLLER, BF_TAB_LINKS, BfActionBarComponent, BfActionDirective, BfAlertComponent, BfAppFrameComponent, BfAvatarComponent, BfBadgeComponent, BfBreadcrumbComponent, BfBreadcrumbItemComponent, BfButtonComponent, BfCalendarComponent, BfCardComponent, BfCheckboxComponent, BfChipComponent, BfChipGroupComponent, BfColorSchemeService, BfDescriptionItemComponent, BfDescriptionListComponent, BfEmptyStateComponent, BfFieldComponent, BfIconButtonComponent, BfInputComponent, BfListComponent, BfListItemComponent, BfNavGroupComponent, BfNavItemComponent, BfPageHeaderComponent, BfPaginationComponent, BfProgressComponent, BfRadioGroupComponent, BfSegmentedComponent, BfSelectComponent, BfSidebarComponent, BfSidebarStateService, BfSkeletonComponent, BfSpinnerComponent, BfStatComponent, BfTabBarComponent, BfTabComponent, BfTabGroupComponent, BfTabPanelComponent, BfTableCellDirective, BfTableComponent, BfTextareaComponent, BfThemeSwitchComponent, BfToggleComponent, BfToolbarComponent, BfTopNavComponent, bfFieldControlClass, bfValidationMessage, provideBfColorScheme, provideBfDefaults, provideBfLabels, provideBfSidebarState, BUTTON_CLASSES as ɵBF_BUTTON_CLASSES, ICON_BUTTON_CLASSES as ɵBF_ICON_BUTTON_CLASSES, BF_NAV as ɵBF_NAV, 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 };
12703
13335
 
12704
13336
  //# sourceMappingURL=bitforgehq-ui.mjs.map