@kouji-ui/core 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -3613,6 +3613,18 @@ class KjRovingTabindexItemDirective {
|
|
|
3613
3613
|
/** @internal */
|
|
3614
3614
|
active = signal(false, /* @ts-ignore */
|
|
3615
3615
|
...(ngDevMode ? [{ debugName: "active" }] : /* istanbul ignore next */ []));
|
|
3616
|
+
constructor() {
|
|
3617
|
+
// Registration is by DI, NOT by a content query on the container: a styled
|
|
3618
|
+
// wrapper (`<kj-tab>`) renders its item inside its OWN view, and a content
|
|
3619
|
+
// query cannot cross that boundary. Querying left every item at
|
|
3620
|
+
// tabindex="-1" whenever the wrappers were used — i.e. in every app — so
|
|
3621
|
+
// the tab strip could not be reached by keyboard at all.
|
|
3622
|
+
const parent = inject(KJ_ROVING_TABINDEX, { optional: true });
|
|
3623
|
+
if (!parent)
|
|
3624
|
+
return;
|
|
3625
|
+
parent.register(this);
|
|
3626
|
+
inject(DestroyRef).onDestroy(() => parent.unregister(this));
|
|
3627
|
+
}
|
|
3616
3628
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjRovingTabindexItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3617
3629
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "22.0.5", type: KjRovingTabindexItemDirective, isStandalone: true, selector: "[kjRovingTabindexItem]", host: { properties: { "attr.tabindex": "active() ? \"0\" : \"-1\"" } }, ngImport: i0 });
|
|
3618
3630
|
}
|
|
@@ -3625,7 +3637,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
3625
3637
|
'[attr.tabindex]': 'active() ? "0" : "-1"',
|
|
3626
3638
|
},
|
|
3627
3639
|
}]
|
|
3628
|
-
}] });
|
|
3640
|
+
}], ctorParameters: () => [] });
|
|
3629
3641
|
/**
|
|
3630
3642
|
* Implements the roving tabindex pattern for composite widgets such as toolbars and tab lists.
|
|
3631
3643
|
* Only one item has `tabindex="0"` at a time; arrow keys move focus between items.
|
|
@@ -3643,9 +3655,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
3643
3655
|
*/
|
|
3644
3656
|
class KjRovingTabindex {
|
|
3645
3657
|
host = inject((ElementRef));
|
|
3646
|
-
|
|
3658
|
+
registered = signal([], /* @ts-ignore */
|
|
3659
|
+
...(ngDevMode ? [{ debugName: "registered" }] : /* istanbul ignore next */ []));
|
|
3660
|
+
/** Items in DOM order — registration order follows creation, which a
|
|
3661
|
+
* re-order (`@for` with a changing track) does not preserve. */
|
|
3662
|
+
items = computed(() => [...this.registered()].sort((a, b) => a.el.nativeElement.compareDocumentPosition(b.el.nativeElement) &
|
|
3663
|
+
Node.DOCUMENT_POSITION_FOLLOWING
|
|
3664
|
+
? -1
|
|
3665
|
+
: 1), /* @ts-ignore */
|
|
3666
|
+
...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
3647
3667
|
activeIndex = signal(0, /* @ts-ignore */
|
|
3648
3668
|
...(ngDevMode ? [{ debugName: "activeIndex" }] : /* istanbul ignore next */ []));
|
|
3669
|
+
/** @internal */
|
|
3670
|
+
register(item) {
|
|
3671
|
+
this.registered.update((all) => [...all, item]);
|
|
3672
|
+
}
|
|
3673
|
+
/** @internal */
|
|
3674
|
+
unregister(item) {
|
|
3675
|
+
this.registered.update((all) => all.filter((i) => i !== item));
|
|
3676
|
+
}
|
|
3649
3677
|
/**
|
|
3650
3678
|
* Restricts arrow-key navigation to a single axis.
|
|
3651
3679
|
* - `'horizontal'`: only ArrowLeft / ArrowRight move focus.
|
|
@@ -3726,7 +3754,7 @@ class KjRovingTabindex {
|
|
|
3726
3754
|
all[next].el.nativeElement.focus();
|
|
3727
3755
|
}
|
|
3728
3756
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjRovingTabindex, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
3729
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.
|
|
3757
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjRovingTabindex, isStandalone: true, selector: "[kjRovingTabindex]", inputs: { kjRovingOrientation: { classPropertyName: "kjRovingOrientation", publicName: "kjRovingOrientation", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "keydown": "onKeydown($event)", "focusin": "onFocusIn($event)" } }, providers: [{ provide: KJ_ROVING_TABINDEX, useExisting: forwardRef(() => KjRovingTabindex) }], ngImport: i0 });
|
|
3730
3758
|
}
|
|
3731
3759
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjRovingTabindex, decorators: [{
|
|
3732
3760
|
type: Directive,
|
|
@@ -3739,9 +3767,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
3739
3767
|
'(focusin)': 'onFocusIn($event)',
|
|
3740
3768
|
},
|
|
3741
3769
|
}]
|
|
3742
|
-
}], ctorParameters: () => [], propDecorators: {
|
|
3743
|
-
descendants: true,
|
|
3744
|
-
}, isSignal: true }] }], kjRovingOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRovingOrientation", required: false }] }] } });
|
|
3770
|
+
}], ctorParameters: () => [], propDecorators: { kjRovingOrientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjRovingOrientation", required: false }] }] } });
|
|
3745
3771
|
|
|
3746
3772
|
/**
|
|
3747
3773
|
* Visually hides an element while keeping it accessible to screen readers.
|
|
@@ -13496,8 +13522,23 @@ function nextConfirmPopupMessageId() {
|
|
|
13496
13522
|
* @doc-category Core/Overlay
|
|
13497
13523
|
*/
|
|
13498
13524
|
class KjConfirmPopup {
|
|
13499
|
-
/** The overlay controller
|
|
13500
|
-
|
|
13525
|
+
/** The overlay controller, when the trigger sits on this very element. */
|
|
13526
|
+
selfController = inject(KjOverlayController, { optional: true });
|
|
13527
|
+
/**
|
|
13528
|
+
* The controller of a nested `[kjConfirmPopupTrigger]`. The documented
|
|
13529
|
+
* composition puts the trigger on a CHILD of `[kjConfirmPopup]` (see every
|
|
13530
|
+
* example), so the controller is NOT in this element's injector — without
|
|
13531
|
+
* this registration `close()` bailed out and `(kjConfirmed)` never fired.
|
|
13532
|
+
*/
|
|
13533
|
+
registered = signal(null, /* @ts-ignore */
|
|
13534
|
+
...(ngDevMode ? [{ debugName: "registered" }] : /* istanbul ignore next */ []));
|
|
13535
|
+
/** @internal — called by a nested `[kjConfirmPopupTrigger]`. */
|
|
13536
|
+
_registerController(c) {
|
|
13537
|
+
this.registered.set(c);
|
|
13538
|
+
}
|
|
13539
|
+
controllerOf() {
|
|
13540
|
+
return this.selfController ?? this.registered();
|
|
13541
|
+
}
|
|
13501
13542
|
/** When `true`, the confirm action renders with destructive intent. */
|
|
13502
13543
|
kjDestructive = input(false, { ...(ngDevMode ? { debugName: "kjDestructive" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
13503
13544
|
/** Where to place initial focus. Default `'cancel'`. */
|
|
@@ -13511,10 +13552,8 @@ class KjConfirmPopup {
|
|
|
13511
13552
|
kjResult = output();
|
|
13512
13553
|
// ── KjConfirmPopupContext ──────────────────────────────────────────
|
|
13513
13554
|
/** Open state forwarded from the underlying controller. */
|
|
13514
|
-
open = (() =>
|
|
13515
|
-
|
|
13516
|
-
return ctrl ? ctrl.isOpen : (() => false);
|
|
13517
|
-
})();
|
|
13555
|
+
open = computed(() => this.controllerOf()?.isOpen() ?? false, /* @ts-ignore */
|
|
13556
|
+
...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
|
|
13518
13557
|
/** Whether the confirm action should render destructively. */
|
|
13519
13558
|
destructive = this.kjDestructive;
|
|
13520
13559
|
/** Resolved default focus target. */
|
|
@@ -13526,7 +13565,7 @@ class KjConfirmPopup {
|
|
|
13526
13565
|
constructor() {
|
|
13527
13566
|
// Bridge the controller's open signal into the resolution contract.
|
|
13528
13567
|
effect(() => {
|
|
13529
|
-
const isOpen = this.
|
|
13568
|
+
const isOpen = this.controllerOf()?.isOpen() ?? false;
|
|
13530
13569
|
if (isOpen && !this.wasOpen) {
|
|
13531
13570
|
this.resolved = false;
|
|
13532
13571
|
}
|
|
@@ -13542,7 +13581,8 @@ class KjConfirmPopup {
|
|
|
13542
13581
|
* Close the popup with the given result. `true` confirms, `false` cancels.
|
|
13543
13582
|
*/
|
|
13544
13583
|
close(result) {
|
|
13545
|
-
|
|
13584
|
+
const controller = this.controllerOf();
|
|
13585
|
+
if (!controller || !controller.isOpen())
|
|
13546
13586
|
return;
|
|
13547
13587
|
this.resolved = true;
|
|
13548
13588
|
if (result)
|
|
@@ -13550,7 +13590,7 @@ class KjConfirmPopup {
|
|
|
13550
13590
|
else
|
|
13551
13591
|
this.kjCancelled.emit();
|
|
13552
13592
|
this.kjResult.emit(result);
|
|
13553
|
-
|
|
13593
|
+
controller.close('programmatic');
|
|
13554
13594
|
}
|
|
13555
13595
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: KjConfirmPopup, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
13556
13596
|
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: KjConfirmPopup, isStandalone: true, selector: "[kjConfirmPopup]", inputs: { kjDestructive: { classPropertyName: "kjDestructive", publicName: "kjDestructive", isSignal: true, isRequired: false, transformFunction: null }, kjDefaultFocus: { classPropertyName: "kjDefaultFocus", publicName: "kjDefaultFocus", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { kjConfirmed: "kjConfirmed", kjCancelled: "kjCancelled", kjResult: "kjResult" }, providers: [
|
|
@@ -13578,6 +13618,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
13578
13618
|
*/
|
|
13579
13619
|
class KjConfirmPopupTrigger {
|
|
13580
13620
|
_overlayTrigger = inject(KjOverlayTrigger, { self: true });
|
|
13621
|
+
constructor() {
|
|
13622
|
+
// The trigger normally sits on a CHILD of `[kjConfirmPopup]`, so the root
|
|
13623
|
+
// cannot see this controller through its own injector. Hand it over, or
|
|
13624
|
+
// the confirm/cancel slots resolve nothing.
|
|
13625
|
+
inject(KJ_CONFIRM_POPUP, { optional: true })?._registerController?.(this._overlayTrigger.controller);
|
|
13626
|
+
}
|
|
13581
13627
|
/** Forwarded controller for sibling `[kjFor]` panels. */
|
|
13582
13628
|
get controller() {
|
|
13583
13629
|
return this._overlayTrigger.controller;
|
|
@@ -13596,7 +13642,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
13596
13642
|
exportAs: 'kjConfirmPopupTrigger',
|
|
13597
13643
|
hostDirectives: [KjPopoverTrigger],
|
|
13598
13644
|
}]
|
|
13599
|
-
}] });
|
|
13645
|
+
}], ctorParameters: () => [] });
|
|
13600
13646
|
|
|
13601
13647
|
/**
|
|
13602
13648
|
* The floating confirm popup panel. Composes `kj-popover-content` (a
|
|
@@ -15550,12 +15596,20 @@ class KjCommandPalette {
|
|
|
15550
15596
|
}
|
|
15551
15597
|
});
|
|
15552
15598
|
});
|
|
15553
|
-
//
|
|
15599
|
+
// Re-seed when the visible set changes under the active item: items may
|
|
15600
|
+
// register asynchronously (nothing highlighted yet), and with
|
|
15601
|
+
// `[kjShouldFilter]="false"` the consumer re-renders the list AFTER the
|
|
15602
|
+
// query effect above ran — so that effect highlighted an item that is
|
|
15603
|
+
// already gone. Without the `some()` check the palette kept a stale value,
|
|
15604
|
+
// no row was active, and Enter did nothing (reproducible by typing fast
|
|
15605
|
+
// or pasting a query).
|
|
15554
15606
|
effect(() => {
|
|
15555
15607
|
const visible = this.visibleItems();
|
|
15556
15608
|
const active = this.kjValue();
|
|
15557
15609
|
const autoFirst = this.kjAutoActivateFirst();
|
|
15558
|
-
if (!autoFirst || visible.length === 0
|
|
15610
|
+
if (!autoFirst || visible.length === 0)
|
|
15611
|
+
return;
|
|
15612
|
+
if (active !== null && visible.some(i => i.value() === active))
|
|
15559
15613
|
return;
|
|
15560
15614
|
untracked(() => {
|
|
15561
15615
|
const nav = this._nav();
|