@koobiq/components 20.1.0 → 20.3.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/accordion/_accordion-theme.scss +6 -2
- package/accordion/accordion-tokens.scss +3 -0
- package/accordion/{accordion-trigger.component.scss → accordion-trigger.scss} +10 -0
- package/accordion/accordion.scss +71 -0
- package/accordion/index.d.ts +264 -121
- package/actions-panel/index.d.ts +25 -13
- package/alert/_alert-theme.scss +14 -0
- package/alert/alert.component.scss +24 -13
- package/alert/index.d.ts +63 -29
- package/app-switcher/app-switcher-dropdown-app.scss +7 -5
- package/app-switcher/app-switcher-dropdown-site.scss +6 -4
- package/app-switcher/index.d.ts +41 -4
- package/app-switcher/kbq-app-switcher-list-item.scss +6 -8
- package/autocomplete/autocomplete.scss +2 -1
- package/autocomplete/index.d.ts +58 -37
- package/badge/index.d.ts +2 -3
- package/breadcrumbs/index.d.ts +1 -1
- package/button/index.d.ts +2 -2
- package/button-toggle/button-toggle-tokens.scss +2 -0
- package/button-toggle/button-toggle.scss +9 -0
- package/button-toggle/index.d.ts +5 -0
- package/checkbox/index.d.ts +33 -29
- package/clamped-text/index.d.ts +3 -2
- package/code-block/index.d.ts +24 -19
- package/content-panel/index.d.ts +1 -1
- package/core/index.d.ts +1217 -186
- package/core/option/_action-container-mixins.scss +28 -0
- package/core/option/_option-theme.scss +24 -0
- package/core/option/action.scss +7 -0
- package/core/styles/_core.scss +2 -0
- package/core/styles/_koobiq-theme.scss +2 -0
- package/core/styles/_tokens.scss +1 -0
- package/core/styles/common/_animation.scss +31 -24
- package/core/styles/common/_connected-overlay.scss +39 -0
- package/core/styles/common/_select.scss +19 -2
- package/core/styles/common/_tokens.scss +0 -9
- package/core/styles/theming/_index.scss +0 -1
- package/core/styles/theming/_theming.scss +34 -5
- package/datepicker/index.d.ts +46 -15
- package/dl/dl.scss +26 -0
- package/dl/index.d.ts +8 -1
- package/dropdown/_dropdown-theme.scss +28 -2
- package/dropdown/dropdown-item.scss +29 -0
- package/dropdown/dropdown-tokens.scss +2 -1
- package/dropdown/dropdown.scss +16 -1
- package/dropdown/index.d.ts +331 -17
- package/dynamic-translation/index.d.ts +1 -1
- package/fesm2022/koobiq-components-accordion.mjs +480 -317
- package/fesm2022/koobiq-components-accordion.mjs.map +1 -1
- package/fesm2022/koobiq-components-actions-panel.mjs +57 -46
- package/fesm2022/koobiq-components-actions-panel.mjs.map +1 -1
- package/fesm2022/koobiq-components-alert.mjs +98 -58
- package/fesm2022/koobiq-components-alert.mjs.map +1 -1
- package/fesm2022/koobiq-components-app-switcher.mjs +233 -38
- package/fesm2022/koobiq-components-app-switcher.mjs.map +1 -1
- package/fesm2022/koobiq-components-autocomplete.mjs +89 -52
- package/fesm2022/koobiq-components-autocomplete.mjs.map +1 -1
- package/fesm2022/koobiq-components-badge.mjs +18 -17
- package/fesm2022/koobiq-components-badge.mjs.map +1 -1
- package/fesm2022/koobiq-components-breadcrumbs.mjs +25 -25
- package/fesm2022/koobiq-components-breadcrumbs.mjs.map +1 -1
- package/fesm2022/koobiq-components-button-toggle.mjs +17 -12
- package/fesm2022/koobiq-components-button-toggle.mjs.map +1 -1
- package/fesm2022/koobiq-components-button.mjs +25 -25
- package/fesm2022/koobiq-components-checkbox.mjs +69 -92
- package/fesm2022/koobiq-components-checkbox.mjs.map +1 -1
- package/fesm2022/koobiq-components-clamped-text.mjs +18 -13
- package/fesm2022/koobiq-components-clamped-text.mjs.map +1 -1
- package/fesm2022/koobiq-components-code-block.mjs +56 -69
- package/fesm2022/koobiq-components-code-block.mjs.map +1 -1
- package/fesm2022/koobiq-components-content-panel.mjs +29 -29
- package/fesm2022/koobiq-components-core.mjs +2485 -735
- package/fesm2022/koobiq-components-core.mjs.map +1 -1
- package/fesm2022/koobiq-components-datepicker.mjs +168 -126
- package/fesm2022/koobiq-components-datepicker.mjs.map +1 -1
- package/fesm2022/koobiq-components-divider.mjs +7 -7
- package/fesm2022/koobiq-components-dl.mjs +23 -15
- package/fesm2022/koobiq-components-dl.mjs.map +1 -1
- package/fesm2022/koobiq-components-dropdown.mjs +814 -136
- package/fesm2022/koobiq-components-dropdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-dynamic-translation.mjs +13 -13
- package/fesm2022/koobiq-components-ellipsis-center.mjs +7 -7
- package/fesm2022/koobiq-components-empty-state.mjs +19 -19
- package/fesm2022/koobiq-components-file-upload.mjs +74 -42
- package/fesm2022/koobiq-components-file-upload.mjs.map +1 -1
- package/fesm2022/koobiq-components-filter-bar.mjs +783 -199
- package/fesm2022/koobiq-components-filter-bar.mjs.map +1 -1
- package/fesm2022/koobiq-components-flag.mjs +7 -7
- package/fesm2022/koobiq-components-form-field.mjs +350 -162
- package/fesm2022/koobiq-components-form-field.mjs.map +1 -1
- package/fesm2022/koobiq-components-icon.mjs +52 -25
- package/fesm2022/koobiq-components-icon.mjs.map +1 -1
- package/fesm2022/koobiq-components-inline-edit.mjs +175 -28
- package/fesm2022/koobiq-components-inline-edit.mjs.map +1 -1
- package/fesm2022/koobiq-components-input.mjs +41 -24
- package/fesm2022/koobiq-components-input.mjs.map +1 -1
- package/fesm2022/koobiq-components-link.mjs +8 -8
- package/fesm2022/koobiq-components-list.mjs +657 -143
- package/fesm2022/koobiq-components-list.mjs.map +1 -1
- package/fesm2022/koobiq-components-loader-overlay.mjs +16 -16
- package/fesm2022/koobiq-components-markdown.mjs +14 -11
- package/fesm2022/koobiq-components-markdown.mjs.map +1 -1
- package/fesm2022/koobiq-components-modal.mjs +59 -35
- package/fesm2022/koobiq-components-modal.mjs.map +1 -1
- package/fesm2022/koobiq-components-navbar.mjs +177 -67
- package/fesm2022/koobiq-components-navbar.mjs.map +1 -1
- package/fesm2022/koobiq-components-notification-center.mjs +40 -24
- package/fesm2022/koobiq-components-notification-center.mjs.map +1 -1
- package/fesm2022/koobiq-components-overflow-items.mjs +16 -17
- package/fesm2022/koobiq-components-overflow-items.mjs.map +1 -1
- package/fesm2022/koobiq-components-popover.mjs +31 -21
- package/fesm2022/koobiq-components-popover.mjs.map +1 -1
- package/fesm2022/koobiq-components-progress-bar.mjs +13 -13
- package/fesm2022/koobiq-components-progress-spinner.mjs +13 -13
- package/fesm2022/koobiq-components-radio.mjs +10 -10
- package/fesm2022/koobiq-components-resizer.mjs +33 -14
- package/fesm2022/koobiq-components-resizer.mjs.map +1 -1
- package/fesm2022/koobiq-components-scrollbar.mjs +10 -10
- package/fesm2022/koobiq-components-search-expandable.mjs +49 -14
- package/fesm2022/koobiq-components-search-expandable.mjs.map +1 -1
- package/fesm2022/koobiq-components-select.mjs +450 -146
- package/fesm2022/koobiq-components-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-sidebar.mjs +14 -14
- package/fesm2022/koobiq-components-sidepanel.mjs +26 -26
- package/fesm2022/koobiq-components-skeleton.mjs +10 -10
- package/fesm2022/koobiq-components-split-button.mjs +10 -17
- package/fesm2022/koobiq-components-split-button.mjs.map +1 -1
- package/fesm2022/koobiq-components-splitter.mjs +17 -17
- package/fesm2022/koobiq-components-table.mjs +15 -13
- package/fesm2022/koobiq-components-table.mjs.map +1 -1
- package/fesm2022/koobiq-components-tabs.mjs +80 -68
- package/fesm2022/koobiq-components-tabs.mjs.map +1 -1
- package/fesm2022/koobiq-components-tags.mjs +283 -122
- package/fesm2022/koobiq-components-tags.mjs.map +1 -1
- package/fesm2022/koobiq-components-textarea.mjs +13 -8
- package/fesm2022/koobiq-components-textarea.mjs.map +1 -1
- package/fesm2022/koobiq-components-time-range.mjs +29 -24
- package/fesm2022/koobiq-components-time-range.mjs.map +1 -1
- package/fesm2022/koobiq-components-timepicker.mjs +61 -30
- package/fesm2022/koobiq-components-timepicker.mjs.map +1 -1
- package/fesm2022/koobiq-components-timezone.mjs +77 -42
- package/fesm2022/koobiq-components-timezone.mjs.map +1 -1
- package/fesm2022/koobiq-components-title.mjs +7 -7
- package/fesm2022/koobiq-components-toast.mjs +51 -26
- package/fesm2022/koobiq-components-toast.mjs.map +1 -1
- package/fesm2022/koobiq-components-toggle.mjs +72 -64
- package/fesm2022/koobiq-components-toggle.mjs.map +1 -1
- package/fesm2022/koobiq-components-tooltip.mjs +219 -28
- package/fesm2022/koobiq-components-tooltip.mjs.map +1 -1
- package/fesm2022/koobiq-components-top-bar.mjs +13 -13
- package/fesm2022/koobiq-components-tree-select.mjs +222 -80
- package/fesm2022/koobiq-components-tree-select.mjs.map +1 -1
- package/fesm2022/koobiq-components-tree.mjs +302 -81
- package/fesm2022/koobiq-components-tree.mjs.map +1 -1
- package/fesm2022/koobiq-components-username.mjs +27 -27
- package/file-upload/index.d.ts +25 -6
- package/file-upload/multiple-file-upload.component.scss +14 -0
- package/filter-bar/_filter-bar-theme.scss +0 -10
- package/filter-bar/filter-bar-tokens.scss +3 -0
- package/filter-bar/filters.scss +3 -2
- package/filter-bar/index.d.ts +281 -9
- package/filter-bar/pipes/base-pipe.scss +0 -11
- package/filter-bar/pipes/pipe-input.scss +10 -0
- package/filter-bar/pipes/pipe-multi-tree-select.scss +0 -6
- package/filter-bar/pipes/pipe-multiselect.scss +0 -6
- package/filter-bar/pipes/pipe-tree-select.scss +0 -6
- package/form-field/_form-field-theme.scss +76 -20
- package/form-field/fieldset.scss +10 -0
- package/form-field/form-field-tokens.scss +15 -1
- package/form-field/form-field.scss +15 -19
- package/form-field/index.d.ts +147 -65
- package/icon/icon-button.scss +3 -1
- package/icon/index.d.ts +45 -7
- package/inline-edit/index.d.ts +57 -4
- package/inline-edit/inline-edit.scss +10 -0
- package/input/index.d.ts +17 -2
- package/list/_list-theme.scss +42 -10
- package/list/index.d.ts +326 -79
- package/list/list-tokens.scss +43 -8
- package/list/list.scss +186 -12
- package/markdown/index.d.ts +1 -1
- package/modal/index.d.ts +21 -4
- package/modal/modal-tokens.scss +1 -1
- package/navbar/_navbar-item_vertical.scss +7 -5
- package/navbar/index.d.ts +54 -5
- package/navbar/navbar-brand.scss +23 -7
- package/navbar/vertical-navbar.scss +6 -0
- package/notification-center/index.d.ts +2 -1
- package/notification-center/notification-item.scss +6 -0
- package/package.json +3 -6
- package/popover/index.d.ts +2 -2
- package/prebuilt-themes/dark-theme.css +1 -1
- package/prebuilt-themes/light-theme.css +1 -1
- package/prebuilt-themes/theme.css +1 -1
- package/resizer/index.d.ts +12 -0
- package/schematics/collection.json +10 -0
- package/schematics/migrations/alert-signals/README.md +64 -0
- package/schematics/migrations/alert-signals/data.js +70 -0
- package/schematics/migrations/alert-signals/index.js +350 -0
- package/schematics/migrations/alert-signals/schema.json +20 -0
- package/schematics/migrations/autocomplete-panel-width-auto/README.md +68 -0
- package/schematics/migrations/autocomplete-panel-width-auto/index.js +70 -0
- package/schematics/migrations/autocomplete-panel-width-auto/schema.json +15 -0
- package/schematics/migrations/deprecated-icons/README.md +29 -4
- package/schematics/migrations/deprecated-icons/data.js +7 -0
- package/schematics/migrations/deprecated-icons/index.js +62 -35
- package/schematics/migrations/filter-bar-signals/README.md +1 -1
- package/schematics/migrations/new-icons-pack/README.md +37 -2
- package/schematics/migrations/new-icons-pack/data.js +8 -0
- package/schematics/migrations/new-icons-pack/index.js +144 -53
- package/schematics/migrations.json +11 -1
- package/schematics/ng-add/index.js +3 -3
- package/schematics/utils/angular-parsing.js +41 -14
- package/schematics/utils/ast.js +31 -0
- package/schematics/utils/icon-migration.js +530 -0
- package/schematics/utils/typescript.js +44 -0
- package/scrollbar/index.d.ts +1 -1
- package/search-expandable/index.d.ts +3 -0
- package/select/index.d.ts +212 -40
- package/select/select-tokens.scss +0 -1
- package/select/select.scss +0 -2
- package/splitter/index.d.ts +1 -1
- package/table/_table-theme.scss +4 -0
- package/table/index.d.ts +2 -1
- package/table/table.scss +8 -0
- package/tabs/_tabs-common.scss +60 -31
- package/tabs/_tabs-theme.scss +12 -0
- package/tabs/index.d.ts +2 -2
- package/tabs/tab-header.scss +14 -0
- package/tabs/tab-nav-bar.scss +4 -0
- package/tabs/tabs-tokens.scss +1 -0
- package/tags/index.d.ts +128 -29
- package/textarea/index.d.ts +5 -0
- package/time-range/index.d.ts +1 -1
- package/timepicker/index.d.ts +4 -0
- package/timezone/index.d.ts +10 -8
- package/toast/index.d.ts +26 -3
- package/toggle/index.d.ts +34 -14
- package/tooltip/index.d.ts +119 -7
- package/tree/_tree-theme.scss +25 -5
- package/tree/index.d.ts +71 -3
- package/tree/tree-option.scss +2 -8
- package/tree-select/_tree-select-theme.scss +22 -0
- package/tree-select/index.d.ts +127 -36
- package/accordion/accordion.component.scss +0 -50
- package/core/styles/_tokens.kbq.import.scss +0 -4
- package/core/styles/theming/_components-theming.scss +0 -1927
- package/filter-bar/pipes/pipe-select.scss +0 -5
- package/overflow-items/overflow-items.scss +0 -20
|
@@ -1,200 +1,96 @@
|
|
|
1
|
-
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, ElementRef, ChangeDetectorRef, contentChildren, forwardRef, HostAttributeToken, input, booleanAttribute, output, Input, ViewEncapsulation, ChangeDetectionStrategy, Component, Directive, viewChild, afterNextRender, contentChild, EventEmitter, Renderer2, signal, NgModule } from '@angular/core';
|
|
3
|
-
import { Platform } from '@angular/cdk/platform';
|
|
4
|
-
import { KBQ_WINDOW, kbqInjectNativeElement } from '@koobiq/components/core';
|
|
5
|
-
import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
|
|
6
|
-
import { Subject, merge, Subscription } from 'rxjs';
|
|
7
|
-
import { KbqIcon } from '@koobiq/components/icon';
|
|
8
1
|
import { FocusMonitor, FocusKeyManager } from '@angular/cdk/a11y';
|
|
9
2
|
import { Directionality } from '@angular/cdk/bidi';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
3
|
+
import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
|
|
4
|
+
import { ENTER, SPACE } from '@angular/cdk/keycodes';
|
|
5
|
+
import * as i0 from '@angular/core';
|
|
6
|
+
import { inject, Renderer2, signal, afterNextRender, RendererStyleFlags2, Directive, viewChild, ViewEncapsulation, Component, ChangeDetectorRef, contentChild, forwardRef, input, computed, output, booleanAttribute, Input, Injectable, InjectionToken, ElementRef, Injector, contentChildren, numberAttribute, effect, untracked, isDevMode, ChangeDetectionStrategy, NgModule } from '@angular/core';
|
|
7
|
+
import { Subscription, Subject } from 'rxjs';
|
|
8
|
+
import { kbqInjectNativeElement, KBQ_WINDOW } from '@koobiq/components/core';
|
|
9
|
+
import { KbqIcon } from '@koobiq/components/icon';
|
|
10
|
+
import { Platform } from '@angular/cdk/platform';
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
KbqAccordionVariant["hugSpaceBetween"] = "hugSpaceBetween";
|
|
18
|
-
})(KbqAccordionVariant || (KbqAccordionVariant = {}));
|
|
19
|
-
let uniqueIdCounter$1 = 0;
|
|
20
|
-
class KbqAccordion {
|
|
21
|
-
/**
|
|
22
|
-
* The value of the item to expand when initially rendered and type is "single". Use when you do not need to control the state of the items.
|
|
23
|
-
*/
|
|
24
|
-
// TODO: Skipped for migration because:
|
|
25
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
26
|
-
get defaultValue() {
|
|
27
|
-
return this.isMultiple ? this._defaultValue : this._defaultValue[0];
|
|
28
|
-
}
|
|
29
|
-
set defaultValue(value) {
|
|
30
|
-
if (value !== this._defaultValue) {
|
|
31
|
-
this._defaultValue = Array.isArray(value) ? value : [value];
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
/** The controlled value of the item to expand */
|
|
35
|
-
// TODO: Skipped for migration because:
|
|
36
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
37
|
-
get value() {
|
|
38
|
-
if (this._value === undefined) {
|
|
39
|
-
return this.defaultValue;
|
|
40
|
-
}
|
|
41
|
-
return this.isMultiple ? this._value : this._value[0];
|
|
42
|
-
}
|
|
43
|
-
set value(value) {
|
|
44
|
-
if (value !== this._value) {
|
|
45
|
-
this._value = Array.isArray(value) ? value : [value];
|
|
46
|
-
this.selectionDispatcher.notify(this.value, this.id);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
get id() {
|
|
50
|
-
return this._id;
|
|
51
|
-
}
|
|
52
|
-
get isMultiple() {
|
|
53
|
-
return this.type() === 'multiple';
|
|
12
|
+
class KbqAccordionContentDirective {
|
|
13
|
+
/** @docs-private */
|
|
14
|
+
get contentId() {
|
|
15
|
+
return `${this.item.id}-content`;
|
|
54
16
|
}
|
|
55
|
-
|
|
56
|
-
|
|
17
|
+
/** @docs-private */
|
|
18
|
+
get triggerId() {
|
|
19
|
+
return `${this.item.id}-trigger`;
|
|
57
20
|
}
|
|
58
21
|
constructor() {
|
|
59
|
-
this.
|
|
60
|
-
this.localStorage = inject(KBQ_WINDOW)?.localStorage;
|
|
61
|
-
/** @docs-private */
|
|
62
|
-
this.focusMonitor = inject(FocusMonitor);
|
|
63
|
-
/** @docs-private */
|
|
64
|
-
this.elementRef = inject(ElementRef);
|
|
65
|
-
/** @docs-private */
|
|
66
|
-
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
22
|
+
this.renderer = inject(Renderer2);
|
|
67
23
|
/** @docs-private */
|
|
68
|
-
this.
|
|
24
|
+
this.nativeElement = kbqInjectNativeElement();
|
|
69
25
|
/** @docs-private */
|
|
70
|
-
this.
|
|
26
|
+
this.item = inject(KbqAccordionItem);
|
|
71
27
|
/** @docs-private */
|
|
72
|
-
this.
|
|
73
|
-
/**
|
|
74
|
-
this.
|
|
75
|
-
|
|
76
|
-
this.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
/** Determines whether one or multiple items can be opened at the same time. */
|
|
83
|
-
this.type = input('single', ...(ngDevMode ? [{ debugName: "type" }] : []));
|
|
84
|
-
this.collapsible = input(true, ...(ngDevMode ? [{ debugName: "collapsible" }] : []));
|
|
85
|
-
this.onValueChange = output();
|
|
86
|
-
this._defaultValue = [];
|
|
87
|
-
this._id = `kbq-accordion-${uniqueIdCounter$1++}`;
|
|
88
|
-
if (this.useStateSaving) {
|
|
89
|
-
this.getSavedState();
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
ngAfterContentInit() {
|
|
93
|
-
if (this._value) {
|
|
94
|
-
this.selectionDispatcher.notify(this._value, this.id);
|
|
95
|
-
}
|
|
96
|
-
else if (this.useStateSaving && this.hasSavedState) {
|
|
97
|
-
Object.keys(this.state).forEach((key) => {
|
|
98
|
-
if (this.state && this.state[key].expanded) {
|
|
99
|
-
this.selectionDispatcher.notify(this.state[key].value, this.id);
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
else {
|
|
104
|
-
this.selectionDispatcher.notify(this._defaultValue, this.id);
|
|
105
|
-
}
|
|
106
|
-
this.keyManager = new FocusKeyManager(this.items()).withHomeAndEnd();
|
|
107
|
-
if (this.orientation() === 'horizontal') {
|
|
108
|
-
this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
|
|
109
|
-
}
|
|
110
|
-
else {
|
|
111
|
-
this.keyManager.withVerticalOrientation();
|
|
112
|
-
}
|
|
113
|
-
this.onValueChangeSubscription = merge(...this.items().map((item) => outputToObservable(item.expandedChange))).subscribe(() => this.onValueChange.emit());
|
|
28
|
+
this.hidden = signal(true, ...(ngDevMode ? [{ debugName: "hidden" }] : []));
|
|
29
|
+
/** Whether the first browser render has happened, i.e. whether the content can be measured. */
|
|
30
|
+
this.rendered = false;
|
|
31
|
+
// `afterNextRender` never runs on the server, so no platform check is needed here.
|
|
32
|
+
this.afterRenderRef = afterNextRender(() => {
|
|
33
|
+
this.rendered = true;
|
|
34
|
+
this.updateHeight();
|
|
35
|
+
this.enableAnimation();
|
|
36
|
+
this.afterRenderRef?.destroy();
|
|
37
|
+
});
|
|
114
38
|
}
|
|
115
39
|
ngAfterViewInit() {
|
|
116
|
-
this.
|
|
117
|
-
}
|
|
118
|
-
ngOnDestroy() {
|
|
119
|
-
this.focusMonitor.stopMonitoring(this.elementRef);
|
|
120
|
-
this.openCloseAllActions.complete();
|
|
121
|
-
this.onValueChangeSubscription.unsubscribe();
|
|
122
|
-
}
|
|
123
|
-
/** @docs-private */
|
|
124
|
-
keydownHandler(event) {
|
|
125
|
-
if (!this.keyManager.activeItem) {
|
|
126
|
-
this.keyManager.setFirstItemActive();
|
|
127
|
-
}
|
|
128
|
-
const activeItem = this.keyManager.activeItem;
|
|
129
|
-
if ((event.keyCode === ENTER || event.keyCode === SPACE) &&
|
|
130
|
-
!this.keyManager.isTyping() &&
|
|
131
|
-
activeItem &&
|
|
132
|
-
!activeItem.disabled) {
|
|
133
|
-
event.preventDefault();
|
|
134
|
-
activeItem.toggle();
|
|
135
|
-
}
|
|
136
|
-
else if (event.keyCode === TAB && event.shiftKey) {
|
|
137
|
-
if (this.keyManager.activeItemIndex === 0)
|
|
138
|
-
return;
|
|
139
|
-
this.keyManager.setPreviousItemActive();
|
|
140
|
-
event.preventDefault();
|
|
141
|
-
}
|
|
142
|
-
else if (event.keyCode === TAB) {
|
|
143
|
-
if (this.keyManager.activeItemIndex === this.items().length - 1)
|
|
144
|
-
return;
|
|
145
|
-
this.keyManager.setNextItemActive();
|
|
146
|
-
event.preventDefault();
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
this.keyManager.onKeydown(event);
|
|
150
|
-
}
|
|
40
|
+
this.disableAnimation();
|
|
151
41
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
42
|
+
toggle() {
|
|
43
|
+
// Re-measure while the content is still collapsed. Its natural height depends on the width
|
|
44
|
+
// it is finally laid out at, and that width is not known at first render when the accordion
|
|
45
|
+
// lives in a container sized afterwards (sidepanel, overlay, responsive layout).
|
|
46
|
+
if (this.rendered && this.item.expanded && this.hidden()) {
|
|
47
|
+
this.updateHeight();
|
|
156
48
|
}
|
|
49
|
+
this.hidden.set(!this.item.expanded);
|
|
157
50
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
this.
|
|
161
|
-
}
|
|
162
|
-
/** @docs-private */
|
|
163
|
-
setActiveItem(item) {
|
|
164
|
-
this.keyManager.setActiveItem(item);
|
|
51
|
+
disableAnimation() {
|
|
52
|
+
this.savedTransition = this.nativeElement.style.transition;
|
|
53
|
+
this.nativeElement.style.transition = 'none';
|
|
165
54
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
if (!this.isBrowser || (!force && !!this.state && !!this.state[item.id]))
|
|
169
|
-
return;
|
|
170
|
-
this.state = this.state || {};
|
|
171
|
-
this.state[item.id] = item.getState();
|
|
172
|
-
this.localStorage.setItem(this.id, JSON.stringify(this.state));
|
|
55
|
+
enableAnimation() {
|
|
56
|
+
this.nativeElement.style.transition = this.savedTransition;
|
|
173
57
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Publishes the natural height of the projected content as `--kbq-accordion-content-height`,
|
|
60
|
+
* which the open state animates towards.
|
|
61
|
+
*
|
|
62
|
+
* `scrollHeight` is used rather than `getBoundingClientRect()`: the host is `overflow: hidden`
|
|
63
|
+
* and collapsed to `height: 0` while closed, so its box reports `0`, whereas `scrollHeight`
|
|
64
|
+
* still reports the height of the content it clips.
|
|
65
|
+
*/
|
|
66
|
+
updateHeight() {
|
|
67
|
+
this.renderer.setStyle(this.nativeElement, '--kbq-accordion-content-height', `${this.nativeElement.scrollHeight}px`, RendererStyleFlags2.DashCase);
|
|
178
68
|
}
|
|
179
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
180
|
-
/** @nocollapse */ static { this.ɵ
|
|
181
|
-
{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
|
|
182
|
-
], queries: [{ propertyName: "items", predicate: i0.forwardRef(() => KbqAccordionItem), descendants: true, isSignal: true }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [".kbq-accordion{display:block}.kbq-accordion-item{box-sizing:border-box;display:block;border-width:2px;border-style:solid;border-color:transparent}.kbq-accordion-header{display:flex;height:var(--kbq-accordion-size-item-header-height)}.kbq-accordion-content{display:block;overflow:hidden}.kbq-accordion-content>p{margin:unset;padding:var(--kbq-accordion-size-item-content-padding)}.kbq-accordion-content[data-state=open]{transition:height .3s ease-out;height:var(--radix-accordion-content-height)}.kbq-accordion-content[data-state=closed]{transition:height .3s ease-out;height:0}@media(prefers-reduced-motion:reduce){.kbq-accordion-content[data-state=open],.kbq-accordion-content[data-state=closed]{transition:none}}.kbq-accordion.cdk-keyboard-focused .kbq-accordion-item:focus-within{border-color:var(--kbq-accordion-item-states-focus-border-color)}.kbq-accordion-item{background:var(--kbq-accordion-item-default-background);color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-item .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-default-icon-color)}.kbq-accordion-trigger{width:100%;background:transparent;border:none;outline:none;color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-trigger:hover:not([data-disabled=true]){cursor:pointer}.kbq-accordion-trigger:hover:not([data-disabled=true]) .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-hover-icon-color)}.kbq-accordion-trigger[data-disabled=true]{color:var(--kbq-accordion-item-states-disabled-text-color)}.kbq-accordion-trigger[data-disabled=true] .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-disabled-icon-color)!important}.kbq-accordion-header,.kbq-accordion-trigger{font-size:var(--kbq-typography-text-big-font-size);font-style:var(--kbq-typography-text-big-font-style);font-weight:var(--kbq-typography-text-big-font-weight);line-height:var(--kbq-typography-text-big-line-height);font-family:var(--kbq-typography-text-big-font-family);text-transform:var(--kbq-typography-text-big-text-transform);font-feature-settings:var(--kbq-typography-text-big-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-letter-spacing)}.kbq-accordion-trigger__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-accordion-content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}\n", ".kbq-accordion{--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
69
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionContentDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
70
|
+
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqAccordionContentDirective, isStandalone: true, selector: "[kbqAccordionContent]", host: { listeners: { "transitionend": "toggle()" }, properties: { "attr.id": "contentId", "attr.role": "\"region\"", "attr.hidden": "hidden() ? \"\" : null", "attr.inert": "hidden() ? \"\" : null", "attr.aria-labelledby": "triggerId", "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.data-orientation": "item.orientation" } }, exportAs: ["kbqAccordionContent"], ngImport: i0 }); }
|
|
183
71
|
}
|
|
184
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
185
|
-
type:
|
|
186
|
-
args: [{
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
'[attr.
|
|
191
|
-
'
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
72
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionContentDirective, decorators: [{
|
|
73
|
+
type: Directive,
|
|
74
|
+
args: [{
|
|
75
|
+
selector: '[kbqAccordionContent]',
|
|
76
|
+
host: {
|
|
77
|
+
'[attr.id]': 'contentId',
|
|
78
|
+
'[attr.role]': '"region"',
|
|
79
|
+
'[attr.hidden]': 'hidden() ? "" : null',
|
|
80
|
+
// `hidden` alone does not take the collapsed content out of the tab order: the host keeps an
|
|
81
|
+
// explicit `display: block` so the height can animate, which overrides `[hidden]`'s
|
|
82
|
+
// `display: none`. Without `inert`, every control inside a closed section stays focusable in
|
|
83
|
+
// a zero-height, clipped box.
|
|
84
|
+
'[attr.inert]': 'hidden() ? "" : null',
|
|
85
|
+
'[attr.aria-labelledby]': 'triggerId',
|
|
86
|
+
'[attr.data-state]': 'item.dataState',
|
|
87
|
+
'[attr.data-disabled]': 'item.disabled',
|
|
88
|
+
'[attr.data-orientation]': 'item.orientation',
|
|
89
|
+
'(transitionend)': 'toggle()'
|
|
90
|
+
},
|
|
91
|
+
exportAs: 'kbqAccordionContent'
|
|
92
|
+
}]
|
|
93
|
+
}], ctorParameters: () => [] });
|
|
198
94
|
|
|
199
95
|
class KbqAccordionTriggerDirective {
|
|
200
96
|
constructor() {
|
|
@@ -220,14 +116,38 @@ class KbqAccordionTriggerDirective {
|
|
|
220
116
|
this.item.toggle();
|
|
221
117
|
this.accordion.setActiveItem(this.item);
|
|
222
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Keeps the accordion's key manager in sync with native focus so that arrow-key navigation
|
|
121
|
+
* continues from the header the user has just tabbed/focused into.
|
|
122
|
+
* @docs-private
|
|
123
|
+
*/
|
|
124
|
+
onFocus() {
|
|
125
|
+
this.accordion.setActiveItem(this.item);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Routes keyboard interaction to the accordion, but only while the trigger itself is focused.
|
|
129
|
+
*
|
|
130
|
+
* A `keydown` targets the focused element, so header actions placed next to the trigger and
|
|
131
|
+
* controls inside the expanded content keep their own keys — the accordion no longer toggles the
|
|
132
|
+
* section on Enter/Space nor moves focus to another header on the arrow keys. The `target` check
|
|
133
|
+
* additionally covers focusable content mistakenly nested inside the trigger.
|
|
134
|
+
*/
|
|
135
|
+
onKeydown(event) {
|
|
136
|
+
if (event.target !== this.nativeElement)
|
|
137
|
+
return;
|
|
138
|
+
// The key manager can lag behind when focus was moved programmatically rather than by the
|
|
139
|
+
// user, in which case `onFocus` never ran.
|
|
140
|
+
this.accordion.setActiveItem(this.item);
|
|
141
|
+
this.accordion.keydownHandler(event);
|
|
142
|
+
}
|
|
223
143
|
/** @docs-private */
|
|
224
144
|
focus() {
|
|
225
145
|
this.nativeElement.focus();
|
|
226
146
|
}
|
|
227
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
228
|
-
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.
|
|
147
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionTriggerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
148
|
+
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqAccordionTriggerDirective, isStandalone: true, selector: "[kbqAccordionTrigger]", host: { listeners: { "click": "onClick()", "focus": "onFocus()", "keydown": "onKeydown($event)" }, properties: { "attr.id": "triggerId", "attr.role": "\"button\"", "attr.aria-expanded": "item.expanded", "attr.aria-controls": "contentId", "attr.aria-disabled": "item.disabled", "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.data-orientation": "item.orientation" } }, ngImport: i0 }); }
|
|
229
149
|
}
|
|
230
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
150
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionTriggerDirective, decorators: [{
|
|
231
151
|
type: Directive,
|
|
232
152
|
args: [{
|
|
233
153
|
selector: '[kbqAccordionTrigger]',
|
|
@@ -240,20 +160,22 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
240
160
|
'[attr.data-state]': 'item.dataState',
|
|
241
161
|
'[attr.data-disabled]': 'item.disabled',
|
|
242
162
|
'[attr.data-orientation]': 'item.orientation',
|
|
243
|
-
'(click)': 'onClick()'
|
|
163
|
+
'(click)': 'onClick()',
|
|
164
|
+
'(focus)': 'onFocus()',
|
|
165
|
+
'(keydown)': 'onKeydown($event)'
|
|
244
166
|
}
|
|
245
167
|
}]
|
|
246
168
|
}] });
|
|
247
169
|
|
|
248
170
|
class KbqAccordionTrigger {
|
|
249
171
|
get isFill() {
|
|
250
|
-
return this.accordion.variant() ===
|
|
172
|
+
return this.accordion.variant() === 'fill';
|
|
251
173
|
}
|
|
252
174
|
get isHug() {
|
|
253
|
-
return this.accordion.variant() ===
|
|
175
|
+
return this.accordion.variant() === 'hug';
|
|
254
176
|
}
|
|
255
177
|
get isHugSpaceBetween() {
|
|
256
|
-
return this.accordion.variant() ===
|
|
178
|
+
return this.accordion.variant() === 'hugSpaceBetween';
|
|
257
179
|
}
|
|
258
180
|
constructor() {
|
|
259
181
|
/** @docs-private */
|
|
@@ -263,13 +185,16 @@ class KbqAccordionTrigger {
|
|
|
263
185
|
/** @docs-private */
|
|
264
186
|
this.icon = viewChild.required(KbqIcon);
|
|
265
187
|
this.afterRenderRef = afterNextRender(() => {
|
|
266
|
-
setTimeout(() => this.enableAnimation());
|
|
188
|
+
this.animationTimerId = setTimeout(() => this.enableAnimation());
|
|
267
189
|
this.afterRenderRef?.destroy();
|
|
268
190
|
});
|
|
269
191
|
}
|
|
270
192
|
ngAfterViewInit() {
|
|
271
193
|
this.disableAnimation();
|
|
272
194
|
}
|
|
195
|
+
ngOnDestroy() {
|
|
196
|
+
clearTimeout(this.animationTimerId);
|
|
197
|
+
}
|
|
273
198
|
disableAnimation() {
|
|
274
199
|
this.savedTransition = this.icon().elementRef.nativeElement.style.transition;
|
|
275
200
|
this.icon().getHostElement().style.transition = 'none';
|
|
@@ -277,17 +202,17 @@ class KbqAccordionTrigger {
|
|
|
277
202
|
enableAnimation() {
|
|
278
203
|
this.icon().getHostElement().style.transition = this.savedTransition;
|
|
279
204
|
}
|
|
280
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
281
|
-
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.
|
|
205
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionTrigger, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
206
|
+
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.30", type: KbqAccordionTrigger, isStandalone: true, selector: "kbq-accordion-trigger, [kbq-accordion-trigger]", host: { properties: { "class.kbq-accordion-trigger_fill": "isFill", "class.kbq-accordion-trigger_hug": "isHug", "class.kbq-accordion-trigger_hug-space-between": "isHugSpaceBetween" }, classAttribute: "kbq-accordion-trigger" }, viewQueries: [{ propertyName: "icon", first: true, predicate: KbqIcon, descendants: true, isSignal: true }], hostDirectives: [{ directive: KbqAccordionTriggerDirective }], ngImport: i0, template: `
|
|
282
207
|
<i
|
|
283
208
|
kbq-icon="{{ isHugSpaceBetween ? 'kbq-chevron-down-s_16' : 'kbq-chevron-right-s_16' }}"
|
|
284
209
|
class="kbq-accordion-trigger__icon"
|
|
285
210
|
></i>
|
|
286
211
|
|
|
287
212
|
<ng-content />
|
|
288
|
-
`, isInline: true, styles: [".kbq-accordion-trigger{display:flex;flex-direction:row;align-items:center}.kbq-accordion-trigger .kbq-accordion-trigger__icon{box-sizing:initial;align-self:flex-start;padding:var(--kbq-size-xxs);transition:transform .3s ease-out}.kbq-accordion-trigger .kbq-accordion-trigger__badge,.kbq-accordion-trigger .kbq-accordion-trigger__caption{margin-top:var(--kbq-size-xxs);margin-right:var(--kbq-size-s)}.kbq-accordion-trigger .kbq-accordion-trigger__action{padding:var(--kbq-size-xxs) var(--kbq-size-xxs) var(--kbq-size-3xs);margin-bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-accordion-trigger.kbq-accordion-trigger_fill{padding:var(--kbq-accordion-size-item-header-variant-fill-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_fill[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug{flex-direction:row-reverse;justify-content:flex-end;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between{flex-direction:row-reverse;justify-content:space-between;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(-180deg)}button.kbq-accordion-trigger{flex:1}\n", ".kbq-accordion{--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
213
|
+
`, isInline: true, styles: [".kbq-accordion-trigger{display:flex;flex-direction:row;align-items:center}.kbq-accordion-trigger .kbq-accordion-trigger__icon{box-sizing:initial;align-self:flex-start;padding:var(--kbq-size-xxs);transition:transform .3s ease-out}@media(prefers-reduced-motion:reduce){.kbq-accordion-trigger .kbq-accordion-trigger__icon{transition:none}}.kbq-accordion-trigger .kbq-accordion-trigger__badge,.kbq-accordion-trigger .kbq-accordion-trigger__caption{margin-top:var(--kbq-size-xxs);margin-right:var(--kbq-size-s)}.kbq-accordion-trigger .kbq-accordion-trigger__action{padding:var(--kbq-size-xxs) var(--kbq-size-xxs) var(--kbq-size-3xs);margin-bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-accordion-trigger.kbq-accordion-trigger_fill{padding:var(--kbq-accordion-size-item-header-variant-fill-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_fill[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug{flex-direction:row-reverse;justify-content:flex-end;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between{flex-direction:row-reverse;justify-content:space-between;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(-180deg)}button.kbq-accordion-trigger{flex:1;min-width:0}\n", ".kbq-accordion{--kbq-accordion-size-item-border-width: 2px;--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-size-item-header-actions-gap: var(--kbq-size-3xs);--kbq-accordion-size-item-header-actions-padding-right: var(--kbq-size-s);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"], dependencies: [{ kind: "component", type: KbqIcon, selector: "[kbq-icon]", inputs: ["small", "autoColor", "kbq-icon"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
289
214
|
}
|
|
290
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
215
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionTrigger, decorators: [{
|
|
291
216
|
type: Component,
|
|
292
217
|
args: [{ selector: 'kbq-accordion-trigger, [kbq-accordion-trigger]', imports: [KbqIcon], template: `
|
|
293
218
|
<i
|
|
@@ -301,24 +226,27 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
301
226
|
'[class.kbq-accordion-trigger_fill]': 'isFill',
|
|
302
227
|
'[class.kbq-accordion-trigger_hug]': 'isHug',
|
|
303
228
|
'[class.kbq-accordion-trigger_hug-space-between]': 'isHugSpaceBetween'
|
|
304
|
-
}, hostDirectives: [KbqAccordionTriggerDirective], styles: [".kbq-accordion-trigger{display:flex;flex-direction:row;align-items:center}.kbq-accordion-trigger .kbq-accordion-trigger__icon{box-sizing:initial;align-self:flex-start;padding:var(--kbq-size-xxs);transition:transform .3s ease-out}.kbq-accordion-trigger .kbq-accordion-trigger__badge,.kbq-accordion-trigger .kbq-accordion-trigger__caption{margin-top:var(--kbq-size-xxs);margin-right:var(--kbq-size-s)}.kbq-accordion-trigger .kbq-accordion-trigger__action{padding:var(--kbq-size-xxs) var(--kbq-size-xxs) var(--kbq-size-3xs);margin-bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-accordion-trigger.kbq-accordion-trigger_fill{padding:var(--kbq-accordion-size-item-header-variant-fill-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_fill[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug{flex-direction:row-reverse;justify-content:flex-end;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between{flex-direction:row-reverse;justify-content:space-between;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(-180deg)}button.kbq-accordion-trigger{flex:1}\n", ".kbq-accordion{--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"] }]
|
|
229
|
+
}, hostDirectives: [KbqAccordionTriggerDirective], styles: [".kbq-accordion-trigger{display:flex;flex-direction:row;align-items:center}.kbq-accordion-trigger .kbq-accordion-trigger__icon{box-sizing:initial;align-self:flex-start;padding:var(--kbq-size-xxs);transition:transform .3s ease-out}@media(prefers-reduced-motion:reduce){.kbq-accordion-trigger .kbq-accordion-trigger__icon{transition:none}}.kbq-accordion-trigger .kbq-accordion-trigger__badge,.kbq-accordion-trigger .kbq-accordion-trigger__caption{margin-top:var(--kbq-size-xxs);margin-right:var(--kbq-size-s)}.kbq-accordion-trigger .kbq-accordion-trigger__action{padding:var(--kbq-size-xxs) var(--kbq-size-xxs) var(--kbq-size-3xs);margin-bottom:calc(-1 * var(--kbq-size-3xs))}.kbq-accordion-trigger.kbq-accordion-trigger_fill{padding:var(--kbq-accordion-size-item-header-variant-fill-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_fill[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug{flex-direction:row-reverse;justify-content:flex-end;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(90deg)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between{flex-direction:row-reverse;justify-content:space-between;padding:var(--kbq-accordion-size-item-header-variant-hug-padding)}.kbq-accordion-trigger.kbq-accordion-trigger_hug-space-between[data-state=open]>.kbq-accordion-trigger__icon{transform:rotate(-180deg)}button.kbq-accordion-trigger{flex:1;min-width:0}\n", ".kbq-accordion{--kbq-accordion-size-item-border-width: 2px;--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-size-item-header-actions-gap: var(--kbq-size-3xs);--kbq-accordion-size-item-header-actions-padding-right: var(--kbq-size-s);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"] }]
|
|
305
230
|
}], ctorParameters: () => [], propDecorators: { icon: [{ type: i0.ViewChild, args: [i0.forwardRef(() => KbqIcon), { isSignal: true }] }] } });
|
|
306
231
|
|
|
307
|
-
let uniqueIdCounter = 0;
|
|
232
|
+
let uniqueIdCounter$1 = 0;
|
|
308
233
|
class KbqAccordionItem {
|
|
309
234
|
/** The unique AccordionItem id. */
|
|
310
235
|
get id() {
|
|
311
236
|
return this._id;
|
|
312
237
|
}
|
|
238
|
+
/** The current open/closed state of the item. @docs-private */
|
|
313
239
|
get dataState() {
|
|
314
240
|
return this.expanded ? 'open' : 'closed';
|
|
315
241
|
}
|
|
242
|
+
/** The layout orientation inherited from the parent accordion. @docs-private */
|
|
316
243
|
get orientation() {
|
|
317
244
|
return this.accordion.orientation();
|
|
318
245
|
}
|
|
319
246
|
/** Whether the AccordionItem is expanded. */
|
|
320
|
-
//
|
|
321
|
-
//
|
|
247
|
+
// Kept as an `@Input` accessor (not `model()`): the setter runs a synchronous side-effect
|
|
248
|
+
// cascade (emits opened/closed/expandedChange, notifies the selection dispatcher, toggles the
|
|
249
|
+
// content and persists state) that sibling items rely on within the same change-detection tick.
|
|
322
250
|
get expanded() {
|
|
323
251
|
return this._expanded;
|
|
324
252
|
}
|
|
@@ -334,39 +262,35 @@ class KbqAccordionItem {
|
|
|
334
262
|
* In the unique selection dispatcher, the id parameter is the id of the KbqAccordionItem,
|
|
335
263
|
* the name value is the id of the accordion.
|
|
336
264
|
*/
|
|
337
|
-
|
|
338
|
-
this.expansionDispatcher.notify(this.value, accordionId);
|
|
265
|
+
this.expansionDispatcher.notify(this.value(), this.accordion.id);
|
|
339
266
|
}
|
|
340
267
|
else {
|
|
341
268
|
// TODO: The 'emit' function requires a mandatory void argument
|
|
342
269
|
this.closed.emit();
|
|
343
270
|
}
|
|
344
|
-
this.content()
|
|
271
|
+
this.content()?.toggle();
|
|
345
272
|
this.accordion.saveItemState(this);
|
|
346
273
|
// Ensures that the animation will run when the value is set outside of an `@Input`.
|
|
347
274
|
// This includes cases like the open, close and toggle methods.
|
|
348
275
|
this.changeDetectorRef.markForCheck();
|
|
349
276
|
}
|
|
350
277
|
}
|
|
351
|
-
// TODO: Skipped for migration because:
|
|
352
|
-
// Accessor inputs cannot be migrated as they are too complex.
|
|
353
|
-
set value(value) {
|
|
354
|
-
this._value = value;
|
|
355
|
-
}
|
|
356
|
-
get value() {
|
|
357
|
-
return this._value || this.id;
|
|
358
|
-
}
|
|
359
278
|
/** Whether the AccordionItem is disabled. */
|
|
360
|
-
//
|
|
361
|
-
//
|
|
279
|
+
// Kept as an `@Input` accessor (not a signal): `KbqAccordionItem` is a `FocusKeyManager` option,
|
|
280
|
+
// and `ListKeyManagerOption.disabled` (core/a11y/key-manager) is read as a plain `boolean` — a
|
|
281
|
+
// signal function is always truthy, which makes the key manager treat every item as disabled.
|
|
282
|
+
// The getter also merges the item's own state with the parent accordion's (an effective value).
|
|
362
283
|
get disabled() {
|
|
363
|
-
return this.accordion.disabled()
|
|
284
|
+
return this.accordion.disabled() || this._disabled;
|
|
364
285
|
}
|
|
365
286
|
set disabled(value) {
|
|
366
287
|
this._disabled = value;
|
|
367
288
|
}
|
|
368
289
|
constructor() {
|
|
369
|
-
/**
|
|
290
|
+
/**
|
|
291
|
+
* The accordion this item belongs to — always the nearest one, because it is injected.
|
|
292
|
+
* The accordion reads it back to tell its own items apart from a nested accordion's.
|
|
293
|
+
*/
|
|
370
294
|
this.accordion = inject(KbqAccordion);
|
|
371
295
|
/** @docs-private */
|
|
372
296
|
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
@@ -378,20 +302,23 @@ class KbqAccordionItem {
|
|
|
378
302
|
this.triggerComponent = contentChild(KbqAccordionTrigger, ...(ngDevMode ? [{ debugName: "triggerComponent" }] : []));
|
|
379
303
|
/** @docs-private */
|
|
380
304
|
this.content = contentChild(forwardRef(() => KbqAccordionContentDirective), ...(ngDevMode ? [{ debugName: "content" }] : []));
|
|
381
|
-
this._id = `kbq-accordion-item-${uniqueIdCounter++}`;
|
|
305
|
+
this._id = `kbq-accordion-item-${uniqueIdCounter$1++}`;
|
|
382
306
|
this._expanded = false;
|
|
307
|
+
/**
|
|
308
|
+
* The item's own `value` input. Must stay `public`: a `protected` input cannot be bound from a
|
|
309
|
+
* consumer template (TS2445 under full AOT template type-checking).
|
|
310
|
+
* @docs-private
|
|
311
|
+
*/
|
|
312
|
+
this.valueInput = input('', ...(ngDevMode ? [{ debugName: "valueInput", alias: 'value' }] : [{ alias: 'value' }]));
|
|
313
|
+
/** The item's effective value — its own value, or the item id when none is provided. */
|
|
314
|
+
this.value = computed(() => this.valueInput() || this.id, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
383
315
|
this._disabled = false;
|
|
384
316
|
/** Event emitted every time the AccordionItem is closed. */
|
|
385
317
|
this.closed = output();
|
|
386
318
|
/** Event emitted every time the AccordionItem is opened. */
|
|
387
319
|
this.opened = output();
|
|
388
320
|
/**
|
|
389
|
-
*
|
|
390
|
-
* @docs-private
|
|
391
|
-
*/
|
|
392
|
-
this.destroyed = new EventEmitter();
|
|
393
|
-
/**
|
|
394
|
-
* Emits whenever the expanded state of the accordion changes.
|
|
321
|
+
* Emits whenever the expanded state of the accordion item changes.
|
|
395
322
|
* Primarily used to facilitate two-way binding.
|
|
396
323
|
* @docs-private
|
|
397
324
|
*/
|
|
@@ -399,28 +326,36 @@ class KbqAccordionItem {
|
|
|
399
326
|
/** Subscription to openAll/closeAll events. */
|
|
400
327
|
this.openCloseAllSubscription = Subscription.EMPTY;
|
|
401
328
|
this.removeUniqueSelectionListener = this.expansionDispatcher.listen((id, accordionId) => {
|
|
402
|
-
if (this.accordion.
|
|
403
|
-
|
|
329
|
+
if (this.accordion.id !== accordionId)
|
|
330
|
+
return;
|
|
331
|
+
// The dispatcher payload is a single value (individual toggle / single-mode value) or an
|
|
332
|
+
// array (controlled `[value]`, default value and restored state). Match exactly to avoid
|
|
333
|
+
// substring collisions (e.g. `item-10` must not open `item-1`).
|
|
334
|
+
const value = id;
|
|
335
|
+
const ownValue = this.value();
|
|
336
|
+
if (Array.isArray(value)) {
|
|
337
|
+
// Sync to array membership: opens members, closes non-members.
|
|
338
|
+
this.expanded = value.includes(ownValue);
|
|
339
|
+
}
|
|
340
|
+
else if (this.accordion.isMultiple) {
|
|
341
|
+
// Individual toggle in multiple mode: only the matching item opens; others stay independent.
|
|
342
|
+
if (value === ownValue) {
|
|
404
343
|
this.expanded = true;
|
|
405
344
|
}
|
|
406
345
|
}
|
|
407
346
|
else {
|
|
408
|
-
|
|
347
|
+
// Individual toggle / controlled value in single mode: exactly one item stays open.
|
|
348
|
+
this.expanded = value === ownValue;
|
|
409
349
|
}
|
|
410
350
|
});
|
|
411
351
|
// When an accordion item is hosted in an accordion, subscribe to open/close events.
|
|
412
|
-
|
|
413
|
-
this.openCloseAllSubscription = this.subscribeToOpenCloseAllActions();
|
|
414
|
-
}
|
|
415
|
-
this.accordion.saveItemState(this, false);
|
|
352
|
+
this.openCloseAllSubscription = this.subscribeToOpenCloseAllActions();
|
|
416
353
|
}
|
|
417
|
-
/** Emits an event for the accordion item being destroyed. */
|
|
418
354
|
ngOnDestroy() {
|
|
419
|
-
this.destroyed.emit();
|
|
420
|
-
this.destroyed.complete();
|
|
421
355
|
this.removeUniqueSelectionListener();
|
|
422
356
|
this.openCloseAllSubscription.unsubscribe();
|
|
423
357
|
}
|
|
358
|
+
/** Moves focus to the item's trigger. */
|
|
424
359
|
focus() {
|
|
425
360
|
this.trigger()?.focus();
|
|
426
361
|
}
|
|
@@ -442,16 +377,19 @@ class KbqAccordionItem {
|
|
|
442
377
|
this.expanded = true;
|
|
443
378
|
}
|
|
444
379
|
}
|
|
380
|
+
/** Returns a snapshot of the item's current persisted state. @docs-private */
|
|
445
381
|
getState() {
|
|
446
382
|
return {
|
|
447
383
|
expanded: this.expanded,
|
|
448
|
-
value: this.value
|
|
384
|
+
value: this.value()
|
|
449
385
|
};
|
|
450
386
|
}
|
|
387
|
+
/** Disables the open/close animation of the item's content and chevron. @docs-private */
|
|
451
388
|
disableAnimation() {
|
|
452
389
|
this.content()?.disableAnimation();
|
|
453
390
|
this.triggerComponent()?.disableAnimation();
|
|
454
391
|
}
|
|
392
|
+
/** Restores the open/close animation of the item's content and chevron. @docs-private */
|
|
455
393
|
enableAnimation() {
|
|
456
394
|
this.content()?.enableAnimation();
|
|
457
395
|
this.triggerComponent()?.enableAnimation();
|
|
@@ -464,10 +402,10 @@ class KbqAccordionItem {
|
|
|
464
402
|
}
|
|
465
403
|
});
|
|
466
404
|
}
|
|
467
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
468
|
-
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.
|
|
405
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionItem, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
406
|
+
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "20.3.30", type: KbqAccordionItem, isStandalone: true, selector: "kbq-accordion-item, [kbq-accordion-item]", inputs: { expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: false, isRequired: false, transformFunction: booleanAttribute }, valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: false, isRequired: false, transformFunction: booleanAttribute } }, outputs: { closed: "closed", opened: "opened", expandedChange: "expandedChange" }, host: { properties: { "attr.data-state": "dataState", "attr.data-disabled": "disabled", "attr.data-orientation": "orientation" }, classAttribute: "kbq-accordion-item" }, queries: [{ propertyName: "trigger", first: true, predicate: KbqAccordionTriggerDirective, descendants: true, isSignal: true }, { propertyName: "triggerComponent", first: true, predicate: KbqAccordionTrigger, descendants: true, isSignal: true }, { propertyName: "content", first: true, predicate: i0.forwardRef(() => KbqAccordionContentDirective), descendants: true, isSignal: true }], ngImport: i0 }); }
|
|
469
407
|
}
|
|
470
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
408
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionItem, decorators: [{
|
|
471
409
|
type: Directive,
|
|
472
410
|
args: [{
|
|
473
411
|
selector: 'kbq-accordion-item, [kbq-accordion-item]',
|
|
@@ -481,92 +419,314 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
481
419
|
}], ctorParameters: () => [], propDecorators: { trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqAccordionTriggerDirective), { isSignal: true }] }], triggerComponent: [{ type: i0.ContentChild, args: [i0.forwardRef(() => KbqAccordionTrigger), { isSignal: true }] }], content: [{ type: i0.ContentChild, args: [forwardRef(() => KbqAccordionContentDirective), { isSignal: true }] }], expanded: [{
|
|
482
420
|
type: Input,
|
|
483
421
|
args: [{ transform: booleanAttribute }]
|
|
484
|
-
}], value: [{
|
|
485
|
-
type: Input
|
|
486
|
-
}], disabled: [{
|
|
422
|
+
}], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], disabled: [{
|
|
487
423
|
type: Input,
|
|
488
424
|
args: [{ transform: booleanAttribute }]
|
|
489
425
|
}], closed: [{ type: i0.Output, args: ["closed"] }], opened: [{ type: i0.Output, args: ["opened"] }], expandedChange: [{ type: i0.Output, args: ["expandedChange"] }] } });
|
|
490
426
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
427
|
+
/**
|
|
428
|
+
* Default `KbqAccordionStateStore` implementation backed by `localStorage`.
|
|
429
|
+
*
|
|
430
|
+
* All access is guarded so it is safe on the server (SSR) and in environments where storage
|
|
431
|
+
* throws on access (private mode, sandboxed iframes) or contains corrupt JSON.
|
|
432
|
+
*/
|
|
433
|
+
class KbqAccordionLocalStorageStateStore {
|
|
434
|
+
constructor() {
|
|
435
|
+
this.isBrowser = inject(Platform).isBrowser;
|
|
436
|
+
this.window = inject(KBQ_WINDOW);
|
|
495
437
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
438
|
+
getState(key) {
|
|
439
|
+
if (!this.isBrowser)
|
|
440
|
+
return null;
|
|
441
|
+
try {
|
|
442
|
+
const raw = this.window.localStorage.getItem(key);
|
|
443
|
+
return raw ? JSON.parse(raw) : null;
|
|
444
|
+
}
|
|
445
|
+
catch {
|
|
446
|
+
return null;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
setState(key, state) {
|
|
450
|
+
if (!this.isBrowser)
|
|
451
|
+
return;
|
|
452
|
+
try {
|
|
453
|
+
this.window.localStorage.setItem(key, JSON.stringify(state));
|
|
454
|
+
}
|
|
455
|
+
catch {
|
|
456
|
+
// Ignore storage write failures (quota exceeded, disabled/blocked storage, etc.).
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionLocalStorageStateStore, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
460
|
+
/** @nocollapse */ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionLocalStorageStateStore, providedIn: 'root' }); }
|
|
461
|
+
}
|
|
462
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionLocalStorageStateStore, decorators: [{
|
|
463
|
+
type: Injectable,
|
|
464
|
+
args: [{ providedIn: 'root' }]
|
|
465
|
+
}] });
|
|
466
|
+
/**
|
|
467
|
+
* Injection token for the store used to persist accordion state while `useStateSaving` is enabled.
|
|
468
|
+
* Defaults to a `localStorage`-backed implementation (`KbqAccordionLocalStorageStateStore`).
|
|
469
|
+
*/
|
|
470
|
+
const KBQ_ACCORDION_STATE_STORE = new InjectionToken('KBQ_ACCORDION_STATE_STORE', {
|
|
471
|
+
providedIn: 'root',
|
|
472
|
+
factory: () => inject(KbqAccordionLocalStorageStateStore)
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
let uniqueIdCounter = 0;
|
|
476
|
+
class KbqAccordion {
|
|
477
|
+
/** The unique id of this accordion. */
|
|
478
|
+
get id() {
|
|
479
|
+
return this._id;
|
|
480
|
+
}
|
|
481
|
+
/** Whether multiple items can be expanded at the same time. */
|
|
482
|
+
get isMultiple() {
|
|
483
|
+
return this.type() === 'multiple';
|
|
484
|
+
}
|
|
485
|
+
/** Whether a persisted state exists for this accordion. */
|
|
486
|
+
get hasSavedState() {
|
|
487
|
+
return typeof this.state === 'object' && this.state !== null;
|
|
499
488
|
}
|
|
500
489
|
constructor() {
|
|
501
|
-
this.renderer = inject(Renderer2);
|
|
502
|
-
this.platform = inject(Platform);
|
|
503
490
|
/** @docs-private */
|
|
504
|
-
this.
|
|
491
|
+
this.focusMonitor = inject(FocusMonitor);
|
|
505
492
|
/** @docs-private */
|
|
506
|
-
this.
|
|
493
|
+
this.elementRef = inject(ElementRef);
|
|
507
494
|
/** @docs-private */
|
|
508
|
-
this.
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
495
|
+
this.changeDetectorRef = inject(ChangeDetectorRef);
|
|
496
|
+
/** @docs-private */
|
|
497
|
+
this.selectionDispatcher = inject(UniqueSelectionDispatcher);
|
|
498
|
+
/** @docs-private */
|
|
499
|
+
this.dir = inject(Directionality, { optional: true });
|
|
500
|
+
this.injector = inject(Injector);
|
|
501
|
+
this.stateStore = inject(KBQ_ACCORDION_STATE_STORE);
|
|
502
|
+
/** Emits every time `openAll()` or `closeAll()` is called. @docs-private */
|
|
503
|
+
this.openCloseAllActions = new Subject();
|
|
504
|
+
/**
|
|
505
|
+
* Every item the content query matches, including those of a nested accordion.
|
|
506
|
+
* Use `items` instead — this one is the raw, unfiltered query.
|
|
507
|
+
* @docs-private
|
|
508
|
+
*/
|
|
509
|
+
// The generic is explicit because `forwardRef` erases the locator type, which would leave both
|
|
510
|
+
// this query and `items` as `Signal<any[]>` in the public API report.
|
|
511
|
+
this.allItems = contentChildren(forwardRef(() => KbqAccordionItem), ...(ngDevMode ? [{ debugName: "allItems", descendants: true }] : [{ descendants: true }]));
|
|
512
|
+
/**
|
|
513
|
+
* The accordion items that belong to this accordion.
|
|
514
|
+
*
|
|
515
|
+
* A descendant content query resolves against the template the tag is authored in and does not
|
|
516
|
+
* stop at a nested component of the same type, so `allItems` of an outer accordion also matches
|
|
517
|
+
* the items of an accordion rendered inside an item's content. Each item's own `accordion` is
|
|
518
|
+
* injected and therefore always its nearest one, which makes ownership the reliable filter.
|
|
519
|
+
* Without it the key manager would move focus into the nested accordion's headers, `valueChange`
|
|
520
|
+
* would report a nested item's value and state saving would persist it under the outer key.
|
|
521
|
+
* @docs-private
|
|
522
|
+
*/
|
|
523
|
+
this.items = computed(() => this.allItems().filter((item) => item.accordion === this), ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
524
|
+
/** Whether the accordion persists the expanded state of its items across reloads. Defaults to `false`. */
|
|
525
|
+
this.useStateSaving = input(false, ...(ngDevMode ? [{ debugName: "useStateSaving", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
526
|
+
/**
|
|
527
|
+
* A stable, consumer-provided key used to persist state when `useStateSaving` is enabled.
|
|
528
|
+
* Strongly recommended: without it the accordion falls back to an auto-generated,
|
|
529
|
+
* instantiation-order-dependent id that is unreliable under lazy/conditional/reordered rendering.
|
|
530
|
+
*/
|
|
531
|
+
this.stateSavingKey = input('', ...(ngDevMode ? [{ debugName: "stateSavingKey" }] : []));
|
|
532
|
+
/** The visual variant of the accordion. Defaults to `fill`. */
|
|
533
|
+
this.variant = input('fill', ...(ngDevMode ? [{ debugName: "variant" }] : []));
|
|
534
|
+
/** Whether the whole accordion is disabled. */
|
|
535
|
+
this.disabled = input(undefined, ...(ngDevMode ? [{ debugName: "disabled", transform: booleanAttribute }] : [{ transform: booleanAttribute }]));
|
|
536
|
+
/** The layout orientation of the accordion. Defaults to `vertical`. */
|
|
537
|
+
this.orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
538
|
+
/**
|
|
539
|
+
* The `aria-level` applied to the item headings. Defaults to `2`.
|
|
540
|
+
* Set it to match the surrounding document outline (e.g. `3` when nested under an `<h2>` section).
|
|
541
|
+
*/
|
|
542
|
+
this.level = input(2, ...(ngDevMode ? [{ debugName: "level", transform: numberAttribute }] : [{ transform: numberAttribute }]));
|
|
543
|
+
/**
|
|
544
|
+
* The value of the item(s) to expand when initially rendered.
|
|
545
|
+
* Use when you do not need to control the state of the items.
|
|
546
|
+
*/
|
|
547
|
+
this.defaultValue = input([], ...(ngDevMode ? [{ debugName: "defaultValue" }] : []));
|
|
548
|
+
/** Determines whether one or multiple items can be expanded at the same time. */
|
|
549
|
+
this.type = input('single', ...(ngDevMode ? [{ debugName: "type" }] : []));
|
|
550
|
+
/** Whether an expanded item can be collapsed by the user. Defaults to `true`. */
|
|
551
|
+
this.collapsible = input(true, ...(ngDevMode ? [{ debugName: "collapsible" }] : []));
|
|
552
|
+
/**
|
|
553
|
+
* The raw controlled `value` input. Must stay `public`: a `protected` input cannot be bound from
|
|
554
|
+
* a consumer template (TS2445 under full AOT template type-checking).
|
|
555
|
+
* @docs-private
|
|
556
|
+
*/
|
|
557
|
+
// `input()` (not `model()`): a `model()` would auto-create a colliding `valueChange` output.
|
|
558
|
+
this.valueInput = input(undefined, ...(ngDevMode ? [{ debugName: "valueInput", alias: 'value' }] : [{ alias: 'value' }]));
|
|
559
|
+
/**
|
|
560
|
+
* The controlled value of the item(s) to expand, reshaped by mode. Supports `[(value)]`.
|
|
561
|
+
* Falls back to `defaultValue` while `value` is unbound.
|
|
562
|
+
*
|
|
563
|
+
* Always an array in `multiple` mode and always a string in `single` mode — an empty string
|
|
564
|
+
* when nothing is expanded, matching what `valueChange` emits.
|
|
565
|
+
*/
|
|
566
|
+
this.value = computed(() => {
|
|
567
|
+
const value = this.valueInput() ?? this.defaultValue();
|
|
568
|
+
const array = Array.isArray(value) ? value : [value];
|
|
569
|
+
return this.isMultiple ? array : (array[0] ?? '');
|
|
570
|
+
}, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
571
|
+
/** Emits the current value whenever the expanded state of the accordion changes. */
|
|
572
|
+
this.valueChange = output();
|
|
573
|
+
/** `defaultValue` normalized to an array for internal coordination. */
|
|
574
|
+
this.defaultValueArray = computed(() => {
|
|
575
|
+
const value = this.defaultValue();
|
|
576
|
+
return Array.isArray(value) ? value : [value];
|
|
577
|
+
}, ...(ngDevMode ? [{ debugName: "defaultValueArray" }] : []));
|
|
578
|
+
this._id = `kbq-accordion-${uniqueIdCounter++}`;
|
|
579
|
+
this.state = null;
|
|
580
|
+
// Re-emit `valueChange` whenever any (current or future) item toggles its expanded state.
|
|
581
|
+
// Reading `items()` inside the effect keeps the subscriptions in sync with dynamically
|
|
582
|
+
// added/removed items.
|
|
583
|
+
effect((onCleanup) => {
|
|
584
|
+
const subscriptions = this.items().map((item) => item.expandedChange.subscribe(() => this.valueChange.emit(this.getCurrentValue())));
|
|
585
|
+
onCleanup(() => subscriptions.forEach((subscription) => subscription.unsubscribe()));
|
|
512
586
|
});
|
|
587
|
+
// Notify the selection dispatcher when the controlled `[value]` changes (the old setter's
|
|
588
|
+
// side-effect). The `undefined` sentinel keeps the mandatory first run a no-op when unbound;
|
|
589
|
+
// when bound it re-notifies the value `ngAfterContentInit` already sent (idempotent).
|
|
590
|
+
effect(() => {
|
|
591
|
+
const value = this.valueInput();
|
|
592
|
+
if (value === undefined)
|
|
593
|
+
return;
|
|
594
|
+
untracked(() => this.selectionDispatcher.notify(this.value(), this.id));
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
ngAfterContentInit() {
|
|
598
|
+
if (this.useStateSaving()) {
|
|
599
|
+
if (isDevMode() && !this.stateSavingKey()) {
|
|
600
|
+
// eslint-disable-next-line no-console
|
|
601
|
+
console.warn('KbqAccordion: `useStateSaving` is enabled without a `stateSavingKey`. Falling back to an ' +
|
|
602
|
+
'auto-generated id, which is unreliable across lazy/conditional/reordered rendering. ' +
|
|
603
|
+
'Provide a stable `stateSavingKey`.');
|
|
604
|
+
}
|
|
605
|
+
this.state = this.stateStore.getState(this.stateStorageKey);
|
|
606
|
+
}
|
|
607
|
+
if (this.valueInput() !== undefined) {
|
|
608
|
+
this.selectionDispatcher.notify(this.value(), this.id);
|
|
609
|
+
}
|
|
610
|
+
else if (this.useStateSaving() && this.hasSavedState) {
|
|
611
|
+
const expandedValues = Object.keys(this.state)
|
|
612
|
+
.filter((key) => this.state[key].expanded)
|
|
613
|
+
.map((key) => this.state[key].value);
|
|
614
|
+
if (expandedValues.length) {
|
|
615
|
+
this.selectionDispatcher.notify((this.isMultiple ? expandedValues : expandedValues[0]), this.id);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
else {
|
|
619
|
+
this.selectionDispatcher.notify(this.defaultValueArray(), this.id);
|
|
620
|
+
}
|
|
621
|
+
// Seed initial state for any items missing from the store (without overwriting existing entries).
|
|
622
|
+
if (this.useStateSaving()) {
|
|
623
|
+
this.items().forEach((item) => this.saveItemState(item, false));
|
|
624
|
+
}
|
|
625
|
+
this.keyManager = new FocusKeyManager(this.items, this.injector).withHomeAndEnd();
|
|
626
|
+
if (this.orientation() === 'horizontal') {
|
|
627
|
+
this.keyManager.withHorizontalOrientation(this.dir?.value || 'ltr');
|
|
628
|
+
}
|
|
629
|
+
else {
|
|
630
|
+
this.keyManager.withVerticalOrientation();
|
|
631
|
+
}
|
|
513
632
|
}
|
|
514
633
|
ngAfterViewInit() {
|
|
515
|
-
this.
|
|
634
|
+
this.focusMonitor.monitor(this.elementRef, true);
|
|
516
635
|
}
|
|
517
|
-
|
|
518
|
-
|
|
636
|
+
ngOnDestroy() {
|
|
637
|
+
this.focusMonitor.stopMonitoring(this.elementRef);
|
|
638
|
+
this.openCloseAllActions.complete();
|
|
639
|
+
this.keyManager?.destroy();
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Handles a key pressed on an item's trigger.
|
|
643
|
+
*
|
|
644
|
+
* Invoked by `KbqAccordionTriggerDirective`, not bound on the accordion host: a root listener
|
|
645
|
+
* also receives keys bubbling from the section content and from controls placed next to the
|
|
646
|
+
* trigger, and would swallow their Enter/Space and hijack their arrow keys. It would also
|
|
647
|
+
* activate the first item — stealing focus — the first time any key was pressed anywhere inside.
|
|
648
|
+
* @docs-private
|
|
649
|
+
*/
|
|
650
|
+
keydownHandler(event) {
|
|
651
|
+
const activeItem = this.keyManager?.activeItem;
|
|
652
|
+
if (!activeItem)
|
|
519
653
|
return;
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
654
|
+
if ((event.keyCode === ENTER || event.keyCode === SPACE) &&
|
|
655
|
+
!this.keyManager.isTyping() &&
|
|
656
|
+
!activeItem.disabled) {
|
|
657
|
+
event.preventDefault();
|
|
658
|
+
activeItem.toggle();
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
// Arrow/Home/End move between headers; Tab falls through natively (WAI-ARIA APG pattern).
|
|
662
|
+
this.keyManager.onKeydown(event);
|
|
663
|
+
}
|
|
525
664
|
}
|
|
526
|
-
|
|
527
|
-
|
|
665
|
+
/** Opens all enabled accordion items in an accordion where `type` is `multiple`. */
|
|
666
|
+
openAll() {
|
|
667
|
+
if (this.isMultiple) {
|
|
668
|
+
this.openCloseAllActions.next(true);
|
|
669
|
+
}
|
|
528
670
|
}
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
this.
|
|
671
|
+
/** Closes all enabled accordion items. */
|
|
672
|
+
closeAll() {
|
|
673
|
+
this.openCloseAllActions.next(false);
|
|
532
674
|
}
|
|
533
|
-
|
|
534
|
-
|
|
675
|
+
/** @docs-private */
|
|
676
|
+
setActiveItem(item) {
|
|
677
|
+
this.keyManager?.setActiveItem(item);
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Persists the current state of the given item when `useStateSaving` is enabled.
|
|
681
|
+
* @docs-private
|
|
682
|
+
*/
|
|
683
|
+
saveItemState(item, force = true) {
|
|
684
|
+
if (!this.useStateSaving())
|
|
685
|
+
return;
|
|
686
|
+
if (!force && this.state?.[item.id])
|
|
687
|
+
return;
|
|
688
|
+
this.state = this.state ?? {};
|
|
689
|
+
this.state[item.id] = item.getState();
|
|
690
|
+
this.stateStore.setState(this.stateStorageKey, this.state);
|
|
535
691
|
}
|
|
536
|
-
/**
|
|
537
|
-
|
|
692
|
+
/** The current expanded value(s) derived from the live item state. */
|
|
693
|
+
getCurrentValue() {
|
|
694
|
+
const expandedValues = this.items()
|
|
695
|
+
.filter((item) => item.expanded)
|
|
696
|
+
.map((item) => item.value());
|
|
697
|
+
return this.isMultiple ? expandedValues : (expandedValues[0] ?? '');
|
|
698
|
+
}
|
|
699
|
+
/** The key used to persist/restore state. */
|
|
700
|
+
get stateStorageKey() {
|
|
701
|
+
return this.stateSavingKey() || this.id;
|
|
702
|
+
}
|
|
703
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordion, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
704
|
+
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.3.30", type: KbqAccordion, isStandalone: true, selector: "kbq-accordion, [kbq-accordion]", inputs: { useStateSaving: { classPropertyName: "useStateSaving", publicName: "useStateSaving", isSignal: true, isRequired: false, transformFunction: null }, stateSavingKey: { classPropertyName: "stateSavingKey", publicName: "stateSavingKey", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, level: { classPropertyName: "level", publicName: "level", isSignal: true, isRequired: false, transformFunction: null }, defaultValue: { classPropertyName: "defaultValue", publicName: "defaultValue", isSignal: true, isRequired: false, transformFunction: null }, type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: false, transformFunction: null }, collapsible: { classPropertyName: "collapsible", publicName: "collapsible", isSignal: true, isRequired: false, transformFunction: null }, valueInput: { classPropertyName: "valueInput", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange" }, host: { properties: { "attr.data-orientation": "orientation()" }, classAttribute: "kbq-accordion" }, providers: [
|
|
705
|
+
{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
|
|
706
|
+
], queries: [{ propertyName: "allItems", predicate: i0.forwardRef(() => KbqAccordionItem), descendants: true, isSignal: true }], ngImport: i0, template: '<ng-content />', isInline: true, styles: [".kbq-accordion{display:block}.kbq-accordion-item{box-sizing:border-box;display:block;border-width:var(--kbq-accordion-size-item-border-width);border-style:solid;border-color:transparent}.kbq-accordion-header{display:flex;height:var(--kbq-accordion-size-item-header-height);overflow:hidden}.kbq-accordion-header>.kbq-accordion-header__actions{display:flex;align-items:center;gap:var(--kbq-accordion-size-item-header-actions-gap);flex-shrink:0;padding-right:var(--kbq-accordion-size-item-header-actions-padding-right)}.kbq-accordion-content{display:block;overflow:hidden}.kbq-accordion-content>.kbq-accordion-content__body{margin:unset;padding:var(--kbq-accordion-size-item-content-padding)}.kbq-accordion-content[data-state=open]{transition:height .3s ease-out;height:var(--kbq-accordion-content-height)}.kbq-accordion-content[data-state=closed]{transition:height .3s ease-out;height:0}@media(prefers-reduced-motion:reduce){.kbq-accordion-content[data-state=open],.kbq-accordion-content[data-state=closed]{transition:none}}.kbq-accordion.cdk-keyboard-focused .kbq-accordion-item:has(>.kbq-accordion-trigger:focus),.kbq-accordion.cdk-keyboard-focused .kbq-accordion-item:has(>.kbq-accordion-header .kbq-accordion-trigger:focus){border-color:var(--kbq-accordion-item-states-focus-border-color)}.kbq-accordion-item{background:var(--kbq-accordion-item-default-background);color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-item .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-default-icon-color)}.kbq-accordion-trigger{width:100%;background:transparent;border:none;outline:none;color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-trigger:hover:not([data-disabled=true]){cursor:pointer}.kbq-accordion-trigger:hover:not([data-disabled=true]) .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-hover-icon-color)}.kbq-accordion-trigger[data-disabled=true]{color:var(--kbq-accordion-item-states-disabled-text-color)}.kbq-accordion-trigger[data-disabled=true] .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-disabled-icon-color)}.kbq-accordion-header,.kbq-accordion-trigger{font-size:var(--kbq-typography-text-big-font-size);font-style:var(--kbq-typography-text-big-font-style);font-weight:var(--kbq-typography-text-big-font-weight);line-height:var(--kbq-typography-text-big-line-height);font-family:var(--kbq-typography-text-big-font-family);text-transform:var(--kbq-typography-text-big-text-transform);font-feature-settings:var(--kbq-typography-text-big-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-letter-spacing)}.kbq-accordion-trigger__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-accordion-content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}\n", ".kbq-accordion{--kbq-accordion-size-item-border-width: 2px;--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-size-item-header-actions-gap: var(--kbq-size-3xs);--kbq-accordion-size-item-header-actions-padding-right: var(--kbq-size-s);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
538
707
|
}
|
|
539
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
540
|
-
type:
|
|
541
|
-
args: [{
|
|
542
|
-
|
|
543
|
-
host: {
|
|
544
|
-
|
|
545
|
-
'[attr.
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
'[attr.data-state]': 'item.dataState',
|
|
549
|
-
'[attr.data-disabled]': 'item.disabled',
|
|
550
|
-
'[attr.data-orientation]': 'item.orientation',
|
|
551
|
-
'(transitionend)': 'toggle()'
|
|
552
|
-
},
|
|
553
|
-
exportAs: 'kbqAccordionContent'
|
|
554
|
-
}]
|
|
555
|
-
}], ctorParameters: () => [] });
|
|
708
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordion, decorators: [{
|
|
709
|
+
type: Component,
|
|
710
|
+
args: [{ selector: 'kbq-accordion, [kbq-accordion]', template: '<ng-content />', providers: [
|
|
711
|
+
{ provide: UniqueSelectionDispatcher, useClass: UniqueSelectionDispatcher }
|
|
712
|
+
], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
|
|
713
|
+
class: 'kbq-accordion',
|
|
714
|
+
'[attr.data-orientation]': 'orientation()'
|
|
715
|
+
}, styles: [".kbq-accordion{display:block}.kbq-accordion-item{box-sizing:border-box;display:block;border-width:var(--kbq-accordion-size-item-border-width);border-style:solid;border-color:transparent}.kbq-accordion-header{display:flex;height:var(--kbq-accordion-size-item-header-height);overflow:hidden}.kbq-accordion-header>.kbq-accordion-header__actions{display:flex;align-items:center;gap:var(--kbq-accordion-size-item-header-actions-gap);flex-shrink:0;padding-right:var(--kbq-accordion-size-item-header-actions-padding-right)}.kbq-accordion-content{display:block;overflow:hidden}.kbq-accordion-content>.kbq-accordion-content__body{margin:unset;padding:var(--kbq-accordion-size-item-content-padding)}.kbq-accordion-content[data-state=open]{transition:height .3s ease-out;height:var(--kbq-accordion-content-height)}.kbq-accordion-content[data-state=closed]{transition:height .3s ease-out;height:0}@media(prefers-reduced-motion:reduce){.kbq-accordion-content[data-state=open],.kbq-accordion-content[data-state=closed]{transition:none}}.kbq-accordion.cdk-keyboard-focused .kbq-accordion-item:has(>.kbq-accordion-trigger:focus),.kbq-accordion.cdk-keyboard-focused .kbq-accordion-item:has(>.kbq-accordion-header .kbq-accordion-trigger:focus){border-color:var(--kbq-accordion-item-states-focus-border-color)}.kbq-accordion-item{background:var(--kbq-accordion-item-default-background);color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-item .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-default-icon-color)}.kbq-accordion-trigger{width:100%;background:transparent;border:none;outline:none;color:var(--kbq-accordion-item-default-text-color)}.kbq-accordion-trigger:hover:not([data-disabled=true]){cursor:pointer}.kbq-accordion-trigger:hover:not([data-disabled=true]) .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-hover-icon-color)}.kbq-accordion-trigger[data-disabled=true]{color:var(--kbq-accordion-item-states-disabled-text-color)}.kbq-accordion-trigger[data-disabled=true] .kbq-accordion-trigger__icon{color:var(--kbq-accordion-item-states-disabled-icon-color)}.kbq-accordion-header,.kbq-accordion-trigger{font-size:var(--kbq-typography-text-big-font-size);font-style:var(--kbq-typography-text-big-font-style);font-weight:var(--kbq-typography-text-big-font-weight);line-height:var(--kbq-typography-text-big-line-height);font-family:var(--kbq-typography-text-big-font-family);text-transform:var(--kbq-typography-text-big-text-transform);font-feature-settings:var(--kbq-typography-text-big-font-feature-settings);letter-spacing:var(--kbq-typography-text-big-letter-spacing)}.kbq-accordion-trigger__caption{font-size:var(--kbq-typography-text-compact-font-size);font-style:var(--kbq-typography-text-compact-font-style);font-weight:var(--kbq-typography-text-compact-font-weight);line-height:var(--kbq-typography-text-compact-line-height);font-family:var(--kbq-typography-text-compact-font-family);text-transform:var(--kbq-typography-text-compact-text-transform);font-feature-settings:var(--kbq-typography-text-compact-font-feature-settings);letter-spacing:var(--kbq-typography-text-compact-letter-spacing)}.kbq-accordion-content{font-size:var(--kbq-typography-text-normal-font-size);font-style:var(--kbq-typography-text-normal-font-style);font-weight:var(--kbq-typography-text-normal-font-weight);line-height:var(--kbq-typography-text-normal-line-height);font-family:var(--kbq-typography-text-normal-font-family);text-transform:var(--kbq-typography-text-normal-text-transform);font-feature-settings:var(--kbq-typography-text-normal-font-feature-settings);letter-spacing:var(--kbq-typography-text-normal-letter-spacing)}\n", ".kbq-accordion{--kbq-accordion-size-item-border-width: 2px;--kbq-accordion-size-item-header-height: 36px;--kbq-accordion-size-item-header-variant-fill-padding: var(--kbq-size-xs) var(--kbq-size-s);--kbq-accordion-size-item-header-variant-hug-padding: var(--kbq-size-xs) var(--kbq-size-s) var(--kbq-size-xs) var(--kbq-size-m);--kbq-accordion-size-item-content-padding: 0px var(--kbq-size-m) var(--kbq-size-s) var(--kbq-size-m);--kbq-accordion-size-item-header-actions-gap: var(--kbq-size-3xs);--kbq-accordion-size-item-header-actions-padding-right: var(--kbq-size-s);--kbq-accordion-item-default-background: transparent;--kbq-accordion-item-default-text-color: var(--kbq-foreground-contrast);--kbq-accordion-item-default-icon-color: var(--kbq-icon-contrast-fade);--kbq-accordion-item-states-hover-icon-color: var(--kbq-icon-contrast);--kbq-accordion-item-states-focus-border-color: var(--kbq-line-theme);--kbq-accordion-item-states-disabled-text-color: var(--kbq-foreground-contrast-secondary);--kbq-accordion-item-states-disabled-icon-color: var(--kbq-states-icon-disabled)}\n"] }]
|
|
716
|
+
}], ctorParameters: () => [], propDecorators: { allItems: [{ type: i0.ContentChildren, args: [forwardRef(() => KbqAccordionItem), { ...{ descendants: true }, isSignal: true }] }], useStateSaving: [{ type: i0.Input, args: [{ isSignal: true, alias: "useStateSaving", required: false }] }], stateSavingKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateSavingKey", required: false }] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], level: [{ type: i0.Input, args: [{ isSignal: true, alias: "level", required: false }] }], defaultValue: [{ type: i0.Input, args: [{ isSignal: true, alias: "defaultValue", required: false }] }], type: [{ type: i0.Input, args: [{ isSignal: true, alias: "type", required: false }] }], collapsible: [{ type: i0.Input, args: [{ isSignal: true, alias: "collapsible", required: false }] }], valueInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }] } });
|
|
556
717
|
|
|
557
718
|
class KbqAccordionContent {
|
|
558
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
559
|
-
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.
|
|
560
|
-
<p><ng-content /></p>
|
|
561
|
-
`, isInline: true }); }
|
|
719
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionContent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
720
|
+
/** @nocollapse */ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.30", type: KbqAccordionContent, isStandalone: true, selector: "kbq-accordion-content, [kbq-accordion-content]", host: { classAttribute: "kbq-accordion-content" }, hostDirectives: [{ directive: KbqAccordionContentDirective }], ngImport: i0, template: '<div class="kbq-accordion-content__body"><ng-content /></div>', isInline: true }); }
|
|
562
721
|
}
|
|
563
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
722
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionContent, decorators: [{
|
|
564
723
|
type: Component,
|
|
565
724
|
args: [{
|
|
566
725
|
selector: 'kbq-accordion-content, [kbq-accordion-content]',
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
726
|
+
// A `<div>` wrapper (not `<p>`) carries the content padding: `<p>` is invalid for projected
|
|
727
|
+
// block content (a `<div>` would auto-close it), and keeping padding off the animated
|
|
728
|
+
// `.kbq-accordion-content` host lets it collapse cleanly to `height: 0`.
|
|
729
|
+
template: '<div class="kbq-accordion-content__body"><ng-content /></div>',
|
|
570
730
|
host: {
|
|
571
731
|
class: 'kbq-accordion-content'
|
|
572
732
|
},
|
|
@@ -574,20 +734,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
574
734
|
}]
|
|
575
735
|
}] });
|
|
576
736
|
|
|
577
|
-
class
|
|
737
|
+
class KbqAccordionHeader {
|
|
578
738
|
constructor() {
|
|
739
|
+
/** @docs-private */
|
|
579
740
|
this.item = inject(KbqAccordionItem);
|
|
741
|
+
/** @docs-private */
|
|
742
|
+
this.accordion = inject(KbqAccordion);
|
|
580
743
|
}
|
|
581
|
-
/**
|
|
582
|
-
|
|
744
|
+
/**
|
|
745
|
+
* Names the heading after the trigger alone.
|
|
746
|
+
*
|
|
747
|
+
* A `role="heading"` takes its name from its content, so the header actions sitting beside the
|
|
748
|
+
* trigger would otherwise append their own labels to it — a section titled "Profile" would be
|
|
749
|
+
* announced as "Profile Run More" when navigating by heading. Pointing at the trigger yields the
|
|
750
|
+
* announcement the WAI-ARIA APG gets by keeping the button the only element in the heading,
|
|
751
|
+
* which this component cannot do because the header is also the row that lays the actions out.
|
|
752
|
+
* @docs-private
|
|
753
|
+
*/
|
|
754
|
+
get labelledBy() {
|
|
755
|
+
return this.item.trigger()?.triggerId ?? null;
|
|
756
|
+
}
|
|
757
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
758
|
+
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.30", type: KbqAccordionHeader, isStandalone: true, selector: "kbq-accordion-header, [kbq-accordion-header]", host: { properties: { "attr.role": "\"heading\"", "attr.aria-level": "accordion.level()", "attr.aria-labelledby": "labelledBy", "attr.data-state": "item.dataState", "attr.data-disabled": "item.disabled", "attr.data-orientation": "item.orientation" }, classAttribute: "kbq-accordion-header" }, ngImport: i0 }); }
|
|
583
759
|
}
|
|
584
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
760
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionHeader, decorators: [{
|
|
585
761
|
type: Directive,
|
|
586
762
|
args: [{
|
|
587
|
-
selector: '[
|
|
763
|
+
selector: 'kbq-accordion-header, [kbq-accordion-header]',
|
|
588
764
|
host: {
|
|
765
|
+
class: 'kbq-accordion-header',
|
|
589
766
|
'[attr.role]': '"heading"',
|
|
590
|
-
'[attr.aria-level]': '
|
|
767
|
+
'[attr.aria-level]': 'accordion.level()',
|
|
768
|
+
'[attr.aria-labelledby]': 'labelledBy',
|
|
591
769
|
'[attr.data-state]': 'item.dataState',
|
|
592
770
|
'[attr.data-disabled]': 'item.disabled',
|
|
593
771
|
'[attr.data-orientation]': 'item.orientation'
|
|
@@ -595,24 +773,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
595
773
|
}]
|
|
596
774
|
}] });
|
|
597
775
|
|
|
598
|
-
class KbqAccordionHeader {
|
|
599
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqAccordionHeader, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
600
|
-
/** @nocollapse */ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.25", type: KbqAccordionHeader, isStandalone: true, selector: "kbq-accordion-header, [kbq-accordion-header]", host: { classAttribute: "kbq-accordion-header" }, hostDirectives: [{ directive: KbqAccordionHeaderDirective }], ngImport: i0 }); }
|
|
601
|
-
}
|
|
602
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImport: i0, type: KbqAccordionHeader, decorators: [{
|
|
603
|
-
type: Directive,
|
|
604
|
-
args: [{
|
|
605
|
-
selector: 'kbq-accordion-header, [kbq-accordion-header]',
|
|
606
|
-
host: {
|
|
607
|
-
class: 'kbq-accordion-header'
|
|
608
|
-
},
|
|
609
|
-
hostDirectives: [KbqAccordionHeaderDirective]
|
|
610
|
-
}]
|
|
611
|
-
}] });
|
|
612
|
-
|
|
613
776
|
class KbqAccordionModule {
|
|
614
|
-
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.
|
|
615
|
-
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.
|
|
777
|
+
/** @nocollapse */ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
778
|
+
/** @nocollapse */ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionModule, imports: [KbqIcon,
|
|
616
779
|
KbqAccordion,
|
|
617
780
|
KbqAccordionContent,
|
|
618
781
|
KbqAccordionHeader,
|
|
@@ -622,10 +785,10 @@ class KbqAccordionModule {
|
|
|
622
785
|
KbqAccordionHeader,
|
|
623
786
|
KbqAccordionItem,
|
|
624
787
|
KbqAccordionTrigger] }); }
|
|
625
|
-
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.
|
|
788
|
+
/** @nocollapse */ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionModule, imports: [KbqIcon,
|
|
626
789
|
KbqAccordionTrigger] }); }
|
|
627
790
|
}
|
|
628
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.
|
|
791
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.30", ngImport: i0, type: KbqAccordionModule, decorators: [{
|
|
629
792
|
type: NgModule,
|
|
630
793
|
args: [{
|
|
631
794
|
imports: [
|
|
@@ -650,5 +813,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.25", ngImpo
|
|
|
650
813
|
* Generated bundle index. Do not edit.
|
|
651
814
|
*/
|
|
652
815
|
|
|
653
|
-
export { KbqAccordion, KbqAccordionContent, KbqAccordionContentDirective, KbqAccordionHeader,
|
|
816
|
+
export { KBQ_ACCORDION_STATE_STORE, KbqAccordion, KbqAccordionContent, KbqAccordionContentDirective, KbqAccordionHeader, KbqAccordionItem, KbqAccordionLocalStorageStateStore, KbqAccordionModule, KbqAccordionTrigger, KbqAccordionTriggerDirective };
|
|
654
817
|
//# sourceMappingURL=koobiq-components-accordion.mjs.map
|