@neuravision/ng-construct 0.3.3 → 0.3.6

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.
@@ -1,5 +1,5 @@
1
1
  import * as i0 from '@angular/core';
2
- import { input, output, signal, computed, ChangeDetectionStrategy, Component, inject, forwardRef, model, booleanAttribute, viewChild, contentChildren, effect, contentChild, ElementRef, TemplateRef, Directive, Injectable, viewChildren, Renderer2, InjectionToken, DOCUMENT, numberAttribute, Pipe } from '@angular/core';
2
+ import { input, output, signal, computed, ChangeDetectionStrategy, Component, inject, forwardRef, model, booleanAttribute, viewChild, contentChildren, effect, DOCUMENT, contentChild, ElementRef, TemplateRef, Directive, Injectable, viewChildren, Renderer2, InjectionToken, numberAttribute, Pipe } from '@angular/core';
3
3
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
4
4
  import { NgTemplateOutlet } from '@angular/common';
5
5
  import { RouterLink, RouterLinkActive } from '@angular/router';
@@ -354,6 +354,464 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
354
354
  `, styles: [":host{display:block}\n"] }]
355
355
  }], propDecorators: { multi: [{ type: i0.Input, args: [{ isSignal: true, alias: "multi", required: false }] }], bordered: [{ type: i0.Input, args: [{ isSignal: true, alias: "bordered", required: false }] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => AfAccordionItemComponent), { isSignal: true }] }] } });
356
356
 
357
+ /**
358
+ * Skip-link component for keyboard-only navigation bypass.
359
+ *
360
+ * Renders an anchor that is visually hidden off-screen and slides into view
361
+ * when focused. On activation it moves focus to the target element, allowing
362
+ * keyboard users to skip repetitive navigation blocks.
363
+ *
364
+ * Must be placed as the first focusable element in the document.
365
+ *
366
+ * @example
367
+ * <af-skip-link target="main-content" />
368
+ * <nav>…</nav>
369
+ * <main id="main-content" tabindex="-1">…</main>
370
+ */
371
+ class AfSkipLinkComponent {
372
+ /** ID of the element to skip to (without the leading `#`). */
373
+ target = input.required(...(ngDevMode ? [{ debugName: "target" }] : []));
374
+ /** Visible label text shown when the link receives focus. */
375
+ label = input('Skip to main content', ...(ngDevMode ? [{ debugName: "label" }] : []));
376
+ document = inject(DOCUMENT);
377
+ /**
378
+ * Moves focus to the target element so keyboard navigation
379
+ * continues from there instead of the top of the page.
380
+ */
381
+ focusTarget(event) {
382
+ event.preventDefault();
383
+ const el = this.document.getElementById(this.target());
384
+ if (!el) {
385
+ return;
386
+ }
387
+ if (!el.hasAttribute('tabindex')) {
388
+ el.setAttribute('tabindex', '-1');
389
+ }
390
+ el.focus();
391
+ }
392
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
393
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: AfSkipLinkComponent, isStandalone: true, selector: "af-skip-link", inputs: { target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
394
+ <a
395
+ class="ct-skip-link"
396
+ [attr.href]="'#' + target()"
397
+ (click)="focusTarget($event)"
398
+ >
399
+ {{ label() }}
400
+ </a>
401
+ `, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
402
+ }
403
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, decorators: [{
404
+ type: Component,
405
+ args: [{ selector: 'af-skip-link', changeDetection: ChangeDetectionStrategy.OnPush, template: `
406
+ <a
407
+ class="ct-skip-link"
408
+ [attr.href]="'#' + target()"
409
+ (click)="focusTarget($event)"
410
+ >
411
+ {{ label() }}
412
+ </a>
413
+ `, styles: [":host{display:contents}\n"] }]
414
+ }], propDecorators: { target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
415
+
416
+ /**
417
+ * Page header rendered inside the main content area of an App Shell.
418
+ *
419
+ * Displays breadcrumbs, page title, and actions in a flex row.
420
+ * Place inside `<af-app-shell>` without any slot attribute so it
421
+ * projects into the main area.
422
+ *
423
+ * @example
424
+ * <af-app-shell>
425
+ * <af-app-shell-page-header sticky>
426
+ * <nav aria-label="Breadcrumb">Home / Dashboard</nav>
427
+ * <h1>Dashboard</h1>
428
+ * <button class="ct-button">New Item</button>
429
+ * </af-app-shell-page-header>
430
+ * <p>Main content…</p>
431
+ * </af-app-shell>
432
+ */
433
+ class AfAppShellPageHeaderComponent {
434
+ /** Pin the page header to the top of the scrollable main area. */
435
+ sticky = input(false, { ...(ngDevMode ? { debugName: "sticky" } : {}), transform: booleanAttribute });
436
+ classes = computed(() => {
437
+ const c = ['ct-app-shell__page-header'];
438
+ if (this.sticky()) {
439
+ c.push('ct-app-shell__page-header--sticky');
440
+ }
441
+ return c.join(' ');
442
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : []));
443
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellPageHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
444
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: AfAppShellPageHeaderComponent, isStandalone: true, selector: "af-app-shell-page-header", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
445
+ <div [class]="classes()">
446
+ <ng-content />
447
+ </div>
448
+ `, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
449
+ }
450
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellPageHeaderComponent, decorators: [{
451
+ type: Component,
452
+ args: [{ selector: 'af-app-shell-page-header', changeDetection: ChangeDetectionStrategy.OnPush, template: `
453
+ <div [class]="classes()">
454
+ <ng-content />
455
+ </div>
456
+ `, styles: [":host{display:contents}\n"] }]
457
+ }], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }] } });
458
+ /**
459
+ * Classic CSS-Grid App Shell that orchestrates header, sidebar,
460
+ * main content, optional panel, and footer.
461
+ *
462
+ * Wraps the `ct-app-shell` CSS component from the Construct Design System.
463
+ * Sidebar and panel states are two-way bindable via `model()` signals.
464
+ *
465
+ * Content projection slots:
466
+ * - `[header]` — Navbar / top bar
467
+ * - `[sidebar]` — Navigation sidebar
468
+ * - `[panel]` — Right-side contextual panel
469
+ * - `[footer]` — Footer area
470
+ * - `[bottomNav]` — Mobile bottom navigation (requires `bottomNav` modifier)
471
+ * - *(default)* — Main content (including `<af-app-shell-page-header>`)
472
+ *
473
+ * @example
474
+ * <af-app-shell [(sidebarState)]="sidebarState" [(panelState)]="panelState" sidebarFullHeight>
475
+ * <af-navbar header ariaLabel="Main">…</af-navbar>
476
+ * <af-sidebar sidebar ariaLabel="Navigation">…</af-sidebar>
477
+ * <af-app-shell-page-header sticky>
478
+ * <h1>Dashboard</h1>
479
+ * </af-app-shell-page-header>
480
+ * <p>Content goes here</p>
481
+ * <div panel>Inspector</div>
482
+ * <footer footer>&copy; 2026</footer>
483
+ * </af-app-shell>
484
+ */
485
+ class AfAppShellComponent {
486
+ /** Current sidebar state — two-way bindable. */
487
+ sidebarState = model('expanded', ...(ngDevMode ? [{ debugName: "sidebarState" }] : []));
488
+ /** Current panel state — two-way bindable. */
489
+ panelState = model('closed', ...(ngDevMode ? [{ debugName: "panelState" }] : []));
490
+ /** Remove the sidebar column entirely. */
491
+ noSidebar = input(false, { ...(ngDevMode ? { debugName: "noSidebar" } : {}), transform: booleanAttribute });
492
+ /** Place the sidebar on the right side. */
493
+ sidebarRight = input(false, { ...(ngDevMode ? { debugName: "sidebarRight" } : {}), transform: booleanAttribute });
494
+ /** Sidebar spans the full viewport height (header sits beside it). */
495
+ sidebarFullHeight = input(false, { ...(ngDevMode ? { debugName: "sidebarFullHeight" } : {}), transform: booleanAttribute });
496
+ /** Stick the footer to the bottom with a top border. */
497
+ footerSticky = input(false, { ...(ngDevMode ? { debugName: "footerSticky" } : {}), transform: booleanAttribute });
498
+ /** Enable bottom navigation on mobile (hides sidebar and footer). */
499
+ bottomNav = input(false, { ...(ngDevMode ? { debugName: "bottomNav" } : {}), transform: booleanAttribute });
500
+ /** Accessible label for the sidebar landmark. */
501
+ sidebarLabel = input('Site navigation', ...(ngDevMode ? [{ debugName: "sidebarLabel" }] : []));
502
+ /** Accessible label for the panel landmark. */
503
+ panelLabel = input('Details', ...(ngDevMode ? [{ debugName: "panelLabel" }] : []));
504
+ /** ID of the main content element (used by skip-link). */
505
+ mainId = input('main-content', ...(ngDevMode ? [{ debugName: "mainId" }] : []));
506
+ /** Visible text of the skip-link. */
507
+ skipLinkLabel = input('Skip to content', ...(ngDevMode ? [{ debugName: "skipLinkLabel" }] : []));
508
+ shellClasses = computed(() => {
509
+ const classes = ['ct-app-shell'];
510
+ if (this.noSidebar()) {
511
+ classes.push('ct-app-shell--no-sidebar');
512
+ }
513
+ if (this.sidebarRight()) {
514
+ classes.push('ct-app-shell--sidebar-right');
515
+ }
516
+ if (this.sidebarFullHeight()) {
517
+ classes.push('ct-app-shell--sidebar-full-height');
518
+ }
519
+ if (this.footerSticky()) {
520
+ classes.push('ct-app-shell--footer-sticky');
521
+ }
522
+ if (this.bottomNav()) {
523
+ classes.push('ct-app-shell--bottom-nav');
524
+ }
525
+ return classes.join(' ');
526
+ }, ...(ngDevMode ? [{ debugName: "shellClasses" }] : []));
527
+ /** Dismiss the mobile sidebar overlay. */
528
+ onBackdropClick() {
529
+ this.sidebarState.set('hidden');
530
+ }
531
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
532
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: AfAppShellComponent, isStandalone: true, selector: "af-app-shell", inputs: { sidebarState: { classPropertyName: "sidebarState", publicName: "sidebarState", isSignal: true, isRequired: false, transformFunction: null }, panelState: { classPropertyName: "panelState", publicName: "panelState", isSignal: true, isRequired: false, transformFunction: null }, noSidebar: { classPropertyName: "noSidebar", publicName: "noSidebar", isSignal: true, isRequired: false, transformFunction: null }, sidebarRight: { classPropertyName: "sidebarRight", publicName: "sidebarRight", isSignal: true, isRequired: false, transformFunction: null }, sidebarFullHeight: { classPropertyName: "sidebarFullHeight", publicName: "sidebarFullHeight", isSignal: true, isRequired: false, transformFunction: null }, footerSticky: { classPropertyName: "footerSticky", publicName: "footerSticky", isSignal: true, isRequired: false, transformFunction: null }, bottomNav: { classPropertyName: "bottomNav", publicName: "bottomNav", isSignal: true, isRequired: false, transformFunction: null }, sidebarLabel: { classPropertyName: "sidebarLabel", publicName: "sidebarLabel", isSignal: true, isRequired: false, transformFunction: null }, panelLabel: { classPropertyName: "panelLabel", publicName: "panelLabel", isSignal: true, isRequired: false, transformFunction: null }, mainId: { classPropertyName: "mainId", publicName: "mainId", isSignal: true, isRequired: false, transformFunction: null }, skipLinkLabel: { classPropertyName: "skipLinkLabel", publicName: "skipLinkLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sidebarState: "sidebarStateChange", panelState: "panelStateChange" }, ngImport: i0, template: `
533
+ <div
534
+ [class]="shellClasses()"
535
+ [attr.data-sidebar-state]="sidebarState()"
536
+ [attr.data-panel-state]="panelState()">
537
+ <af-skip-link [target]="mainId()" [label]="skipLinkLabel()" />
538
+
539
+ <header class="ct-app-shell__header">
540
+ <ng-content select="[header]" />
541
+ </header>
542
+
543
+ <aside class="ct-app-shell__sidebar" [attr.aria-label]="sidebarLabel()">
544
+ <ng-content select="[sidebar]" />
545
+ </aside>
546
+
547
+ <main class="ct-app-shell__main" [id]="mainId()" tabindex="0">
548
+ <ng-content />
549
+ </main>
550
+
551
+ <aside class="ct-app-shell__panel" [attr.aria-label]="panelLabel()">
552
+ <ng-content select="[panel]" />
553
+ </aside>
554
+
555
+ <footer class="ct-app-shell__footer">
556
+ <ng-content select="[footer]" />
557
+ </footer>
558
+
559
+ <div class="ct-app-shell__bottom-nav">
560
+ <ng-content select="[bottomNav]" />
561
+ </div>
562
+
563
+ <div
564
+ class="ct-app-shell__backdrop"
565
+ (click)="onBackdropClick()"
566
+ aria-hidden="true"></div>
567
+ </div>
568
+ `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: AfSkipLinkComponent, selector: "af-skip-link", inputs: ["target", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
569
+ }
570
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellComponent, decorators: [{
571
+ type: Component,
572
+ args: [{ selector: 'af-app-shell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AfSkipLinkComponent], template: `
573
+ <div
574
+ [class]="shellClasses()"
575
+ [attr.data-sidebar-state]="sidebarState()"
576
+ [attr.data-panel-state]="panelState()">
577
+ <af-skip-link [target]="mainId()" [label]="skipLinkLabel()" />
578
+
579
+ <header class="ct-app-shell__header">
580
+ <ng-content select="[header]" />
581
+ </header>
582
+
583
+ <aside class="ct-app-shell__sidebar" [attr.aria-label]="sidebarLabel()">
584
+ <ng-content select="[sidebar]" />
585
+ </aside>
586
+
587
+ <main class="ct-app-shell__main" [id]="mainId()" tabindex="0">
588
+ <ng-content />
589
+ </main>
590
+
591
+ <aside class="ct-app-shell__panel" [attr.aria-label]="panelLabel()">
592
+ <ng-content select="[panel]" />
593
+ </aside>
594
+
595
+ <footer class="ct-app-shell__footer">
596
+ <ng-content select="[footer]" />
597
+ </footer>
598
+
599
+ <div class="ct-app-shell__bottom-nav">
600
+ <ng-content select="[bottomNav]" />
601
+ </div>
602
+
603
+ <div
604
+ class="ct-app-shell__backdrop"
605
+ (click)="onBackdropClick()"
606
+ aria-hidden="true"></div>
607
+ </div>
608
+ `, styles: [":host{display:contents}\n"] }]
609
+ }], propDecorators: { sidebarState: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarState", required: false }] }, { type: i0.Output, args: ["sidebarStateChange"] }], panelState: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelState", required: false }] }, { type: i0.Output, args: ["panelStateChange"] }], noSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSidebar", required: false }] }], sidebarRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarRight", required: false }] }], sidebarFullHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarFullHeight", required: false }] }], footerSticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "footerSticky", required: false }] }], bottomNav: [{ type: i0.Input, args: [{ isSignal: true, alias: "bottomNav", required: false }] }], sidebarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarLabel", required: false }] }], panelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelLabel", required: false }] }], mainId: [{ type: i0.Input, args: [{ isSignal: true, alias: "mainId", required: false }] }], skipLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLinkLabel", required: false }] }] } });
610
+
611
+ /**
612
+ * Toolbar rendered inside the main content area of an App Shell V2.
613
+ *
614
+ * Replaces the classic full-width page header with a toolbar row
615
+ * for breadcrumbs, page title, and actions. Place inside
616
+ * `<af-app-shell-v2>` without any slot attribute so it projects
617
+ * into the main area.
618
+ *
619
+ * @example
620
+ * <af-app-shell-v2>
621
+ * <af-app-shell-v2-toolbar sticky>
622
+ * <nav aria-label="Breadcrumb">Home / Dashboard</nav>
623
+ * <div>
624
+ * <button class="ct-button">Export</button>
625
+ * </div>
626
+ * </af-app-shell-v2-toolbar>
627
+ * <p>Main content…</p>
628
+ * </af-app-shell-v2>
629
+ */
630
+ class AfAppShellV2ToolbarComponent {
631
+ /** Pin the toolbar to the top of the scrollable main area. */
632
+ sticky = input(false, { ...(ngDevMode ? { debugName: "sticky" } : {}), transform: booleanAttribute });
633
+ classes = computed(() => {
634
+ const c = ['ct-app-shell-v2__toolbar'];
635
+ if (this.sticky()) {
636
+ c.push('ct-app-shell-v2__toolbar--sticky');
637
+ }
638
+ return c.join(' ');
639
+ }, ...(ngDevMode ? [{ debugName: "classes" }] : []));
640
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellV2ToolbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
641
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: AfAppShellV2ToolbarComponent, isStandalone: true, selector: "af-app-shell-v2-toolbar", inputs: { sticky: { classPropertyName: "sticky", publicName: "sticky", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
642
+ <div [class]="classes()">
643
+ <ng-content />
644
+ </div>
645
+ `, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
646
+ }
647
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellV2ToolbarComponent, decorators: [{
648
+ type: Component,
649
+ args: [{ selector: 'af-app-shell-v2-toolbar', changeDetection: ChangeDetectionStrategy.OnPush, template: `
650
+ <div [class]="classes()">
651
+ <ng-content />
652
+ </div>
653
+ `, styles: [":host{display:contents}\n"] }]
654
+ }], propDecorators: { sticky: [{ type: i0.Input, args: [{ isSignal: true, alias: "sticky", required: false }] }] } });
655
+ /**
656
+ * Floating-canvas App Shell with elevated surfaces, rounded corners,
657
+ * and optional glass/branded modifiers.
658
+ *
659
+ * Wraps the `ct-app-shell-v2` CSS component from the Construct Design System.
660
+ * Sidebar and panel states are two-way bindable via `model()` signals.
661
+ *
662
+ * Content projection slots:
663
+ * - `[header]` — Optional floating header bar (requires `withHeader` input)
664
+ * - `[sidebar]` — Floating sidebar surface
665
+ * - `[panel]` — Right-side contextual panel (inside body flex container)
666
+ * - `[footer]` — Footer inside the main area
667
+ * - *(default)* — Main content (including `<af-app-shell-v2-toolbar>`)
668
+ *
669
+ * @example
670
+ * <af-app-shell-v2
671
+ * [(sidebarState)]="sidebarState"
672
+ * [(panelState)]="panelState"
673
+ * withHeader
674
+ * sidebarBranded
675
+ * glass>
676
+ * <af-navbar header ariaLabel="Main">…</af-navbar>
677
+ * <af-sidebar sidebar ariaLabel="Navigation">…</af-sidebar>
678
+ * <af-app-shell-v2-toolbar sticky>
679
+ * <h1>Dashboard</h1>
680
+ * </af-app-shell-v2-toolbar>
681
+ * <p>Content goes here</p>
682
+ * <div panel>Inspector</div>
683
+ * <footer footer>&copy; 2026</footer>
684
+ * </af-app-shell-v2>
685
+ */
686
+ class AfAppShellV2Component {
687
+ /** Current sidebar state — two-way bindable. */
688
+ sidebarState = model('expanded', ...(ngDevMode ? [{ debugName: "sidebarState" }] : []));
689
+ /** Current panel state — two-way bindable. */
690
+ panelState = model('closed', ...(ngDevMode ? [{ debugName: "panelState" }] : []));
691
+ /** Remove the sidebar entirely. */
692
+ noSidebar = input(false, { ...(ngDevMode ? { debugName: "noSidebar" } : {}), transform: booleanAttribute });
693
+ /** Place the sidebar on the right side. */
694
+ sidebarRight = input(false, { ...(ngDevMode ? { debugName: "sidebarRight" } : {}), transform: booleanAttribute });
695
+ /** Sidebar spans the full viewport height (header sits beside it). */
696
+ sidebarFullHeight = input(false, { ...(ngDevMode ? { debugName: "sidebarFullHeight" } : {}), transform: booleanAttribute });
697
+ /** Show the optional floating header bar. */
698
+ withHeader = input(false, { ...(ngDevMode ? { debugName: "withHeader" } : {}), transform: booleanAttribute });
699
+ /** Dark-branded sidebar (Slack / Linear / Discord aesthetic). */
700
+ sidebarBranded = input(false, { ...(ngDevMode ? { debugName: "sidebarBranded" } : {}), transform: booleanAttribute });
701
+ /** Frosted glass morphism effect on all floating surfaces. */
702
+ glass = input(false, { ...(ngDevMode ? { debugName: "glass" } : {}), transform: booleanAttribute });
703
+ /** Accessible label for the sidebar landmark. */
704
+ sidebarLabel = input('Site navigation', ...(ngDevMode ? [{ debugName: "sidebarLabel" }] : []));
705
+ /** Accessible label for the panel landmark. */
706
+ panelLabel = input('Details', ...(ngDevMode ? [{ debugName: "panelLabel" }] : []));
707
+ /** ID of the main content element (used by skip-link). */
708
+ mainId = input('main-content', ...(ngDevMode ? [{ debugName: "mainId" }] : []));
709
+ /** Visible text of the skip-link. */
710
+ skipLinkLabel = input('Skip to content', ...(ngDevMode ? [{ debugName: "skipLinkLabel" }] : []));
711
+ shellClasses = computed(() => {
712
+ const classes = ['ct-app-shell-v2'];
713
+ if (this.noSidebar()) {
714
+ classes.push('ct-app-shell-v2--no-sidebar');
715
+ }
716
+ if (this.sidebarRight()) {
717
+ classes.push('ct-app-shell-v2--sidebar-right');
718
+ }
719
+ if (this.sidebarFullHeight()) {
720
+ classes.push('ct-app-shell-v2--sidebar-full-height');
721
+ }
722
+ if (this.withHeader()) {
723
+ classes.push('ct-app-shell-v2--with-header');
724
+ }
725
+ if (this.sidebarBranded()) {
726
+ classes.push('ct-app-shell-v2--sidebar-branded');
727
+ }
728
+ if (this.glass()) {
729
+ classes.push('ct-app-shell-v2--glass');
730
+ }
731
+ return classes.join(' ');
732
+ }, ...(ngDevMode ? [{ debugName: "shellClasses" }] : []));
733
+ /** Dismiss the mobile sidebar overlay. */
734
+ onBackdropClick() {
735
+ this.sidebarState.set('hidden');
736
+ }
737
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellV2Component, deps: [], target: i0.ɵɵFactoryTarget.Component });
738
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AfAppShellV2Component, isStandalone: true, selector: "af-app-shell-v2", inputs: { sidebarState: { classPropertyName: "sidebarState", publicName: "sidebarState", isSignal: true, isRequired: false, transformFunction: null }, panelState: { classPropertyName: "panelState", publicName: "panelState", isSignal: true, isRequired: false, transformFunction: null }, noSidebar: { classPropertyName: "noSidebar", publicName: "noSidebar", isSignal: true, isRequired: false, transformFunction: null }, sidebarRight: { classPropertyName: "sidebarRight", publicName: "sidebarRight", isSignal: true, isRequired: false, transformFunction: null }, sidebarFullHeight: { classPropertyName: "sidebarFullHeight", publicName: "sidebarFullHeight", isSignal: true, isRequired: false, transformFunction: null }, withHeader: { classPropertyName: "withHeader", publicName: "withHeader", isSignal: true, isRequired: false, transformFunction: null }, sidebarBranded: { classPropertyName: "sidebarBranded", publicName: "sidebarBranded", isSignal: true, isRequired: false, transformFunction: null }, glass: { classPropertyName: "glass", publicName: "glass", isSignal: true, isRequired: false, transformFunction: null }, sidebarLabel: { classPropertyName: "sidebarLabel", publicName: "sidebarLabel", isSignal: true, isRequired: false, transformFunction: null }, panelLabel: { classPropertyName: "panelLabel", publicName: "panelLabel", isSignal: true, isRequired: false, transformFunction: null }, mainId: { classPropertyName: "mainId", publicName: "mainId", isSignal: true, isRequired: false, transformFunction: null }, skipLinkLabel: { classPropertyName: "skipLinkLabel", publicName: "skipLinkLabel", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { sidebarState: "sidebarStateChange", panelState: "panelStateChange" }, ngImport: i0, template: `
739
+ <div
740
+ [class]="shellClasses()"
741
+ [attr.data-sidebar-state]="sidebarState()"
742
+ [attr.data-panel-state]="panelState()">
743
+ <af-skip-link [target]="mainId()" [label]="skipLinkLabel()" />
744
+
745
+ @if (withHeader()) {
746
+ <header class="ct-app-shell-v2__header">
747
+ <ng-content select="[header]" />
748
+ </header>
749
+ }
750
+
751
+ <aside class="ct-app-shell-v2__sidebar" [attr.aria-label]="sidebarLabel()">
752
+ <ng-content select="[sidebar]" />
753
+ </aside>
754
+
755
+ <div class="ct-app-shell-v2__body">
756
+ <main class="ct-app-shell-v2__main" [id]="mainId()" tabindex="0">
757
+ <ng-content />
758
+ <div class="ct-app-shell-v2__footer">
759
+ <ng-content select="[footer]" />
760
+ </div>
761
+ </main>
762
+
763
+ <aside class="ct-app-shell-v2__panel" [attr.aria-label]="panelLabel()">
764
+ <ng-content select="[panel]" />
765
+ </aside>
766
+ </div>
767
+
768
+ <div
769
+ class="ct-app-shell-v2__backdrop"
770
+ (click)="onBackdropClick()"
771
+ aria-hidden="true"></div>
772
+ </div>
773
+ `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "component", type: AfSkipLinkComponent, selector: "af-skip-link", inputs: ["target", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
774
+ }
775
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfAppShellV2Component, decorators: [{
776
+ type: Component,
777
+ args: [{ selector: 'af-app-shell-v2', changeDetection: ChangeDetectionStrategy.OnPush, imports: [AfSkipLinkComponent], template: `
778
+ <div
779
+ [class]="shellClasses()"
780
+ [attr.data-sidebar-state]="sidebarState()"
781
+ [attr.data-panel-state]="panelState()">
782
+ <af-skip-link [target]="mainId()" [label]="skipLinkLabel()" />
783
+
784
+ @if (withHeader()) {
785
+ <header class="ct-app-shell-v2__header">
786
+ <ng-content select="[header]" />
787
+ </header>
788
+ }
789
+
790
+ <aside class="ct-app-shell-v2__sidebar" [attr.aria-label]="sidebarLabel()">
791
+ <ng-content select="[sidebar]" />
792
+ </aside>
793
+
794
+ <div class="ct-app-shell-v2__body">
795
+ <main class="ct-app-shell-v2__main" [id]="mainId()" tabindex="0">
796
+ <ng-content />
797
+ <div class="ct-app-shell-v2__footer">
798
+ <ng-content select="[footer]" />
799
+ </div>
800
+ </main>
801
+
802
+ <aside class="ct-app-shell-v2__panel" [attr.aria-label]="panelLabel()">
803
+ <ng-content select="[panel]" />
804
+ </aside>
805
+ </div>
806
+
807
+ <div
808
+ class="ct-app-shell-v2__backdrop"
809
+ (click)="onBackdropClick()"
810
+ aria-hidden="true"></div>
811
+ </div>
812
+ `, styles: [":host{display:contents}\n"] }]
813
+ }], propDecorators: { sidebarState: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarState", required: false }] }, { type: i0.Output, args: ["sidebarStateChange"] }], panelState: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelState", required: false }] }, { type: i0.Output, args: ["panelStateChange"] }], noSidebar: [{ type: i0.Input, args: [{ isSignal: true, alias: "noSidebar", required: false }] }], sidebarRight: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarRight", required: false }] }], sidebarFullHeight: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarFullHeight", required: false }] }], withHeader: [{ type: i0.Input, args: [{ isSignal: true, alias: "withHeader", required: false }] }], sidebarBranded: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarBranded", required: false }] }], glass: [{ type: i0.Input, args: [{ isSignal: true, alias: "glass", required: false }] }], sidebarLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "sidebarLabel", required: false }] }], panelLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelLabel", required: false }] }], mainId: [{ type: i0.Input, args: [{ isSignal: true, alias: "mainId", required: false }] }], skipLinkLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "skipLinkLabel", required: false }] }] } });
814
+
357
815
  /**
358
816
  * Avatar component displaying a user image with fallback to initials.
359
817
  *
@@ -2526,6 +2984,10 @@ class AfDropdownComponent {
2526
2984
  label = input('Actions', ...(ngDevMode ? [{ debugName: "label" }] : []));
2527
2985
  /** Trigger button size. */
2528
2986
  size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : []));
2987
+ /** Horizontal alignment of the menu relative to the trigger. */
2988
+ align = input('start', ...(ngDevMode ? [{ debugName: "align" }] : []));
2989
+ /** Which side of the trigger the menu opens on. */
2990
+ side = input('bottom', ...(ngDevMode ? [{ debugName: "side" }] : []));
2529
2991
  /** Menu items. */
2530
2992
  items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
2531
2993
  /** Emits the selected item's value. */
@@ -2712,8 +3174,8 @@ class AfDropdownComponent {
2712
3174
  }
2713
3175
  }
2714
3176
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2715
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AfDropdownComponent, isStandalone: true, selector: "af-dropdown", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "menuRef", first: true, predicate: ["menu"], descendants: true, isSignal: true }, { propertyName: "itemButtons", predicate: ["itemButton"], descendants: true, isSignal: true }], ngImport: i0, template: `
2716
- <div class="ct-dropdown" [attr.data-state]="isOpen() ? 'open' : 'closed'">
3177
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AfDropdownComponent, isStandalone: true, selector: "af-dropdown", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, align: { classPropertyName: "align", publicName: "align", isSignal: true, isRequired: false, transformFunction: null }, side: { classPropertyName: "side", publicName: "side", isSignal: true, isRequired: false, transformFunction: null }, items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { itemSelected: "itemSelected" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["trigger"], descendants: true, isSignal: true }, { propertyName: "menuRef", first: true, predicate: ["menu"], descendants: true, isSignal: true }, { propertyName: "itemButtons", predicate: ["itemButton"], descendants: true, isSignal: true }], ngImport: i0, template: `
3178
+ <div class="ct-dropdown" [attr.data-state]="isOpen() ? 'open' : 'closed'" [attr.data-align]="align()" [attr.data-side]="side()">
2717
3179
  <button
2718
3180
  #trigger
2719
3181
  [id]="triggerId"
@@ -2761,7 +3223,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
2761
3223
  args: [{ selector: 'af-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, host: {
2762
3224
  '(document:click)': 'onDocumentClick($event)',
2763
3225
  }, template: `
2764
- <div class="ct-dropdown" [attr.data-state]="isOpen() ? 'open' : 'closed'">
3226
+ <div class="ct-dropdown" [attr.data-state]="isOpen() ? 'open' : 'closed'" [attr.data-align]="align()" [attr.data-side]="side()">
2765
3227
  <button
2766
3228
  #trigger
2767
3229
  [id]="triggerId"
@@ -2803,7 +3265,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
2803
3265
  }
2804
3266
  </div>
2805
3267
  `, styles: [":host{display:inline-block}\n"] }]
2806
- }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], menuRef: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }], itemButtons: [{ type: i0.ViewChildren, args: ['itemButton', { isSignal: true }] }] } });
3268
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], align: [{ type: i0.Input, args: [{ isSignal: true, alias: "align", required: false }] }], side: [{ type: i0.Input, args: [{ isSignal: true, alias: "side", required: false }] }], items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: false }] }], itemSelected: [{ type: i0.Output, args: ["itemSelected"] }], triggerRef: [{ type: i0.ViewChild, args: ['trigger', { isSignal: true }] }], menuRef: [{ type: i0.ViewChild, args: ['menu', { isSignal: true }] }], itemButtons: [{ type: i0.ViewChildren, args: ['itemButton', { isSignal: true }] }] } });
2807
3269
 
2808
3270
  /**
2809
3271
  * Pagination component
@@ -6253,6 +6715,10 @@ class AfNavItemComponent {
6253
6715
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6254
6716
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AfNavItemComponent, isStandalone: true, selector: "af-nav-item", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, href: { classPropertyName: "href", publicName: "href", isSignal: true, isRequired: false, transformFunction: null }, routerLink: { classPropertyName: "routerLink", publicName: "routerLink", isSignal: true, isRequired: false, transformFunction: null }, active: { classPropertyName: "active", publicName: "active", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { clicked: "clicked" }, viewQueries: [{ propertyName: "linkRef", first: true, predicate: ["linkEl"], descendants: true, isSignal: true }], ngImport: i0, template: `
6255
6717
  <li class="ct-navbar__item" role="none">
6718
+ <ng-template #contentTpl>
6719
+ <ng-content>{{ label() }}</ng-content>
6720
+ </ng-template>
6721
+
6256
6722
  @if (routerLink()) {
6257
6723
  <a
6258
6724
  #linkEl
@@ -6263,7 +6729,7 @@ class AfNavItemComponent {
6263
6729
  [attr.aria-disabled]="disabled() || null"
6264
6730
  [attr.tabindex]="rovingTabindex()"
6265
6731
  (click)="onClick($event)">
6266
- <ng-content>{{ label() }}</ng-content>
6732
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6267
6733
  </a>
6268
6734
  } @else if (href()) {
6269
6735
  <a
@@ -6276,7 +6742,7 @@ class AfNavItemComponent {
6276
6742
  [attr.aria-disabled]="disabled() || null"
6277
6743
  [attr.tabindex]="rovingTabindex()"
6278
6744
  (click)="onClick($event)">
6279
- <ng-content>{{ label() }}</ng-content>
6745
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6280
6746
  </a>
6281
6747
  } @else {
6282
6748
  <button
@@ -6289,16 +6755,20 @@ class AfNavItemComponent {
6289
6755
  [attr.aria-disabled]="disabled() || null"
6290
6756
  [attr.tabindex]="rovingTabindex()"
6291
6757
  (click)="onClick($event)">
6292
- <ng-content>{{ label() }}</ng-content>
6758
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6293
6759
  </button>
6294
6760
  }
6295
6761
  </li>
6296
- `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6762
+ `, isInline: true, styles: [":host{display:contents}\n"], dependencies: [{ kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
6297
6763
  }
6298
6764
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavItemComponent, decorators: [{
6299
6765
  type: Component,
6300
- args: [{ selector: 'af-nav-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink, RouterLinkActive], template: `
6766
+ args: [{ selector: 'af-nav-item', changeDetection: ChangeDetectionStrategy.OnPush, imports: [RouterLink, RouterLinkActive, NgTemplateOutlet], template: `
6301
6767
  <li class="ct-navbar__item" role="none">
6768
+ <ng-template #contentTpl>
6769
+ <ng-content>{{ label() }}</ng-content>
6770
+ </ng-template>
6771
+
6302
6772
  @if (routerLink()) {
6303
6773
  <a
6304
6774
  #linkEl
@@ -6309,7 +6779,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
6309
6779
  [attr.aria-disabled]="disabled() || null"
6310
6780
  [attr.tabindex]="rovingTabindex()"
6311
6781
  (click)="onClick($event)">
6312
- <ng-content>{{ label() }}</ng-content>
6782
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6313
6783
  </a>
6314
6784
  } @else if (href()) {
6315
6785
  <a
@@ -6322,7 +6792,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
6322
6792
  [attr.aria-disabled]="disabled() || null"
6323
6793
  [attr.tabindex]="rovingTabindex()"
6324
6794
  (click)="onClick($event)">
6325
- <ng-content>{{ label() }}</ng-content>
6795
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6326
6796
  </a>
6327
6797
  } @else {
6328
6798
  <button
@@ -6335,7 +6805,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
6335
6805
  [attr.aria-disabled]="disabled() || null"
6336
6806
  [attr.tabindex]="rovingTabindex()"
6337
6807
  (click)="onClick($event)">
6338
- <ng-content>{{ label() }}</ng-content>
6808
+ <ng-container [ngTemplateOutlet]="contentTpl" />
6339
6809
  </button>
6340
6810
  }
6341
6811
  </li>
@@ -6537,7 +7007,9 @@ class AfNavbarComponent {
6537
7007
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6538
7008
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.2", type: AfNavbarComponent, isStandalone: true, selector: "af-navbar", inputs: { size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, center: { classPropertyName: "center", publicName: "center", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "handleKeydown($event)", "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "items", predicate: AfNavItemComponent, isSignal: true }], viewQueries: [{ propertyName: "toggleRef", first: true, predicate: ["toggleBtn"], descendants: true, isSignal: true }, { propertyName: "mobileLinks", predicate: ["mobileLink"], descendants: true, isSignal: true }], ngImport: i0, template: `
6539
7009
  <header [class]="navbarClasses()">
6540
- <ng-content select="[brand]" />
7010
+ <div class="ct-navbar__brand-wrapper">
7011
+ <ng-content select="[brand]" />
7012
+ </div>
6541
7013
 
6542
7014
  <button
6543
7015
  #toggleBtn
@@ -6622,7 +7094,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
6622
7094
  '(document:click)': 'onDocumentClick($event)',
6623
7095
  }, template: `
6624
7096
  <header [class]="navbarClasses()">
6625
- <ng-content select="[brand]" />
7097
+ <div class="ct-navbar__brand-wrapper">
7098
+ <ng-content select="[brand]" />
7099
+ </div>
6626
7100
 
6627
7101
  <button
6628
7102
  #toggleBtn
@@ -7117,65 +7591,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
7117
7591
  `, styles: [":host{display:contents}\n"] }]
7118
7592
  }], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], appearance: [{ type: i0.Input, args: [{ isSignal: true, alias: "appearance", required: false }] }], position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], compact: [{ type: i0.Input, args: [{ isSignal: true, alias: "compact", required: false }] }], full: [{ type: i0.Input, args: [{ isSignal: true, alias: "full", required: false }] }], autoClose: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoClose", required: false }] }], closeAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeAriaLabel", required: false }] }], dismissed: [{ type: i0.Output, args: ["dismissed"] }] } });
7119
7593
 
7120
- /**
7121
- * Skip-link component for keyboard-only navigation bypass.
7122
- *
7123
- * Renders an anchor that is visually hidden off-screen and slides into view
7124
- * when focused. On activation it moves focus to the target element, allowing
7125
- * keyboard users to skip repetitive navigation blocks.
7126
- *
7127
- * Must be placed as the first focusable element in the document.
7128
- *
7129
- * @example
7130
- * <af-skip-link target="main-content" />
7131
- * <nav>…</nav>
7132
- * <main id="main-content" tabindex="-1">…</main>
7133
- */
7134
- class AfSkipLinkComponent {
7135
- /** ID of the element to skip to (without the leading `#`). */
7136
- target = input.required(...(ngDevMode ? [{ debugName: "target" }] : []));
7137
- /** Visible label text shown when the link receives focus. */
7138
- label = input('Skip to main content', ...(ngDevMode ? [{ debugName: "label" }] : []));
7139
- document = inject(DOCUMENT);
7140
- /**
7141
- * Moves focus to the target element so keyboard navigation
7142
- * continues from there instead of the top of the page.
7143
- */
7144
- focusTarget(event) {
7145
- event.preventDefault();
7146
- const el = this.document.getElementById(this.target());
7147
- if (!el) {
7148
- return;
7149
- }
7150
- if (!el.hasAttribute('tabindex')) {
7151
- el.setAttribute('tabindex', '-1');
7152
- }
7153
- el.focus();
7154
- }
7155
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
7156
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.1.2", type: AfSkipLinkComponent, isStandalone: true, selector: "af-skip-link", inputs: { target: { classPropertyName: "target", publicName: "target", isSignal: true, isRequired: true, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: `
7157
- <a
7158
- class="ct-skip-link"
7159
- [attr.href]="'#' + target()"
7160
- (click)="focusTarget($event)"
7161
- >
7162
- {{ label() }}
7163
- </a>
7164
- `, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7165
- }
7166
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, decorators: [{
7167
- type: Component,
7168
- args: [{ selector: 'af-skip-link', changeDetection: ChangeDetectionStrategy.OnPush, template: `
7169
- <a
7170
- class="ct-skip-link"
7171
- [attr.href]="'#' + target()"
7172
- (click)="focusTarget($event)"
7173
- >
7174
- {{ label() }}
7175
- </a>
7176
- `, styles: [":host{display:contents}\n"] }]
7177
- }], propDecorators: { target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
7178
-
7179
7594
  /**
7180
7595
  * Empty state component for displaying placeholder content when no data is available.
7181
7596
  *
@@ -7738,5 +8153,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
7738
8153
  * Generated bundle index. Do not edit.
7739
8154
  */
7740
8155
 
7741
- export { AfAccordionComponent, AfAccordionItemComponent, AfAlertComponent, AfAvatarComponent, AfBadgeComponent, AfBannerComponent, AfBreadcrumbsComponent, AfButtonComponent, AfCardComponent, AfCellDefDirective, AfCheckboxComponent, AfChipInputComponent, AfComboboxComponent, AfDataTableComponent, AfDatepickerComponent, AfDividerComponent, AfDrawerComponent, AfDropdownComponent, AfEmptyStateComponent, AfFieldComponent, AfFileUploadComponent, AfFormatLabelPipe, AfIconComponent, AfInputComponent, AfModalComponent, AfNavItemComponent, AfNavbarComponent, AfPaginationComponent, AfPopoverComponent, AfPopoverTriggerDirective, AfProgressBarComponent, AfRadioComponent, AfRadioGroupComponent, AfSelectComponent, AfSelectMenuComponent, AfSidebarComponent, AfSkeletonComponent, AfSkipLinkComponent, AfSliderComponent, AfSpinnerComponent, AfSwitchComponent, AfTabPanelComponent, AfTableBodyComponent, AfTableCellComponent, AfTableComponent, AfTableHeaderCellComponent, AfTableHeaderComponent, AfTableRowComponent, AfTabsComponent, AfTextareaComponent, AfToastContainerComponent, AfToastService, AfToggleGroupComponent, AfToolbarComponent, AfTooltipDirective };
8156
+ export { AfAccordionComponent, AfAccordionItemComponent, AfAlertComponent, AfAppShellComponent, AfAppShellPageHeaderComponent, AfAppShellV2Component, AfAppShellV2ToolbarComponent, AfAvatarComponent, AfBadgeComponent, AfBannerComponent, AfBreadcrumbsComponent, AfButtonComponent, AfCardComponent, AfCellDefDirective, AfCheckboxComponent, AfChipInputComponent, AfComboboxComponent, AfDataTableComponent, AfDatepickerComponent, AfDividerComponent, AfDrawerComponent, AfDropdownComponent, AfEmptyStateComponent, AfFieldComponent, AfFileUploadComponent, AfFormatLabelPipe, AfIconComponent, AfInputComponent, AfModalComponent, AfNavItemComponent, AfNavbarComponent, AfPaginationComponent, AfPopoverComponent, AfPopoverTriggerDirective, AfProgressBarComponent, AfRadioComponent, AfRadioGroupComponent, AfSelectComponent, AfSelectMenuComponent, AfSidebarComponent, AfSkeletonComponent, AfSkipLinkComponent, AfSliderComponent, AfSpinnerComponent, AfSwitchComponent, AfTabPanelComponent, AfTableBodyComponent, AfTableCellComponent, AfTableComponent, AfTableHeaderCellComponent, AfTableHeaderComponent, AfTableRowComponent, AfTabsComponent, AfTextareaComponent, AfToastContainerComponent, AfToastService, AfToggleGroupComponent, AfToolbarComponent, AfTooltipDirective };
7742
8157
  //# sourceMappingURL=neuravision-ng-construct.mjs.map