@neuravision/ng-construct 0.3.2 → 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,
|
|
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>© 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>© 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
|
*
|
|
@@ -2521,15 +2979,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
2521
2979
|
*/
|
|
2522
2980
|
class AfDropdownComponent {
|
|
2523
2981
|
static nextId = 0;
|
|
2982
|
+
hostRef = inject(ElementRef);
|
|
2524
2983
|
/** Dropdown button label. */
|
|
2525
2984
|
label = input('Actions', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
2985
|
+
/** Trigger button size. */
|
|
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" }] : []));
|
|
2526
2991
|
/** Menu items. */
|
|
2527
2992
|
items = input([], ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
2528
2993
|
/** Emits the selected item's value. */
|
|
2529
2994
|
itemSelected = output();
|
|
2995
|
+
/** Computed CSS classes for the trigger button. */
|
|
2996
|
+
triggerClasses = computed(() => {
|
|
2997
|
+
const classes = ['ct-button', 'ct-button--secondary', 'ct-dropdown__trigger'];
|
|
2998
|
+
if (this.size() !== 'md') {
|
|
2999
|
+
classes.push(`ct-button--${this.size()}`);
|
|
3000
|
+
}
|
|
3001
|
+
return classes.join(' ');
|
|
3002
|
+
}, ...(ngDevMode ? [{ debugName: "triggerClasses" }] : []));
|
|
2530
3003
|
triggerRef = viewChild('trigger', ...(ngDevMode ? [{ debugName: "triggerRef" }] : []));
|
|
2531
3004
|
menuRef = viewChild('menu', ...(ngDevMode ? [{ debugName: "menuRef" }] : []));
|
|
2532
3005
|
itemButtons = viewChildren('itemButton', ...(ngDevMode ? [{ debugName: "itemButtons" }] : []));
|
|
3006
|
+
/** Non-separator items that can receive focus and be selected. */
|
|
3007
|
+
actionableItems = computed(() => this.items().filter((item) => !item.separator), ...(ngDevMode ? [{ debugName: "actionableItems" }] : []));
|
|
2533
3008
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
2534
3009
|
focusedItemIndex = signal(0, ...(ngDevMode ? [{ debugName: "focusedItemIndex" }] : []));
|
|
2535
3010
|
instanceId = AfDropdownComponent.nextId++;
|
|
@@ -2572,7 +3047,7 @@ class AfDropdownComponent {
|
|
|
2572
3047
|
}
|
|
2573
3048
|
/** Handles keyboard events within the open menu. */
|
|
2574
3049
|
onMenuKeydown(event) {
|
|
2575
|
-
const actionableItems = this.
|
|
3050
|
+
const actionableItems = this.actionableItems();
|
|
2576
3051
|
if (actionableItems.length === 0)
|
|
2577
3052
|
return;
|
|
2578
3053
|
switch (event.key) {
|
|
@@ -2623,8 +3098,7 @@ class AfDropdownComponent {
|
|
|
2623
3098
|
}
|
|
2624
3099
|
}
|
|
2625
3100
|
onDocumentClick(event) {
|
|
2626
|
-
|
|
2627
|
-
if (!target.closest('.ct-dropdown')) {
|
|
3101
|
+
if (!this.hostRef.nativeElement.contains(event.target)) {
|
|
2628
3102
|
this.close(false);
|
|
2629
3103
|
}
|
|
2630
3104
|
}
|
|
@@ -2633,11 +3107,11 @@ class AfDropdownComponent {
|
|
|
2633
3107
|
* actionable (non-separator) items.
|
|
2634
3108
|
*/
|
|
2635
3109
|
getActionableIndex(item) {
|
|
2636
|
-
return this.
|
|
3110
|
+
return this.actionableItems().indexOf(item);
|
|
2637
3111
|
}
|
|
2638
3112
|
open(focusLast = false) {
|
|
2639
3113
|
this.isOpen.set(true);
|
|
2640
|
-
const actionableItems = this.
|
|
3114
|
+
const actionableItems = this.actionableItems();
|
|
2641
3115
|
const startIndex = focusLast
|
|
2642
3116
|
? this.nextEnabledIndex(actionableItems.length, -1)
|
|
2643
3117
|
: this.nextEnabledIndex(-1, 1);
|
|
@@ -2663,7 +3137,7 @@ class AfDropdownComponent {
|
|
|
2663
3137
|
buttons[idx]?.nativeElement.focus();
|
|
2664
3138
|
}
|
|
2665
3139
|
nextEnabledIndex(from, direction) {
|
|
2666
|
-
const actionableItems = this.
|
|
3140
|
+
const actionableItems = this.actionableItems();
|
|
2667
3141
|
const len = actionableItems.length;
|
|
2668
3142
|
if (len === 0)
|
|
2669
3143
|
return 0;
|
|
@@ -2679,9 +3153,6 @@ class AfDropdownComponent {
|
|
|
2679
3153
|
}
|
|
2680
3154
|
return from;
|
|
2681
3155
|
}
|
|
2682
|
-
getActionableItems() {
|
|
2683
|
-
return this.items().filter((item) => !item.separator);
|
|
2684
|
-
}
|
|
2685
3156
|
handleTypeAhead(char) {
|
|
2686
3157
|
if (this.typeAheadTimer) {
|
|
2687
3158
|
clearTimeout(this.typeAheadTimer);
|
|
@@ -2691,7 +3162,7 @@ class AfDropdownComponent {
|
|
|
2691
3162
|
this.typeAheadBuffer = '';
|
|
2692
3163
|
this.typeAheadTimer = null;
|
|
2693
3164
|
}, 500);
|
|
2694
|
-
const actionableItems = this.
|
|
3165
|
+
const actionableItems = this.actionableItems();
|
|
2695
3166
|
const startIndex = this.focusedItemIndex() + 1;
|
|
2696
3167
|
for (let i = 0; i < actionableItems.length; i++) {
|
|
2697
3168
|
const idx = (startIndex + i) % actionableItems.length;
|
|
@@ -2703,11 +3174,12 @@ class AfDropdownComponent {
|
|
|
2703
3174
|
}
|
|
2704
3175
|
}
|
|
2705
3176
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2706
|
-
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 }, 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: `
|
|
2707
|
-
<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()">
|
|
2708
3179
|
<button
|
|
2709
3180
|
#trigger
|
|
2710
|
-
|
|
3181
|
+
[id]="triggerId"
|
|
3182
|
+
[class]="triggerClasses()"
|
|
2711
3183
|
[attr.aria-expanded]="isOpen()"
|
|
2712
3184
|
[attr.aria-controls]="menuId"
|
|
2713
3185
|
aria-haspopup="menu"
|
|
@@ -2751,10 +3223,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
2751
3223
|
args: [{ selector: 'af-dropdown', changeDetection: ChangeDetectionStrategy.OnPush, host: {
|
|
2752
3224
|
'(document:click)': 'onDocumentClick($event)',
|
|
2753
3225
|
}, template: `
|
|
2754
|
-
<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()">
|
|
2755
3227
|
<button
|
|
2756
3228
|
#trigger
|
|
2757
|
-
|
|
3229
|
+
[id]="triggerId"
|
|
3230
|
+
[class]="triggerClasses()"
|
|
2758
3231
|
[attr.aria-expanded]="isOpen()"
|
|
2759
3232
|
[attr.aria-controls]="menuId"
|
|
2760
3233
|
aria-haspopup="menu"
|
|
@@ -2792,7 +3265,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
2792
3265
|
}
|
|
2793
3266
|
</div>
|
|
2794
3267
|
`, styles: [":host{display:inline-block}\n"] }]
|
|
2795
|
-
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", 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 }] }] } });
|
|
2796
3269
|
|
|
2797
3270
|
/**
|
|
2798
3271
|
* Pagination component
|
|
@@ -6242,6 +6715,10 @@ class AfNavItemComponent {
|
|
|
6242
6715
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6243
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: `
|
|
6244
6717
|
<li class="ct-navbar__item" role="none">
|
|
6718
|
+
<ng-template #contentTpl>
|
|
6719
|
+
<ng-content>{{ label() }}</ng-content>
|
|
6720
|
+
</ng-template>
|
|
6721
|
+
|
|
6245
6722
|
@if (routerLink()) {
|
|
6246
6723
|
<a
|
|
6247
6724
|
#linkEl
|
|
@@ -6252,7 +6729,7 @@ class AfNavItemComponent {
|
|
|
6252
6729
|
[attr.aria-disabled]="disabled() || null"
|
|
6253
6730
|
[attr.tabindex]="rovingTabindex()"
|
|
6254
6731
|
(click)="onClick($event)">
|
|
6255
|
-
<ng-
|
|
6732
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6256
6733
|
</a>
|
|
6257
6734
|
} @else if (href()) {
|
|
6258
6735
|
<a
|
|
@@ -6265,7 +6742,7 @@ class AfNavItemComponent {
|
|
|
6265
6742
|
[attr.aria-disabled]="disabled() || null"
|
|
6266
6743
|
[attr.tabindex]="rovingTabindex()"
|
|
6267
6744
|
(click)="onClick($event)">
|
|
6268
|
-
<ng-
|
|
6745
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6269
6746
|
</a>
|
|
6270
6747
|
} @else {
|
|
6271
6748
|
<button
|
|
@@ -6278,16 +6755,20 @@ class AfNavItemComponent {
|
|
|
6278
6755
|
[attr.aria-disabled]="disabled() || null"
|
|
6279
6756
|
[attr.tabindex]="rovingTabindex()"
|
|
6280
6757
|
(click)="onClick($event)">
|
|
6281
|
-
<ng-
|
|
6758
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6282
6759
|
</button>
|
|
6283
6760
|
}
|
|
6284
6761
|
</li>
|
|
6285
|
-
`, 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 });
|
|
6286
6763
|
}
|
|
6287
6764
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavItemComponent, decorators: [{
|
|
6288
6765
|
type: Component,
|
|
6289
|
-
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: `
|
|
6290
6767
|
<li class="ct-navbar__item" role="none">
|
|
6768
|
+
<ng-template #contentTpl>
|
|
6769
|
+
<ng-content>{{ label() }}</ng-content>
|
|
6770
|
+
</ng-template>
|
|
6771
|
+
|
|
6291
6772
|
@if (routerLink()) {
|
|
6292
6773
|
<a
|
|
6293
6774
|
#linkEl
|
|
@@ -6298,7 +6779,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
6298
6779
|
[attr.aria-disabled]="disabled() || null"
|
|
6299
6780
|
[attr.tabindex]="rovingTabindex()"
|
|
6300
6781
|
(click)="onClick($event)">
|
|
6301
|
-
<ng-
|
|
6782
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6302
6783
|
</a>
|
|
6303
6784
|
} @else if (href()) {
|
|
6304
6785
|
<a
|
|
@@ -6311,7 +6792,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
6311
6792
|
[attr.aria-disabled]="disabled() || null"
|
|
6312
6793
|
[attr.tabindex]="rovingTabindex()"
|
|
6313
6794
|
(click)="onClick($event)">
|
|
6314
|
-
<ng-
|
|
6795
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6315
6796
|
</a>
|
|
6316
6797
|
} @else {
|
|
6317
6798
|
<button
|
|
@@ -6324,7 +6805,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
6324
6805
|
[attr.aria-disabled]="disabled() || null"
|
|
6325
6806
|
[attr.tabindex]="rovingTabindex()"
|
|
6326
6807
|
(click)="onClick($event)">
|
|
6327
|
-
<ng-
|
|
6808
|
+
<ng-container [ngTemplateOutlet]="contentTpl" />
|
|
6328
6809
|
</button>
|
|
6329
6810
|
}
|
|
6330
6811
|
</li>
|
|
@@ -6526,7 +7007,9 @@ class AfNavbarComponent {
|
|
|
6526
7007
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfNavbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6527
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: `
|
|
6528
7009
|
<header [class]="navbarClasses()">
|
|
6529
|
-
<
|
|
7010
|
+
<div class="ct-navbar__brand-wrapper">
|
|
7011
|
+
<ng-content select="[brand]" />
|
|
7012
|
+
</div>
|
|
6530
7013
|
|
|
6531
7014
|
<button
|
|
6532
7015
|
#toggleBtn
|
|
@@ -6611,7 +7094,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
6611
7094
|
'(document:click)': 'onDocumentClick($event)',
|
|
6612
7095
|
}, template: `
|
|
6613
7096
|
<header [class]="navbarClasses()">
|
|
6614
|
-
<
|
|
7097
|
+
<div class="ct-navbar__brand-wrapper">
|
|
7098
|
+
<ng-content select="[brand]" />
|
|
7099
|
+
</div>
|
|
6615
7100
|
|
|
6616
7101
|
<button
|
|
6617
7102
|
#toggleBtn
|
|
@@ -7106,65 +7591,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
7106
7591
|
`, styles: [":host{display:contents}\n"] }]
|
|
7107
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"] }] } });
|
|
7108
7593
|
|
|
7109
|
-
/**
|
|
7110
|
-
* Skip-link component for keyboard-only navigation bypass.
|
|
7111
|
-
*
|
|
7112
|
-
* Renders an anchor that is visually hidden off-screen and slides into view
|
|
7113
|
-
* when focused. On activation it moves focus to the target element, allowing
|
|
7114
|
-
* keyboard users to skip repetitive navigation blocks.
|
|
7115
|
-
*
|
|
7116
|
-
* Must be placed as the first focusable element in the document.
|
|
7117
|
-
*
|
|
7118
|
-
* @example
|
|
7119
|
-
* <af-skip-link target="main-content" />
|
|
7120
|
-
* <nav>…</nav>
|
|
7121
|
-
* <main id="main-content" tabindex="-1">…</main>
|
|
7122
|
-
*/
|
|
7123
|
-
class AfSkipLinkComponent {
|
|
7124
|
-
/** ID of the element to skip to (without the leading `#`). */
|
|
7125
|
-
target = input.required(...(ngDevMode ? [{ debugName: "target" }] : []));
|
|
7126
|
-
/** Visible label text shown when the link receives focus. */
|
|
7127
|
-
label = input('Skip to main content', ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
7128
|
-
document = inject(DOCUMENT);
|
|
7129
|
-
/**
|
|
7130
|
-
* Moves focus to the target element so keyboard navigation
|
|
7131
|
-
* continues from there instead of the top of the page.
|
|
7132
|
-
*/
|
|
7133
|
-
focusTarget(event) {
|
|
7134
|
-
event.preventDefault();
|
|
7135
|
-
const el = this.document.getElementById(this.target());
|
|
7136
|
-
if (!el) {
|
|
7137
|
-
return;
|
|
7138
|
-
}
|
|
7139
|
-
if (!el.hasAttribute('tabindex')) {
|
|
7140
|
-
el.setAttribute('tabindex', '-1');
|
|
7141
|
-
}
|
|
7142
|
-
el.focus();
|
|
7143
|
-
}
|
|
7144
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
7145
|
-
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: `
|
|
7146
|
-
<a
|
|
7147
|
-
class="ct-skip-link"
|
|
7148
|
-
[attr.href]="'#' + target()"
|
|
7149
|
-
(click)="focusTarget($event)"
|
|
7150
|
-
>
|
|
7151
|
-
{{ label() }}
|
|
7152
|
-
</a>
|
|
7153
|
-
`, isInline: true, styles: [":host{display:contents}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
7154
|
-
}
|
|
7155
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImport: i0, type: AfSkipLinkComponent, decorators: [{
|
|
7156
|
-
type: Component,
|
|
7157
|
-
args: [{ selector: 'af-skip-link', changeDetection: ChangeDetectionStrategy.OnPush, template: `
|
|
7158
|
-
<a
|
|
7159
|
-
class="ct-skip-link"
|
|
7160
|
-
[attr.href]="'#' + target()"
|
|
7161
|
-
(click)="focusTarget($event)"
|
|
7162
|
-
>
|
|
7163
|
-
{{ label() }}
|
|
7164
|
-
</a>
|
|
7165
|
-
`, styles: [":host{display:contents}\n"] }]
|
|
7166
|
-
}], propDecorators: { target: [{ type: i0.Input, args: [{ isSignal: true, alias: "target", required: true }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }] } });
|
|
7167
|
-
|
|
7168
7594
|
/**
|
|
7169
7595
|
* Empty state component for displaying placeholder content when no data is available.
|
|
7170
7596
|
*
|
|
@@ -7727,5 +8153,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.2", ngImpor
|
|
|
7727
8153
|
* Generated bundle index. Do not edit.
|
|
7728
8154
|
*/
|
|
7729
8155
|
|
|
7730
|
-
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 };
|
|
7731
8157
|
//# sourceMappingURL=neuravision-ng-construct.mjs.map
|