@kirbydesign/extensions-angular 3.2.0 → 3.4.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.
Files changed (41) hide show
  1. package/assets/spot-illustrations/airballoon.wind.ballon-part.cloud.medium.svg +8 -0
  2. package/assets/spot-illustrations/banknotes.arrow.dot.circle.medium.svg +16 -0
  3. package/assets/spot-illustrations/bell.checkmark.dot.bars.xlarge.svg +9 -0
  4. package/assets/spot-illustrations/bell.exclamation-mark.triangle.bars.medium.svg +9 -0
  5. package/assets/spot-illustrations/box.curve.box.half-circle.medium.svg +8 -0
  6. package/assets/spot-illustrations/box.none.plus-dot.bars.large.svg +9 -0
  7. package/assets/spot-illustrations/calculator.money.coin.rectangle.medium.svg +9 -0
  8. package/assets/spot-illustrations/calendar.money.coin.bars.medium.svg +9 -0
  9. package/assets/spot-illustrations/calender.loop-arrow.zoom.bars.large.svg +9 -0
  10. package/assets/spot-illustrations/calender.loop-arrow.zoom.bars.xlarge.svg +8 -0
  11. package/assets/spot-illustrations/calender.money-arrows.header.bars.large.svg +9 -0
  12. package/assets/spot-illustrations/calender.money-arrows.header.bars.medium.svg +9 -0
  13. package/assets/spot-illustrations/checkmark.circle.circle-part.shadow.large.svg +9 -0
  14. package/assets/spot-illustrations/computer.certificate.padlock.circle.large.svg +9 -0
  15. package/assets/spot-illustrations/cross.circle.circle-part.shadow.large.svg +9 -0
  16. package/assets/spot-illustrations/exclamation-mark.circle.circle-part.shadow.large.svg +9 -0
  17. package/assets/spot-illustrations/hand-money.line.money-dot.bars.medium.svg +8 -0
  18. package/assets/spot-illustrations/hand.balloon.balloon.circle.xlarge.svg +9 -0
  19. package/assets/spot-illustrations/invest-document.graph.bars.square.medium.svg +9 -0
  20. package/assets/spot-illustrations/invest-document.graph.bars.square.xlarge.svg +9 -0
  21. package/assets/spot-illustrations/invest-page.money.dot.circle.medium.svg +8 -0
  22. package/assets/spot-illustrations/megaphone.sound.megaphone-part.circle.xlarge.svg +9 -0
  23. package/assets/spot-illustrations/money.arrow.coin.bars.medium.svg +12 -0
  24. package/assets/spot-illustrations/money.none.coin.bars.medium.svg +16 -0
  25. package/assets/spot-illustrations/piggy-bank.money.money-dot.bars.medium.svg +8 -0
  26. package/assets/spot-illustrations/plant.bars.leaf.bars.medium.svg +9 -0
  27. package/assets/spot-illustrations/robot.none.antenna-dot.body.large.svg +8 -0
  28. package/assets/spot-illustrations/robot.none.antenna-dot.body.medium.svg +29 -0
  29. package/fesm2022/kirbydesign-extensions-angular-image-banner.mjs +10 -12
  30. package/fesm2022/kirbydesign-extensions-angular-image-banner.mjs.map +1 -1
  31. package/fesm2022/kirbydesign-extensions-angular-localization.mjs +30 -30
  32. package/fesm2022/kirbydesign-extensions-angular-localization.mjs.map +1 -1
  33. package/fesm2022/kirbydesign-extensions-angular-sidebar-menu.mjs +571 -0
  34. package/fesm2022/kirbydesign-extensions-angular-sidebar-menu.mjs.map +1 -0
  35. package/fesm2022/kirbydesign-extensions-angular-skeleton-loader.mjs +6 -6
  36. package/fesm2022/kirbydesign-extensions-angular-skeleton-loader.mjs.map +1 -1
  37. package/fesm2022/kirbydesign-extensions-angular-spot-illustration.mjs +126 -0
  38. package/fesm2022/kirbydesign-extensions-angular-spot-illustration.mjs.map +1 -0
  39. package/package.json +15 -1
  40. package/sidebar-menu/index.d.ts +73 -0
  41. package/spot-illustration/index.d.ts +157 -0
@@ -0,0 +1,571 @@
1
+ import * as i0 from '@angular/core';
2
+ import { input, computed, Component, signal, Injectable, inject, ElementRef, forwardRef, ChangeDetectionStrategy, afterNextRender, output, Directive, model, effect, EventEmitter, Output, Input, NgModule } from '@angular/core';
3
+ import { DividerComponent } from '@kirbydesign/designsystem/divider';
4
+ import { RouterLink } from '@angular/router';
5
+ import * as i1 from '@kirbydesign/designsystem/icon';
6
+ import { IconModule, IconComponent } from '@kirbydesign/designsystem/icon';
7
+ import { BadgeComponent } from '@kirbydesign/designsystem/badge';
8
+ import { trigger, transition, style, animate, AUTO_STYLE } from '@angular/animations';
9
+ import { Subject, debounceTime } from 'rxjs';
10
+ import { distinctUntilChanged } from 'rxjs/operators';
11
+
12
+ /**
13
+ * the HTMLElement.scrollIntoViewIfNecessary is non-standard and not supported in all browsers (e.g. firefox),
14
+ * so we implement a version based on standard
15
+ */
16
+ function scrollIntoViewIfNecessary(scrollContainer, child, position = 'center') {
17
+ const containerRect = scrollContainer.getBoundingClientRect();
18
+ const elementRect = child.getBoundingClientRect();
19
+ if (containerRect.top > elementRect.top || containerRect.bottom < elementRect.bottom) {
20
+ child.scrollIntoView({
21
+ behavior: 'instant',
22
+ block: position,
23
+ inline: position,
24
+ });
25
+ }
26
+ }
27
+
28
+ class MenuItemComponent {
29
+ constructor() {
30
+ this.id = input.required(...(ngDevMode ? [{ debugName: "id" }] : []));
31
+ this.size = input.required(...(ngDevMode ? [{ debugName: "size" }] : []));
32
+ this.icon = input(...(ngDevMode ? [undefined, { debugName: "icon" }] : []));
33
+ this.badge = input(...(ngDevMode ? [undefined, { debugName: "badge" }] : []));
34
+ this.iconSize = computed(() => (this.size() === 'lg' ? 'sm' : 'xs'), ...(ngDevMode ? [{ debugName: "iconSize" }] : []));
35
+ }
36
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
37
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: MenuItemComponent, isStandalone: true, selector: "a[kirby-x-menu-item],button[kirby-x-menu-item]", inputs: { id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: true, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, badge: { classPropertyName: "badge", publicName: "badge", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "\"item\" + id()", "class": "size()" } }, ngImport: i0, template: "<div class=\"menu-item-start {{ size() }}\">\n @if (icon(); as icon) {\n <kirby-icon [size]=\"iconSize()\" [name]=\"icon\"></kirby-icon>\n }\n</div>\n\n<div class=\"menu-item-content {{ size() }}\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"menu-item-end\">\n @if (badge(); as badge) {\n <kirby-badge class=\"item-badge\" [themeColor]=\"badge.themeColor ?? 'primary'\">\n {{ badge.value }}\n </kirby-badge>\n }\n <ng-content select=\"[slot='end']\"></ng-content>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-grow:1;align-items:center;align-self:stretch;box-sizing:border-box;min-height:32px;border-radius:8px;padding:4px 12px;gap:8px;border:none;background:inherit;color:inherit;text-decoration:none;cursor:pointer}:host.lg{min-height:40px}@media (pointer: coarse){:host.md{min-height:40px}}:host:hover{background:var(--menuitem-hover-background-color, var(--kirby-inputs-background-color-hover))}:host:active{background:var(--menuitem-active-background-color, var(--kirby-inputs-background-color-active))}:host:focus-visible{outline:none}@media (hover: hover) and (pointer: fine){:host:focus{transition:all 80ms linear 0ms;box-shadow:0 0 0 2px var(--kirby-background-color),0 0 0 4px #4d90fe}:host:focus:not(:focus-visible){box-shadow:0 0 0 0 transparent}:host:focus-visible{transition:all 80ms linear 0ms;box-shadow:0 0 0 2px var(--kirby-background-color),0 0 0 4px #4d90fe}}.menu-item-start{display:inline-flex;align-items:center;justify-content:center}.menu-item-start.lg,.menu-item-start.md{width:24px;height:24px}.menu-item-start.sm,.menu-item-start.xs{width:16px;height:16px}.menu-item-start.sm{padding-left:32px}.menu-item-start.xs{padding-left:56px}.menu-item-content{display:flex;flex-grow:1;align-items:center;text-align:left}.menu-item-content.lg,.menu-item-content.md{font-size:16px;line-height:24px}.menu-item-content.sm{font-size:14px;line-height:20px}.menu-item-content.xs{font-size:12px;line-height:16px}.menu-item-end{display:inline-flex;align-items:center}.item-badge{display:flex;justify-content:center;min-width:24px}\n"], dependencies: [{ kind: "ngmodule", type: IconModule }, { kind: "component", type: i1.IconComponent, selector: "kirby-icon", inputs: ["size", "name"] }, { kind: "component", type: BadgeComponent, selector: "kirby-badge", inputs: ["text", "size"] }] }); }
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuItemComponent, decorators: [{
40
+ type: Component,
41
+ args: [{ selector: 'a[kirby-x-menu-item],button[kirby-x-menu-item]', host: {
42
+ '[attr.id]': '"item" + id()',
43
+ '[class]': 'size()',
44
+ }, imports: [IconModule, BadgeComponent], template: "<div class=\"menu-item-start {{ size() }}\">\n @if (icon(); as icon) {\n <kirby-icon [size]=\"iconSize()\" [name]=\"icon\"></kirby-icon>\n }\n</div>\n\n<div class=\"menu-item-content {{ size() }}\">\n <ng-content></ng-content>\n</div>\n\n<div class=\"menu-item-end\">\n @if (badge(); as badge) {\n <kirby-badge class=\"item-badge\" [themeColor]=\"badge.themeColor ?? 'primary'\">\n {{ badge.value }}\n </kirby-badge>\n }\n <ng-content select=\"[slot='end']\"></ng-content>\n</div>\n", styles: [":host{display:flex;flex-direction:row;flex-grow:1;align-items:center;align-self:stretch;box-sizing:border-box;min-height:32px;border-radius:8px;padding:4px 12px;gap:8px;border:none;background:inherit;color:inherit;text-decoration:none;cursor:pointer}:host.lg{min-height:40px}@media (pointer: coarse){:host.md{min-height:40px}}:host:hover{background:var(--menuitem-hover-background-color, var(--kirby-inputs-background-color-hover))}:host:active{background:var(--menuitem-active-background-color, var(--kirby-inputs-background-color-active))}:host:focus-visible{outline:none}@media (hover: hover) and (pointer: fine){:host:focus{transition:all 80ms linear 0ms;box-shadow:0 0 0 2px var(--kirby-background-color),0 0 0 4px #4d90fe}:host:focus:not(:focus-visible){box-shadow:0 0 0 0 transparent}:host:focus-visible{transition:all 80ms linear 0ms;box-shadow:0 0 0 2px var(--kirby-background-color),0 0 0 4px #4d90fe}}.menu-item-start{display:inline-flex;align-items:center;justify-content:center}.menu-item-start.lg,.menu-item-start.md{width:24px;height:24px}.menu-item-start.sm,.menu-item-start.xs{width:16px;height:16px}.menu-item-start.sm{padding-left:32px}.menu-item-start.xs{padding-left:56px}.menu-item-content{display:flex;flex-grow:1;align-items:center;text-align:left}.menu-item-content.lg,.menu-item-content.md{font-size:16px;line-height:24px}.menu-item-content.sm{font-size:14px;line-height:20px}.menu-item-content.xs{font-size:12px;line-height:16px}.menu-item-end{display:inline-flex;align-items:center}.item-badge{display:flex;justify-content:center;min-width:24px}\n"] }]
45
+ }], propDecorators: { id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: true }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], badge: [{ type: i0.Input, args: [{ isSignal: true, alias: "badge", required: false }] }] } });
46
+
47
+ class MenuStateService {
48
+ #toggledSubmenu = signal(undefined, ...(ngDevMode ? [{ debugName: "#toggledSubmenu" }] : []));
49
+ #selectedItem = signal(undefined, ...(ngDevMode ? [{ debugName: "#selectedItem" }] : []));
50
+ get toggledSubmenu() {
51
+ return this.#toggledSubmenu;
52
+ }
53
+ set toggledSubmenu(item) {
54
+ this.#toggledSubmenu.set(item);
55
+ }
56
+ get selectedItem() {
57
+ return this.#selectedItem;
58
+ }
59
+ set selectedItem(item) {
60
+ if (item.selectable ?? true) {
61
+ this.#selectedItem.set(item);
62
+ }
63
+ }
64
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuStateService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
65
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuStateService, providedIn: 'root' }); }
66
+ }
67
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuStateService, decorators: [{
68
+ type: Injectable,
69
+ args: [{ providedIn: 'root' }]
70
+ }] });
71
+
72
+ class MenuAnchorItemComponent {
73
+ constructor() {
74
+ this.item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
75
+ this.size = input.required(...(ngDevMode ? [{ debugName: "size" }] : []));
76
+ this.#menuStateService = inject(MenuStateService);
77
+ this.vm = {
78
+ link: computed(() => determineLinkType(this.item())),
79
+ id: computed(() => this.item().id),
80
+ size: this.size,
81
+ badge: computed(() => this.item().badge),
82
+ icon: computed(() => this.item().icon),
83
+ isSelected: computed(() => this.item().selected ?? false),
84
+ title: computed(() => this.item().title ?? ''),
85
+ selectItem: this.#selectItem.bind(this),
86
+ };
87
+ }
88
+ #menuStateService;
89
+ #selectItem() {
90
+ this.#menuStateService.selectedItem = this.item();
91
+ }
92
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuAnchorItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
93
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: MenuAnchorItemComponent, isStandalone: true, selector: "li[kirby-x-menu-anchor-item]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "@let link = vm.link();\n@if (link) {\n @switch (link.type) {\n @case ('action') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.href]=\"link.url\"\n (click)=\"$event.preventDefault(); vm.selectItem()\"\n (keydown.enter)=\"$event.preventDefault(); vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n @case ('router-link') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [routerLink]=\"link.route\"\n [queryParams]=\"link.queryParams\"\n [skipLocationChange]=\"link.skipLocationChange\"\n [replaceUrl]=\"link.replaceUrl\"\n (click)=\"vm.selectItem()\"\n (keydown.enter)=\"vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n @case ('external-link') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.href]=\"link.url\"\n [attr.target]=\"link.target\"\n (click)=\"vm.selectItem()\"\n (keydown.enter)=\"vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n }\n}\n", styles: [".selected,.selected:hover,.selected:active,.selected:focus-visible{background:var(--menuitem-selected-background-color, var(--kirby-primary));color:var(--menuitem-selected-color, var(--kirby-primary-contrast));font-weight:700}\n"], dependencies: [{ kind: "component", type: MenuItemComponent, selector: "a[kirby-x-menu-item],button[kirby-x-menu-item]", inputs: ["id", "size", "icon", "badge"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); }
94
+ }
95
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuAnchorItemComponent, decorators: [{
96
+ type: Component,
97
+ args: [{ selector: 'li[kirby-x-menu-anchor-item]', imports: [MenuItemComponent, RouterLink], template: "@let link = vm.link();\n@if (link) {\n @switch (link.type) {\n @case ('action') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.href]=\"link.url\"\n (click)=\"$event.preventDefault(); vm.selectItem()\"\n (keydown.enter)=\"$event.preventDefault(); vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n @case ('router-link') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [routerLink]=\"link.route\"\n [queryParams]=\"link.queryParams\"\n [skipLocationChange]=\"link.skipLocationChange\"\n [replaceUrl]=\"link.replaceUrl\"\n (click)=\"vm.selectItem()\"\n (keydown.enter)=\"vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n @case ('external-link') {\n <a\n kirby-x-menu-item\n [class.selected]=\"vm.isSelected()\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.href]=\"link.url\"\n [attr.target]=\"link.target\"\n (click)=\"vm.selectItem()\"\n (keydown.enter)=\"vm.selectItem()\"\n >\n {{ vm.title() }}\n </a>\n }\n }\n}\n", styles: [".selected,.selected:hover,.selected:active,.selected:focus-visible{background:var(--menuitem-selected-background-color, var(--kirby-primary));color:var(--menuitem-selected-color, var(--kirby-primary-contrast));font-weight:700}\n"] }]
98
+ }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: true }] }] } });
99
+ function determineLinkType(item) {
100
+ if (item.isAction) {
101
+ return {
102
+ type: 'action',
103
+ url: item.link?.url ?? '',
104
+ };
105
+ }
106
+ if (item.link?.relativeLink) {
107
+ return {
108
+ type: 'router-link',
109
+ target: item.link.target ?? '_self',
110
+ route: item.link.relativeLink,
111
+ queryParams: item.link.queryParams,
112
+ skipLocationChange: item.skipLocationChange ?? false,
113
+ replaceUrl: item.replaceUrl ?? false,
114
+ };
115
+ }
116
+ if (item.link?.url) {
117
+ return {
118
+ type: 'external-link',
119
+ url: item.link.url,
120
+ target: item.link.target ?? '_self',
121
+ };
122
+ }
123
+ return undefined;
124
+ }
125
+
126
+ /**
127
+ * Ensures the element top is not smaller than the scroll container top.
128
+ */
129
+ function ensureInView(scrollContainer, element, durationMs) {
130
+ let startTime = null;
131
+ const updatePosition = (timestamp) => {
132
+ if (!startTime) {
133
+ startTime = timestamp;
134
+ }
135
+ const elapsedTime = timestamp - startTime;
136
+ if (elapsedTime < durationMs) {
137
+ scrollIntoViewIfNecessary(scrollContainer, element, 'start');
138
+ requestAnimationFrame(updatePosition);
139
+ }
140
+ };
141
+ requestAnimationFrame(updatePosition);
142
+ }
143
+
144
+ const DropDownAnimation = trigger('dropDownMenu', [
145
+ transition(':enter', [
146
+ style({ height: 0, overflow: 'hidden' }),
147
+ animate('300ms ease', style({ height: AUTO_STYLE })),
148
+ ]),
149
+ transition(':leave', [
150
+ style({ height: AUTO_STYLE, overflow: 'hidden' }),
151
+ animate('300ms ease', style({ height: 0 })),
152
+ ]),
153
+ ]);
154
+
155
+ class MenuSubmenuItemComponent {
156
+ constructor() {
157
+ this.item = input.required(...(ngDevMode ? [{ debugName: "item" }] : []));
158
+ this.size = input.required(...(ngDevMode ? [{ debugName: "size" }] : []));
159
+ this.disableAnimations = input.required(...(ngDevMode ? [{ debugName: "disableAnimations" }] : []));
160
+ this.#element = inject(ElementRef).nativeElement;
161
+ this.#menuStateService = inject(MenuStateService);
162
+ this.#isExpanded = computed(() => this.item().isExpanded ?? false, ...(ngDevMode ? [{ debugName: "#isExpanded" }] : []));
163
+ this.#submenuSize = computed(() => {
164
+ switch (this.size()) {
165
+ case 'lg':
166
+ return 'md';
167
+ case 'md':
168
+ return 'sm';
169
+ default:
170
+ return 'xs';
171
+ }
172
+ }, ...(ngDevMode ? [{ debugName: "#submenuSize" }] : []));
173
+ this.vm = {
174
+ id: computed(() => this.item().id),
175
+ submenuId: computed(() => `item-${this.item().id}-content`),
176
+ title: computed(() => this.item().title ?? ''),
177
+ size: this.size,
178
+ icon: computed(() => this.item().icon),
179
+ badge: computed(() => this.item().badge),
180
+ isExpanded: this.#isExpanded,
181
+ children: computed(() => this.item().children ?? []),
182
+ submenuSize: this.#submenuSize,
183
+ disableAnimations: this.disableAnimations,
184
+ toggleSubmenu: this.#toggleSubmenu.bind(this),
185
+ };
186
+ }
187
+ #element;
188
+ #menuStateService;
189
+ #isExpanded;
190
+ #submenuSize;
191
+ #toggleSubmenu() {
192
+ const button = this.#element.querySelector('button[kirby-x-menu-item]');
193
+ const scrollContainer = this.#element.closest('.sidebar-content');
194
+ if (button && scrollContainer) {
195
+ console.log('Ensuring submenu item is in view');
196
+ ensureInView(scrollContainer, button, 400);
197
+ }
198
+ this.#menuStateService.toggledSubmenu = this.item();
199
+ }
200
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuSubmenuItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
201
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: MenuSubmenuItemComponent, isStandalone: true, selector: "li[kirby-x-menu-submenu-item]", inputs: { item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: true, transformFunction: null }, disableAnimations: { classPropertyName: "disableAnimations", publicName: "disableAnimations", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: "<button\n kirby-x-menu-item\n type=\"button\"\n class=\"submenu-toggle\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.aria-controls]=\"vm.submenuId()\"\n [attr.aria-expanded]=\"vm.isExpanded()\"\n (click)=\"vm.toggleSubmenu()\"\n>\n {{ vm.title() }}\n <kirby-icon\n slot=\"end\"\n name=\"arrow-more\"\n class=\"disclosure\"\n [class.rotate]=\"vm.isExpanded()\"\n ></kirby-icon>\n</button>\n@if (vm.isExpanded()) {\n <ul\n kirby-x-menu-item-list\n [items]=\"vm.children()\"\n [size]=\"vm.submenuSize()\"\n [id]=\"vm.submenuId()\"\n [disableAnimations]=\"vm.disableAnimations()\"\n [@dropDownMenu]\n [@.disabled]=\"vm.disableAnimations()\"\n ></ul>\n}\n", styles: [":host{display:flex;flex-direction:column}.submenu-toggle{width:100%}.submenu-toggle[aria-expanded=true]{font-weight:700}.disclosure{transition:transform .2s}.disclosure.rotate{transform:rotate(90deg)}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => MenuItemComponent), selector: "a[kirby-x-menu-item],button[kirby-x-menu-item]", inputs: ["id", "size", "icon", "badge"] }, { kind: "component", type: i0.forwardRef(() => IconComponent), selector: "kirby-icon", inputs: ["size", "name"] }, { kind: "component", type: i0.forwardRef(() => MenuItemListComponent), selector: "ul[kirby-x-menu-item-list]", inputs: ["items", "size", "id", "disableAnimations"] }], animations: [DropDownAnimation] }); }
202
+ }
203
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuSubmenuItemComponent, decorators: [{
204
+ type: Component,
205
+ args: [{ selector: 'li[kirby-x-menu-submenu-item]', animations: [DropDownAnimation], imports: [MenuItemComponent, IconComponent, forwardRef(() => MenuItemListComponent)], template: "<button\n kirby-x-menu-item\n type=\"button\"\n class=\"submenu-toggle\"\n [id]=\"vm.id()\"\n [size]=\"vm.size()\"\n [icon]=\"vm.icon()\"\n [badge]=\"vm.badge()\"\n [attr.aria-controls]=\"vm.submenuId()\"\n [attr.aria-expanded]=\"vm.isExpanded()\"\n (click)=\"vm.toggleSubmenu()\"\n>\n {{ vm.title() }}\n <kirby-icon\n slot=\"end\"\n name=\"arrow-more\"\n class=\"disclosure\"\n [class.rotate]=\"vm.isExpanded()\"\n ></kirby-icon>\n</button>\n@if (vm.isExpanded()) {\n <ul\n kirby-x-menu-item-list\n [items]=\"vm.children()\"\n [size]=\"vm.submenuSize()\"\n [id]=\"vm.submenuId()\"\n [disableAnimations]=\"vm.disableAnimations()\"\n [@dropDownMenu]\n [@.disabled]=\"vm.disableAnimations()\"\n ></ul>\n}\n", styles: [":host{display:flex;flex-direction:column}.submenu-toggle{width:100%}.submenu-toggle[aria-expanded=true]{font-weight:700}.disclosure{transition:transform .2s}.disclosure.rotate{transform:rotate(90deg)}\n"] }]
206
+ }], propDecorators: { item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: true }] }], disableAnimations: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableAnimations", required: true }] }] } });
207
+
208
+ class MenuItemListComponent {
209
+ constructor() {
210
+ this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
211
+ this.size = input('lg', ...(ngDevMode ? [{ debugName: "size" }] : []));
212
+ this.id = input(...(ngDevMode ? [undefined, { debugName: "id" }] : []));
213
+ this.disableAnimations = input(false, ...(ngDevMode ? [{ debugName: "disableAnimations" }] : []));
214
+ this.vm = {
215
+ id: this.id,
216
+ size: this.size,
217
+ items: computed(() => this.items().filter((item) => !item.hidden)),
218
+ disableAnimations: this.disableAnimations,
219
+ };
220
+ }
221
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuItemListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
222
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.13", type: MenuItemListComponent, isStandalone: true, selector: "ul[kirby-x-menu-item-list]", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, disableAnimations: { classPropertyName: "disableAnimations", publicName: "disableAnimations", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.id": "vm.id()", "class": "vm.size()" } }, ngImport: i0, template: "@for (item of vm.items(); track item.id) {\n @if (item.isDivider) {\n <kirby-divider aria-hidden=\"true\"></kirby-divider>\n } @else if (item.children) {\n <li\n kirby-x-menu-submenu-item\n [item]=\"item\"\n [size]=\"vm.size()\"\n [disableAnimations]=\"vm.disableAnimations()\"\n ></li>\n } @else {\n <li kirby-x-menu-anchor-item [item]=\"item\" [size]=\"vm.size()\"></li>\n }\n}\n", styles: [":host{display:flex;flex-direction:column;margin:0;padding-left:0;padding-right:0;list-style-type:none}kirby-divider{display:flex;background:var(--kirby-white-overlay-20);margin:8px 0}li{margin-block-start:0!important}\n"], dependencies: [{ kind: "component", type: i0.forwardRef(() => DividerComponent), selector: "kirby-divider", inputs: ["hasMargin"] }, { kind: "component", type: i0.forwardRef(() => MenuAnchorItemComponent), selector: "li[kirby-x-menu-anchor-item]", inputs: ["item", "size"] }, { kind: "component", type: i0.forwardRef(() => MenuSubmenuItemComponent), selector: "li[kirby-x-menu-submenu-item]", inputs: ["item", "size", "disableAnimations"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
223
+ }
224
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuItemListComponent, decorators: [{
225
+ type: Component,
226
+ args: [{ selector: 'ul[kirby-x-menu-item-list]', host: {
227
+ '[attr.id]': 'vm.id()',
228
+ '[class]': 'vm.size()',
229
+ }, changeDetection: ChangeDetectionStrategy.OnPush, imports: [DividerComponent, MenuAnchorItemComponent, forwardRef(() => MenuSubmenuItemComponent)], template: "@for (item of vm.items(); track item.id) {\n @if (item.isDivider) {\n <kirby-divider aria-hidden=\"true\"></kirby-divider>\n } @else if (item.children) {\n <li\n kirby-x-menu-submenu-item\n [item]=\"item\"\n [size]=\"vm.size()\"\n [disableAnimations]=\"vm.disableAnimations()\"\n ></li>\n } @else {\n <li kirby-x-menu-anchor-item [item]=\"item\" [size]=\"vm.size()\"></li>\n }\n}\n", styles: [":host{display:flex;flex-direction:column;margin:0;padding-left:0;padding-right:0;list-style-type:none}kirby-divider{display:flex;background:var(--kirby-white-overlay-20);margin:8px 0}li{margin-block-start:0!important}\n"] }]
230
+ }], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], id: [{ type: i0.Input, args: [{ isSignal: true, alias: "id", required: false }] }], disableAnimations: [{ type: i0.Input, args: [{ isSignal: true, alias: "disableAnimations", required: false }] }] } });
231
+
232
+ class MenuContainerComponent {
233
+ #element;
234
+ #disableAnimations;
235
+ constructor() {
236
+ this.items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
237
+ this.#element = inject(ElementRef).nativeElement;
238
+ this.#disableAnimations = signal(true, ...(ngDevMode ? [{ debugName: "#disableAnimations" }] : []));
239
+ this.vm = {
240
+ items: this.items,
241
+ disableAnimations: this.#disableAnimations.asReadonly(),
242
+ };
243
+ afterNextRender({
244
+ read: () => {
245
+ this.#scrollSelectedItemIntoView();
246
+ this.#disableAnimations.set(false);
247
+ },
248
+ });
249
+ }
250
+ #scrollSelectedItemIntoView() {
251
+ const selectedItem = this.#element.querySelector('.menu-item.selected');
252
+ const scrollContainer = this.#element.closest('.sidebar-content');
253
+ if (selectedItem && scrollContainer) {
254
+ scrollIntoViewIfNecessary(scrollContainer, selectedItem);
255
+ }
256
+ }
257
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuContainerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
258
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: MenuContainerComponent, isStandalone: true, selector: "kirby-x-menu-container", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
259
+ <nav aria-label="Sidebar Menu">
260
+ <ul
261
+ kirby-x-menu-item-list
262
+ [items]="vm.items()"
263
+ [disableAnimations]="vm.disableAnimations()"
264
+ ></ul>
265
+ </nav>
266
+ `, isInline: true, styles: ["nav{padding:0 var(--kirby-spacing-xxs)}\n"], dependencies: [{ kind: "component", type: MenuItemListComponent, selector: "ul[kirby-x-menu-item-list]", inputs: ["items", "size", "id", "disableAnimations"] }] }); }
267
+ }
268
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: MenuContainerComponent, decorators: [{
269
+ type: Component,
270
+ args: [{ selector: 'kirby-x-menu-container', template: `
271
+ <nav aria-label="Sidebar Menu">
272
+ <ul
273
+ kirby-x-menu-item-list
274
+ [items]="vm.items()"
275
+ [disableAnimations]="vm.disableAnimations()"
276
+ ></ul>
277
+ </nav>
278
+ `, imports: [MenuItemListComponent], styles: ["nav{padding:0 var(--kirby-spacing-xxs)}\n"] }]
279
+ }], ctorParameters: () => [], propDecorators: { items: [{ type: i0.Input, args: [{ isSignal: true, alias: "items", required: true }] }] } });
280
+
281
+ class HeightObserverDirective {
282
+ #element;
283
+ #heightChanges;
284
+ #observer;
285
+ constructor() {
286
+ this.heightChange = output();
287
+ this.#element = inject(ElementRef).nativeElement;
288
+ this.#heightChanges = new Subject();
289
+ this.#observer = new ResizeObserver((entries) => {
290
+ this.#heightChanges.next(entries[0].contentRect.height);
291
+ });
292
+ this.#observer.observe(this.#element, { box: 'content-box' });
293
+ this.#heightChanges
294
+ .pipe(debounceTime(50), distinctUntilChanged())
295
+ .subscribe(this.heightChange.emit.bind(this.heightChange));
296
+ }
297
+ ngOnDestroy() {
298
+ this.#observer.unobserve(this.#element);
299
+ this.#observer.disconnect();
300
+ }
301
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HeightObserverDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
302
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.13", type: HeightObserverDirective, isStandalone: true, selector: "[kirbyXHeightObserver]", outputs: { heightChange: "heightChange" }, ngImport: i0 }); }
303
+ }
304
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: HeightObserverDirective, decorators: [{
305
+ type: Directive,
306
+ args: [{
307
+ selector: '[kirbyXHeightObserver]',
308
+ }]
309
+ }], ctorParameters: () => [], propDecorators: { heightChange: [{ type: i0.Output, args: ["heightChange"] }] } });
310
+
311
+ function selectMenuItem(itemId, items) {
312
+ return items.map((item) => {
313
+ if (item.id === itemId) {
314
+ return { ...item, selected: true };
315
+ }
316
+ if (item.children) {
317
+ return { ...item, children: selectMenuItem(itemId, item.children) };
318
+ }
319
+ return { ...item, selected: false };
320
+ });
321
+ }
322
+
323
+ function toggleSubmenu(itemId, items) {
324
+ return items.map((item) => {
325
+ if (item.id === itemId) {
326
+ return { ...item, isExpanded: !item.isExpanded };
327
+ }
328
+ if (item.children && item.isExpanded) {
329
+ return { ...item, children: toggleSubmenu(itemId, item.children) };
330
+ }
331
+ return item;
332
+ });
333
+ }
334
+
335
+ function toggleSubmenuAutoCollapsed(itemId, items) {
336
+ return toggleSubmenuAndCollapseNonAncestors(itemId, items).updatedItems;
337
+ }
338
+ function toggleSubmenuAndCollapseNonAncestors(itemId, items) {
339
+ let found = false;
340
+ const updatedItems = items.map((item) => {
341
+ if (found) {
342
+ return collapse(item);
343
+ }
344
+ if (item.id === itemId) {
345
+ found = true;
346
+ return item.isExpanded ? collapse(item) : { ...item, isExpanded: true };
347
+ }
348
+ if (item.children && item.isExpanded) {
349
+ const { updatedItems, isAncestor } = toggleSubmenuAndCollapseNonAncestors(itemId, item.children);
350
+ found = isAncestor;
351
+ return { ...item, isExpanded: isAncestor, children: updatedItems };
352
+ }
353
+ return item;
354
+ });
355
+ return { updatedItems, isAncestor: found };
356
+ }
357
+ function collapse(item) {
358
+ if (item.children && item.isExpanded) {
359
+ return { ...item, isExpanded: false, children: item.children.map(collapse) };
360
+ }
361
+ return item;
362
+ }
363
+
364
+ class SidebarService {
365
+ #menuHeight = signal(0, ...(ngDevMode ? [{ debugName: "#menuHeight" }] : []));
366
+ #containerHeight = signal(0, ...(ngDevMode ? [{ debugName: "#containerHeight" }] : []));
367
+ #scrollDistance = signal(0, ...(ngDevMode ? [{ debugName: "#scrollDistance" }] : []));
368
+ #scrollableDistance = computed(() => Math.max(0, this.#menuHeight() - this.#containerHeight()), ...(ngDevMode ? [{ debugName: "#scrollableDistance" }] : []));
369
+ #hasScrollbar = computed(() => this.#scrollableDistance() > 0, ...(ngDevMode ? [{ debugName: "#hasScrollbar" }] : []));
370
+ #notAtBottom = computed(() => this.#scrollDistance() < this.#scrollableDistance(), ...(ngDevMode ? [{ debugName: "#notAtBottom" }] : []));
371
+ #showHeaderBottomBorder = computed(() => this.#scrollDistance() > 0, ...(ngDevMode ? [{ debugName: "#showHeaderBottomBorder" }] : []));
372
+ #showFooterTopBorder = computed(() => this.#hasScrollbar() && this.#notAtBottom(), ...(ngDevMode ? [{ debugName: "#showFooterTopBorder" }] : []));
373
+ get showHeaderBottomBorder() {
374
+ return this.#showHeaderBottomBorder;
375
+ }
376
+ get showFooterTopBorder() {
377
+ return this.#showFooterTopBorder;
378
+ }
379
+ set menuHeight(height) {
380
+ this.#menuHeight.set(height);
381
+ }
382
+ set containerHeight(height) {
383
+ this.#containerHeight.set(height);
384
+ }
385
+ set scrollDistance(distance) {
386
+ this.#scrollDistance.set(distance);
387
+ }
388
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
389
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarService, providedIn: 'root' }); }
390
+ }
391
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarService, decorators: [{
392
+ type: Injectable,
393
+ args: [{ providedIn: 'root' }]
394
+ }] });
395
+
396
+ class SidebarMenuComponent {
397
+ #sidebarService;
398
+ #menuStateService;
399
+ constructor() {
400
+ this.menuItems = model.required(...(ngDevMode ? [{ debugName: "menuItems" }] : []));
401
+ this.autoCollapse = input(false, ...(ngDevMode ? [{ debugName: "autoCollapse" }] : []));
402
+ this.submenuToggle = output();
403
+ this.itemClick = output();
404
+ this.#sidebarService = inject(SidebarService);
405
+ this.#menuStateService = inject((MenuStateService));
406
+ this.vm = {
407
+ items: this.menuItems.asReadonly(),
408
+ showHeaderBottomBorder: this.#sidebarService.showHeaderBottomBorder,
409
+ showFooterTopBorder: this.#sidebarService.showFooterTopBorder,
410
+ setContainerHeight: this.#setContainerHeight.bind(this),
411
+ setMenuHeight: this.#setMenuHeight.bind(this),
412
+ setScroll: this.#setScrollDistance.bind(this),
413
+ };
414
+ effect(() => {
415
+ const toggledSubmenu = this.#menuStateService.toggledSubmenu();
416
+ if (toggledSubmenu) {
417
+ this.submenuToggle.emit(toggledSubmenu);
418
+ this.menuItems.update((items) => this.autoCollapse()
419
+ ? toggleSubmenuAutoCollapsed(toggledSubmenu.id, items)
420
+ : toggleSubmenu(toggledSubmenu.id, items));
421
+ }
422
+ });
423
+ effect(() => {
424
+ const selectedItem = this.#menuStateService.selectedItem();
425
+ if (selectedItem) {
426
+ this.itemClick.emit(selectedItem);
427
+ this.menuItems.update((items) => selectMenuItem(selectedItem.id, items));
428
+ }
429
+ });
430
+ }
431
+ #setContainerHeight(height) {
432
+ this.#sidebarService.containerHeight = height;
433
+ }
434
+ #setMenuHeight(height) {
435
+ this.#sidebarService.menuHeight = height;
436
+ }
437
+ #setScrollDistance(event) {
438
+ const target = event.target;
439
+ if (target) {
440
+ this.#sidebarService.scrollDistance = target.scrollTop;
441
+ }
442
+ }
443
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
444
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "20.3.13", type: SidebarMenuComponent, isStandalone: true, selector: "aside[kirby-x-sidebar-menu]", inputs: { menuItems: { classPropertyName: "menuItems", publicName: "menuItems", isSignal: true, isRequired: true, transformFunction: null }, autoCollapse: { classPropertyName: "autoCollapse", publicName: "autoCollapse", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { menuItems: "menuItemsChange", submenuToggle: "submenuToggle", itemClick: "itemClick" }, ngImport: i0, template: "<div class=\"sidebar-header\" [class.bottom-border]=\"vm.showHeaderBottomBorder()\">\n <ng-content select=\"[slot='header']\"></ng-content>\n</div>\n<div\n kirbyXHeightObserver\n class=\"sidebar-content\"\n (scroll)=\"vm.setScroll($event)\"\n (heightChange)=\"vm.setContainerHeight($event)\"\n>\n <kirby-x-menu-container\n kirbyXHeightObserver\n [items]=\"vm.items()\"\n (heightChange)=\"vm.setMenuHeight($event)\"\n ></kirby-x-menu-container>\n</div>\n<div class=\"sidebar-footer\" [class.top-border]=\"vm.showFooterTopBorder()\">\n <ng-content select=\"[slot='footer']\"></ng-content>\n</div>\n", styles: ["ion-item-option.primary{background-color:var(--kirby-primary);color:var(--kirby-primary-contrast)}ion-item-option.secondary{background-color:var(--kirby-secondary);color:var(--kirby-secondary-contrast)}ion-item-option.tertiary{background-color:var(--kirby-tertiary);color:var(--kirby-tertiary-contrast)}ion-item-option.success{background-color:var(--kirby-success);color:var(--kirby-success-contrast)}ion-item-option.warning{background-color:var(--kirby-warning);color:var(--kirby-warning-contrast)}ion-item-option.danger{background-color:var(--kirby-danger);color:var(--kirby-danger-contrast)}ion-item-option.white-overlay{background-color:var(--kirby-white-overlay);color:var(--kirby-white-overlay-contrast)}ion-item-option.light{background-color:var(--kirby-light);color:var(--kirby-light-contrast)}ion-item-option.medium{background-color:var(--kirby-medium);color:var(--kirby-medium-contrast)}ion-item-option.dark{background-color:var(--kirby-dark);color:var(--kirby-dark-contrast)}ion-item-option.dark-overlay{background-color:var(--kirby-dark-overlay);color:var(--kirby-dark-overlay-contrast)}:host{--kirby-inputs-background-color: var(--kirby-white-overlay);--kirby-inputs-background-color-hover: var(--kirby-white-overlay-30);--kirby-inputs-background-color-active: var(--kirby-white-overlay-40);--kirby-inputs-color: var(--kirby-white);--kirby-inputs-indicator-background-color: var(--kirby-white);--kirby-inputs-indicator-color: var(--kirby-black);--kirby-inputs-placeholder-color: var(--kirby-white-overlay-50);--kirby-inputs-elevation: none;height:100%;height:100dvh;background-color:var(--sidebar-background-color, var(--kirby-tertiary));color:var(--sidebar-color, var(--kirby-tertiary-contrast));display:flex;flex-direction:column;overflow:auto}:host *{scrollbar-width:thin;scrollbar-color:var(--kirby-semi-dark) var(--kirby-tertiary)}:host *::-webkit-scrollbar{width:16px}:host *::-webkit-scrollbar-track{background:transparent}:host *::-webkit-scrollbar-thumb{background-color:#8e8e8e80;border-radius:20px;border:4px solid transparent;background-clip:content-box}.sidebar-content{flex-grow:1;display:flex;flex-direction:column;overflow-y:auto}@supports (scrollbar-gutter: stable){.sidebar-content{overflow:hidden auto;scrollbar-gutter:auto}}.sidebar-header,.sidebar-footer{z-index:1;display:flex;align-items:center;justify-content:center;position:sticky}.sidebar-header.bottom-border{box-shadow:0 4px 10px 2px #1c1c1c4d;transition:opacity .3s}.sidebar-footer.top-border{box-shadow:0 -4px 10px 2px #1c1c1c4d;transition:opacity .3s}\n"], dependencies: [{ kind: "directive", type: HeightObserverDirective, selector: "[kirbyXHeightObserver]", outputs: ["heightChange"] }, { kind: "component", type: MenuContainerComponent, selector: "kirby-x-menu-container", inputs: ["items"] }] }); }
445
+ }
446
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarMenuComponent, decorators: [{
447
+ type: Component,
448
+ args: [{ selector: 'aside[kirby-x-sidebar-menu]', imports: [HeightObserverDirective, MenuContainerComponent], template: "<div class=\"sidebar-header\" [class.bottom-border]=\"vm.showHeaderBottomBorder()\">\n <ng-content select=\"[slot='header']\"></ng-content>\n</div>\n<div\n kirbyXHeightObserver\n class=\"sidebar-content\"\n (scroll)=\"vm.setScroll($event)\"\n (heightChange)=\"vm.setContainerHeight($event)\"\n>\n <kirby-x-menu-container\n kirbyXHeightObserver\n [items]=\"vm.items()\"\n (heightChange)=\"vm.setMenuHeight($event)\"\n ></kirby-x-menu-container>\n</div>\n<div class=\"sidebar-footer\" [class.top-border]=\"vm.showFooterTopBorder()\">\n <ng-content select=\"[slot='footer']\"></ng-content>\n</div>\n", styles: ["ion-item-option.primary{background-color:var(--kirby-primary);color:var(--kirby-primary-contrast)}ion-item-option.secondary{background-color:var(--kirby-secondary);color:var(--kirby-secondary-contrast)}ion-item-option.tertiary{background-color:var(--kirby-tertiary);color:var(--kirby-tertiary-contrast)}ion-item-option.success{background-color:var(--kirby-success);color:var(--kirby-success-contrast)}ion-item-option.warning{background-color:var(--kirby-warning);color:var(--kirby-warning-contrast)}ion-item-option.danger{background-color:var(--kirby-danger);color:var(--kirby-danger-contrast)}ion-item-option.white-overlay{background-color:var(--kirby-white-overlay);color:var(--kirby-white-overlay-contrast)}ion-item-option.light{background-color:var(--kirby-light);color:var(--kirby-light-contrast)}ion-item-option.medium{background-color:var(--kirby-medium);color:var(--kirby-medium-contrast)}ion-item-option.dark{background-color:var(--kirby-dark);color:var(--kirby-dark-contrast)}ion-item-option.dark-overlay{background-color:var(--kirby-dark-overlay);color:var(--kirby-dark-overlay-contrast)}:host{--kirby-inputs-background-color: var(--kirby-white-overlay);--kirby-inputs-background-color-hover: var(--kirby-white-overlay-30);--kirby-inputs-background-color-active: var(--kirby-white-overlay-40);--kirby-inputs-color: var(--kirby-white);--kirby-inputs-indicator-background-color: var(--kirby-white);--kirby-inputs-indicator-color: var(--kirby-black);--kirby-inputs-placeholder-color: var(--kirby-white-overlay-50);--kirby-inputs-elevation: none;height:100%;height:100dvh;background-color:var(--sidebar-background-color, var(--kirby-tertiary));color:var(--sidebar-color, var(--kirby-tertiary-contrast));display:flex;flex-direction:column;overflow:auto}:host *{scrollbar-width:thin;scrollbar-color:var(--kirby-semi-dark) var(--kirby-tertiary)}:host *::-webkit-scrollbar{width:16px}:host *::-webkit-scrollbar-track{background:transparent}:host *::-webkit-scrollbar-thumb{background-color:#8e8e8e80;border-radius:20px;border:4px solid transparent;background-clip:content-box}.sidebar-content{flex-grow:1;display:flex;flex-direction:column;overflow-y:auto}@supports (scrollbar-gutter: stable){.sidebar-content{overflow:hidden auto;scrollbar-gutter:auto}}.sidebar-header,.sidebar-footer{z-index:1;display:flex;align-items:center;justify-content:center;position:sticky}.sidebar-header.bottom-border{box-shadow:0 4px 10px 2px #1c1c1c4d;transition:opacity .3s}.sidebar-footer.top-border{box-shadow:0 -4px 10px 2px #1c1c1c4d;transition:opacity .3s}\n"] }]
449
+ }], ctorParameters: () => [], propDecorators: { menuItems: [{ type: i0.Input, args: [{ isSignal: true, alias: "menuItems", required: true }] }, { type: i0.Output, args: ["menuItemsChange"] }], autoCollapse: [{ type: i0.Input, args: [{ isSignal: true, alias: "autoCollapse", required: false }] }], submenuToggle: [{ type: i0.Output, args: ["submenuToggle"] }], itemClick: [{ type: i0.Output, args: ["itemClick"] }] } });
450
+
451
+ class SidebarComponent {
452
+ constructor() {
453
+ this.autoCollapse = false;
454
+ this.menuItemsChange = new EventEmitter();
455
+ this.afterMenuClicked = new EventEmitter();
456
+ this.afterMenuToggled = new EventEmitter();
457
+ /**
458
+ * @deprecated has not had an effect for a long time
459
+ */
460
+ this.expandIconOnHover = false;
461
+ /**
462
+ * @deprecated should use menuItemsChange or two-way binding on menuItems instead
463
+ **/
464
+ this.menuItemsChanged = new EventEmitter();
465
+ }
466
+ changeMenuItems(event) {
467
+ this.menuItems = event;
468
+ this.menuItemsChange.emit(this.menuItems);
469
+ this.menuItemsChanged.emit(this.menuItems);
470
+ }
471
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
472
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: SidebarComponent, isStandalone: true, selector: "kirby-x-sidebar", inputs: { menuItems: "menuItems", autoCollapse: "autoCollapse", expandIconOnHover: "expandIconOnHover" }, outputs: { menuItemsChange: "menuItemsChange", afterMenuClicked: "afterMenuClicked", afterMenuToggled: "afterMenuToggled", menuItemsChanged: "menuItemsChanged" }, ngImport: i0, template: `
473
+ <aside
474
+ kirby-x-sidebar-menu
475
+ [menuItems]="menuItems"
476
+ [autoCollapse]="autoCollapse"
477
+ (menuItemsChange)="changeMenuItems($event)"
478
+ (itemClick)="afterMenuClicked.emit($event)"
479
+ (submenuToggle)="afterMenuToggled.emit($event)"
480
+ >
481
+ <ng-content select="kirby-x-sidebar-header" slot="header"></ng-content>
482
+ <ng-content select="kirby-x-sidebar-footer" slot="footer"></ng-content>
483
+ </aside>
484
+ `, isInline: true, dependencies: [{ kind: "component", type: SidebarMenuComponent, selector: "aside[kirby-x-sidebar-menu]", inputs: ["menuItems", "autoCollapse"], outputs: ["menuItemsChange", "submenuToggle", "itemClick"] }] }); }
485
+ }
486
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarComponent, decorators: [{
487
+ type: Component,
488
+ args: [{
489
+ selector: 'kirby-x-sidebar',
490
+ template: `
491
+ <aside
492
+ kirby-x-sidebar-menu
493
+ [menuItems]="menuItems"
494
+ [autoCollapse]="autoCollapse"
495
+ (menuItemsChange)="changeMenuItems($event)"
496
+ (itemClick)="afterMenuClicked.emit($event)"
497
+ (submenuToggle)="afterMenuToggled.emit($event)"
498
+ >
499
+ <ng-content select="kirby-x-sidebar-header" slot="header"></ng-content>
500
+ <ng-content select="kirby-x-sidebar-footer" slot="footer"></ng-content>
501
+ </aside>
502
+ `,
503
+ imports: [SidebarMenuComponent],
504
+ }]
505
+ }], propDecorators: { menuItems: [{
506
+ type: Input
507
+ }], autoCollapse: [{
508
+ type: Input
509
+ }], menuItemsChange: [{
510
+ type: Output
511
+ }], afterMenuClicked: [{
512
+ type: Output
513
+ }], afterMenuToggled: [{
514
+ type: Output
515
+ }], expandIconOnHover: [{
516
+ type: Input
517
+ }], menuItemsChanged: [{
518
+ type: Output
519
+ }] } });
520
+
521
+ class SidebarFooterComponent {
522
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarFooterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
523
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: SidebarFooterComponent, isStandalone: true, selector: "kirby-x-sidebar-footer", ngImport: i0, template: '<footer><ng-content></ng-content></footer>', isInline: true, styles: [":host,footer{display:flex;flex-direction:column;align-items:center;justify-content:center}:host{min-height:80px}footer{width:100%}\n"] }); }
524
+ }
525
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarFooterComponent, decorators: [{
526
+ type: Component,
527
+ args: [{ selector: 'kirby-x-sidebar-footer', template: '<footer><ng-content></ng-content></footer>', styles: [":host,footer{display:flex;flex-direction:column;align-items:center;justify-content:center}:host{min-height:80px}footer{width:100%}\n"] }]
528
+ }] });
529
+
530
+ class SidebarHeaderComponent {
531
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarHeaderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
532
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.13", type: SidebarHeaderComponent, isStandalone: true, selector: "kirby-x-sidebar-header", ngImport: i0, template: `
533
+ <header>
534
+ <span class="sidebar-logo"><ng-content slot="logo"></ng-content></span>
535
+ <div class="action-bar">
536
+ <ng-content select="[slot='action']"></ng-content>
537
+ </div>
538
+ </header>
539
+ `, isInline: true, styles: [":host,header{display:flex;flex-direction:column;align-items:center;justify-content:center}:host{flex-grow:1}header{width:100%}:host::ng-deep [slot=logo]{height:inherit}:host::ng-deep [slot=logo] img{object-fit:contain;width:100%;height:100%}.sidebar-logo{display:flex;align-items:center;height:50px;margin:var(--kirby-spacing-l) var(--kirby-spacing-m)}.action-bar{display:flex;flex-direction:row;align-items:center;justify-content:center;box-sizing:border-box;width:100%}.action-bar:has([slot=action]){padding:0 var(--kirby-spacing-xs) var(--kirby-spacing-xs)}\n"] }); }
540
+ }
541
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarHeaderComponent, decorators: [{
542
+ type: Component,
543
+ args: [{ selector: 'kirby-x-sidebar-header', template: `
544
+ <header>
545
+ <span class="sidebar-logo"><ng-content slot="logo"></ng-content></span>
546
+ <div class="action-bar">
547
+ <ng-content select="[slot='action']"></ng-content>
548
+ </div>
549
+ </header>
550
+ `, styles: [":host,header{display:flex;flex-direction:column;align-items:center;justify-content:center}:host{flex-grow:1}header{width:100%}:host::ng-deep [slot=logo]{height:inherit}:host::ng-deep [slot=logo] img{object-fit:contain;width:100%;height:100%}.sidebar-logo{display:flex;align-items:center;height:50px;margin:var(--kirby-spacing-l) var(--kirby-spacing-m)}.action-bar{display:flex;flex-direction:row;align-items:center;justify-content:center;box-sizing:border-box;width:100%}.action-bar:has([slot=action]){padding:0 var(--kirby-spacing-xs) var(--kirby-spacing-xs)}\n"] }]
551
+ }] });
552
+
553
+ class SidebarModule {
554
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
555
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.13", ngImport: i0, type: SidebarModule, imports: [SidebarComponent, SidebarFooterComponent, SidebarHeaderComponent], exports: [SidebarComponent, SidebarFooterComponent, SidebarHeaderComponent] }); }
556
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarModule, imports: [SidebarComponent] }); }
557
+ }
558
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.13", ngImport: i0, type: SidebarModule, decorators: [{
559
+ type: NgModule,
560
+ args: [{
561
+ imports: [SidebarComponent, SidebarFooterComponent, SidebarHeaderComponent],
562
+ exports: [SidebarComponent, SidebarFooterComponent, SidebarHeaderComponent],
563
+ }]
564
+ }] });
565
+
566
+ /**
567
+ * Generated bundle index. Do not edit.
568
+ */
569
+
570
+ export { SidebarComponent, SidebarFooterComponent, SidebarHeaderComponent, SidebarModule };
571
+ //# sourceMappingURL=kirbydesign-extensions-angular-sidebar-menu.mjs.map