@koobiq/components 20.3.3 → 20.4.1
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/core/index.d.ts +114 -6
- package/core/option/_option-theme.scss +3 -0
- package/ellipsis-center/ellipsis-center.scss +31 -0
- package/ellipsis-center/index.d.ts +3 -3
- package/fesm2022/koobiq-components-core.mjs +173 -16
- package/fesm2022/koobiq-components-core.mjs.map +1 -1
- package/fesm2022/koobiq-components-ellipsis-center.mjs +27 -15
- package/fesm2022/koobiq-components-ellipsis-center.mjs.map +1 -1
- package/fesm2022/koobiq-components-file-upload.mjs +4 -4
- package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
- package/fesm2022/koobiq-components-filter-bar.mjs +36 -32
- package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-inline-edit.mjs +177 -14
- package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
- package/fesm2022/koobiq-components-list.mjs +357 -42
- package/fesm2022/koobiq-components-list.mjs.map +1 -1
- package/fesm2022/koobiq-components-navbar.mjs +5 -1
- package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
- package/fesm2022/koobiq-components-search-expandable.mjs +2 -1
- package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
- package/fesm2022/koobiq-components-select.mjs +20 -2
- package/fesm2022/koobiq-components-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-tabs.mjs +453 -196
- package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
- package/fesm2022/koobiq-components-timezone.mjs +2 -2
- package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
- package/file-upload/file-upload.scss +0 -29
- package/filter-bar/index.d.ts +16 -0
- package/filter-bar/pipes/base-pipe.scss +11 -0
- package/inline-edit/index.d.ts +87 -8
- package/inline-edit/inline-edit-tokens.scss +1 -0
- package/inline-edit/inline-edit.scss +26 -0
- package/list/index.d.ts +126 -5
- package/navbar/index.d.ts +5 -1
- package/package.json +3 -3
- package/schematics/ng-add/index.js +1 -1
- package/select/index.d.ts +6 -0
- package/tabs/_tabs-common.scss +111 -2
- package/tabs/index.d.ts +78 -48
- package/tabs/tab-group.scss +0 -4
- package/tabs/tab-header.scss +0 -2
- package/tabs/tab-nav-bar.scss +3 -11
package/inline-edit/index.d.ts
CHANGED
|
@@ -1,14 +1,46 @@
|
|
|
1
|
+
import * as _koobiq_components_core from '@koobiq/components/core';
|
|
2
|
+
import { KbqConnectedOverlayOriginProvider, PopUpPlacements, KbqComponentColors } from '@koobiq/components/core';
|
|
1
3
|
import * as _angular_core from '@angular/core';
|
|
2
|
-
import { ElementRef, TemplateRef } from '@angular/core';
|
|
4
|
+
import { InjectionToken, ElementRef, TemplateRef } from '@angular/core';
|
|
3
5
|
import { ScrollStrategy, CdkConnectedOverlay } from '@angular/cdk/overlay';
|
|
4
|
-
import { KbqConnectedOverlayOriginProvider, PopUpPlacements, KbqComponentColors } from '@koobiq/components/core';
|
|
5
6
|
import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
|
|
6
7
|
import { KbqLabel, KbqFormField } from '@koobiq/components/form-field';
|
|
7
8
|
import { KbqSelect } from '@koobiq/components/select';
|
|
8
9
|
import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
|
|
10
|
+
import { Observable } from 'rxjs';
|
|
9
11
|
import * as i1 from '@angular/cdk/a11y';
|
|
10
12
|
|
|
13
|
+
/** Delay before the save progress state appears, so a fast response causes no flicker. */
|
|
14
|
+
declare const kbqInlineEditSaveProgressDelay = 100;
|
|
15
|
+
/** Minimum time the save progress state stays once it has appeared. */
|
|
16
|
+
declare const kbqInlineEditSaveProgressMinimumDuration = 300;
|
|
11
17
|
type KbqInlineEditMode = 'view' | 'edit';
|
|
18
|
+
/**
|
|
19
|
+
* Saves the edited value, e.g. sends it to a server. Only the first emission counts, and the observable must emit
|
|
20
|
+
* or complete: destroying the row does not cancel it, so one that never settles keeps the row in memory.
|
|
21
|
+
*
|
|
22
|
+
* Called without a receiver, so bind an arrow function rather than a method that relies on `this`.
|
|
23
|
+
*/
|
|
24
|
+
type KbqInlineEditSaveHandler = () => Observable<unknown>;
|
|
25
|
+
/** State of the save request started by `saveHandler`. `progress` is `pending` past the indicator delay. */
|
|
26
|
+
type KbqInlineEditSaveStatus = 'idle' | 'pending' | 'progress' | 'error';
|
|
27
|
+
/** Recovery a failed-save notification can offer: retry, edit again, discard the unsaved value. */
|
|
28
|
+
interface KbqInlineEditSaveRecovery {
|
|
29
|
+
retrySave(): void;
|
|
30
|
+
toggleMode(): void;
|
|
31
|
+
rollback(): void;
|
|
32
|
+
}
|
|
33
|
+
/** Failed save, reported through `saveError` and `KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER`. */
|
|
34
|
+
interface KbqInlineEditSaveErrorContext<E = any> {
|
|
35
|
+
/** Parameterise the interface to type this. */
|
|
36
|
+
readonly error: E;
|
|
37
|
+
/** Inline edit whose save failed. */
|
|
38
|
+
readonly inlineEdit: KbqInlineEditSaveRecovery;
|
|
39
|
+
}
|
|
40
|
+
/** Reaction to a failed save, e.g. opening a toast. */
|
|
41
|
+
type KbqInlineEditSaveErrorHandler = (context: KbqInlineEditSaveErrorContext) => void;
|
|
42
|
+
/** Reports every failed save the same way across the application. Declare it in the root injector. */
|
|
43
|
+
declare const KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER: InjectionToken<KbqInlineEditSaveErrorHandler>;
|
|
12
44
|
/** @docs-private */
|
|
13
45
|
declare class KbqFocusRegionItem {
|
|
14
46
|
readonly tabOut: _angular_core.OutputEmitterRef<KeyboardEvent>;
|
|
@@ -38,7 +70,9 @@ declare class KbqInlineEditMenu {
|
|
|
38
70
|
* This component is projecting edit/view mode templates and adds keyboard/pointer handlers.
|
|
39
71
|
* Edit mode opens in a positioned overlay that matches the view mode width or can be customized.
|
|
40
72
|
*/
|
|
41
|
-
declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
73
|
+
declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider, KbqInlineEditSaveRecovery {
|
|
74
|
+
/** Texts of the save status announcements. */
|
|
75
|
+
protected readonly a11yLocaleConfiguration: _angular_core.Signal<_koobiq_components_core.KbqA11yLocaleConfiguration>;
|
|
42
76
|
private readonly overlay;
|
|
43
77
|
private readonly document;
|
|
44
78
|
private readonly window;
|
|
@@ -46,6 +80,7 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
46
80
|
protected readonly elementRef: ElementRef<HTMLElement>;
|
|
47
81
|
private readonly ngZone;
|
|
48
82
|
private readonly scrollDispatcher;
|
|
83
|
+
private readonly destroyRef;
|
|
49
84
|
/**
|
|
50
85
|
* The validation tooltip is anchored inside the edit-mode overlay — an overlay inside another
|
|
51
86
|
* overlay. Its default `close()` scroll strategy would close it the moment either overlay's
|
|
@@ -83,6 +118,22 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
83
118
|
readonly getValueHandler: _angular_core.InputSignal<(() => unknown) | undefined>;
|
|
84
119
|
/** Handler function to update the value */
|
|
85
120
|
readonly setValueHandler: _angular_core.InputSignal<((value: any) => void) | undefined>;
|
|
121
|
+
/**
|
|
122
|
+
* Whether the value still equals the one the editor opened with, in which case `saveHandler` is not called.
|
|
123
|
+
* The default suits text and numbers; bind your own for arrays and objects, or `null` to send every time.
|
|
124
|
+
* A failed save is always retried, however the values compare.
|
|
125
|
+
*/
|
|
126
|
+
readonly compareWith: _angular_core.InputSignal<((a: any, b: any) => boolean) | null>;
|
|
127
|
+
/**
|
|
128
|
+
* Saves a valid value in the background: edit mode closes right away and view mode reports how the request
|
|
129
|
+
* went. Without it, a valid value is saved immediately.
|
|
130
|
+
*/
|
|
131
|
+
readonly saveHandler: _angular_core.InputSignal<KbqInlineEditSaveHandler | undefined>;
|
|
132
|
+
/**
|
|
133
|
+
* Reaction to a failed save for this inline edit alone. Defaults to `KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER`;
|
|
134
|
+
* bind `null` to leave it without one.
|
|
135
|
+
*/
|
|
136
|
+
readonly saveErrorHandler: _angular_core.InputSignal<KbqInlineEditSaveErrorHandler | null>;
|
|
86
137
|
/** Customizable function that checks if saving on enter available. */
|
|
87
138
|
readonly canSaveOnEnter: _angular_core.InputSignal<(event: KeyboardEvent) => boolean>;
|
|
88
139
|
/**
|
|
@@ -97,6 +148,8 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
97
148
|
protected readonly saved: _angular_core.OutputEmitterRef<void>;
|
|
98
149
|
/** Emitted when the inline edit is canceled and changes are discarded. */
|
|
99
150
|
protected readonly canceled: _angular_core.OutputEmitterRef<void>;
|
|
151
|
+
/** Emitted when a `saveHandler` request fails. Silent once the row is destroyed; `saveErrorHandler` is not. */
|
|
152
|
+
protected readonly saveError: _angular_core.OutputEmitterRef<KbqInlineEditSaveErrorContext<any>>;
|
|
100
153
|
/** Emitted when mode switched to edit/view */
|
|
101
154
|
protected readonly modeChange: _angular_core.OutputEmitterRef<KbqInlineEditMode>;
|
|
102
155
|
/** @docs-private */
|
|
@@ -133,6 +186,17 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
133
186
|
protected readonly scrollStrategy: _angular_core.WritableSignal<ScrollStrategy>;
|
|
134
187
|
/** @docs-private */
|
|
135
188
|
readonly modeAsReadonly: _angular_core.Signal<KbqInlineEditMode>;
|
|
189
|
+
private readonly saveStatusSource;
|
|
190
|
+
/** State of the background save started by `saveHandler`. */
|
|
191
|
+
readonly saveStatus: _angular_core.Signal<KbqInlineEditSaveStatus>;
|
|
192
|
+
/** @docs-private */
|
|
193
|
+
protected readonly isSaving: _angular_core.Signal<boolean>;
|
|
194
|
+
/**
|
|
195
|
+
* Both save states are otherwise conveyed by colour alone. `aria-busy` cannot carry the first one: it is set
|
|
196
|
+
* on the row, which contains this region, and that tells assistive tech to hold the announcement back.
|
|
197
|
+
* @docs-private
|
|
198
|
+
*/
|
|
199
|
+
protected readonly saveStatusMessage: _angular_core.Signal<string>;
|
|
136
200
|
/** @docs-private */
|
|
137
201
|
protected readonly className: _angular_core.Signal<string>;
|
|
138
202
|
/** @docs-private */
|
|
@@ -148,10 +212,15 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
148
212
|
/** @docs-private */
|
|
149
213
|
protected readonly colors: typeof KbqComponentColors;
|
|
150
214
|
private initialValue;
|
|
215
|
+
/** Value sent by the in-flight `saveHandler` request, which becomes `lastSavedValue` once it succeeds. */
|
|
216
|
+
private submittedValue;
|
|
217
|
+
/** Last value the server accepted — what `rollback()` restores after a failed save. */
|
|
218
|
+
private lastSavedValue;
|
|
219
|
+
private destroyed;
|
|
151
220
|
/** Handle for an in-flight `showValidationTooltip()` scroll/settle request, if any. */
|
|
152
221
|
private validationTooltipScrollHandle;
|
|
153
222
|
constructor();
|
|
154
|
-
/** Manually switch mode */
|
|
223
|
+
/** Manually switch mode. Does nothing while a `saveHandler` request is in flight. */
|
|
155
224
|
toggleMode(): void;
|
|
156
225
|
/**
|
|
157
226
|
* Implements `KbqConnectedOverlayOriginProvider`, letting a nested `KbqFormField`'s control
|
|
@@ -160,14 +229,22 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
160
229
|
* @docs-private
|
|
161
230
|
*/
|
|
162
231
|
getConnectedOverlayOrigin(): ElementRef | undefined;
|
|
163
|
-
/** Saves the current value
|
|
232
|
+
/** Saves the current value, running the same validation as a normal save. */
|
|
164
233
|
commit(): void;
|
|
234
|
+
/** Repeats the request for a value the server rejected. Does nothing unless the last save failed. */
|
|
235
|
+
retrySave(): void;
|
|
236
|
+
/** Discards the value the server rejected, restoring the last saved one and closing the editor. */
|
|
237
|
+
rollback(): void;
|
|
165
238
|
/** @docs-private */
|
|
166
239
|
protected onClick(event: Event): void;
|
|
167
240
|
/** @docs-private */
|
|
168
241
|
protected onAttach(): void;
|
|
169
242
|
/** @docs-private */
|
|
170
243
|
protected save($event?: Event): void;
|
|
244
|
+
/** Runs `saveHandler` once and maps its lifecycle onto `saveStatus`, holding the progress state steady. */
|
|
245
|
+
private startSave;
|
|
246
|
+
private onSaveSucceeded;
|
|
247
|
+
private onSaveFailed;
|
|
171
248
|
/**
|
|
172
249
|
* Whether `overlayOrigin` is fully within the viewport and every registered `CdkScrollable`
|
|
173
250
|
* ancestor between it and the viewport. Ancestors without the `CdkScrollable` directive aren't
|
|
@@ -207,6 +284,8 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
207
284
|
*/
|
|
208
285
|
private setOverlayKeydownListener;
|
|
209
286
|
private saveAndFocusNextInlineEdit;
|
|
287
|
+
/** Whether saving would send back the value the editor opened with. */
|
|
288
|
+
private isUnchanged;
|
|
210
289
|
private isInvalid;
|
|
211
290
|
private getValue;
|
|
212
291
|
private setValue;
|
|
@@ -216,7 +295,7 @@ declare class KbqInlineEdit implements KbqConnectedOverlayOriginProvider {
|
|
|
216
295
|
private getInputNativeElement;
|
|
217
296
|
private markAllAsTouched;
|
|
218
297
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqInlineEdit, never>;
|
|
219
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqInlineEdit, "kbq-inline-edit", ["kbqInlineEdit"], { "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "showTooltipOnError": { "alias": "showTooltipOnError"; "required": false; "isSignal": true; }; "validationTooltip": { "alias": "validationTooltip"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "editModeWidth": { "alias": "editModeWidth"; "required": false; "isSignal": true; }; "tooltipPlacement": { "alias": "tooltipPlacement"; "required": false; "isSignal": true; }; "overlayPanelClass": { "alias": "overlayPanelClass"; "required": false; "isSignal": true; }; "getValueHandler": { "alias": "getValueHandler"; "required": false; "isSignal": true; }; "setValueHandler": { "alias": "setValueHandler"; "required": false; "isSignal": true; }; "canSaveOnEnter": { "alias": "canSaveOnEnter"; "required": false; "isSignal": true; }; "interactiveSelectors": { "alias": "interactiveSelectors"; "required": false; "isSignal": true; }; }, { "saved": "saved"; "canceled": "canceled"; "modeChange": "modeChange"; }, ["menu", "label", "formFieldRefList", "selectRef"], ["kbq-label", "[kbqInlineEditViewMode]", "[kbqInlineEditMenu]", "[kbqInlineEditEditMode]"], true, [{ directive: typeof i1.CdkMonitorFocus; inputs: {}; outputs: {}; }]>;
|
|
298
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqInlineEdit, "kbq-inline-edit", ["kbqInlineEdit"], { "showActions": { "alias": "showActions"; "required": false; "isSignal": true; }; "showTooltipOnError": { "alias": "showTooltipOnError"; "required": false; "isSignal": true; }; "validationTooltip": { "alias": "validationTooltip"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "editModeWidth": { "alias": "editModeWidth"; "required": false; "isSignal": true; }; "tooltipPlacement": { "alias": "tooltipPlacement"; "required": false; "isSignal": true; }; "overlayPanelClass": { "alias": "overlayPanelClass"; "required": false; "isSignal": true; }; "getValueHandler": { "alias": "getValueHandler"; "required": false; "isSignal": true; }; "setValueHandler": { "alias": "setValueHandler"; "required": false; "isSignal": true; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "saveHandler": { "alias": "saveHandler"; "required": false; "isSignal": true; }; "saveErrorHandler": { "alias": "saveErrorHandler"; "required": false; "isSignal": true; }; "canSaveOnEnter": { "alias": "canSaveOnEnter"; "required": false; "isSignal": true; }; "interactiveSelectors": { "alias": "interactiveSelectors"; "required": false; "isSignal": true; }; }, { "saved": "saved"; "canceled": "canceled"; "saveError": "saveError"; "modeChange": "modeChange"; }, ["menu", "label", "formFieldRefList", "selectRef"], ["kbq-label", "[kbqInlineEditViewMode]", "[kbqInlineEditMenu]", "[kbqInlineEditEditMode]"], true, [{ directive: typeof i1.CdkMonitorFocus; inputs: {}; outputs: {}; }]>;
|
|
220
299
|
}
|
|
221
300
|
|
|
222
301
|
declare class KbqInlineEditModule {
|
|
@@ -225,5 +304,5 @@ declare class KbqInlineEditModule {
|
|
|
225
304
|
static ɵinj: _angular_core.ɵɵInjectorDeclaration<KbqInlineEditModule>;
|
|
226
305
|
}
|
|
227
306
|
|
|
228
|
-
export { KbqFocusRegionItem, KbqInlineEdit, KbqInlineEditMenu, KbqInlineEditModule, KbqInlineEditPlaceholder };
|
|
229
|
-
export type { KbqInlineEditMode };
|
|
307
|
+
export { KBQ_INLINE_EDIT_SAVE_ERROR_HANDLER, KbqFocusRegionItem, KbqInlineEdit, KbqInlineEditMenu, KbqInlineEditModule, KbqInlineEditPlaceholder, kbqInlineEditSaveProgressDelay, kbqInlineEditSaveProgressMinimumDuration };
|
|
308
|
+
export type { KbqInlineEditMode, KbqInlineEditSaveErrorContext, KbqInlineEditSaveErrorHandler, KbqInlineEditSaveHandler, KbqInlineEditSaveRecovery, KbqInlineEditSaveStatus };
|
|
@@ -5,4 +5,5 @@
|
|
|
5
5
|
--kbq-inline-edit-padding-vertical: calc(var(--kbq-size-xs) - var(--kbq-size-border-width));
|
|
6
6
|
--kbq-inline-edit-panel-shadow: var(--kbq-shadow-popup);
|
|
7
7
|
--kbq-inline-edit-label-color: var(--kbq-foreground-contrast-secondary);
|
|
8
|
+
--kbq-inline-edit-error-background: var(--kbq-background-error-less);
|
|
8
9
|
}
|
|
@@ -81,6 +81,31 @@
|
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
/**
|
|
85
|
+
* A save the server rejected keeps the unsaved value marked until the user reacts to the notification, so the
|
|
86
|
+
* state outlives the request itself. Every state `_inline-edit-theme()` paints a background for is repeated here
|
|
87
|
+
* with the error color: each of its selectors is more specific than the plain `.kbq-inline-edit_save-error` rule,
|
|
88
|
+
* so leaving one out would drop the marking in that state.
|
|
89
|
+
*/
|
|
90
|
+
@mixin _inline-edit-save-error-theme {
|
|
91
|
+
&.kbq-inline-edit_view.kbq-inline-edit_save-error {
|
|
92
|
+
--kbq-inline-edit-background: var(--kbq-inline-edit-error-background);
|
|
93
|
+
|
|
94
|
+
&:not(.kbq-inline-edit_disabled) {
|
|
95
|
+
&:hover {
|
|
96
|
+
--kbq-inline-edit-background: var(--kbq-states-background-error-less-hover);
|
|
97
|
+
--kbq-mask-background: var(--kbq-states-background-error-less-hover);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
&:active,
|
|
101
|
+
&:has(.kbq-inline-edit__menu.kbq-active) {
|
|
102
|
+
--kbq-inline-edit-background: var(--kbq-states-background-error-less-active);
|
|
103
|
+
--kbq-mask-background: var(--kbq-states-background-error-less-active);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
84
109
|
@mixin _inline-edit-typography {
|
|
85
110
|
@include tokens.kbq-typography-level-to-styles-css-variables(typography, text-normal);
|
|
86
111
|
}
|
|
@@ -97,6 +122,7 @@
|
|
|
97
122
|
min-height: var(--kbq-inline-edit-height);
|
|
98
123
|
|
|
99
124
|
@include _inline-edit-theme();
|
|
125
|
+
@include _inline-edit-save-error-theme();
|
|
100
126
|
@include _inline-edit-typography();
|
|
101
127
|
|
|
102
128
|
&:not(.kbq-inline-edit_with-label) {
|
package/list/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import * as i1 from '@angular/cdk/drag-drop';
|
|
|
8
8
|
import { CdkDragDrop } from '@angular/cdk/drag-drop';
|
|
9
9
|
import { ControlValueAccessor } from '@angular/forms';
|
|
10
10
|
import * as i3 from '@koobiq/components/core';
|
|
11
|
-
import { FocusKeyManager, IFocusableOption, KbqTitleTextRef, KbqOptgroup, KbqOptionActionComponent, KbqPseudoCheckbox, MultipleMode, KbqLine } from '@koobiq/components/core';
|
|
11
|
+
import { FocusKeyManager, IFocusableOption, KbqTitleTextRef, KbqOptgroup, KbqOptionActionComponent, KbqPseudoCheckbox, KbqPseudoCheckboxState, MultipleMode, KbqLine } from '@koobiq/components/core';
|
|
12
12
|
import { KbqDropdownTrigger } from '@koobiq/components/dropdown';
|
|
13
13
|
import { KbqTooltipTrigger } from '@koobiq/components/tooltip';
|
|
14
14
|
import { Subject, Observable } from 'rxjs';
|
|
@@ -125,6 +125,72 @@ declare class KbqListSelection<T = any> implements AfterContentInit, AfterViewIn
|
|
|
125
125
|
readonly dropped: _angular_core.OutputEmitterRef<KbqListSelectionDroppedEvent>;
|
|
126
126
|
/** When `true`, a repeated Ctrl/Cmd+A deselects all options. Off by default (Ctrl+A only selects). */
|
|
127
127
|
readonly selectAllToggle: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
128
|
+
/**
|
|
129
|
+
* Whether to render the "select all" master checkbox above the options. `multiple="checkbox"` only —
|
|
130
|
+
* a vertical list, since the row is a full-width heading of the column it governs.
|
|
131
|
+
*
|
|
132
|
+
* The row acts on every option the user can toggle, disabled ones excluded. Enabling it also makes
|
|
133
|
+
* Ctrl/Cmd + A a two-way toggle, so the shortcut and the checkbox never disagree ({@link selectAllToggle}
|
|
134
|
+
* is implied).
|
|
135
|
+
*
|
|
136
|
+
* Aliased rather than named `selectAll`, which is already taken by the imperative method of that name.
|
|
137
|
+
*/
|
|
138
|
+
readonly selectAllEnabled: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
139
|
+
/**
|
|
140
|
+
* Reference to the built-in "select all" row, rendered only while `selectAll` is on.
|
|
141
|
+
*
|
|
142
|
+
* Located by template reference rather than by the `KbqListOption` type: that class is declared
|
|
143
|
+
* below this one in the same file, and a query locator is evaluated while this class is being
|
|
144
|
+
* defined, which would read it in its temporal dead zone.
|
|
145
|
+
*/
|
|
146
|
+
readonly selectAllOption: _angular_core.Signal<KbqListOption<T> | undefined>;
|
|
147
|
+
/**
|
|
148
|
+
* The options the key manager navigates: the "select all" row first, then the projected ones.
|
|
149
|
+
*
|
|
150
|
+
* Kept apart from {@link options} because that query is public API and means "the options the consumer
|
|
151
|
+
* projected" — a synthetic entry there would corrupt `getSelectedOptionValues`, the drop-indicator
|
|
152
|
+
* geometry and every consumer tally built on it.
|
|
153
|
+
* @docs-private
|
|
154
|
+
*/
|
|
155
|
+
readonly navigableOptions: QueryList<KbqListOption<T>>;
|
|
156
|
+
/**
|
|
157
|
+
* The virtual scroller rendering the options, when the consumer projected one.
|
|
158
|
+
*
|
|
159
|
+
* A signal query rather than a DOM probe, mirroring `KbqSelect.cdkVirtualForOf`: it resolves on the
|
|
160
|
+
* server as well as in the browser, and it follows a viewport that appears later behind the
|
|
161
|
+
* consumer's own `@if`.
|
|
162
|
+
*/
|
|
163
|
+
private readonly virtualScroll;
|
|
164
|
+
/**
|
|
165
|
+
* Whether the "select all" row is currently rendered.
|
|
166
|
+
*
|
|
167
|
+
* Suppressed inside a `cdk-virtual-scroll-viewport`: `options` then holds only the options currently
|
|
168
|
+
* rendered, so the checkbox would report "everything selected" after touching a fraction of the data
|
|
169
|
+
* — the same reason `kbq-select` refuses the row under `withVirtualScroll`. Suppressed on an empty
|
|
170
|
+
* list too: a master checkbox over nothing has nothing to say.
|
|
171
|
+
*/
|
|
172
|
+
protected get showSelectAll(): boolean;
|
|
173
|
+
/** Label of the "select all" row. Follows the active locale. */
|
|
174
|
+
protected selectAllText: string;
|
|
175
|
+
private readonly localeService?;
|
|
176
|
+
/** Updates locale parameters from the locale service. */
|
|
177
|
+
private updateLocaleParams;
|
|
178
|
+
/** Whether every option "select all" can act on is selected. */
|
|
179
|
+
get allOptionsSelected(): boolean;
|
|
180
|
+
/** State of the "select all" master checkbox. */
|
|
181
|
+
get selectAllState(): KbqPseudoCheckboxState;
|
|
182
|
+
/**
|
|
183
|
+
* Options "select all" acts on, and the ones its checkbox state is derived from. Read from
|
|
184
|
+
* {@link options}, so the row it renders itself is never among them.
|
|
185
|
+
*/
|
|
186
|
+
private get selectAllTargets();
|
|
187
|
+
/**
|
|
188
|
+
* Adapter shared by the master checkbox and the Ctrl/Cmd + A handler, so the two cannot drift apart.
|
|
189
|
+
*
|
|
190
|
+
* Takes the items rather than reading {@link selectAllTargets} itself: the toggle needs that array for
|
|
191
|
+
* the emitted event anyway, and deriving it here as well would walk the whole option list twice.
|
|
192
|
+
*/
|
|
193
|
+
private selectAllAdapter;
|
|
128
194
|
multipleMode: MultipleMode | null;
|
|
129
195
|
get multiple(): boolean;
|
|
130
196
|
readonly horizontal: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
@@ -179,15 +245,49 @@ declare class KbqListSelection<T = any> implements AfterContentInit, AfterViewIn
|
|
|
179
245
|
/** Whether a form control has ever written to the list, i.e. whether {@link _value} speaks for a model. */
|
|
180
246
|
private hasWrittenValue;
|
|
181
247
|
constructor();
|
|
248
|
+
/** Rebuilds {@link navigableOptions}: the "select all" row, when rendered, leads the projected options. */
|
|
249
|
+
private syncNavigableOptions;
|
|
250
|
+
/**
|
|
251
|
+
* Marks the list for check after an option changed something the "select all" row is derived from —
|
|
252
|
+
* its selection or its `disabled` state.
|
|
253
|
+
*
|
|
254
|
+
* An option marking itself only asks its ancestors to traverse down to it; it does not re-evaluate
|
|
255
|
+
* their own bindings. Without this the row keeps painting a state the options have already left, and
|
|
256
|
+
* a click on a checkbox showing `indeterminate` over an already-full selection takes the deselect
|
|
257
|
+
* branch — doing the opposite of what the user was shown.
|
|
258
|
+
* @docs-private
|
|
259
|
+
*/
|
|
260
|
+
refreshSelectAllState(): void;
|
|
261
|
+
/** Whether the option is the built-in "select all" row rather than one the consumer projected. */
|
|
262
|
+
private isSelectAllRow;
|
|
263
|
+
/**
|
|
264
|
+
* Selects every option "select all" can act on, or deselects them all when they are already selected.
|
|
265
|
+
*
|
|
266
|
+
* Backs both the master checkbox and Ctrl/Cmd + A, so the two can never disagree. Reports the value
|
|
267
|
+
* once for the whole batch instead of once per option.
|
|
268
|
+
*/
|
|
269
|
+
toggleSelectAll(): void;
|
|
270
|
+
/**
|
|
271
|
+
* Whether a repeated toggle deselects. Keyed on {@link showSelectAll} rather than on the raw input:
|
|
272
|
+
* with no row on screen there is no checkbox for the shortcut to agree with, so the attribute must
|
|
273
|
+
* not quietly change what Ctrl/Cmd + A does.
|
|
274
|
+
*/
|
|
275
|
+
private get allowSelectAllDeselect();
|
|
182
276
|
ngAfterContentInit(): void;
|
|
183
277
|
ngAfterViewInit(): void;
|
|
184
278
|
ngOnDestroy(): void;
|
|
185
279
|
focus(): void;
|
|
186
280
|
/** Clears the active key-manager item (unless an option is still focused) and marks the list as touched. */
|
|
187
281
|
blur(): void;
|
|
188
|
-
/**
|
|
282
|
+
/**
|
|
283
|
+
* Selects every option and reports the new value to the `ControlValueAccessor`.
|
|
284
|
+
*
|
|
285
|
+
* Unlike the `selectAll` attribute and Ctrl/Cmd + A, this acts on disabled options as well — it is
|
|
286
|
+
* an imperative command, not something the user performed. See {@link toggleSelectAll} for the
|
|
287
|
+
* behaviour the master checkbox has.
|
|
288
|
+
*/
|
|
189
289
|
selectAll(): void;
|
|
190
|
-
/** Deselects every option and reports the new value
|
|
290
|
+
/** Deselects every option, disabled ones included, and reports the new value. See {@link selectAll}. */
|
|
191
291
|
deselectAll(): void;
|
|
192
292
|
updateScrollSize(): void;
|
|
193
293
|
setSelectedOptionsByClick(option: KbqListOption<T>, shiftKey: boolean, ctrlKey: boolean): void;
|
|
@@ -235,6 +335,11 @@ declare class KbqListSelection<T = any> implements AfterContentInit, AfterViewIn
|
|
|
235
335
|
private isValidIndex;
|
|
236
336
|
private getOptionIndex;
|
|
237
337
|
private setupDropListInitialProperties;
|
|
338
|
+
/**
|
|
339
|
+
* Says once, in dev mode, why `selectAll` produced no row: the master checkbox could only ever act on
|
|
340
|
+
* the options the scroller happens to have rendered, so the row is dropped rather than left lying.
|
|
341
|
+
*/
|
|
342
|
+
private warnOnUnsupportedSelectAllContainer;
|
|
238
343
|
/**
|
|
239
344
|
* `CdkDropList` numbers only the options it has rendered, so inside a virtual scroll the indices
|
|
240
345
|
* `dropped` reports do not address the consumer's backing array and the move silently lands on the
|
|
@@ -287,7 +392,7 @@ declare class KbqListSelection<T = any> implements AfterContentInit, AfterViewIn
|
|
|
287
392
|
private _selectAllHandler;
|
|
288
393
|
private copyActiveOption;
|
|
289
394
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqListSelection<any>, never>;
|
|
290
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqListSelection<any>, "kbq-list-selection", ["kbqListSelection"], { "autoSelect": { "alias": "autoSelect"; "required": false; }; "noUnselectLast": { "alias": "noUnselectLast"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "connectedTo": { "alias": "connectedTo"; "required": false; "isSignal": true; }; "dragPreview": { "alias": "dragPreview"; "required": false; "isSignal": true; }; "dragCursor": { "alias": "dragCursor"; "required": false; "isSignal": true; }; "selectAllToggle": { "alias": "selectAllToggle"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "selectAllHandler": { "alias": "selectAllHandler"; "required": false; }; }, { "onSelectAll": "onSelectAll"; "onCopy": "onCopy"; "dropped": "dropped"; "selectionChange": "selectionChange"; }, ["options"], ["*"], true, [{ directive: typeof i1.CdkDropList; inputs: { "id": "id"; }; outputs: {}; }]>;
|
|
395
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqListSelection<any>, "kbq-list-selection", ["kbqListSelection"], { "autoSelect": { "alias": "autoSelect"; "required": false; }; "noUnselectLast": { "alias": "noUnselectLast"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "connectedTo": { "alias": "connectedTo"; "required": false; "isSignal": true; }; "dragPreview": { "alias": "dragPreview"; "required": false; "isSignal": true; }; "dragCursor": { "alias": "dragCursor"; "required": false; "isSignal": true; }; "selectAllToggle": { "alias": "selectAllToggle"; "required": false; "isSignal": true; }; "selectAllEnabled": { "alias": "selectAll"; "required": false; "isSignal": true; }; "horizontal": { "alias": "horizontal"; "required": false; "isSignal": true; }; "tabIndex": { "alias": "tabIndex"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "compareWith": { "alias": "compareWith"; "required": false; "isSignal": true; }; "selectAllHandler": { "alias": "selectAllHandler"; "required": false; }; }, { "onSelectAll": "onSelectAll"; "onCopy": "onCopy"; "dropped": "dropped"; "selectionChange": "selectionChange"; }, ["virtualScroll", "options"], ["*"], true, [{ directive: typeof i1.CdkDropList; inputs: { "id": "id"; }; outputs: {}; }]>;
|
|
291
396
|
static ngAcceptInputType_draggable: unknown;
|
|
292
397
|
static ngAcceptInputType_disabled: unknown;
|
|
293
398
|
}
|
|
@@ -335,6 +440,15 @@ declare class KbqListOption<T = any> implements OnDestroy, OnInit, IFocusableOpt
|
|
|
335
440
|
*/
|
|
336
441
|
textElement: ElementRef;
|
|
337
442
|
readonly checkboxPosition: _angular_core.InputSignal<"before" | "after">;
|
|
443
|
+
/**
|
|
444
|
+
* Whether this option is the list's "select all" row rather than one the consumer projected.
|
|
445
|
+
*
|
|
446
|
+
* Such a row has no `value` and no place in the `SelectionModel`, so everything that would resolve
|
|
447
|
+
* it against the list's selection is skipped; its checkbox state and its selected look are driven
|
|
448
|
+
* from the outside instead. It also stays out of the drag-and-drop registry — see the constructor.
|
|
449
|
+
* @docs-private
|
|
450
|
+
*/
|
|
451
|
+
readonly selectAllRow: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
338
452
|
/**
|
|
339
453
|
* This is set to true after the first OnChanges cycle so we don't clear the value of `selected`
|
|
340
454
|
* in the first cycle.
|
|
@@ -381,6 +495,13 @@ declare class KbqListOption<T = any> implements OnDestroy, OnInit, IFocusableOpt
|
|
|
381
495
|
set selected(value: boolean);
|
|
382
496
|
private _selected;
|
|
383
497
|
get tabIndex(): number | null;
|
|
498
|
+
/** `aria-selected` of the row. The "select all" row reports `aria-checked` instead. */
|
|
499
|
+
protected get ariaSelected(): boolean | null;
|
|
500
|
+
/**
|
|
501
|
+
* Tri-state of the "select all" row, `mixed` included. `null` for an ordinary option, which
|
|
502
|
+
* reports `aria-selected` instead.
|
|
503
|
+
*/
|
|
504
|
+
protected get ariaChecked(): string | null;
|
|
384
505
|
protected get externalPseudoCheckbox(): boolean;
|
|
385
506
|
/**
|
|
386
507
|
* Whether the row itself advertises the grab. Gated on `draggable` so that a pinned option inside a
|
|
@@ -437,7 +558,7 @@ declare class KbqListOption<T = any> implements OnDestroy, OnInit, IFocusableOpt
|
|
|
437
558
|
/** The option's host DOM element. */
|
|
438
559
|
getHostElement(): HTMLElement;
|
|
439
560
|
static ɵfac: _angular_core.ɵɵFactoryDeclaration<KbqListOption<any>, never>;
|
|
440
|
-
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqListOption<any>, "kbq-list-option", ["kbqListOption"], { "checkboxPosition": { "alias": "checkboxPosition"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "showCheckbox": { "alias": "showCheckbox"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; }, {}, ["actionButton", "pseudoCheckbox", "dragHandles", "tooltipTrigger", "dropdownTrigger"], ["kbq-pseudo-checkbox", "[kbq-icon]", "*", "[kbq-list-option-caption]", "kbq-option-action"], true, [{ directive: typeof i1.CdkDrag; inputs: {}; outputs: {}; }]>;
|
|
561
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<KbqListOption<any>, "kbq-list-option", ["kbqListOption"], { "checkboxPosition": { "alias": "checkboxPosition"; "required": false; "isSignal": true; }; "selectAllRow": { "alias": "selectAllRow"; "required": false; "isSignal": true; }; "value": { "alias": "value"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "draggable": { "alias": "draggable"; "required": false; }; "showCheckbox": { "alias": "showCheckbox"; "required": false; }; "selected": { "alias": "selected"; "required": false; }; }, {}, ["actionButton", "pseudoCheckbox", "dragHandles", "tooltipTrigger", "dropdownTrigger"], ["kbq-pseudo-checkbox", "[kbq-icon]", "*", "[kbq-list-option-caption]", "kbq-option-action"], true, [{ directive: typeof i1.CdkDrag; inputs: {}; outputs: {}; }]>;
|
|
441
562
|
static ngAcceptInputType_disabled: unknown;
|
|
442
563
|
static ngAcceptInputType_draggable: unknown;
|
|
443
564
|
static ngAcceptInputType_selected: unknown;
|
package/navbar/index.d.ts
CHANGED
|
@@ -74,7 +74,11 @@ declare class KbqNavbarFocusableItem implements AfterContentInit, AfterViewInit,
|
|
|
74
74
|
get hasFocus(): boolean;
|
|
75
75
|
set hasFocus(value: boolean);
|
|
76
76
|
private _hasFocus;
|
|
77
|
-
/**
|
|
77
|
+
/**
|
|
78
|
+
* Whether the item is disabled.
|
|
79
|
+
*
|
|
80
|
+
* Also reads `true` for a decorative element, which the key manager has to skip just the same.
|
|
81
|
+
*/
|
|
78
82
|
get disabled(): boolean;
|
|
79
83
|
set disabled(value: boolean);
|
|
80
84
|
private _disabled;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koobiq/components",
|
|
3
|
-
"version": "20.
|
|
3
|
+
"version": "20.4.1",
|
|
4
4
|
"description": "koobiq",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
"@angular/cdk": ">=20.0.0",
|
|
26
26
|
"@angular/core": ">=20.0.0",
|
|
27
27
|
"@angular/forms": ">=20.0.0",
|
|
28
|
-
"@koobiq/angular-moment-adapter": "20.
|
|
29
|
-
"@koobiq/angular-luxon-adapter": "20.
|
|
28
|
+
"@koobiq/angular-moment-adapter": "20.4.1",
|
|
29
|
+
"@koobiq/angular-luxon-adapter": "20.4.1",
|
|
30
30
|
"@koobiq/date-formatter": "^3.2.3",
|
|
31
31
|
"@koobiq/icons": "^11.1.3",
|
|
32
32
|
"@koobiq/design-tokens": "^3.14.0"
|
|
@@ -27,7 +27,7 @@ function ngAdd(options) {
|
|
|
27
27
|
}
|
|
28
28
|
// Installing dependencies
|
|
29
29
|
utils_packageConfig.addPackageToPackageJson(tree, '@angular/cdk', "^20.2.14");
|
|
30
|
-
utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^20.
|
|
30
|
+
utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/angular-luxon-adapter', "^20.4.1");
|
|
31
31
|
utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-formatter', "^3.5.1");
|
|
32
32
|
utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/date-adapter', "^3.5.1");
|
|
33
33
|
utils_packageConfig.addPackageToPackageJson(tree, '@koobiq/icons', "^12.2.0");
|
package/select/index.d.ts
CHANGED
|
@@ -54,12 +54,18 @@ declare class KbqOptionTooltip extends KbqTooltipTrigger implements AfterViewIni
|
|
|
54
54
|
private readonly resizeObserver;
|
|
55
55
|
private readonly contentObserver;
|
|
56
56
|
private readonly isBrowser;
|
|
57
|
+
private readonly window;
|
|
57
58
|
private readonly debounceInterval;
|
|
58
59
|
private resizeSubscription;
|
|
59
60
|
private contentObserverSubscription;
|
|
60
61
|
private focusMonitorSubscription;
|
|
61
62
|
get textElement(): HTMLElement;
|
|
62
63
|
get isOverflown(): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Whether one of the option's own line boxes is truncating its text. The ellipsis is part of the
|
|
66
|
+
* condition, so a child clipping for another reason is not read as truncated text.
|
|
67
|
+
*/
|
|
68
|
+
private hasClippedLine;
|
|
63
69
|
constructor();
|
|
64
70
|
ngAfterViewInit(): void;
|
|
65
71
|
ngOnDestroy(): void;
|
package/tabs/_tabs-common.scss
CHANGED
|
@@ -139,14 +139,23 @@
|
|
|
139
139
|
.kbq-tab-header__pagination {
|
|
140
140
|
@include vendor-prefixes.user-select(none);
|
|
141
141
|
|
|
142
|
-
|
|
142
|
+
// Overlaid on top of the scroll container (rather than a flex sibling reserving its own
|
|
143
|
+
// space) so the tab list always spans the full width, matching Koobiq React: the button
|
|
144
|
+
// itself fades away at each scroll bound instead of the tab list resizing around it.
|
|
145
|
+
position: absolute;
|
|
146
|
+
inset-block: 0;
|
|
143
147
|
display: none;
|
|
144
148
|
justify-content: center;
|
|
145
149
|
align-items: center;
|
|
146
150
|
z-index: 2;
|
|
147
151
|
-webkit-tap-highlight-color: transparent;
|
|
148
|
-
|
|
152
|
+
// Not `none`: this element overlays live scroll-container edge, so `none` also blocks a
|
|
153
|
+
// touch swipe that starts in that band from panning the strip at all. `manipulation` still
|
|
154
|
+
// suppresses double-tap-to-zoom, which is all this was here for.
|
|
155
|
+
touch-action: manipulation;
|
|
149
156
|
padding: 0 var(--kbq-size-m);
|
|
157
|
+
opacity: 1;
|
|
158
|
+
visibility: visible;
|
|
150
159
|
|
|
151
160
|
.kbq-tab-header__pagination-controls_enabled & {
|
|
152
161
|
display: flex;
|
|
@@ -155,6 +164,106 @@
|
|
|
155
164
|
&:not(.kbq-disabled) {
|
|
156
165
|
cursor: pointer;
|
|
157
166
|
}
|
|
167
|
+
|
|
168
|
+
&.kbq-disabled {
|
|
169
|
+
opacity: 0;
|
|
170
|
+
visibility: hidden;
|
|
171
|
+
pointer-events: none;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.kbq-tab-header__pagination_before {
|
|
176
|
+
inset-inline-start: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.kbq-tab-header__pagination_after {
|
|
180
|
+
inset-inline-end: 0;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.kbq-tab-header__scroll-container {
|
|
184
|
+
@include vendor-prefixes.user-select(none);
|
|
185
|
+
|
|
186
|
+
// Matches `.kbq-tab-header__pagination`'s real rendered width (its horizontal padding
|
|
187
|
+
// twice, plus the 16px arrow icon) rather than an unrelated constant — otherwise the label
|
|
188
|
+
// underneath fades in for a few pixels *before* it clears the paginator it's still hidden
|
|
189
|
+
// behind, which is a band that's visible but can't be clicked (the paginator, not the
|
|
190
|
+
// label, is what's on top there).
|
|
191
|
+
--mask-size: calc(var(--kbq-size-m) * 2 + 16px);
|
|
192
|
+
|
|
193
|
+
overflow-x: auto;
|
|
194
|
+
overflow-y: hidden;
|
|
195
|
+
scrollbar-width: none;
|
|
196
|
+
-ms-overflow-style: none;
|
|
197
|
+
|
|
198
|
+
&::-webkit-scrollbar {
|
|
199
|
+
display: none;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// `kbq-tab-group_vertical` sits on an ancestor either way: the `<kbq-tab-group>` wrapping a
|
|
203
|
+
// `kbq-tab-header`, or the `[kbqTabNavBar]` host itself — so one descendant selector covers
|
|
204
|
+
// both `KbqPaginatedTabHeader` subclasses instead of the two disagreeing on the scrollbar.
|
|
205
|
+
.kbq-tab-group_vertical & {
|
|
206
|
+
overflow-x: hidden;
|
|
207
|
+
overflow-y: auto;
|
|
208
|
+
scrollbar-width: auto;
|
|
209
|
+
|
|
210
|
+
&::-webkit-scrollbar {
|
|
211
|
+
display: block;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.kbq-tab-header__pagination-controls_enabled & {
|
|
216
|
+
cursor: grab;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
&.kbq-tab-header__scroll-container_dragging {
|
|
220
|
+
cursor: grabbing;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
&.kbq-tab-header__scroll-container_overflow-before {
|
|
224
|
+
mask-image: linear-gradient(to right, transparent var(--mask-size), #000 calc(var(--mask-size) * 1.5));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
&.kbq-tab-header__scroll-container_overflow-after {
|
|
228
|
+
mask-image: linear-gradient(
|
|
229
|
+
to right,
|
|
230
|
+
#000 calc(100% - var(--mask-size) * 1.5),
|
|
231
|
+
transparent calc(100% - var(--mask-size))
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&.kbq-tab-header__scroll-container_overflow-before.kbq-tab-header__scroll-container_overflow-after {
|
|
236
|
+
mask-image: linear-gradient(
|
|
237
|
+
to right,
|
|
238
|
+
transparent var(--mask-size),
|
|
239
|
+
#000 calc(var(--mask-size) * 1.5),
|
|
240
|
+
#000 calc(100% - var(--mask-size) * 1.5),
|
|
241
|
+
transparent calc(100% - var(--mask-size))
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
.kbq-tab-header_rtl &.kbq-tab-header__scroll-container_overflow-before {
|
|
246
|
+
mask-image: linear-gradient(to left, transparent var(--mask-size), #000 calc(var(--mask-size) * 1.5));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
.kbq-tab-header_rtl &.kbq-tab-header__scroll-container_overflow-after {
|
|
250
|
+
mask-image: linear-gradient(
|
|
251
|
+
to left,
|
|
252
|
+
#000 calc(100% - var(--mask-size) * 1.5),
|
|
253
|
+
transparent calc(100% - var(--mask-size))
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.kbq-tab-header_rtl
|
|
258
|
+
&.kbq-tab-header__scroll-container_overflow-before.kbq-tab-header__scroll-container_overflow-after {
|
|
259
|
+
mask-image: linear-gradient(
|
|
260
|
+
to left,
|
|
261
|
+
transparent var(--mask-size),
|
|
262
|
+
#000 calc(var(--mask-size) * 1.5),
|
|
263
|
+
#000 calc(100% - var(--mask-size) * 1.5),
|
|
264
|
+
transparent calc(100% - var(--mask-size))
|
|
265
|
+
);
|
|
266
|
+
}
|
|
158
267
|
}
|
|
159
268
|
|
|
160
269
|
.kbq-tab-header_underlined:not(.kbq-tab-header_vertical) .kbq-tab-list__content {
|