@akcelik/strct 4.0.0 → 4.2.0
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.
- package/fesm2022/akcelik-strct.mjs +363 -56
- package/fesm2022/akcelik-strct.mjs.map +1 -1
- package/package.json +1 -1
- package/types/akcelik-strct.d.ts +85 -14
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, DOCUMENT, signal, computed, Injectable, input, isDevMode, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, NgZone, booleanAttribute, afterNextRender, Directive, model, output, HostListener, contentChildren, effect, ApplicationRef, EnvironmentInjector, createComponent, forwardRef, DestroyRef, contentChild, viewChild, InjectionToken, untracked, Injector, viewChildren,
|
|
2
|
+
import { inject, DOCUMENT, signal, computed, Injectable, input, isDevMode, ViewEncapsulation, ChangeDetectionStrategy, Component, ElementRef, NgZone, booleanAttribute, afterNextRender, Directive, model, output, HostListener, contentChildren, effect, ApplicationRef, EnvironmentInjector, createComponent, forwardRef, DestroyRef, TemplateRef, contentChild, viewChild, InjectionToken, untracked, Injector, viewChildren, Renderer2, Pipe, PLATFORM_ID, afterRenderEffect } from '@angular/core';
|
|
3
3
|
import { DomSanitizer } from '@angular/platform-browser';
|
|
4
4
|
import { NgTemplateOutlet, DOCUMENT as DOCUMENT$1, isPlatformBrowser } from '@angular/common';
|
|
5
5
|
import { RouterLink, RouterLinkActive } from '@angular/router';
|
|
@@ -2340,6 +2340,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
2340
2340
|
`, host: { class: 'strct-tabs' }, styles: [".strct-tabs{display:block}.strct-tabs__bar{display:flex;gap:2px;border-bottom:1px solid var(--b2);overflow-x:auto;white-space:nowrap;scrollbar-width:none}.strct-tabs__btn{appearance:none;background:transparent;border:0;cursor:pointer;font-family:var(--font);font-size:13px;font-weight:500;color:var(--t2);padding:9px 14px;border-bottom:2px solid transparent;margin-bottom:-1px;transition:color .14s ease,border-color .14s ease}.strct-tabs__btn:hover{color:var(--t1)}.strct-tabs__btn--active{color:var(--acc);border-bottom-color:var(--acc)}.strct-tabs__btn:disabled{color:var(--t4);cursor:not-allowed}.strct-tabs__panels{padding-top:16px}.strct-tab[hidden]{display:none}\n"] }]
|
|
2341
2341
|
}], ctorParameters: () => [], propDecorators: { tabs: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTab), { isSignal: true }] }], selectedIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "selectedIndex", required: false }] }, { type: i0.Output, args: ["selectedIndexChange"] }], keepAlive: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepAlive", required: false }] }] } });
|
|
2342
2342
|
|
|
2343
|
+
let menuPanelCounter = 0;
|
|
2343
2344
|
/**
|
|
2344
2345
|
* Floating menu panel — portaled into `<body>` (so it escapes overflow /
|
|
2345
2346
|
* transform clipping), positioned by its real measured size, with full keyboard
|
|
@@ -2381,15 +2382,26 @@ class StrctMenuPanel {
|
|
|
2381
2382
|
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
2382
2383
|
openSubIndex = signal(null, /* @ts-ignore */
|
|
2383
2384
|
...(ngDevMode ? [{ debugName: "openSubIndex" }] : /* istanbul ignore next */ []));
|
|
2385
|
+
/** Entries the keyboard visits: not dividers, and not a disabled entry that
|
|
2386
|
+
* has nothing to say — a disabled entry WITH a hint is reachable so its
|
|
2387
|
+
* reason can be read. (Before, disabled entries were "visited" but a
|
|
2388
|
+
* natively disabled button refused focus, stranding the keyboard.) */
|
|
2384
2389
|
navIndices = computed(() => this.items()
|
|
2385
|
-
.map((it, i) => (it.divider ? -1 : i))
|
|
2390
|
+
.map((it, i) => (it.divider || (it.disabled && !it.hint) ? -1 : i))
|
|
2386
2391
|
.filter((i) => i >= 0), /* @ts-ignore */
|
|
2387
2392
|
...(ngDevMode ? [{ debugName: "navIndices" }] : /* istanbul ignore next */ []));
|
|
2393
|
+
uid = ++menuPanelCounter;
|
|
2394
|
+
hintId(i) {
|
|
2395
|
+
return `strct-menu-${this.uid}-hint-${i}`;
|
|
2396
|
+
}
|
|
2388
2397
|
constructor() {
|
|
2389
2398
|
this.posX.set(this.x());
|
|
2390
2399
|
this.posY.set(this.y());
|
|
2391
2400
|
afterNextRender(() => {
|
|
2392
|
-
|
|
2401
|
+
// Open on the first entry that can act; a disabled-but-hinted one is
|
|
2402
|
+
// reachable by arrow keys, not the landing spot.
|
|
2403
|
+
const nav = this.navIndices();
|
|
2404
|
+
this.activeIndex.set(nav.find((i) => !this.items()[i].disabled) ?? nav[0] ?? 0);
|
|
2393
2405
|
this.clampToViewport();
|
|
2394
2406
|
this.focusItem(this.activeIndex());
|
|
2395
2407
|
});
|
|
@@ -2441,7 +2453,7 @@ class StrctMenuPanel {
|
|
|
2441
2453
|
onHover(i) {
|
|
2442
2454
|
this.activeIndex.set(i);
|
|
2443
2455
|
const it = this.items()[i];
|
|
2444
|
-
this.openSubIndex.set(it?.children?.length ? i : null);
|
|
2456
|
+
this.openSubIndex.set(it?.children?.length && !it.disabled ? i : null);
|
|
2445
2457
|
}
|
|
2446
2458
|
onLeave(i) {
|
|
2447
2459
|
if (this.openSubIndex() === i)
|
|
@@ -2487,7 +2499,7 @@ class StrctMenuPanel {
|
|
|
2487
2499
|
this.focusItem(this.navIndices().at(-1) ?? 0);
|
|
2488
2500
|
break;
|
|
2489
2501
|
case 'ArrowRight':
|
|
2490
|
-
if (item?.children?.length) {
|
|
2502
|
+
if (item?.children?.length && !item.disabled) {
|
|
2491
2503
|
event.preventDefault();
|
|
2492
2504
|
event.stopPropagation();
|
|
2493
2505
|
this.openSubIndex.set(this.activeIndex());
|
|
@@ -2532,13 +2544,21 @@ class StrctMenuPanel {
|
|
|
2532
2544
|
<div class="strct-menu__sep" role="separator"></div>
|
|
2533
2545
|
} @else {
|
|
2534
2546
|
<div class="strct-menu__wrap" (mouseenter)="onHover(i)" (mouseleave)="onLeave(i)">
|
|
2547
|
+
<!-- aria-disabled, not [disabled]: a natively disabled button takes no
|
|
2548
|
+
focus and, in some browsers, no pointer events — so neither the
|
|
2549
|
+
keyboard nor the hint's tooltip could reach it. Activation is
|
|
2550
|
+
blocked in code. The tooltip sits on the button, not the wrapper:
|
|
2551
|
+
the wrapper also holds the submenu, whose entries would otherwise
|
|
2552
|
+
inherit this entry's title. -->
|
|
2535
2553
|
<button
|
|
2536
2554
|
type="button"
|
|
2537
2555
|
class="strct-menu__item"
|
|
2538
2556
|
[attr.data-idx]="i"
|
|
2539
2557
|
[class.strct-menu__item--critical]="item.critical"
|
|
2540
2558
|
[class.strct-menu__item--active]="i === activeIndex()"
|
|
2541
|
-
[disabled]="item.disabled"
|
|
2559
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
2560
|
+
[attr.aria-describedby]="item.hint ? hintId(i) : null"
|
|
2561
|
+
[attr.title]="item.hint || null"
|
|
2542
2562
|
role="menuitem"
|
|
2543
2563
|
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
2544
2564
|
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
@@ -2565,6 +2585,11 @@ class StrctMenuPanel {
|
|
|
2565
2585
|
/>
|
|
2566
2586
|
}
|
|
2567
2587
|
</button>
|
|
2588
|
+
@if (item.hint) {
|
|
2589
|
+
<!-- hidden: kept out of the entry's accessible NAME, yet still read
|
|
2590
|
+
as its description through aria-describedby. -->
|
|
2591
|
+
<span [id]="hintId(i)" hidden>{{ item.hint }}</span>
|
|
2592
|
+
}
|
|
2568
2593
|
@if (openSubIndex() === i && item.children?.length) {
|
|
2569
2594
|
<strct-menu-panel
|
|
2570
2595
|
submenu
|
|
@@ -2581,7 +2606,7 @@ class StrctMenuPanel {
|
|
|
2581
2606
|
}
|
|
2582
2607
|
}
|
|
2583
2608
|
</div>
|
|
2584
|
-
`, isInline: true, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:start}.strct-menu__item:hover:not(
|
|
2609
|
+
`, isInline: true, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:start}.strct-menu__item:hover:not([aria-disabled=true]),.strct-menu__item--active:not([aria-disabled=true]){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--critical{color:var(--critical)}.strct-menu__item--critical:hover:not([aria-disabled=true]),.strct-menu__item--critical.strct-menu__item--active:not([aria-disabled=true]){background:var(--critical-bg)}.strct-menu__item[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--critical .strct-menu__icon{color:var(--critical)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;inset-inline-start:100%;margin-inline-start:2px;z-index:var(--z-base)}.strct-menu__subpanel--flip{inset-inline-start:auto;inset-inline-end:100%;margin-inline-start:0;margin-inline-end:2px}[dir=rtl] .strct-menu__arrow{transform:rotate(180deg)}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"], dependencies: [{ kind: "component", type: StrctMenuPanel, selector: "strct-menu-panel", inputs: ["items", "data", "x", "y", "submenu"], outputs: ["select", "close", "back"] }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
2585
2610
|
}
|
|
2586
2611
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMenuPanel, decorators: [{
|
|
2587
2612
|
type: Component,
|
|
@@ -2592,13 +2617,21 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
2592
2617
|
<div class="strct-menu__sep" role="separator"></div>
|
|
2593
2618
|
} @else {
|
|
2594
2619
|
<div class="strct-menu__wrap" (mouseenter)="onHover(i)" (mouseleave)="onLeave(i)">
|
|
2620
|
+
<!-- aria-disabled, not [disabled]: a natively disabled button takes no
|
|
2621
|
+
focus and, in some browsers, no pointer events — so neither the
|
|
2622
|
+
keyboard nor the hint's tooltip could reach it. Activation is
|
|
2623
|
+
blocked in code. The tooltip sits on the button, not the wrapper:
|
|
2624
|
+
the wrapper also holds the submenu, whose entries would otherwise
|
|
2625
|
+
inherit this entry's title. -->
|
|
2595
2626
|
<button
|
|
2596
2627
|
type="button"
|
|
2597
2628
|
class="strct-menu__item"
|
|
2598
2629
|
[attr.data-idx]="i"
|
|
2599
2630
|
[class.strct-menu__item--critical]="item.critical"
|
|
2600
2631
|
[class.strct-menu__item--active]="i === activeIndex()"
|
|
2601
|
-
[disabled]="item.disabled"
|
|
2632
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
2633
|
+
[attr.aria-describedby]="item.hint ? hintId(i) : null"
|
|
2634
|
+
[attr.title]="item.hint || null"
|
|
2602
2635
|
role="menuitem"
|
|
2603
2636
|
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
2604
2637
|
[attr.aria-expanded]="item.children?.length ? openSubIndex() === i : null"
|
|
@@ -2625,6 +2658,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
2625
2658
|
/>
|
|
2626
2659
|
}
|
|
2627
2660
|
</button>
|
|
2661
|
+
@if (item.hint) {
|
|
2662
|
+
<!-- hidden: kept out of the entry's accessible NAME, yet still read
|
|
2663
|
+
as its description through aria-describedby. -->
|
|
2664
|
+
<span [id]="hintId(i)" hidden>{{ item.hint }}</span>
|
|
2665
|
+
}
|
|
2628
2666
|
@if (openSubIndex() === i && item.children?.length) {
|
|
2629
2667
|
<strct-menu-panel
|
|
2630
2668
|
submenu
|
|
@@ -2647,7 +2685,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
2647
2685
|
'[style.left.px]': 'submenu() ? null : posX()',
|
|
2648
2686
|
'[style.top.px]': 'submenu() ? subTop() : posY()',
|
|
2649
2687
|
'[style.zIndex]': 'submenu() ? null : 1100',
|
|
2650
|
-
}, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:start}.strct-menu__item:hover:not(
|
|
2688
|
+
}, styles: [".strct-menu-host{display:block}.strct-menu{min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);animation:strct-menu-in .1s ease}.strct-menu:focus{outline:none}.strct-menu__wrap{position:relative}.strct-menu__item{display:flex;align-items:center;gap:8px;width:100%;padding:7px 8px 7px 10px;border:0;border-radius:5px;cursor:pointer;background:transparent;color:var(--t1);font-size:13px;font-family:var(--font);text-align:start}.strct-menu__item:hover:not([aria-disabled=true]),.strct-menu__item--active:not([aria-disabled=true]){background:var(--bg-3)}.strct-menu__item:focus-visible{outline:none;background:var(--bg-3)}.strct-menu__item--critical{color:var(--critical)}.strct-menu__item--critical:hover:not([aria-disabled=true]),.strct-menu__item--critical.strct-menu__item--active:not([aria-disabled=true]){background:var(--critical-bg)}.strct-menu__item[aria-disabled=true]{opacity:.45;cursor:not-allowed}.strct-menu__icon{color:var(--t2);flex-shrink:0}.strct-menu__item--critical .strct-menu__icon{color:var(--critical)}.strct-menu__icon-spacer{width:14px;flex-shrink:0}.strct-menu__label{flex:1;white-space:nowrap}.strct-menu__arrow{color:var(--t3);flex-shrink:0}.strct-menu__sep{height:1px;margin:4px 6px;background:var(--b1)}.strct-menu__subpanel{position:absolute;top:-5px;inset-inline-start:100%;margin-inline-start:2px;z-index:var(--z-base)}.strct-menu__subpanel--flip{inset-inline-start:auto;inset-inline-end:100%;margin-inline-start:0;margin-inline-end:2px}[dir=rtl] .strct-menu__arrow{transform:rotate(180deg)}@keyframes strct-menu-in{0%{opacity:0;transform:scale(.97)}}\n"] }]
|
|
2651
2689
|
}], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], x: [{ type: i0.Input, args: [{ isSignal: true, alias: "x", required: false }] }], y: [{ type: i0.Input, args: [{ isSignal: true, alias: "y", required: false }] }], submenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "submenu", required: false }] }], select: [{ type: i0.Output, args: ["select"] }], close: [{ type: i0.Output, args: ["close"] }], back: [{ type: i0.Output, args: ["back"] }] } });
|
|
2652
2690
|
/**
|
|
2653
2691
|
* Imperatively opens the data-driven menu panel, portaled into `<body>`. Shared
|
|
@@ -3344,6 +3382,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
3344
3382
|
}, styles: [".strct-tree{display:block}.strct-tree--comfortable .strct-tnode__row{gap:7px;padding:6px 10px;border-radius:6px;font-size:14px}.strct-tree--comfortable .strct-tnode__chevron{margin:-4px;margin-inline-end:-9px}.strct-tree--comfortable .strct-tnode__spacer{width:16px}.strct-tree--comfortable .strct-tnode__children{margin-inline-start:19px}\n"] }]
|
|
3345
3383
|
}], propDecorators: { nodes: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodes", required: false }] }], density: [{ type: i0.Input, args: [{ isSignal: true, alias: "density", required: false }] }], nodeMenu: [{ type: i0.Input, args: [{ isSignal: true, alias: "nodeMenu", required: false }] }], chevronAriaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "chevronAriaLabel", required: false }] }], nodeActivated: [{ type: i0.Output, args: ["nodeActivated"] }], nodeMenuSelect: [{ type: i0.Output, args: ["nodeMenuSelect"] }], expandedIds: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandedIds", required: false }] }, { type: i0.Output, args: ["expandedIdsChange"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }], nodeToggled: [{ type: i0.Output, args: ["nodeToggled"] }], projectedNodes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => StrctTreeNode), { ...{ descendants: false }, isSignal: true }] }] } });
|
|
3346
3384
|
|
|
3385
|
+
/**
|
|
3386
|
+
* Dev-mode diagnostics for combinations a component accepts but cannot honour.
|
|
3387
|
+
*
|
|
3388
|
+
* Every message names what was ignored and what to do instead. Keyed: a
|
|
3389
|
+
* condition warns once per page load, not once per change detection.
|
|
3390
|
+
*
|
|
3391
|
+
* Production cost: none, PROVIDED each call site is guarded INLINE with
|
|
3392
|
+
* if (typeof ngDevMode !== 'undefined' && ngDevMode) { … }
|
|
3393
|
+
* Production builds define `ngDevMode` as false, and the minifier then drops
|
|
3394
|
+
* the whole block — messages included. A helper function returning that same
|
|
3395
|
+
* expression would NOT be folded across the call, so the check and its
|
|
3396
|
+
* strings would ship; that is why no such helper exists here.
|
|
3397
|
+
*/
|
|
3398
|
+
const warned = new Set();
|
|
3399
|
+
function strctDevWarn(key, message) {
|
|
3400
|
+
if (typeof ngDevMode === 'undefined' || !ngDevMode || warned.has(key))
|
|
3401
|
+
return;
|
|
3402
|
+
warned.add(key);
|
|
3403
|
+
console.warn(message);
|
|
3404
|
+
}
|
|
3405
|
+
/** Test hook: forget which warnings have fired. Not part of the public API. */
|
|
3406
|
+
function resetStrctDevWarnings() {
|
|
3407
|
+
warned.clear();
|
|
3408
|
+
}
|
|
3409
|
+
|
|
3347
3410
|
/**
|
|
3348
3411
|
* Refcounted body scroll-lock shared across any number of simultaneously
|
|
3349
3412
|
* open transient surfaces (modal, drawer …): the first lock hides body
|
|
@@ -3378,6 +3441,27 @@ function removeOpenModal(modal) {
|
|
|
3378
3441
|
function isTopmostModal(modal) {
|
|
3379
3442
|
return openModalStack[openModalStack.length - 1] === modal;
|
|
3380
3443
|
}
|
|
3444
|
+
/**
|
|
3445
|
+
* Lazily rendered modal body. Plain projected content is created by the PARENT
|
|
3446
|
+
* with the parent's own view, so it is instantiated — and costs — even while
|
|
3447
|
+
* the modal is closed. Content inside this template is created only while the
|
|
3448
|
+
* modal is open, and destroyed when it closes (state does not survive a close):
|
|
3449
|
+
*
|
|
3450
|
+
* <strct-modal [(open)]="show" title="Import hosts">
|
|
3451
|
+
* <ng-template strctModalContent>
|
|
3452
|
+
* <strct-datagrid [rows]="hosts" … />
|
|
3453
|
+
* </ng-template>
|
|
3454
|
+
* </strct-modal>
|
|
3455
|
+
*/
|
|
3456
|
+
class StrctModalContent {
|
|
3457
|
+
template = inject(TemplateRef);
|
|
3458
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctModalContent, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3459
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.1.4", type: StrctModalContent, isStandalone: true, selector: "[strctModalContent]", ngImport: i0 });
|
|
3460
|
+
}
|
|
3461
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctModalContent, decorators: [{
|
|
3462
|
+
type: Directive,
|
|
3463
|
+
args: [{ selector: '[strctModalContent]' }]
|
|
3464
|
+
}] });
|
|
3381
3465
|
/**
|
|
3382
3466
|
* Overlay dialog with two-way `open`:
|
|
3383
3467
|
* <strct-modal [(open)]="show" title="Confirm">
|
|
@@ -3396,7 +3480,8 @@ class StrctModal {
|
|
|
3396
3480
|
/** Dialog title. */
|
|
3397
3481
|
title = input('', /* @ts-ignore */
|
|
3398
3482
|
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
3399
|
-
/** Size variant (fixed scale; defaults to `sm` = 480px).
|
|
3483
|
+
/** Size variant (fixed scale; defaults to `sm` = 480px). Ignored by
|
|
3484
|
+
* `chromeless`, which sizes from the wizard it hosts. */
|
|
3400
3485
|
size = input('sm', /* @ts-ignore */
|
|
3401
3486
|
...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
3402
3487
|
/** Hide the footer slot. */
|
|
@@ -3406,6 +3491,11 @@ class StrctModal {
|
|
|
3406
3491
|
* content (a `flush` vertical wizard) is the dialog surface. `title` still
|
|
3407
3492
|
* names the dialog for assistive tech; backdrop/Escape dismissal follow
|
|
3408
3493
|
* `dismissible` as usual.
|
|
3494
|
+
*
|
|
3495
|
+
* The dialog's width comes from the wizard's geometry, not from `size`:
|
|
3496
|
+
* rail + `--strct-wiz-content-min` (default 864px) [+ aside]. To change it,
|
|
3497
|
+
* set that variable on this `strct-modal` or an ancestor — the dialog reads
|
|
3498
|
+
* it on itself, so setting it on the `strct-wizard` inside does not reach it.
|
|
3409
3499
|
*/
|
|
3410
3500
|
chromeless = input(false, { ...(ngDevMode ? { debugName: "chromeless" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
3411
3501
|
/** Accessible label of the X close button (localizable). */
|
|
@@ -3431,6 +3521,22 @@ class StrctModal {
|
|
|
3431
3521
|
...(ngDevMode ? [{ debugName: "variant" }] : /* istanbul ignore next */ []));
|
|
3432
3522
|
/** Emitted when the alert is dismissed. */
|
|
3433
3523
|
closed = output();
|
|
3524
|
+
/** Lazily rendered body, if one is provided (see {@link StrctModalContent}). */
|
|
3525
|
+
lazyContent = contentChild(StrctModalContent, /* @ts-ignore */
|
|
3526
|
+
...(ngDevMode ? [{ debugName: "lazyContent" }] : /* istanbul ignore next */ []));
|
|
3527
|
+
// Dev mode only: `size` is accepted alongside `chromeless` but cannot apply.
|
|
3528
|
+
sizeDiagnostic = typeof ngDevMode !== 'undefined' && ngDevMode
|
|
3529
|
+
? effect(() => {
|
|
3530
|
+
const size = this.size();
|
|
3531
|
+
if (this.chromeless() && size !== 'sm') {
|
|
3532
|
+
strctDevWarn(`modal:chromeless-size:${size}`, `[strct-modal] size="${size}" has no effect with chromeless: a chromeless ` +
|
|
3533
|
+
`dialog sizes itself from the wizard it hosts (rail + --strct-wiz-content-min, ` +
|
|
3534
|
+
`default 864px). To change its width, set --strct-wiz-content-min on the ` +
|
|
3535
|
+
`strct-modal or an ancestor — on the strct-wizard alone it does not reach ` +
|
|
3536
|
+
`the dialog.`);
|
|
3537
|
+
}
|
|
3538
|
+
})
|
|
3539
|
+
: null;
|
|
3434
3540
|
titleId = `strct-modal-${++modalCounter}`;
|
|
3435
3541
|
/** Element that had focus before the dialog opened, restored on close. */
|
|
3436
3542
|
previousActive = null;
|
|
@@ -3573,7 +3679,7 @@ class StrctModal {
|
|
|
3573
3679
|
(items[0] ?? this.dialog())?.focus();
|
|
3574
3680
|
}
|
|
3575
3681
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctModal, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
3576
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, chromeless: { classPropertyName: "chromeless", publicName: "chromeless", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, ngImport: i0, template: `
|
|
3682
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctModal, isStandalone: true, selector: "strct-modal", inputs: { open: { classPropertyName: "open", publicName: "open", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, hideFooter: { classPropertyName: "hideFooter", publicName: "hideFooter", isSignal: true, isRequired: false, transformFunction: null }, chromeless: { classPropertyName: "chromeless", publicName: "chromeless", isSignal: true, isRequired: false, transformFunction: null }, closeLabel: { classPropertyName: "closeLabel", publicName: "closeLabel", isSignal: true, isRequired: false, transformFunction: null }, dismissible: { classPropertyName: "dismissible", publicName: "dismissible", isSignal: true, isRequired: false, transformFunction: null }, draggable: { classPropertyName: "draggable", publicName: "draggable", isSignal: true, isRequired: false, transformFunction: null }, panelClass: { classPropertyName: "panelClass", publicName: "panelClass", isSignal: true, isRequired: false, transformFunction: null }, backdropClass: { classPropertyName: "backdropClass", publicName: "backdropClass", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { open: "openChange", closed: "closed" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "lazyContent", first: true, predicate: StrctModalContent, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
3577
3683
|
@if (open()) {
|
|
3578
3684
|
<!-- Backdrop: pointer-only dismiss target. No role/tabindex — keyboard users
|
|
3579
3685
|
dismiss via Escape, and the focus trap makes the backdrop unreachable
|
|
@@ -3619,18 +3725,23 @@ class StrctModal {
|
|
|
3619
3725
|
</button>
|
|
3620
3726
|
</div>
|
|
3621
3727
|
}
|
|
3622
|
-
<div class="strct-modal__body"
|
|
3728
|
+
<div class="strct-modal__body">
|
|
3729
|
+
<ng-content />
|
|
3730
|
+
@if (lazyContent(); as lazy) {
|
|
3731
|
+
<ng-container [ngTemplateOutlet]="lazy.template" />
|
|
3732
|
+
}
|
|
3733
|
+
</div>
|
|
3623
3734
|
@if (!hideFooter() && !chromeless()) {
|
|
3624
3735
|
<div class="strct-modal__foot"><ng-content select="[strctModalFooter]" /></div>
|
|
3625
3736
|
}
|
|
3626
3737
|
</div>
|
|
3627
3738
|
</div>
|
|
3628
3739
|
}
|
|
3629
|
-
`, isInline: true, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:var(--backdrop);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(480px,calc(100vw - 32px))}.strct-modal__dialog--md{max-width:min(640px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(860px,calc(100vw - 32px))}.strct-modal__dialog--xl{max-width:min(1080px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__head--drag{cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-modal__overlay--glass{background:#00000061;-webkit-backdrop-filter:blur(10px) saturate(1.25);backdrop-filter:blur(10px) saturate(1.25)}.strct-modal__dialog--glass{background:color-mix(in srgb,var(--bg-1) 72%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.4);backdrop-filter:blur(24px) saturate(1.4)}.strct-modal__dialog--glass .strct-modal__foot{background:color-mix(in srgb,var(--bg-2) 55%,transparent)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__dialog--chromeless{width:calc(232px + var(--strct-wiz-content-min, 864px) + 2px);max-width:calc(100vw - 32px)}.strct-modal__dialog--chromeless:has(.strct-wiz__layout--aside){width:calc(232px + var(--strct-wiz-content-min, 864px) + 280px + 2px)}.strct-modal__dialog--chromeless .strct-modal__body{padding:0;overflow:hidden;display:flex;flex-direction:column}.strct-modal__dialog--chromeless .strct-modal__body>*{flex:1;min-height:0}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}@media(prefers-reduced-motion:reduce){.strct-modal__overlay,.strct-modal__dialog{animation:none}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3740
|
+
`, isInline: true, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:var(--backdrop);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(480px,calc(100vw - 32px))}.strct-modal__dialog--md{max-width:min(640px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(860px,calc(100vw - 32px))}.strct-modal__dialog--xl{max-width:min(1080px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__head--drag{cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-modal__overlay--glass{background:#00000061;-webkit-backdrop-filter:blur(10px) saturate(1.25);backdrop-filter:blur(10px) saturate(1.25)}.strct-modal__dialog--glass{background:color-mix(in srgb,var(--bg-1) 72%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.4);backdrop-filter:blur(24px) saturate(1.4)}.strct-modal__dialog--glass .strct-modal__foot{background:color-mix(in srgb,var(--bg-2) 55%,transparent)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__dialog--chromeless{width:calc(232px + var(--strct-wiz-content-min, 864px) + 2px);max-width:calc(100vw - 32px)}.strct-modal__dialog--chromeless:has(.strct-wiz__layout--aside){width:calc(232px + var(--strct-wiz-content-min, 864px) + 280px + 2px)}.strct-modal__dialog--chromeless .strct-modal__body{padding:0;overflow:hidden;display:flex;flex-direction:column}.strct-modal__dialog--chromeless .strct-modal__body>*{flex:1;min-height:0}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}@media(prefers-reduced-motion:reduce){.strct-modal__overlay,.strct-modal__dialog{animation:none}}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
3630
3741
|
}
|
|
3631
3742
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctModal, decorators: [{
|
|
3632
3743
|
type: Component,
|
|
3633
|
-
args: [{ selector: 'strct-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StrctIcon], template: `
|
|
3744
|
+
args: [{ selector: 'strct-modal', changeDetection: ChangeDetectionStrategy.OnPush, imports: [StrctIcon, NgTemplateOutlet], template: `
|
|
3634
3745
|
@if (open()) {
|
|
3635
3746
|
<!-- Backdrop: pointer-only dismiss target. No role/tabindex — keyboard users
|
|
3636
3747
|
dismiss via Escape, and the focus trap makes the backdrop unreachable
|
|
@@ -3676,7 +3787,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
3676
3787
|
</button>
|
|
3677
3788
|
</div>
|
|
3678
3789
|
}
|
|
3679
|
-
<div class="strct-modal__body"
|
|
3790
|
+
<div class="strct-modal__body">
|
|
3791
|
+
<ng-content />
|
|
3792
|
+
@if (lazyContent(); as lazy) {
|
|
3793
|
+
<ng-container [ngTemplateOutlet]="lazy.template" />
|
|
3794
|
+
}
|
|
3795
|
+
</div>
|
|
3680
3796
|
@if (!hideFooter() && !chromeless()) {
|
|
3681
3797
|
<div class="strct-modal__foot"><ng-content select="[strctModalFooter]" /></div>
|
|
3682
3798
|
}
|
|
@@ -3686,7 +3802,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
3686
3802
|
`, host: {
|
|
3687
3803
|
'(document:keydown.escape)': 'onEscape()',
|
|
3688
3804
|
}, styles: [".strct-modal__overlay{position:fixed;inset:0;z-index:var(--z-modal);display:flex;align-items:center;justify-content:center;padding:var(--space-5);background:var(--backdrop);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);animation:strct-modal-fade .12s ease}@media(max-width:768px){.strct-modal__overlay{padding:var(--space-3)}}.strct-modal__dialog{width:100%;max-height:calc(100vh - 48px);display:flex;flex-direction:column;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-xl);box-shadow:var(--shadow-elevated);overflow:hidden;animation:strct-modal-rise .14s ease}.strct-modal__dialog--sm{max-width:min(480px,calc(100vw - 32px))}.strct-modal__dialog--md{max-width:min(640px,calc(100vw - 32px))}.strct-modal__dialog--lg{max-width:min(860px,calc(100vw - 32px))}.strct-modal__dialog--xl{max-width:min(1080px,calc(100vw - 32px))}.strct-modal__head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-3) var(--space-4);border-bottom:1px solid var(--b1)}.strct-modal__head--drag{cursor:move;-webkit-user-select:none;user-select:none;touch-action:none}.strct-modal__overlay--glass{background:#00000061;-webkit-backdrop-filter:blur(10px) saturate(1.25);backdrop-filter:blur(10px) saturate(1.25)}.strct-modal__dialog--glass{background:color-mix(in srgb,var(--bg-1) 72%,transparent);-webkit-backdrop-filter:blur(24px) saturate(1.4);backdrop-filter:blur(24px) saturate(1.4)}.strct-modal__dialog--glass .strct-modal__foot{background:color-mix(in srgb,var(--bg-2) 55%,transparent)}.strct-modal__title{font-size:14px;font-weight:600;color:var(--t1)}.strct-modal__close{display:inline-flex;padding:4px;border:0;border-radius:5px;background:transparent;color:var(--t3);cursor:pointer}.strct-modal__close:hover{color:var(--t1);background:var(--bg-3)}.strct-modal__body{padding:var(--space-4);overflow-y:auto;color:var(--t2);font-size:13px}.strct-modal__dialog--chromeless{width:calc(232px + var(--strct-wiz-content-min, 864px) + 2px);max-width:calc(100vw - 32px)}.strct-modal__dialog--chromeless:has(.strct-wiz__layout--aside){width:calc(232px + var(--strct-wiz-content-min, 864px) + 280px + 2px)}.strct-modal__dialog--chromeless .strct-modal__body{padding:0;overflow:hidden;display:flex;flex-direction:column}.strct-modal__dialog--chromeless .strct-modal__body>*{flex:1;min-height:0}.strct-modal__foot{display:flex;align-items:center;justify-content:flex-end;gap:var(--space-2);padding:var(--space-3) var(--space-4);border-top:1px solid var(--b1);background:var(--bg-2)}@keyframes strct-modal-fade{0%{opacity:0}}@keyframes strct-modal-rise{0%{opacity:0;transform:translateY(8px) scale(.98)}}@media(prefers-reduced-motion:reduce){.strct-modal__overlay,.strct-modal__dialog{animation:none}}\n"] }]
|
|
3689
|
-
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], chromeless: [{ type: i0.Input, args: [{ isSignal: true, alias: "chromeless", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }] } });
|
|
3805
|
+
}], ctorParameters: () => [], propDecorators: { open: [{ type: i0.Input, args: [{ isSignal: true, alias: "open", required: false }] }, { type: i0.Output, args: ["openChange"] }], title: [{ type: i0.Input, args: [{ isSignal: true, alias: "title", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], hideFooter: [{ type: i0.Input, args: [{ isSignal: true, alias: "hideFooter", required: false }] }], chromeless: [{ type: i0.Input, args: [{ isSignal: true, alias: "chromeless", required: false }] }], closeLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeLabel", required: false }] }], dismissible: [{ type: i0.Input, args: [{ isSignal: true, alias: "dismissible", required: false }] }], draggable: [{ type: i0.Input, args: [{ isSignal: true, alias: "draggable", required: false }] }], panelClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelClass", required: false }] }], backdropClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "backdropClass", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], closed: [{ type: i0.Output, args: ["closed"] }], lazyContent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => StrctModalContent), { isSignal: true }] }] } });
|
|
3690
3806
|
|
|
3691
3807
|
/** Marks the drawer's footer action area: `<ng-container strctDrawerFooter>…`. */
|
|
3692
3808
|
class StrctDrawerFooter {
|
|
@@ -3967,7 +4083,7 @@ class StrctDropdown {
|
|
|
3967
4083
|
onMenuKeydown(event) {
|
|
3968
4084
|
if (this.popover())
|
|
3969
4085
|
return;
|
|
3970
|
-
const items = this.
|
|
4086
|
+
const items = this.navItems();
|
|
3971
4087
|
if (!items.length)
|
|
3972
4088
|
return;
|
|
3973
4089
|
const idx = items.indexOf(event.target);
|
|
@@ -3987,7 +4103,9 @@ class StrctDropdown {
|
|
|
3987
4103
|
}
|
|
3988
4104
|
else if (key === 'Enter' || key === ' ') {
|
|
3989
4105
|
event.preventDefault();
|
|
3990
|
-
event.target
|
|
4106
|
+
const target = event.target;
|
|
4107
|
+
if (target.getAttribute('aria-disabled') !== 'true')
|
|
4108
|
+
target.click();
|
|
3991
4109
|
}
|
|
3992
4110
|
else if (key === 'Tab') {
|
|
3993
4111
|
this.close();
|
|
@@ -3998,6 +4116,20 @@ class StrctDropdown {
|
|
|
3998
4116
|
...this.host.nativeElement.querySelectorAll('strct-dropdown-item:not([aria-disabled="true"]), strct-submenu .strct-submenu__trigger'),
|
|
3999
4117
|
];
|
|
4000
4118
|
}
|
|
4119
|
+
/** What the arrow keys visit: enabled items, plus disabled ones that carry a
|
|
4120
|
+
* hint (so the reason can be read). The menu still opens on an enabled one. */
|
|
4121
|
+
navItems() {
|
|
4122
|
+
const host = this.host.nativeElement;
|
|
4123
|
+
const rows = [
|
|
4124
|
+
...host.querySelectorAll('strct-dropdown-item'),
|
|
4125
|
+
...host.querySelectorAll('strct-submenu .strct-submenu__trigger'),
|
|
4126
|
+
].filter((el) => el.getAttribute('aria-disabled') !== 'true' ||
|
|
4127
|
+
el.classList.contains('strct-dd__item--hinted'));
|
|
4128
|
+
// Two queries, so restore DOM order explicitly. (A single comma-separated
|
|
4129
|
+
// selector is DOM-ordered in browsers, but not in every DOM implementation
|
|
4130
|
+
// — jsdom returns it grouped, which scrambles arrow-key order in tests.)
|
|
4131
|
+
return rows.sort((a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1);
|
|
4132
|
+
}
|
|
4001
4133
|
/** Focus the selected item if there is one, else the first — after render. */
|
|
4002
4134
|
focusInitialItem() {
|
|
4003
4135
|
setTimeout(() => {
|
|
@@ -4112,6 +4244,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
4112
4244
|
},
|
|
4113
4245
|
}]
|
|
4114
4246
|
}] });
|
|
4247
|
+
let dropdownItemCounter = 0;
|
|
4115
4248
|
/** A selectable row inside a `<strct-dropdown>`. */
|
|
4116
4249
|
class StrctDropdownItem {
|
|
4117
4250
|
/**
|
|
@@ -4126,15 +4259,42 @@ class StrctDropdownItem {
|
|
|
4126
4259
|
critical = input(false, { ...(ngDevMode ? { debugName: "critical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4127
4260
|
/** Static disable flag. */
|
|
4128
4261
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4262
|
+
/**
|
|
4263
|
+
* A short explanation — typically why a disabled item is unavailable. Shown
|
|
4264
|
+
* as the tooltip and given to assistive technology as the description; never
|
|
4265
|
+
* rendered inline. A disabled item with a hint stays keyboard-reachable so
|
|
4266
|
+
* its reason can be read; activation stays blocked.
|
|
4267
|
+
*/
|
|
4268
|
+
hint = input(null, /* @ts-ignore */
|
|
4269
|
+
...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
4270
|
+
hintId = `strct-dd-item-${++dropdownItemCounter}-hint`;
|
|
4271
|
+
constructor() {
|
|
4272
|
+
// Without pointer-events:none (see the hinted style), a disabled item
|
|
4273
|
+
// would pass clicks to the consumer's (click). Capture-phase at the target
|
|
4274
|
+
// runs before those listeners, and stopping here also keeps the menu's own
|
|
4275
|
+
// activate-and-close handler from seeing it.
|
|
4276
|
+
const host = inject((ElementRef)).nativeElement;
|
|
4277
|
+
host.addEventListener('click', (event) => {
|
|
4278
|
+
if (!this.disabled())
|
|
4279
|
+
return;
|
|
4280
|
+
event.preventDefault();
|
|
4281
|
+
event.stopImmediatePropagation();
|
|
4282
|
+
}, { capture: true });
|
|
4283
|
+
}
|
|
4129
4284
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDropdownItem, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4130
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, critical: { classPropertyName: "critical", publicName: "critical", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "selected() === null ? 'menuitem' : 'menuitemradio'", "attr.aria-checked": "selected()", "attr.tabindex": "disabled() ? null : -1", "class.strct-dd__item--critical": "critical()", "class.strct-dd__item--selected": "selected() === true", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `@if (selected() !== null) {
|
|
4285
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.1.4", type: StrctDropdownItem, isStandalone: true, selector: "strct-dropdown-item", inputs: { selected: { classPropertyName: "selected", publicName: "selected", isSignal: true, isRequired: false, transformFunction: null }, critical: { classPropertyName: "critical", publicName: "critical", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.role": "selected() === null ? 'menuitem' : 'menuitemradio'", "attr.aria-checked": "selected()", "attr.tabindex": "disabled() && !hint() ? null : -1", "attr.title": "hint() || null", "attr.aria-describedby": "hint() ? hintId : null", "class.strct-dd__item--hinted": "!!hint()", "class.strct-dd__item--critical": "critical()", "class.strct-dd__item--selected": "selected() === true", "attr.aria-disabled": "disabled() || null" }, classAttribute: "strct-dd__item" }, ngImport: i0, template: `@if (selected() !== null) {
|
|
4131
4286
|
<span class="strct-dd__check" aria-hidden="true">
|
|
4132
4287
|
@if (selected()) {
|
|
4133
4288
|
<strct-icon strictName="check" [size]="12" [strokeWidth]="1.8" />
|
|
4134
4289
|
}
|
|
4135
4290
|
</span>
|
|
4136
4291
|
}
|
|
4137
|
-
<ng-content
|
|
4292
|
+
<ng-content />
|
|
4293
|
+
@if (hint()) {
|
|
4294
|
+
<!-- hidden: kept out of the item's accessible NAME, still read as its
|
|
4295
|
+
description through aria-describedby. -->
|
|
4296
|
+
<span [id]="hintId" hidden>{{ hint() }}</span>
|
|
4297
|
+
}`, isInline: true, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover,.strct-dd__item:focus-visible{background:var(--bg-3);outline:none}.strct-dd__check{display:inline-flex;width:14px;flex:none;color:var(--acc)}.strct-dd__item--selected{color:var(--t1);font-weight:600;background:var(--acc-s)}.strct-dd__item--critical{color:var(--critical)}.strct-dd__item--critical:hover{background:var(--critical-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}.strct-dd__item--hinted[aria-disabled=true]{pointer-events:auto;cursor:not-allowed}.strct-dd__item--hinted[aria-disabled=true]:hover{background:transparent}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
4138
4298
|
}
|
|
4139
4299
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDropdownItem, decorators: [{
|
|
4140
4300
|
type: Component,
|
|
@@ -4145,16 +4305,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
4145
4305
|
}
|
|
4146
4306
|
</span>
|
|
4147
4307
|
}
|
|
4148
|
-
<ng-content
|
|
4308
|
+
<ng-content />
|
|
4309
|
+
@if (hint()) {
|
|
4310
|
+
<!-- hidden: kept out of the item's accessible NAME, still read as its
|
|
4311
|
+
description through aria-describedby. -->
|
|
4312
|
+
<span [id]="hintId" hidden>{{ hint() }}</span>
|
|
4313
|
+
}`, host: {
|
|
4149
4314
|
class: 'strct-dd__item',
|
|
4150
4315
|
'[attr.role]': "selected() === null ? 'menuitem' : 'menuitemradio'",
|
|
4151
4316
|
'[attr.aria-checked]': 'selected()',
|
|
4152
|
-
|
|
4317
|
+
// A disabled item is skipped — unless it has a hint to be read.
|
|
4318
|
+
'[attr.tabindex]': 'disabled() && !hint() ? null : -1',
|
|
4319
|
+
'[attr.title]': 'hint() || null',
|
|
4320
|
+
'[attr.aria-describedby]': 'hint() ? hintId : null',
|
|
4321
|
+
'[class.strct-dd__item--hinted]': '!!hint()',
|
|
4153
4322
|
'[class.strct-dd__item--critical]': 'critical()',
|
|
4154
4323
|
'[class.strct-dd__item--selected]': 'selected() === true',
|
|
4155
4324
|
'[attr.aria-disabled]': 'disabled() || null',
|
|
4156
|
-
}, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover,.strct-dd__item:focus-visible{background:var(--bg-3);outline:none}.strct-dd__check{display:inline-flex;width:14px;flex:none;color:var(--acc)}.strct-dd__item--selected{color:var(--t1);font-weight:600;background:var(--acc-s)}.strct-dd__item--critical{color:var(--critical)}.strct-dd__item--critical:hover{background:var(--critical-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}\n"] }]
|
|
4157
|
-
}], propDecorators: { selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], critical: [{ type: i0.Input, args: [{ isSignal: true, alias: "critical", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
4325
|
+
}, styles: [".strct-dd__item{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:5px;cursor:pointer;font-size:13px;color:var(--t1)}.strct-dd__item:hover,.strct-dd__item:focus-visible{background:var(--bg-3);outline:none}.strct-dd__check{display:inline-flex;width:14px;flex:none;color:var(--acc)}.strct-dd__item--selected{color:var(--t1);font-weight:600;background:var(--acc-s)}.strct-dd__item--critical{color:var(--critical)}.strct-dd__item--critical:hover{background:var(--critical-bg)}.strct-dd__item[aria-disabled=true]{color:var(--t4);pointer-events:none}.strct-dd__item--hinted[aria-disabled=true]{pointer-events:auto;cursor:not-allowed}.strct-dd__item--hinted[aria-disabled=true]:hover{background:transparent}\n"] }]
|
|
4326
|
+
}], ctorParameters: () => [], propDecorators: { selected: [{ type: i0.Input, args: [{ isSignal: true, alias: "selected", required: false }] }], critical: [{ type: i0.Input, args: [{ isSignal: true, alias: "critical", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }] } });
|
|
4158
4327
|
/** Thin separator between groups of menu items. */
|
|
4159
4328
|
class StrctDropdownDivider {
|
|
4160
4329
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctDropdownDivider, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4209,7 +4378,9 @@ class StrctContextMenu {
|
|
|
4209
4378
|
// guessed size) and focus can land on the first item.
|
|
4210
4379
|
setTimeout(() => {
|
|
4211
4380
|
this.clampToViewport();
|
|
4212
|
-
|
|
4381
|
+
// Land on the first entry that can act, not a disabled-but-hinted one.
|
|
4382
|
+
const first = this.navItems().findIndex((i) => i.getAttribute('aria-disabled') !== 'true');
|
|
4383
|
+
this.focusItem(Math.max(first, 0));
|
|
4213
4384
|
});
|
|
4214
4385
|
}
|
|
4215
4386
|
close() {
|
|
@@ -4220,12 +4391,14 @@ class StrctContextMenu {
|
|
|
4220
4391
|
restoreFocus(this.restoreTo);
|
|
4221
4392
|
this.restoreTo = null;
|
|
4222
4393
|
}
|
|
4223
|
-
/**
|
|
4394
|
+
/** Keyboard-reachable `strct-dropdown-item` elements in DOM order: enabled
|
|
4395
|
+
* ones, plus disabled ones that carry a hint (so the reason can be read). */
|
|
4224
4396
|
navItems() {
|
|
4225
4397
|
const el = this.menuEl()?.nativeElement;
|
|
4226
4398
|
if (!el)
|
|
4227
4399
|
return [];
|
|
4228
|
-
return Array.from(el.querySelectorAll('.strct-dd__item
|
|
4400
|
+
return Array.from(el.querySelectorAll('.strct-dd__item')).filter((i) => i.getAttribute('aria-disabled') !== 'true' ||
|
|
4401
|
+
i.classList.contains('strct-dd__item--hinted'));
|
|
4229
4402
|
}
|
|
4230
4403
|
/**
|
|
4231
4404
|
* Focus-based roving: items keep the `tabindex="-1"` their host binding
|
|
@@ -4438,8 +4611,10 @@ class StrctSubmenu {
|
|
|
4438
4611
|
const panel = this.panel()?.nativeElement;
|
|
4439
4612
|
// Dropdown-item rows carry tabindex=-1, outside FOCUSABLE_SELECTOR —
|
|
4440
4613
|
// fall back to the first rovable row when nothing else is tabbable.
|
|
4441
|
-
if (panel && !focusFirstIn(panel))
|
|
4442
|
-
this.panelItems()
|
|
4614
|
+
if (panel && !focusFirstIn(panel)) {
|
|
4615
|
+
const items = this.panelItems();
|
|
4616
|
+
(items.find((el) => el.getAttribute('aria-disabled') !== 'true') ?? items[0])?.focus();
|
|
4617
|
+
}
|
|
4443
4618
|
});
|
|
4444
4619
|
}
|
|
4445
4620
|
/**
|
|
@@ -4475,11 +4650,13 @@ class StrctSubmenu {
|
|
|
4475
4650
|
items[key === 'Home' ? 0 : items.length - 1].focus();
|
|
4476
4651
|
}
|
|
4477
4652
|
}
|
|
4478
|
-
/** Rovable rows of the open fly-out
|
|
4653
|
+
/** Rovable rows of the open fly-out: enabled dropdown items, plus disabled
|
|
4654
|
+
* ones that carry a hint (so the reason can be read). */
|
|
4479
4655
|
panelItems() {
|
|
4480
4656
|
const panel = this.panel()?.nativeElement;
|
|
4481
4657
|
return panel
|
|
4482
|
-
? [...panel.querySelectorAll('strct-dropdown-item
|
|
4658
|
+
? [...panel.querySelectorAll('strct-dropdown-item')].filter((i) => i.getAttribute('aria-disabled') !== 'true' ||
|
|
4659
|
+
i.classList.contains('strct-dd__item--hinted'))
|
|
4483
4660
|
: [];
|
|
4484
4661
|
}
|
|
4485
4662
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSubmenu, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4668,7 +4845,10 @@ class StrctWizard {
|
|
|
4668
4845
|
* ~720px of component width — it never flips horizontal.
|
|
4669
4846
|
*
|
|
4670
4847
|
* The default can be flipped app-wide via `provideStrctWizardDefaults`;
|
|
4671
|
-
* this input always wins when bound.
|
|
4848
|
+
* this input always wins when bound. **Tests:** a spec that renders a
|
|
4849
|
+
* component using `strct-wizard` must provide the same defaults the app
|
|
4850
|
+
* does, or it renders the horizontal layout — a different DOM, no rail,
|
|
4851
|
+
* no title.
|
|
4672
4852
|
*/
|
|
4673
4853
|
vertical = input(this.defaults?.vertical ?? false, { ...(ngDevMode ? { debugName: "vertical" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4674
4854
|
/**
|
|
@@ -4678,7 +4858,8 @@ class StrctWizard {
|
|
|
4678
4858
|
* Size the host with width/height only; do not override its `display`.
|
|
4679
4859
|
*/
|
|
4680
4860
|
flush = input(false, { ...(ngDevMode ? { debugName: "flush" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
4681
|
-
/** Rail heading shown above the progress bar
|
|
4861
|
+
/** Rail heading shown above the progress bar. Vertical mode only — the
|
|
4862
|
+
* horizontal layout has no title band (a dev-mode warning says so). */
|
|
4682
4863
|
title = input('', /* @ts-ignore */
|
|
4683
4864
|
...(ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []));
|
|
4684
4865
|
/**
|
|
@@ -4730,6 +4911,8 @@ class StrctWizard {
|
|
|
4730
4911
|
canAdvance = computed(() => this.steps()[this.current()]?.canAdvance() ?? true, /* @ts-ignore */
|
|
4731
4912
|
...(ngDevMode ? [{ debugName: "canAdvance" }] : /* istanbul ignore next */ []));
|
|
4732
4913
|
constructor() {
|
|
4914
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode)
|
|
4915
|
+
this.diagnose();
|
|
4733
4916
|
effect(() => {
|
|
4734
4917
|
const idx = this.current();
|
|
4735
4918
|
this.steps().forEach((step, i) => step.setActive(i === idx));
|
|
@@ -4739,6 +4922,37 @@ class StrctWizard {
|
|
|
4739
4922
|
});
|
|
4740
4923
|
});
|
|
4741
4924
|
}
|
|
4925
|
+
/** Dev-mode warnings for inputs the current layout silently ignores. */
|
|
4926
|
+
diagnose() {
|
|
4927
|
+
if (!(typeof ngDevMode !== 'undefined' && ngDevMode))
|
|
4928
|
+
return;
|
|
4929
|
+
effect(() => {
|
|
4930
|
+
const title = this.title();
|
|
4931
|
+
if (title && !this.vertical()) {
|
|
4932
|
+
strctDevWarn('wizard:horizontal-title', `[strct-wizard] title="${title}" is not rendered: only the vertical layout ` +
|
|
4933
|
+
`has a title band. Set \`vertical\` — or, if the app provides ` +
|
|
4934
|
+
`provideStrctWizardDefaults({ vertical: true }), provide it here too ` +
|
|
4935
|
+
`(a test that omits it renders the horizontal wizard).`);
|
|
4936
|
+
}
|
|
4937
|
+
});
|
|
4938
|
+
// A chromeless dialog sizes itself from --strct-wiz-content-min read on the
|
|
4939
|
+
// DIALOG; set on the wizard, it widens the grid but not the dialog.
|
|
4940
|
+
const host = inject((ElementRef)).nativeElement;
|
|
4941
|
+
afterNextRender(() => {
|
|
4942
|
+
const dialog = host.closest('.strct-modal__dialog--chromeless');
|
|
4943
|
+
if (!dialog)
|
|
4944
|
+
return;
|
|
4945
|
+
const prop = '--strct-wiz-content-min';
|
|
4946
|
+
const own = getComputedStyle(host).getPropertyValue(prop).trim();
|
|
4947
|
+
const outer = getComputedStyle(dialog).getPropertyValue(prop).trim();
|
|
4948
|
+
if (own !== outer) {
|
|
4949
|
+
strctDevWarn('wizard:content-min-scope', `[strct-wizard] ${prop} is ${own || '(unset)'} on the wizard but ` +
|
|
4950
|
+
`${outer || '(unset — default 864px)'} on its chromeless dialog. The dialog ` +
|
|
4951
|
+
`reads the variable on itself, so its width ignores the wizard's value. Set ` +
|
|
4952
|
+
`it on the strct-modal or an ancestor instead.`);
|
|
4953
|
+
}
|
|
4954
|
+
});
|
|
4955
|
+
}
|
|
4742
4956
|
next() {
|
|
4743
4957
|
if (!this.isLast() && this.canAdvance()) {
|
|
4744
4958
|
this.current.update((i) => i + 1);
|
|
@@ -10492,7 +10706,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
10492
10706
|
* Per-column cell template for `strct-table` / `strct-datagrid`. The column key
|
|
10493
10707
|
* is the directive value; the row, value and column are the template context:
|
|
10494
10708
|
*
|
|
10495
|
-
* <ng-template strctCell="status" let-row let-value="value">
|
|
10709
|
+
* <ng-template strctCell="status" let-row let-value="value"> (let-row="row" also works)
|
|
10496
10710
|
* <strct-badge [status]="row['success'] ? 'success' : 'critical'">{{ value }}</strct-badge>
|
|
10497
10711
|
* </ng-template>
|
|
10498
10712
|
*/
|
|
@@ -10576,6 +10790,7 @@ class StrctTable {
|
|
|
10576
10790
|
[ngTemplateOutlet]="tpl"
|
|
10577
10791
|
[ngTemplateOutletContext]="{
|
|
10578
10792
|
$implicit: row,
|
|
10793
|
+
row,
|
|
10579
10794
|
value: row[col.key],
|
|
10580
10795
|
column: col,
|
|
10581
10796
|
}"
|
|
@@ -10632,6 +10847,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
10632
10847
|
[ngTemplateOutlet]="tpl"
|
|
10633
10848
|
[ngTemplateOutletContext]="{
|
|
10634
10849
|
$implicit: row,
|
|
10850
|
+
row,
|
|
10635
10851
|
value: row[col.key],
|
|
10636
10852
|
column: col,
|
|
10637
10853
|
}"
|
|
@@ -10809,7 +11025,7 @@ const UTIL_W = { detail: 36, expand: 36, sel: 40 };
|
|
|
10809
11025
|
const STICKY_FALLBACK_W = 120;
|
|
10810
11026
|
/**
|
|
10811
11027
|
* Marks the expandable-row detail template. The row is the template's implicit
|
|
10812
|
-
* context: `<ng-template strctRowDetail let-row> … {{ row['name'] }} … </ng-template>`.
|
|
11028
|
+
* context (`let-row`, or `let-row="row"`): `<ng-template strctRowDetail let-row> … {{ row['name'] }} … </ng-template>`.
|
|
10813
11029
|
*/
|
|
10814
11030
|
class StrctRowDetailDef {
|
|
10815
11031
|
template = inject(TemplateRef);
|
|
@@ -11603,6 +11819,55 @@ class StrctDatagrid {
|
|
|
11603
11819
|
somePageSelected = computed(() => !this.allPageSelected() &&
|
|
11604
11820
|
this.selectionRows().some((r) => this.selected().has(this.idOf(r))), /* @ts-ignore */
|
|
11605
11821
|
...(ngDevMode ? [{ debugName: "somePageSelected" }] : /* istanbul ignore next */ []));
|
|
11822
|
+
/** Dev-mode check that row identities can do their job (see util/dev-warn). */
|
|
11823
|
+
diagnoseIdentity(rowId, rows, init, lazy) {
|
|
11824
|
+
if (!(typeof ngDevMode !== 'undefined' && ngDevMode))
|
|
11825
|
+
return;
|
|
11826
|
+
if (rows.length === 0)
|
|
11827
|
+
return;
|
|
11828
|
+
const label = rowId == null ? '' : typeof rowId === 'function' ? 'rowId (function)' : `rowId="${rowId}"`;
|
|
11829
|
+
if (rowId != null) {
|
|
11830
|
+
const seen = new Set();
|
|
11831
|
+
const dupes = new Set();
|
|
11832
|
+
let unresolved = 0;
|
|
11833
|
+
for (const r of rows) {
|
|
11834
|
+
const raw = typeof rowId === 'function' ? rowId(r) : r[rowId];
|
|
11835
|
+
if (raw == null)
|
|
11836
|
+
unresolved++;
|
|
11837
|
+
else if (seen.has(raw))
|
|
11838
|
+
dupes.add(raw);
|
|
11839
|
+
else
|
|
11840
|
+
seen.add(raw);
|
|
11841
|
+
}
|
|
11842
|
+
if (dupes.size > 0) {
|
|
11843
|
+
const sample = [...dupes]
|
|
11844
|
+
.slice(0, 3)
|
|
11845
|
+
.map((v) => JSON.stringify(v))
|
|
11846
|
+
.join(', ');
|
|
11847
|
+
strctDevWarn(`datagrid:dupe:${label}`, `[strct-datagrid] ${label} resolves to the same value for more than one row ` +
|
|
11848
|
+
`(${sample}). Selection and expansion key on this value, so those rows ` +
|
|
11849
|
+
`will behave as one. Give each row a distinct value, or drop rowId to key ` +
|
|
11850
|
+
`on the row object.`);
|
|
11851
|
+
}
|
|
11852
|
+
if (unresolved > 0) {
|
|
11853
|
+
strctDevWarn(`datagrid:unresolved:${label}`, `[strct-datagrid] ${label} does not resolve for ${unresolved} of ${rows.length} ` +
|
|
11854
|
+
`rows. Those rows fall back to object identity, so their selection and ` +
|
|
11855
|
+
`expansion will not survive a data refresh. Check the field name, or give ` +
|
|
11856
|
+
`every row a value.`);
|
|
11857
|
+
}
|
|
11858
|
+
}
|
|
11859
|
+
// Lazy mode seeds ids for rows on other pages, so a miss there is normal.
|
|
11860
|
+
if (!lazy && init && init.length > 0) {
|
|
11861
|
+
const ids = new Set(rows.map((r) => this.idOf(r)));
|
|
11862
|
+
if (!init.some((v) => ids.has(v))) {
|
|
11863
|
+
strctDevWarn(`datagrid:init:${label}`, `[strct-datagrid] initialSelection has ${init.length} value(s), none of which ` +
|
|
11864
|
+
(rowId == null
|
|
11865
|
+
? `is one of the rows — with no rowId, the values must be the row objects themselves. `
|
|
11866
|
+
: `matches any row's ${label}. `) +
|
|
11867
|
+
`The pre-selection will be empty.`);
|
|
11868
|
+
}
|
|
11869
|
+
}
|
|
11870
|
+
}
|
|
11606
11871
|
/** Resolve a row's stable identity: its `rowId` value, or the row object
|
|
11607
11872
|
* itself when there is no `rowId` or it resolves to null/undefined. */
|
|
11608
11873
|
idOf(row) {
|
|
@@ -11654,6 +11919,17 @@ class StrctDatagrid {
|
|
|
11654
11919
|
return;
|
|
11655
11920
|
untracked(() => this.selected.set(new Set(init)));
|
|
11656
11921
|
});
|
|
11922
|
+
// Dev mode only: say so when rowId or initialSelection cannot do what they
|
|
11923
|
+
// were given to do. In production the effect is never registered.
|
|
11924
|
+
if (typeof ngDevMode !== 'undefined' && ngDevMode) {
|
|
11925
|
+
effect(() => {
|
|
11926
|
+
const rowId = this.rowId();
|
|
11927
|
+
const rows = this.rows();
|
|
11928
|
+
const init = this.initialSelection();
|
|
11929
|
+
const lazy = this.lazy();
|
|
11930
|
+
untracked(() => this.diagnoseIdentity(rowId, rows, init, lazy));
|
|
11931
|
+
});
|
|
11932
|
+
}
|
|
11657
11933
|
// Server-side mode: announce what to load whenever page / sort / pageSize
|
|
11658
11934
|
// change (and once on init, so the consumer fetches the first page).
|
|
11659
11935
|
effect(() => {
|
|
@@ -12340,6 +12616,7 @@ class StrctDatagrid {
|
|
|
12340
12616
|
[ngTemplateOutlet]="tpl"
|
|
12341
12617
|
[ngTemplateOutletContext]="{
|
|
12342
12618
|
$implicit: row,
|
|
12619
|
+
row,
|
|
12343
12620
|
value: row[col.key],
|
|
12344
12621
|
column: col,
|
|
12345
12622
|
}"
|
|
@@ -12368,7 +12645,7 @@ class StrctDatagrid {
|
|
|
12368
12645
|
<div class="strct-dg__detail">
|
|
12369
12646
|
<ng-container
|
|
12370
12647
|
[ngTemplateOutlet]="detailDef()!.template"
|
|
12371
|
-
[ngTemplateOutletContext]="{ $implicit: row }"
|
|
12648
|
+
[ngTemplateOutletContext]="{ $implicit: row, row }"
|
|
12372
12649
|
/>
|
|
12373
12650
|
</div>
|
|
12374
12651
|
</td>
|
|
@@ -12406,7 +12683,7 @@ class StrctDatagrid {
|
|
|
12406
12683
|
<div class="strct-dg__pane-body">
|
|
12407
12684
|
<ng-container
|
|
12408
12685
|
[ngTemplateOutlet]="detailDef()!.template"
|
|
12409
|
-
[ngTemplateOutletContext]="{ $implicit: activeRow() }"
|
|
12686
|
+
[ngTemplateOutletContext]="{ $implicit: activeRow(), row: activeRow() }"
|
|
12410
12687
|
/>
|
|
12411
12688
|
</div>
|
|
12412
12689
|
</aside>
|
|
@@ -12829,6 +13106,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
12829
13106
|
[ngTemplateOutlet]="tpl"
|
|
12830
13107
|
[ngTemplateOutletContext]="{
|
|
12831
13108
|
$implicit: row,
|
|
13109
|
+
row,
|
|
12832
13110
|
value: row[col.key],
|
|
12833
13111
|
column: col,
|
|
12834
13112
|
}"
|
|
@@ -12857,7 +13135,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
12857
13135
|
<div class="strct-dg__detail">
|
|
12858
13136
|
<ng-container
|
|
12859
13137
|
[ngTemplateOutlet]="detailDef()!.template"
|
|
12860
|
-
[ngTemplateOutletContext]="{ $implicit: row }"
|
|
13138
|
+
[ngTemplateOutletContext]="{ $implicit: row, row }"
|
|
12861
13139
|
/>
|
|
12862
13140
|
</div>
|
|
12863
13141
|
</td>
|
|
@@ -12895,7 +13173,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
12895
13173
|
<div class="strct-dg__pane-body">
|
|
12896
13174
|
<ng-container
|
|
12897
13175
|
[ngTemplateOutlet]="detailDef()!.template"
|
|
12898
|
-
[ngTemplateOutletContext]="{ $implicit: activeRow() }"
|
|
13176
|
+
[ngTemplateOutletContext]="{ $implicit: activeRow(), row: activeRow() }"
|
|
12899
13177
|
/>
|
|
12900
13178
|
</div>
|
|
12901
13179
|
</aside>
|
|
@@ -18117,7 +18395,7 @@ class StrctSplitButton {
|
|
|
18117
18395
|
/** Main action label. */
|
|
18118
18396
|
label = input.required(/* @ts-ignore */
|
|
18119
18397
|
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
18120
|
-
/** Menu entries (StrctMenuItem: id, label, icon?, critical?, disabled?). */
|
|
18398
|
+
/** Menu entries (StrctMenuItem: id, label, icon?, critical?, disabled?, hint?). */
|
|
18121
18399
|
items = input([], /* @ts-ignore */
|
|
18122
18400
|
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
18123
18401
|
/** Optional leading icon of the main segment. */
|
|
@@ -18165,6 +18443,7 @@ class StrctSplitButton {
|
|
|
18165
18443
|
<strct-dropdown-item
|
|
18166
18444
|
[critical]="item.critical ?? false"
|
|
18167
18445
|
[disabled]="item.disabled ?? false"
|
|
18446
|
+
[hint]="item.hint"
|
|
18168
18447
|
(click)="!item.disabled && picked.emit(item)"
|
|
18169
18448
|
>
|
|
18170
18449
|
@if (item.icon) {
|
|
@@ -18176,7 +18455,7 @@ class StrctSplitButton {
|
|
|
18176
18455
|
}
|
|
18177
18456
|
</strct-dropdown>
|
|
18178
18457
|
</div>
|
|
18179
|
-
`, isInline: true, styles: [".strct-sbt{display:inline-flex;align-items:stretch}.strct-sbt .strct-dd{display:inline-flex;align-self:stretch}.strct-sbt .strct-dd__trigger{display:inline-flex;align-items:stretch}.strct-sbt__chev{align-self:stretch;height:100%}.strct-sbt__main,.strct-sbt__chev{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--acc);background:transparent;color:var(--acc);font-family:var(--font);font-size:13px;font-weight:600;line-height:1;cursor:pointer;padding:var(--space-2) var(--space-4)}.strct-sbt__main{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md);border-inline-end:0}.strct-sbt__chev{padding:var(--space-2);border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md);border-inline-start:1px solid var(--acc50)}.strct-sbt--solid .strct-sbt__main,.strct-sbt--solid .strct-sbt__chev{background:var(--acc);color:var(--inv)}.strct-sbt--solid .strct-sbt__chev{border-inline-start-color:color-mix(in srgb,var(--inv) 30%,var(--acc))}.strct-sbt__main:hover:not(:disabled),.strct-sbt__chev:hover:not(:disabled){background:var(--acc18)}.strct-sbt--solid .strct-sbt__main:hover:not(:disabled),.strct-sbt--solid .strct-sbt__chev:hover:not(:disabled){filter:brightness(1.08);background:var(--acc)}.strct-sbt__main:disabled,.strct-sbt__chev:disabled{opacity:.5;cursor:default}.strct-sbt__main:focus-visible,.strct-sbt__chev:focus-visible{outline:2px solid var(--acc50);outline-offset:1px;position:relative;z-index:var(--z-base)}\n"], dependencies: [{ kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel"] }, { kind: "component", type: StrctDropdownDivider, selector: "strct-dropdown-divider" }, { kind: "component", type: StrctDropdownItem, selector: "strct-dropdown-item", inputs: ["selected", "critical", "disabled"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
18458
|
+
`, isInline: true, styles: [".strct-sbt{display:inline-flex;align-items:stretch}.strct-sbt .strct-dd{display:inline-flex;align-self:stretch}.strct-sbt .strct-dd__trigger{display:inline-flex;align-items:stretch}.strct-sbt__chev{align-self:stretch;height:100%}.strct-sbt__main,.strct-sbt__chev{display:inline-flex;align-items:center;gap:6px;border:1px solid var(--acc);background:transparent;color:var(--acc);font-family:var(--font);font-size:13px;font-weight:600;line-height:1;cursor:pointer;padding:var(--space-2) var(--space-4)}.strct-sbt__main{border-start-start-radius:var(--radius-md);border-end-start-radius:var(--radius-md);border-inline-end:0}.strct-sbt__chev{padding:var(--space-2);border-start-end-radius:var(--radius-md);border-end-end-radius:var(--radius-md);border-inline-start:1px solid var(--acc50)}.strct-sbt--solid .strct-sbt__main,.strct-sbt--solid .strct-sbt__chev{background:var(--acc);color:var(--inv)}.strct-sbt--solid .strct-sbt__chev{border-inline-start-color:color-mix(in srgb,var(--inv) 30%,var(--acc))}.strct-sbt__main:hover:not(:disabled),.strct-sbt__chev:hover:not(:disabled){background:var(--acc18)}.strct-sbt--solid .strct-sbt__main:hover:not(:disabled),.strct-sbt--solid .strct-sbt__chev:hover:not(:disabled){filter:brightness(1.08);background:var(--acc)}.strct-sbt__main:disabled,.strct-sbt__chev:disabled{opacity:.5;cursor:default}.strct-sbt__main:focus-visible,.strct-sbt__chev:focus-visible{outline:2px solid var(--acc50);outline-offset:1px;position:relative;z-index:var(--z-base)}\n"], dependencies: [{ kind: "component", type: StrctDropdown, selector: "strct-dropdown", inputs: ["align", "popover", "popoverLabel"] }, { kind: "component", type: StrctDropdownDivider, selector: "strct-dropdown-divider" }, { kind: "component", type: StrctDropdownItem, selector: "strct-dropdown-item", inputs: ["selected", "critical", "disabled", "hint"] }, { kind: "directive", type: StrctDropdownTrigger, selector: "[strctDropdownTrigger]" }, { kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
18180
18459
|
}
|
|
18181
18460
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctSplitButton, decorators: [{
|
|
18182
18461
|
type: Component,
|
|
@@ -18216,6 +18495,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18216
18495
|
<strct-dropdown-item
|
|
18217
18496
|
[critical]="item.critical ?? false"
|
|
18218
18497
|
[disabled]="item.disabled ?? false"
|
|
18498
|
+
[hint]="item.hint"
|
|
18219
18499
|
(click)="!item.disabled && picked.emit(item)"
|
|
18220
18500
|
>
|
|
18221
18501
|
@if (item.icon) {
|
|
@@ -18570,6 +18850,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18570
18850
|
args: ['window:scroll']
|
|
18571
18851
|
}] } });
|
|
18572
18852
|
|
|
18853
|
+
let menubarCounter = 0;
|
|
18573
18854
|
/**
|
|
18574
18855
|
* Horizontal menubar — the application-menu strip ("File · Edit · View") for
|
|
18575
18856
|
* dense tool-style consoles:
|
|
@@ -18696,7 +18977,7 @@ class StrctMenubar {
|
|
|
18696
18977
|
event.preventDefault();
|
|
18697
18978
|
event.stopPropagation();
|
|
18698
18979
|
const idx = Number(active?.getAttribute('data-idx'));
|
|
18699
|
-
if (menu.items[idx]?.children?.length) {
|
|
18980
|
+
if (menu.items[idx]?.children?.length && !menu.items[idx].disabled) {
|
|
18700
18981
|
this.subIdx.set(idx);
|
|
18701
18982
|
setTimeout(() => this.navButtons(true)[0]?.focus());
|
|
18702
18983
|
}
|
|
@@ -18747,18 +19028,24 @@ class StrctMenubar {
|
|
|
18747
19028
|
restoreFocus(this.trigger);
|
|
18748
19029
|
this.trigger = null;
|
|
18749
19030
|
}
|
|
19031
|
+
uid = ++menubarCounter;
|
|
19032
|
+
hintId(menuId, i, j) {
|
|
19033
|
+
// menu ids are consumer data; aria-describedby splits on whitespace.
|
|
19034
|
+
const menu = menuId.replace(/\s+/g, '_');
|
|
19035
|
+
return `strct-mb-${this.uid}-${menu}-${i}${j == null ? '' : '-' + j}-hint`;
|
|
19036
|
+
}
|
|
18750
19037
|
topButtons() {
|
|
18751
19038
|
return Array.from(this.host.nativeElement.querySelectorAll('.strct-mb__top'));
|
|
18752
19039
|
}
|
|
18753
|
-
/**
|
|
19040
|
+
/** Keyboard-reachable item buttons of the open menu — either its items or the
|
|
19041
|
+
* open submenu's: enabled ones, plus disabled ones that carry a hint (so the
|
|
19042
|
+
* reason can be read). A disabled entry with nothing to say is skipped. */
|
|
18754
19043
|
navButtons(sub) {
|
|
18755
19044
|
const menuEl = this.host.nativeElement.querySelector('.strct-mb__menu');
|
|
18756
19045
|
if (!menuEl)
|
|
18757
19046
|
return [];
|
|
18758
|
-
const sel = sub
|
|
18759
|
-
|
|
18760
|
-
: '.strct-mb__item:not([disabled]):not(.strct-mb__subitem)';
|
|
18761
|
-
return Array.from(menuEl.querySelectorAll(sel));
|
|
19047
|
+
const sel = sub ? '.strct-mb__subitem' : '.strct-mb__item:not(.strct-mb__subitem)';
|
|
19048
|
+
return Array.from(menuEl.querySelectorAll(sel)).filter((b) => b.getAttribute('aria-disabled') !== 'true' || b.hasAttribute('aria-describedby'));
|
|
18762
19049
|
}
|
|
18763
19050
|
onDocClick(event) {
|
|
18764
19051
|
if (this.openId() && !this.host.nativeElement.contains(event.target)) {
|
|
@@ -18810,7 +19097,9 @@ class StrctMenubar {
|
|
|
18810
19097
|
[class.strct-mb__item--critical]="item.critical"
|
|
18811
19098
|
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
18812
19099
|
[attr.aria-expanded]="item.children?.length ? subIdx() === i : null"
|
|
18813
|
-
[disabled]="item.disabled
|
|
19100
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
19101
|
+
[attr.aria-describedby]="item.hint ? hintId(menu.id, i) : null"
|
|
19102
|
+
[attr.title]="item.hint || null"
|
|
18814
19103
|
(click)="onItemClick(menu, item, i)"
|
|
18815
19104
|
(mouseenter)="onItemHover(item, i)"
|
|
18816
19105
|
>
|
|
@@ -18822,9 +19111,12 @@ class StrctMenubar {
|
|
|
18822
19111
|
<strct-icon class="strct-mb__caret" name="chevronRight" [size]="12" />
|
|
18823
19112
|
}
|
|
18824
19113
|
</button>
|
|
19114
|
+
@if (item.hint) {
|
|
19115
|
+
<span [id]="hintId(menu.id, i)" hidden>{{ item.hint }}</span>
|
|
19116
|
+
}
|
|
18825
19117
|
@if (subIdx() === i && item.children?.length) {
|
|
18826
19118
|
<div class="strct-mb__submenu" role="menu" [attr.aria-label]="item.label">
|
|
18827
|
-
@for (sub of item.children; track $index) {
|
|
19119
|
+
@for (sub of item.children; track $index; let j = $index) {
|
|
18828
19120
|
@if (sub.divider) {
|
|
18829
19121
|
<div class="strct-mb__divider" role="separator"></div>
|
|
18830
19122
|
} @else {
|
|
@@ -18833,7 +19125,9 @@ class StrctMenubar {
|
|
|
18833
19125
|
class="strct-mb__item strct-mb__subitem"
|
|
18834
19126
|
role="menuitem"
|
|
18835
19127
|
[class.strct-mb__item--critical]="sub.critical"
|
|
18836
|
-
[disabled]="sub.disabled
|
|
19128
|
+
[attr.aria-disabled]="sub.disabled ? 'true' : null"
|
|
19129
|
+
[attr.aria-describedby]="sub.hint ? hintId(menu.id, i, j) : null"
|
|
19130
|
+
[attr.title]="sub.hint || null"
|
|
18837
19131
|
(click)="pick(menu, sub)"
|
|
18838
19132
|
>
|
|
18839
19133
|
@if (sub.icon) {
|
|
@@ -18841,6 +19135,9 @@ class StrctMenubar {
|
|
|
18841
19135
|
}
|
|
18842
19136
|
{{ sub.label }}
|
|
18843
19137
|
</button>
|
|
19138
|
+
@if (sub.hint) {
|
|
19139
|
+
<span [id]="hintId(menu.id, i, j)" hidden>{{ sub.hint }}</span>
|
|
19140
|
+
}
|
|
18844
19141
|
}
|
|
18845
19142
|
}
|
|
18846
19143
|
</div>
|
|
@@ -18853,7 +19150,7 @@ class StrctMenubar {
|
|
|
18853
19150
|
</div>
|
|
18854
19151
|
}
|
|
18855
19152
|
</div>
|
|
18856
|
-
`, isInline: true, styles: [".strct-mb{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b1);border-radius:var(--radius-md)}.strct-mb__wrap{position:relative}.strct-mb__top{padding:4px 11px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;cursor:pointer;white-space:nowrap}.strct-mb__top:hover,.strct-mb__top--open{background:var(--bg-3)}.strct-mb__top:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-mb__menu{position:absolute;top:calc(100% + 4px);inset-inline-start:0;z-index:var(--z-dropdown);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}.strct-mb__menu:focus{outline:none}.strct-mb__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;text-align:start;cursor:pointer;white-space:nowrap}.strct-mb__item:hover:not(
|
|
19153
|
+
`, isInline: true, styles: [".strct-mb{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b1);border-radius:var(--radius-md)}.strct-mb__wrap{position:relative}.strct-mb__top{padding:4px 11px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;cursor:pointer;white-space:nowrap}.strct-mb__top:hover,.strct-mb__top--open{background:var(--bg-3)}.strct-mb__top:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-mb__menu{position:absolute;top:calc(100% + 4px);inset-inline-start:0;z-index:var(--z-dropdown);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}.strct-mb__menu:focus{outline:none}.strct-mb__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;text-align:start;cursor:pointer;white-space:nowrap}.strct-mb__item:hover:not([aria-disabled=true]){background:var(--bg-3)}.strct-mb__item--critical{color:var(--critical)}.strct-mb__item--critical:hover:not([aria-disabled=true]){background:var(--critical-bg)}.strct-mb__item[aria-disabled=true]{color:var(--t4);cursor:default}.strct-mb__item:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-mb__divider{height:1px;margin:4px 6px;background:var(--b2)}.strct-mb__row{position:relative}.strct-mb__caret{margin-inline-start:auto;color:var(--t3)}[dir=rtl] .strct-mb__caret{transform:rotate(180deg)}.strct-mb__submenu{position:absolute;top:-5px;inset-inline-start:calc(100% + 2px);z-index:var(--z-base);min-width:160px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}\n"], dependencies: [{ kind: "component", type: StrctIcon, selector: "strct-icon", inputs: ["name", "strictName", "size", "strokeWidth", "badge", "ariaLabel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
|
|
18857
19154
|
}
|
|
18858
19155
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImport: i0, type: StrctMenubar, decorators: [{
|
|
18859
19156
|
type: Component,
|
|
@@ -18895,7 +19192,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18895
19192
|
[class.strct-mb__item--critical]="item.critical"
|
|
18896
19193
|
[attr.aria-haspopup]="item.children?.length ? 'menu' : null"
|
|
18897
19194
|
[attr.aria-expanded]="item.children?.length ? subIdx() === i : null"
|
|
18898
|
-
[disabled]="item.disabled
|
|
19195
|
+
[attr.aria-disabled]="item.disabled ? 'true' : null"
|
|
19196
|
+
[attr.aria-describedby]="item.hint ? hintId(menu.id, i) : null"
|
|
19197
|
+
[attr.title]="item.hint || null"
|
|
18899
19198
|
(click)="onItemClick(menu, item, i)"
|
|
18900
19199
|
(mouseenter)="onItemHover(item, i)"
|
|
18901
19200
|
>
|
|
@@ -18907,9 +19206,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18907
19206
|
<strct-icon class="strct-mb__caret" name="chevronRight" [size]="12" />
|
|
18908
19207
|
}
|
|
18909
19208
|
</button>
|
|
19209
|
+
@if (item.hint) {
|
|
19210
|
+
<span [id]="hintId(menu.id, i)" hidden>{{ item.hint }}</span>
|
|
19211
|
+
}
|
|
18910
19212
|
@if (subIdx() === i && item.children?.length) {
|
|
18911
19213
|
<div class="strct-mb__submenu" role="menu" [attr.aria-label]="item.label">
|
|
18912
|
-
@for (sub of item.children; track $index) {
|
|
19214
|
+
@for (sub of item.children; track $index; let j = $index) {
|
|
18913
19215
|
@if (sub.divider) {
|
|
18914
19216
|
<div class="strct-mb__divider" role="separator"></div>
|
|
18915
19217
|
} @else {
|
|
@@ -18918,7 +19220,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18918
19220
|
class="strct-mb__item strct-mb__subitem"
|
|
18919
19221
|
role="menuitem"
|
|
18920
19222
|
[class.strct-mb__item--critical]="sub.critical"
|
|
18921
|
-
[disabled]="sub.disabled
|
|
19223
|
+
[attr.aria-disabled]="sub.disabled ? 'true' : null"
|
|
19224
|
+
[attr.aria-describedby]="sub.hint ? hintId(menu.id, i, j) : null"
|
|
19225
|
+
[attr.title]="sub.hint || null"
|
|
18922
19226
|
(click)="pick(menu, sub)"
|
|
18923
19227
|
>
|
|
18924
19228
|
@if (sub.icon) {
|
|
@@ -18926,6 +19230,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18926
19230
|
}
|
|
18927
19231
|
{{ sub.label }}
|
|
18928
19232
|
</button>
|
|
19233
|
+
@if (sub.hint) {
|
|
19234
|
+
<span [id]="hintId(menu.id, i, j)" hidden>{{ sub.hint }}</span>
|
|
19235
|
+
}
|
|
18929
19236
|
}
|
|
18930
19237
|
}
|
|
18931
19238
|
</div>
|
|
@@ -18938,7 +19245,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
18938
19245
|
</div>
|
|
18939
19246
|
}
|
|
18940
19247
|
</div>
|
|
18941
|
-
`, styles: [".strct-mb{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b1);border-radius:var(--radius-md)}.strct-mb__wrap{position:relative}.strct-mb__top{padding:4px 11px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;cursor:pointer;white-space:nowrap}.strct-mb__top:hover,.strct-mb__top--open{background:var(--bg-3)}.strct-mb__top:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-mb__menu{position:absolute;top:calc(100% + 4px);inset-inline-start:0;z-index:var(--z-dropdown);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}.strct-mb__menu:focus{outline:none}.strct-mb__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;text-align:start;cursor:pointer;white-space:nowrap}.strct-mb__item:hover:not(
|
|
19248
|
+
`, styles: [".strct-mb{display:inline-flex;gap:2px;padding:2px;background:var(--bg-2);border:1px solid var(--b1);border-radius:var(--radius-md)}.strct-mb__wrap{position:relative}.strct-mb__top{padding:4px 11px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;cursor:pointer;white-space:nowrap}.strct-mb__top:hover,.strct-mb__top--open{background:var(--bg-3)}.strct-mb__top:focus-visible{outline:2px solid var(--acc50);outline-offset:1px}.strct-mb__menu{position:absolute;top:calc(100% + 4px);inset-inline-start:0;z-index:var(--z-dropdown);min-width:180px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}.strct-mb__menu:focus{outline:none}.strct-mb__item{display:flex;align-items:center;gap:8px;width:100%;padding:6px 10px;border:0;border-radius:5px;background:transparent;color:var(--t1);font-family:var(--font);font-size:12.5px;text-align:start;cursor:pointer;white-space:nowrap}.strct-mb__item:hover:not([aria-disabled=true]){background:var(--bg-3)}.strct-mb__item--critical{color:var(--critical)}.strct-mb__item--critical:hover:not([aria-disabled=true]){background:var(--critical-bg)}.strct-mb__item[aria-disabled=true]{color:var(--t4);cursor:default}.strct-mb__item:focus-visible{outline:2px solid var(--acc50);outline-offset:-2px}.strct-mb__divider{height:1px;margin:4px 6px;background:var(--b2)}.strct-mb__row{position:relative}.strct-mb__caret{margin-inline-start:auto;color:var(--t3)}[dir=rtl] .strct-mb__caret{transform:rotate(180deg)}.strct-mb__submenu{position:absolute;top:-5px;inset-inline-start:calc(100% + 2px);z-index:var(--z-base);min-width:160px;padding:4px;background:var(--bg-1);border:1px solid var(--b2);border-radius:var(--radius-md);box-shadow:var(--shh);display:flex;flex-direction:column}\n"] }]
|
|
18942
19249
|
}], propDecorators: { menus: [{ type: i0.Input, args: [{ isSignal: true, alias: "menus", required: true }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], picked: [{ type: i0.Output, args: ["picked"] }], onDocClick: [{
|
|
18943
19250
|
type: HostListener,
|
|
18944
19251
|
args: ['document:click', ['$event']]
|
|
@@ -21573,5 +21880,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.1.4", ngImpor
|
|
|
21573
21880
|
* Generated bundle index. Do not edit.
|
|
21574
21881
|
*/
|
|
21575
21882
|
|
|
21576
|
-
export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChart, StrctCheckbox, StrctChips, StrctCode, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFile, StrctFilterBar, StrctFlow, StrctFooter, StrctGauge, StrctHeader, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLogViewer, StrctLogin, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProgress, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderItem, StrctRowDetailDef, StrctSearchbox, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWizard, StrctWizardAside, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctValidationIcon, strctValidationTone, unlockBodyScroll };
|
|
21883
|
+
export { FOCUSABLE_SELECTOR, STRCT_DP_DOW, STRCT_DP_DOW_FULL, STRCT_DP_MONTHS, STRCT_ICONS, STRCT_ICON_GROUPS, STRCT_ICON_NAMES, STRCT_MASKS, STRCT_NOTIFICATION_HISTORY_LIMIT, STRCT_PALETTES, STRCT_RAW_ICONS, STRCT_TIME_RANGE_PRESETS, STRCT_WIZARD_DEFAULTS, StrctAccordion, StrctAccordionPanel, StrctAlert, StrctAnnouncer, StrctAvatar, StrctBadge, StrctBreadcrumb, StrctBreadcrumbItem, StrctButton, StrctButtonGroup, StrctBytesPipe, StrctCard, StrctCardBlock, StrctCardFooter, StrctCardHeader, StrctCascadeColumn, StrctCascadeHost, StrctCascadeSelect, StrctCellDef, StrctCellStatus, StrctChart, StrctCheckbox, StrctChips, StrctCode, StrctColorPicker, StrctCombobox, StrctCommandPalette, StrctConfirmOutlet, StrctConfirmService, StrctContextMenu, StrctContextMenuTrigger, StrctCopy, StrctDatagrid, StrctDatagridActionBar, StrctDatepicker, StrctDatetimePicker, StrctDesc, StrctDescriptionList, StrctDiff, StrctDivider, StrctDonut, StrctDrawer, StrctDrawerFooter, StrctDropdown, StrctDropdownDivider, StrctDropdownItem, StrctDropdownTrigger, StrctDurationPipe, StrctEmptyState, StrctField, StrctFile, StrctFilterBar, StrctFlow, StrctFooter, StrctGauge, StrctHeader, StrctHeatmap, StrctHero, StrctHotkeysHelp, StrctHotkeysService, StrctIcon, StrctInlineEdit, StrctInput, StrctInputMask, StrctInputOtp, StrctKbd, StrctKnob, StrctLogViewer, StrctLogin, StrctMenuPanel, StrctMenuService, StrctMenubar, StrctMetricTile, StrctModal, StrctModalContent, StrctNav, StrctNavItem, StrctNotificationCenter, StrctNumber, StrctOverlay, StrctPageHeader, StrctPageHeaderActions, StrctPageHeaderCrumbs, StrctPagination, StrctPassword, StrctPopover, StrctPopoverTrigger, StrctProgress, StrctRadio, StrctRadioGroup, StrctRail, StrctRange, StrctRatePipe, StrctRating, StrctReorder, StrctReorderItem, StrctRowDetailDef, StrctSearchbox, StrctSectionMenu, StrctSegmented, StrctSelect, StrctShell, StrctShellService, StrctSiPipe, StrctSignpost, StrctSignpostTrigger, StrctSkeleton, StrctSparkline, StrctSpeedDial, StrctSpinner, StrctSplitButton, StrctSplitter, StrctStack, StrctStackItem, StrctStatusDot, StrctStep, StrctSubmenu, StrctTab, StrctTable, StrctTabs, StrctTag, StrctThemeService, StrctThemeSwitcher, StrctTimeRangePicker, StrctTimeline, StrctTimelineItem, StrctToastOutlet, StrctToastService, StrctToggle, StrctToolbar, StrctToolbarSpacer, StrctTooltip, StrctTour, StrctTransfer, StrctTree, StrctTreeNode, StrctTreeSelect, StrctVerticalNav, StrctWatermark, StrctWizard, StrctWizardAside, focusFirstIn, keepTabInside, lockBodyScroll, parseAnsi, provideStrctWizardDefaults, registerStrctIcon, restoreFocus, saveFocusedElement, strctComputeDiff, strctDpPad, strctFormatBytes, strctFormatDuration, strctFormatRate, strctFormatSi, strctValidationIcon, strctValidationTone, unlockBodyScroll };
|
|
21577
21884
|
//# sourceMappingURL=akcelik-strct.mjs.map
|