@kouji-ui/core 0.9.0 → 0.9.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.
- package/fesm2022/kouji-ui-core.mjs +173 -42
- package/fesm2022/kouji-ui-core.mjs.map +1 -1
- package/package.json +1 -1
- package/types/kouji-ui-core.d.ts +20 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, input, booleanAttribute, Directive, PLATFORM_ID, signal, DestroyRef, Injectable, ElementRef, afterNextRender, forwardRef, InjectionToken, Injector, computed, effect,
|
|
2
|
+
import { inject, input, booleanAttribute, Directive, PLATFORM_ID, signal, DestroyRef, Injectable, ElementRef, afterNextRender, untracked, forwardRef, InjectionToken, Injector, computed, effect, viewChild, ViewContainerRef, ViewEncapsulation, ChangeDetectionStrategy, Component, ApplicationRef, EnvironmentInjector, createComponent, model, isSignal, DOCUMENT as DOCUMENT$1, output, numberAttribute, afterRenderEffect, contentChildren, makeEnvironmentProviders, LOCALE_ID, provideEnvironmentInitializer, contentChild, linkedSignal, PendingTasks, TemplateRef, runInInjectionContext, resource } from '@angular/core';
|
|
3
3
|
import { DOCUMENT, isPlatformBrowser } from '@angular/common';
|
|
4
4
|
import { NG_VALUE_ACCESSOR, NG_VALIDATORS, NgForm, FormGroupDirective, FormGroup, FormArray } from '@angular/forms';
|
|
5
5
|
import { Subject } from 'rxjs';
|
|
@@ -282,10 +282,13 @@ class KjFocusRing {
|
|
|
282
282
|
afterNextRender(() => {
|
|
283
283
|
if (!isPlatformBrowser(this.platformId))
|
|
284
284
|
return;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
285
|
+
// `focus` / `blur` can fire synchronously while Angular renders — a
|
|
286
|
+
// focused element that a binding disables or removes blurs at once in
|
|
287
|
+
// Chromium — and a raw listener inherits the template's reactive
|
|
288
|
+
// context, where a signal write throws NG0600. `untracked` runs the
|
|
289
|
+
// handlers outside it (Angular's own listeners do the same).
|
|
290
|
+
const onFocus = () => untracked(() => this._focusVisible.set(this.inputModality.modality() === 'keyboard'));
|
|
291
|
+
const onBlur = () => untracked(() => this._focusVisible.set(false));
|
|
289
292
|
const releaseModality = this.inputModality.retain();
|
|
290
293
|
this.el.nativeElement.addEventListener('focus', onFocus);
|
|
291
294
|
this.el.nativeElement.addEventListener('blur', onBlur);
|
|
@@ -1971,6 +1974,21 @@ function longestRunMs(durations, delays) {
|
|
|
1971
1974
|
}
|
|
1972
1975
|
/** The strategy slots of a bundle, in attach order. */
|
|
1973
1976
|
const STRATEGY_SLOTS = ['mount', 'position', 'backdrop', 'scrollLock', 'focusTrap', 'liveAnnouncer', 'trigger'];
|
|
1977
|
+
/**
|
|
1978
|
+
* The controller each attached strategy instance serves. A strategy is
|
|
1979
|
+
* stateful (it holds one overlay's context and its inert / scroll-lock
|
|
1980
|
+
* release handles), so one instance must never run two overlays at once.
|
|
1981
|
+
*/
|
|
1982
|
+
const strategyOwners = new WeakMap();
|
|
1983
|
+
/**
|
|
1984
|
+
* @internal The controller `strategy` is attached to, if any. `KjOverlayPanel`
|
|
1985
|
+
* uses it to drop strategies it inherited from an enclosing overlay (a
|
|
1986
|
+
* select inside a modal dialog must not run the dialog's scrim, inert and
|
|
1987
|
+
* focus trap as its own).
|
|
1988
|
+
*/
|
|
1989
|
+
function overlayStrategyOwner(strategy) {
|
|
1990
|
+
return strategyOwners.get(strategy);
|
|
1991
|
+
}
|
|
1974
1992
|
/**
|
|
1975
1993
|
* Owns the overlay's open/closed state machine plus the rAF/transition
|
|
1976
1994
|
* orchestration. Strategies (mount/position/backdrop/focus-trap/scroll-lock/
|
|
@@ -2122,13 +2140,21 @@ class KjOverlayController {
|
|
|
2122
2140
|
}
|
|
2123
2141
|
for (const slot of STRATEGY_SLOTS) {
|
|
2124
2142
|
const old = prev[slot];
|
|
2125
|
-
if (old && old !== next[slot])
|
|
2143
|
+
if (old && old !== next[slot]) {
|
|
2126
2144
|
old.detach();
|
|
2145
|
+
if (strategyOwners.get(old) === this)
|
|
2146
|
+
strategyOwners.delete(old);
|
|
2147
|
+
}
|
|
2127
2148
|
}
|
|
2128
2149
|
}
|
|
2129
2150
|
this.strategies = next;
|
|
2130
|
-
for (const slot of STRATEGY_SLOTS)
|
|
2131
|
-
next[slot]
|
|
2151
|
+
for (const slot of STRATEGY_SLOTS) {
|
|
2152
|
+
const strategy = next[slot];
|
|
2153
|
+
if (!strategy)
|
|
2154
|
+
continue;
|
|
2155
|
+
strategyOwners.set(strategy, this);
|
|
2156
|
+
strategy.attach(this.context);
|
|
2157
|
+
}
|
|
2132
2158
|
}
|
|
2133
2159
|
open() {
|
|
2134
2160
|
const cur = this._state();
|
|
@@ -2195,7 +2221,12 @@ class KjOverlayController {
|
|
|
2195
2221
|
return;
|
|
2196
2222
|
const s = this.strategies;
|
|
2197
2223
|
for (const slot of [...STRATEGY_SLOTS].reverse()) {
|
|
2198
|
-
s[slot]
|
|
2224
|
+
const strategy = s[slot];
|
|
2225
|
+
if (!strategy)
|
|
2226
|
+
continue;
|
|
2227
|
+
strategy.detach();
|
|
2228
|
+
if (strategyOwners.get(strategy) === this)
|
|
2229
|
+
strategyOwners.delete(strategy);
|
|
2199
2230
|
}
|
|
2200
2231
|
this.strategies = null;
|
|
2201
2232
|
}
|
|
@@ -2908,6 +2939,36 @@ function resolveTokens(self) {
|
|
|
2908
2939
|
role: inject(KJ_OVERLAY_PANEL_ROLE, opts),
|
|
2909
2940
|
};
|
|
2910
2941
|
}
|
|
2942
|
+
/**
|
|
2943
|
+
* `tokens` minus every strategy already attached to a controller other than
|
|
2944
|
+
* `controller`. Strategies are resolved through the injector chain, so an
|
|
2945
|
+
* overlay rendered inside another one (a select, combobox or date picker in
|
|
2946
|
+
* a service-launched dialog) would otherwise find the enclosing overlay's
|
|
2947
|
+
* own instances for every slot it does not provide itself — and run the
|
|
2948
|
+
* dialog's scrim, `inert` and focus trap as if the dropdown were a second
|
|
2949
|
+
* modal, freezing the dialog it belongs to. Those instances belong to the
|
|
2950
|
+
* enclosing overlay; the nested one falls back to "none" for that slot.
|
|
2951
|
+
*/
|
|
2952
|
+
function withoutForeign(tokens, controller) {
|
|
2953
|
+
if (!controller)
|
|
2954
|
+
return tokens;
|
|
2955
|
+
const mine = (s) => {
|
|
2956
|
+
if (!s)
|
|
2957
|
+
return s;
|
|
2958
|
+
const owner = overlayStrategyOwner(s);
|
|
2959
|
+
return owner && owner !== controller ? null : s;
|
|
2960
|
+
};
|
|
2961
|
+
return {
|
|
2962
|
+
...tokens,
|
|
2963
|
+
mount: mine(tokens.mount),
|
|
2964
|
+
position: mine(tokens.position),
|
|
2965
|
+
backdrop: mine(tokens.backdrop),
|
|
2966
|
+
focusTrap: mine(tokens.focusTrap),
|
|
2967
|
+
scrollLock: mine(tokens.scrollLock),
|
|
2968
|
+
liveAnnouncer: mine(tokens.liveAnnouncer),
|
|
2969
|
+
trigger: mine(tokens.trigger),
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2911
2972
|
/**
|
|
2912
2973
|
* Marks an element as the overlay's panel — wires it to the controller,
|
|
2913
2974
|
* resolves the panel role/aria-modal, and binds DOM state attributes
|
|
@@ -2922,7 +2983,10 @@ function resolveTokens(self) {
|
|
|
2922
2983
|
* must not inherit the dialog's scroll lock, scrim or `alertdialog` role.
|
|
2923
2984
|
* A panel whose controller is on its host chain (a builder-launched body,
|
|
2924
2985
|
* or the root pattern where one directive provides controller and
|
|
2925
|
-
* strategies for the whole subtree) reads them from that chain
|
|
2986
|
+
* strategies for the whole subtree) reads them from that chain, minus any
|
|
2987
|
+
* strategy instance an enclosing overlay is already running: a select inside
|
|
2988
|
+
* a service-launched dialog finds the dialog's scrim, focus trap and scroll
|
|
2989
|
+
* lock up the chain, and must not adopt them.
|
|
2926
2990
|
*
|
|
2927
2991
|
* A portalled panel whose scope provides a backdrop strategy also gets a
|
|
2928
2992
|
* real `<kj-backdrop>` scrim (created next to the panel, moved into the
|
|
@@ -2977,8 +3041,11 @@ class KjOverlayPanel {
|
|
|
2977
3041
|
return !!t && t.controller !== this.hostController;
|
|
2978
3042
|
}, /* @ts-ignore */
|
|
2979
3043
|
...(ngDevMode ? [{ debugName: "scoped" }] : /* istanbul ignore next */ []));
|
|
2980
|
-
/**
|
|
2981
|
-
|
|
3044
|
+
/**
|
|
3045
|
+
* The tokens that apply to this panel. Inherited ones exclude strategies an
|
|
3046
|
+
* enclosing overlay already runs (see {@link withoutForeign}).
|
|
3047
|
+
*/
|
|
3048
|
+
tokens = computed(() => this.scoped() ? this.own : withoutForeign(this.inherited, this.hostController), /* @ts-ignore */
|
|
2982
3049
|
...(ngDevMode ? [{ debugName: "tokens" }] : /* istanbul ignore next */ []));
|
|
2983
3050
|
role = computed(() => this.tokens().role ?? 'dialog', /* @ts-ignore */
|
|
2984
3051
|
...(ngDevMode ? [{ debugName: "role" }] : /* istanbul ignore next */ []));
|
|
@@ -3105,7 +3172,9 @@ function releaseInert(el) {
|
|
|
3105
3172
|
* Makes everything behind a modal `panel` inert: every child of `<body>`
|
|
3106
3173
|
* outside the overlay container (except script/style nodes and live
|
|
3107
3174
|
* regions), plus every overlay wrapper opened before the panel's own — a
|
|
3108
|
-
* dialog stacked on a dialog freezes the one below.
|
|
3175
|
+
* dialog stacked on a dialog freezes the one below. The container itself is
|
|
3176
|
+
* never inerted, even for a panel mounted outside it, so overlays the modal
|
|
3177
|
+
* opens afterwards (dropdowns, pickers) stay usable. A body child that
|
|
3109
3178
|
* contains the panel (an inline-mounted modal) is left alone, because
|
|
3110
3179
|
* inerting it would inert the panel itself.
|
|
3111
3180
|
*
|
|
@@ -3117,10 +3186,19 @@ function inertSiblingsOf(panel) {
|
|
|
3117
3186
|
const body = panel.ownerDocument?.body;
|
|
3118
3187
|
if (!body)
|
|
3119
3188
|
return () => { };
|
|
3120
|
-
|
|
3189
|
+
// Overlay roots are never inerted, whether or not the panel lives in one.
|
|
3190
|
+
// An inline-mounted (`inPlace`) modal sits outside the root, yet the
|
|
3191
|
+
// overlays it opens — a select, combobox or date picker dropdown — mount
|
|
3192
|
+
// into it after the modal opened: inerting the root would freeze them. The
|
|
3193
|
+
// wrappers open at this point (below the modal) are frozen one by one
|
|
3194
|
+
// instead; later ones stay live.
|
|
3195
|
+
const containers = Array.from(body.children).filter(isOverlayContainer);
|
|
3196
|
+
const own = panel.closest('.kj-overlay-container');
|
|
3197
|
+
if (own && !containers.includes(own))
|
|
3198
|
+
containers.push(own);
|
|
3121
3199
|
const targets = [];
|
|
3122
3200
|
for (const child of Array.from(body.children)) {
|
|
3123
|
-
if (child
|
|
3201
|
+
if (isOverlayContainer(child))
|
|
3124
3202
|
continue;
|
|
3125
3203
|
if (child.contains(panel))
|
|
3126
3204
|
continue;
|
|
@@ -3130,12 +3208,13 @@ function inertSiblingsOf(panel) {
|
|
|
3130
3208
|
continue;
|
|
3131
3209
|
targets.push(child);
|
|
3132
3210
|
}
|
|
3133
|
-
|
|
3134
|
-
const
|
|
3211
|
+
for (const container of containers) {
|
|
3212
|
+
const ownWrapper = Array.from(container.children).find((w) => w.contains(panel));
|
|
3135
3213
|
for (const wrapper of Array.from(container.children)) {
|
|
3136
|
-
if (wrapper ===
|
|
3214
|
+
if (wrapper === ownWrapper)
|
|
3137
3215
|
continue;
|
|
3138
|
-
const below = !
|
|
3216
|
+
const below = !ownWrapper ||
|
|
3217
|
+
!!(wrapper.compareDocumentPosition(ownWrapper) & Node.DOCUMENT_POSITION_FOLLOWING);
|
|
3139
3218
|
if (below)
|
|
3140
3219
|
targets.push(wrapper);
|
|
3141
3220
|
}
|
|
@@ -3151,6 +3230,10 @@ function inertSiblingsOf(panel) {
|
|
|
3151
3230
|
releaseInert(el);
|
|
3152
3231
|
};
|
|
3153
3232
|
}
|
|
3233
|
+
/** Whether `el` is an overlay root (`getOverlayContainer()`'s element, or a look-alike). */
|
|
3234
|
+
function isOverlayContainer(el) {
|
|
3235
|
+
return (el.hasAttribute('data-kj-overlay-container') || el.classList.contains('kj-overlay-container'));
|
|
3236
|
+
}
|
|
3154
3237
|
|
|
3155
3238
|
/**
|
|
3156
3239
|
* Mount strategy for declarative overlays whose panel is rendered inline
|
|
@@ -4515,6 +4598,9 @@ const read$2 = (v, fallback) => {
|
|
|
4515
4598
|
* do not bubble, and elements with `display: contents` (e.g. `<kj-button>`)
|
|
4516
4599
|
* never receive these events because they have no rendered box. Walk to the
|
|
4517
4600
|
* first descendant with a layout box.
|
|
4601
|
+
*
|
|
4602
|
+
* Measures, so it forces a layout: call it only on a hover, never on attach —
|
|
4603
|
+
* a table with a hover trigger per row would otherwise lay out once per row.
|
|
4518
4604
|
*/
|
|
4519
4605
|
const effectiveHoverTarget = (el) => {
|
|
4520
4606
|
if (!el.ownerDocument?.defaultView)
|
|
@@ -4542,7 +4628,9 @@ function onHover(initialOpts = {}) {
|
|
|
4542
4628
|
let openTimer = 0, closeTimer = 0;
|
|
4543
4629
|
let onEnter = null;
|
|
4544
4630
|
let onLeave = null;
|
|
4545
|
-
let
|
|
4631
|
+
let onFirstOver = null;
|
|
4632
|
+
let triggerTarget = null;
|
|
4633
|
+
let boxTarget = null;
|
|
4546
4634
|
let panelTarget = null;
|
|
4547
4635
|
const cancelClose = () => {
|
|
4548
4636
|
if (closeTimer) {
|
|
@@ -4584,11 +4672,12 @@ function onHover(initialOpts = {}) {
|
|
|
4584
4672
|
const trigger = ctx.triggerEl();
|
|
4585
4673
|
if (!trigger || onEnter)
|
|
4586
4674
|
return;
|
|
4587
|
-
listenTarget = effectiveHoverTarget(trigger);
|
|
4588
4675
|
onEnter = () => {
|
|
4589
4676
|
cancelClose();
|
|
4590
4677
|
wirePanel();
|
|
4591
|
-
|
|
4678
|
+
// The first hover can reach here twice (the bubbled `pointerover` that
|
|
4679
|
+
// resolves the box target, then that target's own `pointerenter`).
|
|
4680
|
+
if (ctx?.isOpen() || openTimer)
|
|
4592
4681
|
return;
|
|
4593
4682
|
openTimer = setTimeout(() => {
|
|
4594
4683
|
openTimer = 0;
|
|
@@ -4602,8 +4691,27 @@ function onHover(initialOpts = {}) {
|
|
|
4602
4691
|
wirePanel();
|
|
4603
4692
|
scheduleClose();
|
|
4604
4693
|
};
|
|
4605
|
-
|
|
4606
|
-
|
|
4694
|
+
// Nothing is measured here. The trigger listens directly (enough when it
|
|
4695
|
+
// has a box); a `display: contents` trigger only sees the bubbled
|
|
4696
|
+
// `pointerover` of a descendant, so the first one resolves — and measures,
|
|
4697
|
+
// once — the descendant that actually receives enter / leave.
|
|
4698
|
+
onFirstOver = () => {
|
|
4699
|
+
if (!onEnter || !onLeave || !triggerTarget)
|
|
4700
|
+
return;
|
|
4701
|
+
triggerTarget.removeEventListener('pointerover', onFirstOver);
|
|
4702
|
+
onFirstOver = null;
|
|
4703
|
+
const target = effectiveHoverTarget(triggerTarget);
|
|
4704
|
+
if (target !== triggerTarget) {
|
|
4705
|
+
boxTarget = target;
|
|
4706
|
+
target.addEventListener('pointerenter', onEnter);
|
|
4707
|
+
target.addEventListener('pointerleave', onLeave);
|
|
4708
|
+
}
|
|
4709
|
+
onEnter();
|
|
4710
|
+
};
|
|
4711
|
+
triggerTarget = trigger;
|
|
4712
|
+
trigger.addEventListener('pointerenter', onEnter);
|
|
4713
|
+
trigger.addEventListener('pointerleave', onLeave);
|
|
4714
|
+
trigger.addEventListener('pointerover', onFirstOver);
|
|
4607
4715
|
};
|
|
4608
4716
|
return {
|
|
4609
4717
|
ariaHasPopup: null,
|
|
@@ -4618,10 +4726,16 @@ function onHover(initialOpts = {}) {
|
|
|
4618
4726
|
onOpen() { },
|
|
4619
4727
|
onClose() { },
|
|
4620
4728
|
detach() {
|
|
4621
|
-
|
|
4622
|
-
|
|
4623
|
-
|
|
4624
|
-
|
|
4729
|
+
for (const el of [triggerTarget, boxTarget]) {
|
|
4730
|
+
if (!el)
|
|
4731
|
+
continue;
|
|
4732
|
+
if (onEnter)
|
|
4733
|
+
el.removeEventListener('pointerenter', onEnter);
|
|
4734
|
+
if (onLeave)
|
|
4735
|
+
el.removeEventListener('pointerleave', onLeave);
|
|
4736
|
+
}
|
|
4737
|
+
if (triggerTarget && onFirstOver)
|
|
4738
|
+
triggerTarget.removeEventListener('pointerover', onFirstOver);
|
|
4625
4739
|
if (panelTarget) {
|
|
4626
4740
|
panelTarget.removeEventListener('pointerenter', cancelClose);
|
|
4627
4741
|
panelTarget.removeEventListener('pointerleave', scheduleClose);
|
|
@@ -4630,8 +4744,8 @@ function onHover(initialOpts = {}) {
|
|
|
4630
4744
|
clearTimeout(openTimer);
|
|
4631
4745
|
if (closeTimer)
|
|
4632
4746
|
clearTimeout(closeTimer);
|
|
4633
|
-
onEnter = onLeave = null;
|
|
4634
|
-
|
|
4747
|
+
onEnter = onLeave = onFirstOver = null;
|
|
4748
|
+
triggerTarget = boxTarget = null;
|
|
4635
4749
|
panelTarget = null;
|
|
4636
4750
|
openTimer = closeTimer = 0;
|
|
4637
4751
|
toggle = null;
|
|
@@ -22495,7 +22609,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
22495
22609
|
}]
|
|
22496
22610
|
}], propDecorators: { kjCell: [{ type: i0.Input, args: [{ isSignal: true, alias: "kjCell", required: true }] }] } });
|
|
22497
22611
|
|
|
22498
|
-
/** `Node.DOCUMENT_POSITION_PRECEDING
|
|
22612
|
+
/** `Node.DOCUMENT_POSITION_PRECEDING`, inlined so the module never touches the `Node` global. */
|
|
22499
22613
|
const DOCUMENT_POSITION_PRECEDING = 2;
|
|
22500
22614
|
/** Text-entry controls whose own arrow / Home / End handling must win over grid navigation. */
|
|
22501
22615
|
const TEXT_ENTRY_SELECTOR = 'input:not([type="button"]):not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="reset"]), textarea, select, [contenteditable]:not([contenteditable="false"])';
|
|
@@ -22533,23 +22647,32 @@ class KjTableKeyboardNav {
|
|
|
22533
22647
|
/** Id of the cell the user focused last; survives the cell leaving the DOM. */
|
|
22534
22648
|
activeId = signal(null, /* @ts-ignore */
|
|
22535
22649
|
...(ngDevMode ? [{ debugName: "activeId" }] : /* istanbul ignore next */ []));
|
|
22650
|
+
/** Tab stop resolved after the last render (see {@link tabStopId}). */
|
|
22651
|
+
resolvedStopId = signal(null, /* @ts-ignore */
|
|
22652
|
+
...(ngDevMode ? [{ debugName: "resolvedStopId" }] : /* istanbul ignore next */ []));
|
|
22536
22653
|
/**
|
|
22537
22654
|
* Id of the cell that owns `tabindex="0"`: the last focused cell while it
|
|
22538
22655
|
* is rendered, else the first rendered cell in DOM order.
|
|
22656
|
+
*
|
|
22657
|
+
* Every cell reads this, so it must not touch the `cells` query: each
|
|
22658
|
+
* stamped cell view dirties the query, and a per-cell read would re-collect
|
|
22659
|
+
* it and re-sort the DOM once per cell — O(n²) for an n-cell body. It is
|
|
22660
|
+
* resolved once per render instead, after the cells are in the DOM. Until
|
|
22661
|
+
* then (and on the server) no cell is a Tab stop.
|
|
22539
22662
|
*/
|
|
22540
|
-
tabStopId =
|
|
22541
|
-
|
|
22542
|
-
|
|
22543
|
-
|
|
22544
|
-
|
|
22545
|
-
|
|
22546
|
-
|
|
22547
|
-
|
|
22548
|
-
}, /* @ts-ignore */
|
|
22549
|
-
...(ngDevMode ? [{ debugName: "tabStopId" }] : /* istanbul ignore next */ []));
|
|
22663
|
+
tabStopId = this.resolvedStopId.asReadonly();
|
|
22664
|
+
constructor() {
|
|
22665
|
+
afterRenderEffect(() => {
|
|
22666
|
+
const cells = this.cells();
|
|
22667
|
+
const active = this.activeId();
|
|
22668
|
+
this.resolvedStopId.set(resolveTabStop(cells, active));
|
|
22669
|
+
});
|
|
22670
|
+
}
|
|
22550
22671
|
/** Record `cellId` as the last focused cell. @param cellId TanStack `cell.id`. */
|
|
22551
22672
|
setActive(cellId) {
|
|
22552
22673
|
this.activeId.set(cellId);
|
|
22674
|
+
// A cell that just took focus is rendered: it is the Tab stop right away.
|
|
22675
|
+
this.resolvedStopId.set(cellId);
|
|
22553
22676
|
}
|
|
22554
22677
|
onKeyDown(event) {
|
|
22555
22678
|
if (event.defaultPrevented)
|
|
@@ -22651,7 +22774,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImpor
|
|
|
22651
22774
|
providers: [{ provide: KJ_TABLE_KEYBOARD_NAV, useExisting: KjTableKeyboardNav }],
|
|
22652
22775
|
host: { '(keydown)': 'onKeyDown($event)' },
|
|
22653
22776
|
}]
|
|
22654
|
-
}], propDecorators: { cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KjTableCell), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
22777
|
+
}], ctorParameters: () => [], propDecorators: { cells: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => KjTableCell), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
22778
|
+
/** The active cell while it is rendered, else the first rendered cell in DOM order. */
|
|
22779
|
+
function resolveTabStop(cells, active) {
|
|
22780
|
+
if (cells.length === 0)
|
|
22781
|
+
return null;
|
|
22782
|
+
if (active !== null && cells.some((c) => c.cellId() === active))
|
|
22783
|
+
return active;
|
|
22784
|
+
return firstInDomOrder(cells).cellId();
|
|
22785
|
+
}
|
|
22655
22786
|
/**
|
|
22656
22787
|
* The first cell in DOM order. Query results follow declaration order, which
|
|
22657
22788
|
* a row template stamped into several bodies (pinned top, centre, pinned
|