@ngneers/controls 0.0.1-pre4 → 0.0.1-pre6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngneers-controls-accordion.mjs +32 -32
- package/fesm2022/ngneers-controls-accordion.mjs.map +1 -1
- package/fesm2022/ngneers-controls-api-ng.mjs +19 -19
- package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -1
- package/fesm2022/ngneers-controls-api-resize.mjs +706 -0
- package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -0
- package/fesm2022/ngneers-controls-avatar.mjs +13 -13
- package/fesm2022/ngneers-controls-avatar.mjs.map +1 -1
- package/fesm2022/ngneers-controls-base.mjs +89 -64
- package/fesm2022/ngneers-controls-base.mjs.map +1 -1
- package/fesm2022/ngneers-controls-breadcrumb.mjs +18 -18
- package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -1
- package/fesm2022/ngneers-controls-button-group.mjs +8 -8
- package/fesm2022/ngneers-controls-button-group.mjs.map +1 -1
- package/fesm2022/ngneers-controls-button.mjs +16 -10
- package/fesm2022/ngneers-controls-button.mjs.map +1 -1
- package/fesm2022/{ngneers-controls-calendar-time-C7UnIFzU.mjs → ngneers-controls-calendar-time-Bzlv9Vkn.mjs} +9 -9
- package/fesm2022/{ngneers-controls-calendar-time-C7UnIFzU.mjs.map → ngneers-controls-calendar-time-Bzlv9Vkn.mjs.map} +1 -1
- package/fesm2022/ngneers-controls-calendar.mjs +54 -54
- package/fesm2022/ngneers-controls-calendar.mjs.map +1 -1
- package/fesm2022/ngneers-controls-checkbox.mjs +9 -9
- package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -1
- package/fesm2022/ngneers-controls-chip.mjs +6 -6
- package/fesm2022/ngneers-controls-chip.mjs.map +1 -1
- package/fesm2022/ngneers-controls-defer.mjs +10 -10
- package/fesm2022/ngneers-controls-defer.mjs.map +1 -1
- package/fesm2022/ngneers-controls-dialog.mjs +37 -39
- package/fesm2022/ngneers-controls-dialog.mjs.map +1 -1
- package/fesm2022/ngneers-controls-directives.mjs +45 -39
- package/fesm2022/ngneers-controls-directives.mjs.map +1 -1
- package/fesm2022/ngneers-controls-drawer.mjs +28 -28
- package/fesm2022/ngneers-controls-drawer.mjs.map +1 -1
- package/fesm2022/ngneers-controls-edit-inplace.mjs +15 -15
- package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -1
- package/fesm2022/ngneers-controls-filter.mjs +192 -44
- package/fesm2022/ngneers-controls-filter.mjs.map +1 -1
- package/fesm2022/{ngneers-controls-i18n-de-CdTPeBiR.mjs → ngneers-controls-i18n-de-CF0xTWEX.mjs} +9 -5
- package/fesm2022/ngneers-controls-i18n-de-CF0xTWEX.mjs.map +1 -0
- package/fesm2022/{ngneers-controls-i18n-en-Cfp2pOLY.mjs → ngneers-controls-i18n-en-8B7xAjH2.mjs} +9 -5
- package/fesm2022/ngneers-controls-i18n-en-8B7xAjH2.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n.mjs +5 -5
- package/fesm2022/ngneers-controls-i18n.mjs.map +1 -1
- package/fesm2022/ngneers-controls-icon.mjs +10 -10
- package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
- package/fesm2022/ngneers-controls-inplace.mjs +18 -18
- package/fesm2022/ngneers-controls-inplace.mjs.map +1 -1
- package/fesm2022/ngneers-controls-input-field.mjs +15 -15
- package/fesm2022/ngneers-controls-input-field.mjs.map +1 -1
- package/fesm2022/ngneers-controls-input-mask.mjs +8 -8
- package/fesm2022/ngneers-controls-input-mask.mjs.map +1 -1
- package/fesm2022/ngneers-controls-input.mjs +7 -6
- package/fesm2022/ngneers-controls-input.mjs.map +1 -1
- package/fesm2022/ngneers-controls-item-view.mjs +33 -33
- package/fesm2022/ngneers-controls-item-view.mjs.map +1 -1
- package/fesm2022/ngneers-controls-list-box.mjs +31 -31
- package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
- package/fesm2022/ngneers-controls-menu.mjs +32 -32
- package/fesm2022/ngneers-controls-menu.mjs.map +1 -1
- package/fesm2022/ngneers-controls-message.mjs +4 -4
- package/fesm2022/ngneers-controls-message.mjs.map +1 -1
- package/fesm2022/ngneers-controls-paginator.mjs +12 -12
- package/fesm2022/ngneers-controls-paginator.mjs.map +1 -1
- package/fesm2022/ngneers-controls-popover.mjs +13 -13
- package/fesm2022/ngneers-controls-popover.mjs.map +1 -1
- package/fesm2022/ngneers-controls-progress.mjs +16 -16
- package/fesm2022/ngneers-controls-progress.mjs.map +1 -1
- package/fesm2022/ngneers-controls-scroller.mjs +74 -39
- package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
- package/fesm2022/ngneers-controls-select-button.mjs +6 -6
- package/fesm2022/ngneers-controls-select-button.mjs.map +1 -1
- package/fesm2022/ngneers-controls-select.mjs +46 -46
- package/fesm2022/ngneers-controls-select.mjs.map +1 -1
- package/fesm2022/ngneers-controls-slider.mjs +12 -12
- package/fesm2022/ngneers-controls-slider.mjs.map +1 -1
- package/fesm2022/ngneers-controls-spinner.mjs +7 -7
- package/fesm2022/ngneers-controls-spinner.mjs.map +1 -1
- package/fesm2022/ngneers-controls-splitter.mjs +141 -328
- package/fesm2022/ngneers-controls-splitter.mjs.map +1 -1
- package/fesm2022/ngneers-controls-switch.mjs +3 -3
- package/fesm2022/ngneers-controls-table.mjs +1520 -80
- package/fesm2022/ngneers-controls-table.mjs.map +1 -1
- package/fesm2022/ngneers-controls-tabs.mjs +40 -39
- package/fesm2022/ngneers-controls-tabs.mjs.map +1 -1
- package/fesm2022/ngneers-controls-tag.mjs +4 -4
- package/fesm2022/ngneers-controls-tag.mjs.map +1 -1
- package/fesm2022/ngneers-controls-toast.mjs +18 -18
- package/fesm2022/ngneers-controls-toast.mjs.map +1 -1
- package/fesm2022/ngneers-controls-toggle-button.mjs +9 -9
- package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -1
- package/fesm2022/ngneers-controls-tooltip.mjs +37 -45
- package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -1
- package/fesm2022/ngneers-controls-utils-ng.mjs +9 -9
- package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -1
- package/package.json +14 -10
- package/types/ngneers-controls-api-ng.d.ts +2 -2
- package/types/ngneers-controls-api-resize.d.ts +318 -0
- package/types/ngneers-controls-base.d.ts +8 -0
- package/types/ngneers-controls-breadcrumb.d.ts +1 -1
- package/types/ngneers-controls-button.d.ts +13 -8
- package/types/ngneers-controls-calendar.d.ts +5 -1
- package/types/ngneers-controls-checkbox.d.ts +1 -1
- package/types/ngneers-controls-directives.d.ts +7 -1
- package/types/ngneers-controls-drawer.d.ts +4 -0
- package/types/ngneers-controls-edit-inplace.d.ts +4 -0
- package/types/ngneers-controls-filter.d.ts +53 -4
- package/types/ngneers-controls-i18n.d.ts +4 -0
- package/types/ngneers-controls-icon.d.ts +1 -1
- package/types/ngneers-controls-input-field.d.ts +4 -0
- package/types/ngneers-controls-input.d.ts +1 -1
- package/types/ngneers-controls-list-box.d.ts +5 -1
- package/types/ngneers-controls-menu.d.ts +1 -1
- package/types/ngneers-controls-paginator.d.ts +4 -0
- package/types/ngneers-controls-popover.d.ts +1 -1
- package/types/ngneers-controls-scroller.d.ts +12 -2
- package/types/ngneers-controls-select.d.ts +6 -2
- package/types/ngneers-controls-spinner.d.ts +1 -1
- package/types/ngneers-controls-splitter.d.ts +29 -59
- package/types/ngneers-controls-table.d.ts +392 -24
- package/types/ngneers-controls-toast.d.ts +1 -1
- package/types/ngneers-controls-tooltip.d.ts +1 -7
- package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs.map +0 -1
- package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs.map +0 -1
|
@@ -13,18 +13,18 @@ class ScrollerTemplates extends NgnBase {
|
|
|
13
13
|
* The template to be used for rendering each item in the scroller.
|
|
14
14
|
* Can also be set using the `item` content child.
|
|
15
15
|
*/
|
|
16
|
-
templateItem = input(null, ...(ngDevMode ? [{ debugName: "templateItem" }] : []));
|
|
17
|
-
_userItemTemplate = contentChild('item', ...(ngDevMode ? [{ debugName: "_userItemTemplate" }] : []));
|
|
18
|
-
itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem(), ...(ngDevMode ? [{ debugName: "itemTemplate" }] : []));
|
|
16
|
+
templateItem = input(null, ...(ngDevMode ? [{ debugName: "templateItem" }] : /* istanbul ignore next */ []));
|
|
17
|
+
_userItemTemplate = contentChild('item', ...(ngDevMode ? [{ debugName: "_userItemTemplate" }] : /* istanbul ignore next */ []));
|
|
18
|
+
itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem(), ...(ngDevMode ? [{ debugName: "itemTemplate" }] : /* istanbul ignore next */ []));
|
|
19
19
|
/**
|
|
20
20
|
* Template types for the scroller.
|
|
21
21
|
* Can be used with the {@link NgnTemplate} directive for type safe ng-templates.
|
|
22
22
|
*/
|
|
23
23
|
templateTypes = templateTypesFn();
|
|
24
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
25
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.
|
|
24
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: ScrollerTemplates, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
25
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.2.2", type: ScrollerTemplates, isStandalone: true, inputs: { templateItem: { classPropertyName: "templateItem", publicName: "templateItem", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_userItemTemplate", first: true, predicate: ["item"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0 });
|
|
26
26
|
}
|
|
27
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
27
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: ScrollerTemplates, decorators: [{
|
|
28
28
|
type: Directive
|
|
29
29
|
}], propDecorators: { templateItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "templateItem", required: false }] }], _userItemTemplate: [{ type: i0.ContentChild, args: ['item', { isSignal: true }] }] } });
|
|
30
30
|
|
|
@@ -42,11 +42,11 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
42
42
|
* The items to be displayed in the scroller.
|
|
43
43
|
* This is a required input and should be an array of items of type {@link T}.
|
|
44
44
|
*/
|
|
45
|
-
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
45
|
+
items = input.required(...(ngDevMode ? [{ debugName: "items" }] : /* istanbul ignore next */ []));
|
|
46
46
|
/**
|
|
47
47
|
* The field of the item that uniquely identifies it.
|
|
48
48
|
*/
|
|
49
|
-
fieldId = input(...(ngDevMode ? [undefined, { debugName: "fieldId" }] : []));
|
|
49
|
+
fieldId = input(...(ngDevMode ? [undefined, { debugName: "fieldId" }] : /* istanbul ignore next */ []));
|
|
50
50
|
/**
|
|
51
51
|
* Whether the scroller should use virtual scrolling.
|
|
52
52
|
* When set to true, the scroller will only render the items that are currently visible
|
|
@@ -55,36 +55,54 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
55
55
|
* When virtual scrolling is enabled, {@link itemHeight} must be set to a non-zero value.
|
|
56
56
|
* @default `false`
|
|
57
57
|
*/
|
|
58
|
-
virtual = input(false, ...(ngDevMode ? [{ debugName: "virtual" }] : []));
|
|
58
|
+
virtual = input(false, ...(ngDevMode ? [{ debugName: "virtual" }] : /* istanbul ignore next */ []));
|
|
59
59
|
/**
|
|
60
60
|
* When {@link virtual} scrolling is enabled, this input is required to define the height of each item in pixels.
|
|
61
61
|
*/
|
|
62
|
-
itemHeight = input(undefined, ...(ngDevMode ? [{ debugName: "itemHeight" }] : []));
|
|
62
|
+
itemHeight = input(undefined, ...(ngDevMode ? [{ debugName: "itemHeight" }] : /* istanbul ignore next */ []));
|
|
63
63
|
/**
|
|
64
64
|
* When {@link virtual} scrolling is enabled, this input defines the number of items to be rendered above and below the visible area.
|
|
65
65
|
* This can help to reduce flickering when scrolling.
|
|
66
66
|
* @default `2`
|
|
67
67
|
*/
|
|
68
|
-
virtualPadding = input(2, ...(ngDevMode ? [{ debugName: "virtualPadding" }] : []));
|
|
68
|
+
virtualPadding = input(2, ...(ngDevMode ? [{ debugName: "virtualPadding" }] : /* istanbul ignore next */ []));
|
|
69
69
|
/**
|
|
70
70
|
* Determines whether the scroller should have a tab index and be focusable.
|
|
71
71
|
* @default `false`
|
|
72
72
|
*/
|
|
73
|
-
focusable = input(false, { ...(ngDevMode ? { debugName: "focusable" } : {}), transform: booleanAttribute });
|
|
73
|
+
focusable = input(false, { ...(ngDevMode ? { debugName: "focusable" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
74
74
|
/**
|
|
75
75
|
* Determines whether an item is sticky or not.
|
|
76
76
|
* If set, the scroller will stick the items with a truthy value for the specified field to the top of the scroller.
|
|
77
77
|
*/
|
|
78
|
-
fieldSticky = input(null, ...(ngDevMode ? [{ debugName: "fieldSticky" }] : []));
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
fieldSticky = input(null, ...(ngDevMode ? [{ debugName: "fieldSticky" }] : /* istanbul ignore next */ []));
|
|
79
|
+
/**
|
|
80
|
+
* Viewport size — tracks the scroll ancestor's dimensions so that virtual
|
|
81
|
+
* scrolling works when an outer element handles overflow (e.g. table wrapper).
|
|
82
|
+
*/
|
|
83
|
+
_viewportSize = elementSizeSignal(computed(() => this._scrollAmount.scrollTarget()));
|
|
84
|
+
_itemHeightPx = computed(() => this.itemHeight() ?? 0, ...(ngDevMode ? [{ debugName: "_itemHeightPx" }] : /* istanbul ignore next */ []));
|
|
85
|
+
/**
|
|
86
|
+
* Vertical offset between the scroll container's top and the scroller element.
|
|
87
|
+
* Non-zero when a parent (e.g. table wrapper) owns the scroll and the scroller
|
|
88
|
+
* is positioned below other content (e.g. a sticky header row).
|
|
89
|
+
*/
|
|
90
|
+
_scrollOffset = computed(() => {
|
|
91
|
+
const target = this._scrollAmount.scrollTarget();
|
|
92
|
+
if (target === this._el.nativeElement)
|
|
93
|
+
return 0;
|
|
94
|
+
return this._el.nativeElement.offsetTop;
|
|
95
|
+
}, ...(ngDevMode ? [{ debugName: "_scrollOffset" }] : /* istanbul ignore next */ []));
|
|
81
96
|
_visibleItemCount = computed(() => {
|
|
82
97
|
if (!this.virtual() || this._itemHeightPx() === 0) {
|
|
83
98
|
return 0;
|
|
84
99
|
}
|
|
85
|
-
return Math.ceil(this.
|
|
86
|
-
}, ...(ngDevMode ? [{ debugName: "_visibleItemCount" }] : []));
|
|
87
|
-
_scrollTop = computed(() =>
|
|
100
|
+
return Math.ceil(this._viewportSize().height / this._itemHeightPx() + this.virtualPadding() * 2);
|
|
101
|
+
}, ...(ngDevMode ? [{ debugName: "_visibleItemCount" }] : /* istanbul ignore next */ []));
|
|
102
|
+
_scrollTop = computed(() => {
|
|
103
|
+
const raw = this._scrollAmount.scrollTop();
|
|
104
|
+
return Math.max(0, raw - this._scrollOffset());
|
|
105
|
+
}, ...(ngDevMode ? [{ debugName: "_scrollTop" }] : /* istanbul ignore next */ []));
|
|
88
106
|
/**
|
|
89
107
|
* The index of the first item that is rendered in the (virtual) scroller.
|
|
90
108
|
*/
|
|
@@ -93,22 +111,22 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
93
111
|
return 0;
|
|
94
112
|
}
|
|
95
113
|
return Math.max(0, Math.ceil(this._scrollTop() / this._itemHeightPx()) - this.virtualPadding());
|
|
96
|
-
}, ...(ngDevMode ? [{ debugName: "itemStartIndex" }] : []));
|
|
114
|
+
}, ...(ngDevMode ? [{ debugName: "itemStartIndex" }] : /* istanbul ignore next */ []));
|
|
97
115
|
_itemEndIndex = computed(() => this.virtual()
|
|
98
116
|
? Math.min(this.items().length, this.itemStartIndex() + this._visibleItemCount())
|
|
99
|
-
: 0, ...(ngDevMode ? [{ debugName: "_itemEndIndex" }] : []));
|
|
117
|
+
: 0, ...(ngDevMode ? [{ debugName: "_itemEndIndex" }] : /* istanbul ignore next */ []));
|
|
100
118
|
paddingTop = computed(() => {
|
|
101
119
|
if (!this.virtual()) {
|
|
102
120
|
return 0;
|
|
103
121
|
}
|
|
104
122
|
return (this.itemStartIndex() - (this.latestStickyItem() ? 1 : 0)) * this._itemHeightPx();
|
|
105
|
-
}, ...(ngDevMode ? [{ debugName: "paddingTop" }] : []));
|
|
123
|
+
}, ...(ngDevMode ? [{ debugName: "paddingTop" }] : /* istanbul ignore next */ []));
|
|
106
124
|
paddingBottom = computed(() => {
|
|
107
125
|
if (!this.virtual()) {
|
|
108
126
|
return 0;
|
|
109
127
|
}
|
|
110
128
|
return (this.items().length - this._itemEndIndex()) * this._itemHeightPx();
|
|
111
|
-
}, ...(ngDevMode ? [{ debugName: "paddingBottom" }] : []));
|
|
129
|
+
}, ...(ngDevMode ? [{ debugName: "paddingBottom" }] : /* istanbul ignore next */ []));
|
|
112
130
|
visibleItems = computed(() => {
|
|
113
131
|
if (!this.virtual()) {
|
|
114
132
|
return this.items().map((item, index) => ({ item, index }));
|
|
@@ -121,7 +139,7 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
121
139
|
index: this.itemStartIndex() + index,
|
|
122
140
|
};
|
|
123
141
|
});
|
|
124
|
-
}, ...(ngDevMode ? [{ debugName: "visibleItems" }] : []));
|
|
142
|
+
}, ...(ngDevMode ? [{ debugName: "visibleItems" }] : /* istanbul ignore next */ []));
|
|
125
143
|
/**
|
|
126
144
|
* Returns the last sticky item that is not rendered regularly in the list.
|
|
127
145
|
* Required because sticky items might need to be rendered longer than they would.
|
|
@@ -143,7 +161,7 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
143
161
|
}));
|
|
144
162
|
const stickyItems = unrenderedItemsAtTop.filter(item => item.item[stickyField]);
|
|
145
163
|
return stickyItems[stickyItems.length - 1] ?? null;
|
|
146
|
-
}, ...(ngDevMode ? [{ debugName: "latestStickyItem" }] : []));
|
|
164
|
+
}, ...(ngDevMode ? [{ debugName: "latestStickyItem" }] : /* istanbul ignore next */ []));
|
|
147
165
|
constructor() {
|
|
148
166
|
super();
|
|
149
167
|
effect(() => {
|
|
@@ -158,14 +176,19 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
158
176
|
*/
|
|
159
177
|
scrollToIndex(index, position = 'nearest') {
|
|
160
178
|
untracked(() => {
|
|
179
|
+
const scrollEl = this._scrollAmount.scrollTarget();
|
|
180
|
+
const offset = this._scrollOffset();
|
|
161
181
|
const getItemSize = () => {
|
|
162
182
|
if (this.virtual()) {
|
|
163
183
|
const itemHeight = this._itemHeightPx();
|
|
164
|
-
const itemTop = index * itemHeight;
|
|
184
|
+
const itemTop = index * itemHeight + offset;
|
|
165
185
|
return { itemHeight, itemTop };
|
|
166
186
|
}
|
|
167
187
|
else {
|
|
168
|
-
|
|
188
|
+
let itemElement = this._el.nativeElement.children[index];
|
|
189
|
+
while (!itemElement?.clientHeight && itemElement?.children.length) {
|
|
190
|
+
itemElement = itemElement?.children[0];
|
|
191
|
+
}
|
|
169
192
|
if (itemElement) {
|
|
170
193
|
const itemTop = itemElement.offsetTop;
|
|
171
194
|
const itemHeight = itemElement.clientHeight;
|
|
@@ -179,8 +202,8 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
179
202
|
return;
|
|
180
203
|
}
|
|
181
204
|
const { itemTop, itemHeight } = size;
|
|
182
|
-
|
|
183
|
-
top: getScrollTop(itemTop, itemHeight,
|
|
205
|
+
scrollEl.scrollTo({
|
|
206
|
+
top: getScrollTop(itemTop, itemHeight, scrollEl.clientHeight, scrollEl.scrollTop, position),
|
|
184
207
|
});
|
|
185
208
|
});
|
|
186
209
|
}
|
|
@@ -191,12 +214,12 @@ class NgnScroller extends ScrollerTemplates {
|
|
|
191
214
|
}
|
|
192
215
|
return item.index;
|
|
193
216
|
}
|
|
194
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
195
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
217
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnScroller, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
218
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.2", type: NgnScroller, isStandalone: true, selector: "ngn-scroller, [ngn-scroller]", inputs: { items: { classPropertyName: "items", publicName: "items", isSignal: true, isRequired: true, transformFunction: null }, fieldId: { classPropertyName: "fieldId", publicName: "fieldId", isSignal: true, isRequired: false, transformFunction: null }, virtual: { classPropertyName: "virtual", publicName: "virtual", isSignal: true, isRequired: false, transformFunction: null }, itemHeight: { classPropertyName: "itemHeight", publicName: "itemHeight", isSignal: true, isRequired: false, transformFunction: null }, virtualPadding: { classPropertyName: "virtualPadding", publicName: "virtualPadding", isSignal: true, isRequired: false, transformFunction: null }, focusable: { classPropertyName: "focusable", publicName: "focusable", isSignal: true, isRequired: false, transformFunction: null }, fieldSticky: { classPropertyName: "fieldSticky", publicName: "fieldSticky", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "tabIndex": "focusable() ? 0 : -1", "style.--ngn-scroller-item-height.px": "itemHeight() ?? \"auto\"", "style.--ngn-scroller-padding-top.px": "paddingTop()", "style.--ngn-scroller-padding-bottom.px": "paddingBottom()" } }, providers: [provideSelf(NgnScroller)], usesInheritance: true, hostDirectives: [{ directive: i1.NgnScrollAmount, inputs: ["scrollContainer", "scrollContainer"] }], ngImport: i0, template: "@if (latestStickyItem(); as latestStickyItem) {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n itemTemplate();\r\n context: { $implicit: latestStickyItem.item, index: latestStickyItem.index }\r\n \"\r\n ></ng-container>\r\n}\r\n\r\n@for (item of visibleItems(); track track(item)) {\r\n <ng-container\r\n *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item.item, index: item.index }\"\r\n ></ng-container>\r\n}\r\n", dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
196
219
|
}
|
|
197
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
220
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnScroller, decorators: [{
|
|
198
221
|
type: Component,
|
|
199
|
-
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-scroller, [ngn-scroller]', imports: [NgTemplateOutlet], providers: [provideSelf(NgnScroller)], hostDirectives: [{ directive: NgnScrollAmount }], host: {
|
|
222
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-scroller, [ngn-scroller]', imports: [NgTemplateOutlet], providers: [provideSelf(NgnScroller)], hostDirectives: [{ directive: NgnScrollAmount, inputs: ['scrollContainer'] }], host: {
|
|
200
223
|
'[tabIndex]': 'focusable() ? 0 : -1',
|
|
201
224
|
'[style.--ngn-scroller-item-height.px]': 'itemHeight() ?? "auto"',
|
|
202
225
|
'[style.--ngn-scroller-padding-top.px]': 'paddingTop()',
|
|
@@ -206,8 +229,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImpor
|
|
|
206
229
|
|
|
207
230
|
class NgnScrollerItem {
|
|
208
231
|
_el = inject((ElementRef));
|
|
209
|
-
ngnScrollerItem = input.required(...(ngDevMode ? [{ debugName: "ngnScrollerItem" }] : []));
|
|
210
|
-
_scroller = signal(null, ...(ngDevMode ? [{ debugName: "_scroller" }] : []));
|
|
232
|
+
ngnScrollerItem = input.required(...(ngDevMode ? [{ debugName: "ngnScrollerItem" }] : /* istanbul ignore next */ []));
|
|
233
|
+
_scroller = signal(null, ...(ngDevMode ? [{ debugName: "_scroller" }] : /* istanbul ignore next */ []));
|
|
211
234
|
ngAfterViewInit() {
|
|
212
235
|
if (!this._el.nativeElement.isConnected) {
|
|
213
236
|
return;
|
|
@@ -219,6 +242,8 @@ class NgnScrollerItem {
|
|
|
219
242
|
this._scroller.set(parentInstance);
|
|
220
243
|
}
|
|
221
244
|
constructor() {
|
|
245
|
+
let prevItemClass = '';
|
|
246
|
+
let prevStickyClass = '';
|
|
222
247
|
effect(() => {
|
|
223
248
|
const item = this.ngnScrollerItem();
|
|
224
249
|
const scroller = this._scroller();
|
|
@@ -227,14 +252,24 @@ class NgnScrollerItem {
|
|
|
227
252
|
}
|
|
228
253
|
const stickyField = scroller.fieldSticky();
|
|
229
254
|
const isSticky = !!stickyField && stickyField in item ? !!item[stickyField] : false;
|
|
230
|
-
|
|
231
|
-
|
|
255
|
+
const stickyClass = scroller['theme'].class('item-sticky');
|
|
256
|
+
if (prevStickyClass && prevStickyClass !== stickyClass) {
|
|
257
|
+
toggleClass(this._el.nativeElement, prevStickyClass, false);
|
|
258
|
+
}
|
|
259
|
+
toggleClass(this._el.nativeElement, stickyClass, isSticky);
|
|
260
|
+
prevStickyClass = stickyClass;
|
|
261
|
+
const itemClass = scroller['theme'].class('item');
|
|
262
|
+
if (prevItemClass && prevItemClass !== itemClass) {
|
|
263
|
+
toggleClass(this._el.nativeElement, prevItemClass, false);
|
|
264
|
+
}
|
|
265
|
+
toggleClass(this._el.nativeElement, itemClass, true);
|
|
266
|
+
prevItemClass = itemClass;
|
|
232
267
|
});
|
|
233
268
|
}
|
|
234
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
235
|
-
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.
|
|
269
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnScrollerItem, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
270
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.2.2", type: NgnScrollerItem, isStandalone: true, selector: "[ngnScrollerItem]", inputs: { ngnScrollerItem: { classPropertyName: "ngnScrollerItem", publicName: "ngnScrollerItem", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
236
271
|
}
|
|
237
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
272
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnScrollerItem, decorators: [{
|
|
238
273
|
type: Directive,
|
|
239
274
|
args: [{ selector: '[ngnScrollerItem]' }]
|
|
240
275
|
}], ctorParameters: () => [], propDecorators: { ngnScrollerItem: [{ type: i0.Input, args: [{ isSignal: true, alias: "ngnScrollerItem", required: true }] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngneers-controls-scroller.mjs","sources":["../../src/scroller/scroller-templates.ts","../../src/scroller/scroller.ts","../../src/scroller/scroller.html","../../src/scroller/scroller-item.ts","../../src/scroller/ngneers-controls-scroller.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef } from '@angular/core';\r\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\r\nimport { NgnBase } from '@ngneers/controls/base';\r\n\r\n@Directive()\r\nexport abstract class ScrollerTemplates<T> extends NgnBase<'scroller'> {\r\n /**\r\n * The template to be used for rendering each item in the scroller.\r\n * Can also be set using the `item` content child.\r\n */\r\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\r\n private readonly _userItemTemplate =\r\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\r\n protected readonly itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem());\r\n\r\n /**\r\n * Template types for the scroller.\r\n * Can be used with the {@link NgnTemplate} directive for type safe ng-templates.\r\n */\r\n public readonly templateTypes = templateTypesFn<{\r\n item: {\r\n $implicit: T;\r\n index: number;\r\n };\r\n }>();\r\n}\r\n","import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n booleanAttribute,\r\n Component,\r\n computed,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n untracked,\r\n ChangeDetectionStrategy,\r\n} from '@angular/core';\r\nimport { elementSizeSignal } from '@ngneers/controls/api/ng';\r\nimport { provideSelf } from '@ngneers/controls/base';\r\nimport { NgnScrollAmount } from '@ngneers/controls/directives';\r\nimport { type AllKeysOfUnion, getScrollTop, NgnError } from '@ngneers/controls/utils';\r\nimport { scrollerControlTemplate } from '@ngneers/controls-themes/templates/scroller';\r\n\r\nimport { ScrollerTemplates } from './scroller-templates';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-scroller, [ngn-scroller]',\r\n templateUrl: './scroller.html',\r\n imports: [NgTemplateOutlet],\r\n providers: [provideSelf(NgnScroller)],\r\n hostDirectives: [{ directive: NgnScrollAmount }],\r\n host: {\r\n '[tabIndex]': 'focusable() ? 0 : -1',\r\n '[style.--ngn-scroller-item-height.px]': 'itemHeight() ?? \"auto\"',\r\n '[style.--ngn-scroller-padding-top.px]': 'paddingTop()',\r\n '[style.--ngn-scroller-padding-bottom.px]': 'paddingBottom()',\r\n },\r\n})\r\nexport class NgnScroller<T> extends ScrollerTemplates<T> {\r\n protected readonly theme = this.injectThemeTemplate(scrollerControlTemplate, {\r\n root: true,\r\n virtual: () => !!this.virtual(),\r\n });\r\n private readonly _el = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly _scrollAmount = inject(NgnScrollAmount);\r\n\r\n /**\r\n * The items to be displayed in the scroller.\r\n * This is a required input and should be an array of items of type {@link T}.\r\n */\r\n public readonly items = input.required<readonly T[]>();\r\n /**\r\n * The field of the item that uniquely identifies it.\r\n */\r\n public readonly fieldId = input<keyof T>();\r\n /**\r\n * Whether the scroller should use virtual scrolling.\r\n * When set to true, the scroller will only render the items that are currently visible\r\n * on the screen, improving performance for large lists.\r\n *\r\n * When virtual scrolling is enabled, {@link itemHeight} must be set to a non-zero value.\r\n * @default `false`\r\n */\r\n public readonly virtual = input<boolean | undefined>(false);\r\n /**\r\n * When {@link virtual} scrolling is enabled, this input is required to define the height of each item in pixels.\r\n */\r\n public readonly itemHeight = input<number | undefined>(undefined);\r\n /**\r\n * When {@link virtual} scrolling is enabled, this input defines the number of items to be rendered above and below the visible area.\r\n * This can help to reduce flickering when scrolling.\r\n * @default `2`\r\n */\r\n public readonly virtualPadding = input<number>(2);\r\n /**\r\n * Determines whether the scroller should have a tab index and be focusable.\r\n * @default `false`\r\n */\r\n public readonly focusable = input(false, { transform: booleanAttribute });\r\n /**\r\n * Determines whether an item is sticky or not.\r\n * If set, the scroller will stick the items with a truthy value for the specified field to the top of the scroller.\r\n */\r\n public readonly fieldSticky = input<AllKeysOfUnion<T> | null>(null);\r\n\r\n private readonly _elementSize = elementSizeSignal(this._el);\r\n\r\n private readonly _itemHeightPx = computed(() => this.itemHeight() ?? 0);\r\n\r\n private readonly _visibleItemCount = computed(() => {\r\n if (!this.virtual() || this._itemHeightPx() === 0) {\r\n return 0;\r\n }\r\n return Math.ceil(this._elementSize().height / this._itemHeightPx() + this.virtualPadding() * 2);\r\n });\r\n private readonly _scrollTop = computed(() => this._scrollAmount.scrollTop());\r\n /**\r\n * The index of the first item that is rendered in the (virtual) scroller.\r\n */\r\n public readonly itemStartIndex = computed(() => {\r\n if (!this.virtual() || this._itemHeightPx() === 0) {\r\n return 0;\r\n }\r\n return Math.max(0, Math.ceil(this._scrollTop() / this._itemHeightPx()) - this.virtualPadding());\r\n });\r\n private readonly _itemEndIndex = computed(() =>\r\n this.virtual()\r\n ? Math.min(this.items().length, this.itemStartIndex() + this._visibleItemCount())\r\n : 0\r\n );\r\n\r\n protected readonly paddingTop = computed(() => {\r\n if (!this.virtual()) {\r\n return 0;\r\n }\r\n return (this.itemStartIndex() - (this.latestStickyItem() ? 1 : 0)) * this._itemHeightPx();\r\n });\r\n\r\n protected readonly paddingBottom = computed(() => {\r\n if (!this.virtual()) {\r\n return 0;\r\n }\r\n return (this.items().length - this._itemEndIndex()) * this._itemHeightPx();\r\n });\r\n\r\n protected readonly visibleItems = computed(() => {\r\n if (!this.virtual()) {\r\n return this.items().map((item, index) => ({ item, index }));\r\n }\r\n return this.items()\r\n .slice(this.itemStartIndex(), this._itemEndIndex())\r\n .map((item, index) => {\r\n return {\r\n item,\r\n index: this.itemStartIndex() + index,\r\n };\r\n });\r\n });\r\n\r\n /**\r\n * Returns the last sticky item that is not rendered regularly in the list.\r\n * Required because sticky items might need to be rendered longer than they would.\r\n * Only applicable when virtual scrolling is enabled.\r\n */\r\n protected readonly latestStickyItem = computed(() => {\r\n if (!this.virtual()) {\r\n return null;\r\n }\r\n const stickyField = this.fieldSticky();\r\n if (!stickyField) {\r\n return null;\r\n }\r\n const unrenderedItemsAtTop = this.items()\r\n .slice(0, this.itemStartIndex())\r\n .map((item, index) => ({\r\n item,\r\n index,\r\n }));\r\n const stickyItems = unrenderedItemsAtTop.filter(item => item.item[stickyField]);\r\n return stickyItems[stickyItems.length - 1] ?? null;\r\n });\r\n\r\n constructor() {\r\n super();\r\n effect(() => {\r\n if (this.virtual() && !this.itemHeight()) {\r\n throw new NgnError('scroller', 'itemHeight must be set when virtual is true');\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Scrolls the item with the given index into view.\r\n * @param index The index of the item to scroll to.\r\n */\r\n public scrollToIndex(index: number, position: ScrollLogicalPosition = 'nearest') {\r\n untracked(() => {\r\n const getItemSize = () => {\r\n if (this.virtual()) {\r\n const itemHeight = this._itemHeightPx();\r\n const itemTop = index * itemHeight;\r\n return { itemHeight, itemTop };\r\n } else {\r\n const itemElement = this._el.nativeElement.children[index] as HTMLElement | null;\r\n if (itemElement) {\r\n const itemTop = itemElement.offsetTop;\r\n const itemHeight = itemElement.clientHeight;\r\n return { itemTop, itemHeight };\r\n }\r\n return null;\r\n }\r\n };\r\n const size = getItemSize();\r\n if (!size) {\r\n return;\r\n }\r\n const { itemTop, itemHeight } = size;\r\n this._el.nativeElement.scrollTo({\r\n top: getScrollTop(\r\n itemTop,\r\n itemHeight,\r\n this._el.nativeElement.clientHeight,\r\n this._el.nativeElement.scrollTop,\r\n position\r\n ),\r\n });\r\n });\r\n }\r\n\r\n protected track(item: { item: T; index: number }): unknown {\r\n const fieldId = this.fieldId();\r\n if (fieldId) {\r\n return item.item[fieldId];\r\n }\r\n return item.index;\r\n }\r\n}\r\n","@if (latestStickyItem(); as latestStickyItem) {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n itemTemplate();\r\n context: { $implicit: latestStickyItem.item, index: latestStickyItem.index }\r\n \"\r\n ></ng-container>\r\n}\r\n\r\n@for (item of visibleItems(); track track(item)) {\r\n <ng-container\r\n *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item.item, index: item.index }\"\r\n ></ng-container>\r\n}\r\n","import {\r\n type AfterViewInit,\r\n Directive,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { getNearestNgnInstance } from '@ngneers/controls/base';\r\nimport { NgnError, toggleClass } from '@ngneers/controls/utils';\r\n\r\nimport { NgnScroller } from './scroller';\r\n\r\n@Directive({ selector: '[ngnScrollerItem]' })\r\nexport class NgnScrollerItem implements AfterViewInit {\r\n private readonly _el = inject(ElementRef<HTMLElement>);\r\n public readonly ngnScrollerItem = input.required<object>();\r\n private readonly _scroller = signal<NgnScroller<unknown> | null>(null);\r\n\r\n public ngAfterViewInit() {\r\n if (!this._el.nativeElement.isConnected) {\r\n return;\r\n }\r\n const parentInstance = getNearestNgnInstance(this._el.nativeElement, NgnScroller);\r\n if (!parentInstance) {\r\n throw new NgnError(\r\n 'scroller',\r\n 'ngnScrollerItem must be used within an NgnScroller component'\r\n );\r\n }\r\n this._scroller.set(parentInstance);\r\n }\r\n\r\n constructor() {\r\n effect(() => {\r\n const item = this.ngnScrollerItem() as Record<string, unknown> | null;\r\n const scroller = this._scroller();\r\n if (!item || !scroller) {\r\n return;\r\n }\r\n const stickyField = scroller.fieldSticky() as unknown as string | null;\r\n const isSticky = !!stickyField && stickyField in item ? !!item[stickyField] : false;\r\n\r\n toggleClass(this._el.nativeElement, scroller['theme'].class('item-sticky'), isSticky);\r\n toggleClass(this._el.nativeElement, scroller['theme'].class('item'), true);\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ngneers-controls-scroller.mjs","sources":["../../src/scroller/scroller-templates.ts","../../src/scroller/scroller.ts","../../src/scroller/scroller.html","../../src/scroller/scroller-item.ts","../../src/scroller/ngneers-controls-scroller.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef } from '@angular/core';\r\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\r\nimport { NgnBase } from '@ngneers/controls/base';\r\n\r\n@Directive()\r\nexport abstract class ScrollerTemplates<T> extends NgnBase<'scroller'> {\r\n /**\r\n * The template to be used for rendering each item in the scroller.\r\n * Can also be set using the `item` content child.\r\n */\r\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\r\n private readonly _userItemTemplate =\r\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\r\n protected readonly itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem());\r\n\r\n /**\r\n * Template types for the scroller.\r\n * Can be used with the {@link NgnTemplate} directive for type safe ng-templates.\r\n */\r\n public readonly templateTypes = templateTypesFn<{\r\n item: {\r\n $implicit: T;\r\n index: number;\r\n };\r\n }>();\r\n}\r\n","import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n booleanAttribute,\r\n Component,\r\n computed,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n untracked,\r\n ChangeDetectionStrategy,\r\n} from '@angular/core';\r\nimport { elementSizeSignal } from '@ngneers/controls/api/ng';\r\nimport { provideSelf } from '@ngneers/controls/base';\r\nimport { NgnScrollAmount } from '@ngneers/controls/directives';\r\nimport { type AllKeysOfUnion, getScrollTop, NgnError } from '@ngneers/controls/utils';\r\nimport { scrollerControlTemplate } from '@ngneers/controls-themes/templates/scroller';\r\n\r\nimport { ScrollerTemplates } from './scroller-templates';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-scroller, [ngn-scroller]',\r\n templateUrl: './scroller.html',\r\n imports: [NgTemplateOutlet],\r\n providers: [provideSelf(NgnScroller)],\r\n hostDirectives: [{ directive: NgnScrollAmount, inputs: ['scrollContainer'] }],\r\n host: {\r\n '[tabIndex]': 'focusable() ? 0 : -1',\r\n '[style.--ngn-scroller-item-height.px]': 'itemHeight() ?? \"auto\"',\r\n '[style.--ngn-scroller-padding-top.px]': 'paddingTop()',\r\n '[style.--ngn-scroller-padding-bottom.px]': 'paddingBottom()',\r\n },\r\n})\r\nexport class NgnScroller<T> extends ScrollerTemplates<T> {\r\n protected readonly theme = this.injectThemeTemplate(scrollerControlTemplate, {\r\n root: true,\r\n virtual: () => !!this.virtual(),\r\n });\r\n private readonly _el = inject<ElementRef<HTMLElement>>(ElementRef);\r\n private readonly _scrollAmount = inject(NgnScrollAmount);\r\n\r\n /**\r\n * The items to be displayed in the scroller.\r\n * This is a required input and should be an array of items of type {@link T}.\r\n */\r\n public readonly items = input.required<readonly T[]>();\r\n /**\r\n * The field of the item that uniquely identifies it.\r\n */\r\n public readonly fieldId = input<keyof T>();\r\n /**\r\n * Whether the scroller should use virtual scrolling.\r\n * When set to true, the scroller will only render the items that are currently visible\r\n * on the screen, improving performance for large lists.\r\n *\r\n * When virtual scrolling is enabled, {@link itemHeight} must be set to a non-zero value.\r\n * @default `false`\r\n */\r\n public readonly virtual = input<boolean | undefined>(false);\r\n /**\r\n * When {@link virtual} scrolling is enabled, this input is required to define the height of each item in pixels.\r\n */\r\n public readonly itemHeight = input<number | undefined>(undefined);\r\n /**\r\n * When {@link virtual} scrolling is enabled, this input defines the number of items to be rendered above and below the visible area.\r\n * This can help to reduce flickering when scrolling.\r\n * @default `2`\r\n */\r\n public readonly virtualPadding = input<number>(2);\r\n /**\r\n * Determines whether the scroller should have a tab index and be focusable.\r\n * @default `false`\r\n */\r\n public readonly focusable = input(false, { transform: booleanAttribute });\r\n /**\r\n * Determines whether an item is sticky or not.\r\n * If set, the scroller will stick the items with a truthy value for the specified field to the top of the scroller.\r\n */\r\n public readonly fieldSticky = input<AllKeysOfUnion<T> | null>(null);\r\n\r\n /**\r\n * Viewport size — tracks the scroll ancestor's dimensions so that virtual\r\n * scrolling works when an outer element handles overflow (e.g. table wrapper).\r\n */\r\n private readonly _viewportSize = elementSizeSignal(\r\n computed(() => this._scrollAmount.scrollTarget())\r\n );\r\n\r\n private readonly _itemHeightPx = computed(() => this.itemHeight() ?? 0);\r\n\r\n /**\r\n * Vertical offset between the scroll container's top and the scroller element.\r\n * Non-zero when a parent (e.g. table wrapper) owns the scroll and the scroller\r\n * is positioned below other content (e.g. a sticky header row).\r\n */\r\n private readonly _scrollOffset = computed(() => {\r\n const target = this._scrollAmount.scrollTarget();\r\n if (target === this._el.nativeElement) return 0;\r\n return this._el.nativeElement.offsetTop;\r\n });\r\n\r\n private readonly _visibleItemCount = computed(() => {\r\n if (!this.virtual() || this._itemHeightPx() === 0) {\r\n return 0;\r\n }\r\n return Math.ceil(\r\n this._viewportSize().height / this._itemHeightPx() + this.virtualPadding() * 2\r\n );\r\n });\r\n private readonly _scrollTop = computed(() => {\r\n const raw = this._scrollAmount.scrollTop();\r\n return Math.max(0, raw - this._scrollOffset());\r\n });\r\n /**\r\n * The index of the first item that is rendered in the (virtual) scroller.\r\n */\r\n public readonly itemStartIndex = computed(() => {\r\n if (!this.virtual() || this._itemHeightPx() === 0) {\r\n return 0;\r\n }\r\n return Math.max(0, Math.ceil(this._scrollTop() / this._itemHeightPx()) - this.virtualPadding());\r\n });\r\n private readonly _itemEndIndex = computed(() =>\r\n this.virtual()\r\n ? Math.min(this.items().length, this.itemStartIndex() + this._visibleItemCount())\r\n : 0\r\n );\r\n\r\n protected readonly paddingTop = computed(() => {\r\n if (!this.virtual()) {\r\n return 0;\r\n }\r\n return (this.itemStartIndex() - (this.latestStickyItem() ? 1 : 0)) * this._itemHeightPx();\r\n });\r\n\r\n protected readonly paddingBottom = computed(() => {\r\n if (!this.virtual()) {\r\n return 0;\r\n }\r\n return (this.items().length - this._itemEndIndex()) * this._itemHeightPx();\r\n });\r\n\r\n protected readonly visibleItems = computed(() => {\r\n if (!this.virtual()) {\r\n return this.items().map((item, index) => ({ item, index }));\r\n }\r\n return this.items()\r\n .slice(this.itemStartIndex(), this._itemEndIndex())\r\n .map((item, index) => {\r\n return {\r\n item,\r\n index: this.itemStartIndex() + index,\r\n };\r\n });\r\n });\r\n\r\n /**\r\n * Returns the last sticky item that is not rendered regularly in the list.\r\n * Required because sticky items might need to be rendered longer than they would.\r\n * Only applicable when virtual scrolling is enabled.\r\n */\r\n protected readonly latestStickyItem = computed(() => {\r\n if (!this.virtual()) {\r\n return null;\r\n }\r\n const stickyField = this.fieldSticky();\r\n if (!stickyField) {\r\n return null;\r\n }\r\n const unrenderedItemsAtTop = this.items()\r\n .slice(0, this.itemStartIndex())\r\n .map((item, index) => ({\r\n item,\r\n index,\r\n }));\r\n const stickyItems = unrenderedItemsAtTop.filter(item => item.item[stickyField]);\r\n return stickyItems[stickyItems.length - 1] ?? null;\r\n });\r\n\r\n constructor() {\r\n super();\r\n effect(() => {\r\n if (this.virtual() && !this.itemHeight()) {\r\n throw new NgnError('scroller', 'itemHeight must be set when virtual is true');\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Scrolls the item with the given index into view.\r\n * @param index The index of the item to scroll to.\r\n */\r\n public scrollToIndex(index: number, position: ScrollLogicalPosition = 'nearest') {\r\n untracked(() => {\r\n const scrollEl = this._scrollAmount.scrollTarget();\r\n const offset = this._scrollOffset();\r\n\r\n const getItemSize = () => {\r\n if (this.virtual()) {\r\n const itemHeight = this._itemHeightPx();\r\n const itemTop = index * itemHeight + offset;\r\n return { itemHeight, itemTop };\r\n } else {\r\n let itemElement = this._el.nativeElement.children[index] as HTMLElement | null;\r\n while (!itemElement?.clientHeight && itemElement?.children.length) {\r\n itemElement = itemElement?.children[0] as HTMLElement | null;\r\n }\r\n if (itemElement) {\r\n const itemTop = itemElement.offsetTop;\r\n const itemHeight = itemElement.clientHeight;\r\n return { itemTop, itemHeight };\r\n }\r\n return null;\r\n }\r\n };\r\n const size = getItemSize();\r\n if (!size) {\r\n return;\r\n }\r\n const { itemTop, itemHeight } = size;\r\n scrollEl.scrollTo({\r\n top: getScrollTop(itemTop, itemHeight, scrollEl.clientHeight, scrollEl.scrollTop, position),\r\n });\r\n });\r\n }\r\n\r\n protected track(item: { item: T; index: number }): unknown {\r\n const fieldId = this.fieldId();\r\n if (fieldId) {\r\n return item.item[fieldId];\r\n }\r\n return item.index;\r\n }\r\n}\r\n","@if (latestStickyItem(); as latestStickyItem) {\r\n <ng-container\r\n *ngTemplateOutlet=\"\r\n itemTemplate();\r\n context: { $implicit: latestStickyItem.item, index: latestStickyItem.index }\r\n \"\r\n ></ng-container>\r\n}\r\n\r\n@for (item of visibleItems(); track track(item)) {\r\n <ng-container\r\n *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item.item, index: item.index }\"\r\n ></ng-container>\r\n}\r\n","import {\r\n type AfterViewInit,\r\n Directive,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n signal,\r\n} from '@angular/core';\r\nimport { getNearestNgnInstance } from '@ngneers/controls/base';\r\nimport { NgnError, toggleClass } from '@ngneers/controls/utils';\r\n\r\nimport { NgnScroller } from './scroller';\r\n\r\n@Directive({ selector: '[ngnScrollerItem]' })\r\nexport class NgnScrollerItem implements AfterViewInit {\r\n private readonly _el = inject(ElementRef<HTMLElement>);\r\n public readonly ngnScrollerItem = input.required<object>();\r\n private readonly _scroller = signal<NgnScroller<unknown> | null>(null);\r\n\r\n public ngAfterViewInit() {\r\n if (!this._el.nativeElement.isConnected) {\r\n return;\r\n }\r\n const parentInstance = getNearestNgnInstance(this._el.nativeElement, NgnScroller);\r\n if (!parentInstance) {\r\n throw new NgnError(\r\n 'scroller',\r\n 'ngnScrollerItem must be used within an NgnScroller component'\r\n );\r\n }\r\n this._scroller.set(parentInstance);\r\n }\r\n\r\n constructor() {\r\n let prevItemClass = '';\r\n let prevStickyClass = '';\r\n effect(() => {\r\n const item = this.ngnScrollerItem() as Record<string, unknown> | null;\r\n const scroller = this._scroller();\r\n if (!item || !scroller) {\r\n return;\r\n }\r\n const stickyField = scroller.fieldSticky() as unknown as string | null;\r\n const isSticky = !!stickyField && stickyField in item ? !!item[stickyField] : false;\r\n\r\n const stickyClass = scroller['theme'].class('item-sticky');\r\n if (prevStickyClass && prevStickyClass !== stickyClass) {\r\n toggleClass(this._el.nativeElement, prevStickyClass, false);\r\n }\r\n toggleClass(this._el.nativeElement, stickyClass, isSticky);\r\n prevStickyClass = stickyClass;\r\n\r\n const itemClass = scroller['theme'].class('item');\r\n if (prevItemClass && prevItemClass !== itemClass) {\r\n toggleClass(this._el.nativeElement, prevItemClass, false);\r\n }\r\n toggleClass(this._el.nativeElement, itemClass, true);\r\n prevItemClass = itemClass;\r\n });\r\n }\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -21,17 +21,17 @@ class NgnSelectButton extends ValueControlBase {
|
|
|
21
21
|
* - 'vertical' - The buttons are arranged vertically.
|
|
22
22
|
* @default 'auto'
|
|
23
23
|
*/
|
|
24
|
-
orientation = input('auto', ...(ngDevMode ? [{ debugName: "orientation" }] : []));
|
|
24
|
+
orientation = input('auto', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
25
25
|
/**
|
|
26
26
|
* Defines the options for the select button.
|
|
27
27
|
*/
|
|
28
|
-
options = input.required(...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
28
|
+
options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
|
|
29
29
|
/**
|
|
30
30
|
* When `true`, allows unselecting the currently selected option by clicking on it again.
|
|
31
31
|
* If `false`, clicking on the selected option will not change the selection.
|
|
32
32
|
* @default false
|
|
33
33
|
*/
|
|
34
|
-
allowUnselect = input(false, ...(ngDevMode ? [{ debugName: "allowUnselect" }] : []));
|
|
34
|
+
allowUnselect = input(false, ...(ngDevMode ? [{ debugName: "allowUnselect" }] : /* istanbul ignore next */ []));
|
|
35
35
|
maybeCallback = maybeCallback;
|
|
36
36
|
valueChange(value) {
|
|
37
37
|
if (this.value() === value && !this.allowUnselect()) {
|
|
@@ -39,10 +39,10 @@ class NgnSelectButton extends ValueControlBase {
|
|
|
39
39
|
}
|
|
40
40
|
this.value.set(value);
|
|
41
41
|
}
|
|
42
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.
|
|
43
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.
|
|
42
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnSelectButton, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
43
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.2", type: NgnSelectButton, isStandalone: true, selector: "ngn-select-button", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, allowUnselect: { classPropertyName: "allowUnselect", publicName: "allowUnselect", isSignal: true, isRequired: false, transformFunction: null } }, providers: [provideSelf(NgnSelectButton)], usesInheritance: true, ngImport: i0, template: "<ngn-button-group [orientation]=\"orientation()\">\r\n @for (item of options(); track item.value) {\r\n <ngn-toggle-button\r\n [label]=\"maybeCallback(item.label)\"\r\n [icon]=\"item.icon\"\r\n [fixedWidth]=\"true\"\r\n (valueChange)=\"valueChange(item.value)\"\r\n [value]=\"value() === item.value\"\r\n [readonly]=\"readonly() || (value() === item.value && !allowUnselect())\"\r\n [attr.data-testid]=\"item.testId\"\r\n [disabled]=\"disabled()\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'button'\"\r\n />\r\n }\r\n</ngn-button-group>\r\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }, { kind: "component", type: NgnButtonGroup, selector: "ngn-button-group", inputs: ["orientation"] }, { kind: "component", type: NgnToggleButton, selector: "ngn-toggle-button", inputs: ["labelOn", "labelOff", "icon", "iconOn", "iconOff", "fixedWidth"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
44
44
|
}
|
|
45
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.
|
|
45
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.2", ngImport: i0, type: NgnSelectButton, decorators: [{
|
|
46
46
|
type: Component,
|
|
47
47
|
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-select-button', imports: [NgnPt, NgnButtonGroup, NgnToggleButton], providers: [provideSelf(NgnSelectButton)], template: "<ngn-button-group [orientation]=\"orientation()\">\r\n @for (item of options(); track item.value) {\r\n <ngn-toggle-button\r\n [label]=\"maybeCallback(item.label)\"\r\n [icon]=\"item.icon\"\r\n [fixedWidth]=\"true\"\r\n (valueChange)=\"valueChange(item.value)\"\r\n [value]=\"value() === item.value\"\r\n [readonly]=\"readonly() || (value() === item.value && !allowUnselect())\"\r\n [attr.data-testid]=\"item.testId\"\r\n [disabled]=\"disabled()\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'button'\"\r\n />\r\n }\r\n</ngn-button-group>\r\n" }]
|
|
48
48
|
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], allowUnselect: [{ type: i0.Input, args: [{ isSignal: true, alias: "allowUnselect", required: false }] }] } });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngneers-controls-select-button.mjs","sources":["../../src/select-button/select-button.ts","../../src/select-button/select-button.html","../../src/select-button/ngneers-controls-select-button.ts"],"sourcesContent":["import { Component, ChangeDetectionStrategy, input } from '@angular/core';\r\nimport { NgnPt, provideSelf, ValueControlBase } from '@ngneers/controls/base';\r\nimport { NgnButtonGroup } from '@ngneers/controls/button-group';\r\nimport { NgnToggleButton } from '@ngneers/controls/toggle-button';\r\nimport { maybeCallback } from '@ngneers/controls/utils';\r\nimport { selectButtonControlTemplate } from '@ngneers/controls-themes/templates/select-button';\r\n\r\nimport type { NgnActionItemFlat, NgnItem } from '@ngneers/controls/api';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-select-button',\r\n templateUrl: './select-button.html',\r\n imports: [NgnPt, NgnButtonGroup, NgnToggleButton],\r\n providers: [provideSelf(NgnSelectButton)],\r\n})\r\nexport class NgnSelectButton<V> extends ValueControlBase<'selectButton', V> {\r\n protected readonly theme = this.injectThemeTemplate(selectButtonControlTemplate, {\r\n root: true,\r\n invalid: () => this.invalid(),\r\n });\r\n\r\n /**\r\n * Defines the orientation of the select buttons.\r\n * - 'auto' - The orientation is determined based on the available space.\r\n * - 'horizontal' - The buttons are arranged horizontally. (Default for `auto` if enough space)\r\n * - 'vertical' - The buttons are arranged vertically.\r\n * @default 'auto'\r\n */\r\n public readonly orientation = input<'auto' | 'horizontal' | 'vertical'>('auto');\r\n /**\r\n * Defines the options for the select button.\r\n */\r\n public readonly options = input.required<readonly NgnActionItemFlat<NgnItem<unknown, V>>[]>();\r\n /**\r\n * When `true`, allows unselecting the currently selected option by clicking on it again.\r\n * If `false`, clicking on the selected option will not change the selection.\r\n * @default false\r\n */\r\n public readonly allowUnselect = input<boolean>(false);\r\n\r\n protected readonly maybeCallback = maybeCallback;\r\n\r\n protected valueChange(value: V) {\r\n if (this.value() === value && !this.allowUnselect()) {\r\n return;\r\n }\r\n this.value.set(value);\r\n }\r\n}\r\n","<ngn-button-group [orientation]=\"orientation()\">\r\n @for (item of options(); track item.value) {\r\n <ngn-toggle-button\r\n [label]=\"maybeCallback(item.label)\"\r\n [icon]=\"item.icon\"\r\n [fixedWidth]=\"true\"\r\n (valueChange)=\"valueChange(item.value)\"\r\n [value]=\"value() === item.value\"\r\n [readonly]=\"readonly() || (value() === item.value && !allowUnselect())\"\r\n [attr.data-testid]=\"item.testId\"\r\n [disabled]=\"disabled()\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'button'\"\r\n />\r\n }\r\n</ngn-button-group>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;AASA;;AAEG;AAQG,MAAO,eAAmB,SAAQ,gBAAmC,CAAA;AACtD,IAAA,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,2BAA2B,EAAE;AAC/E,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,EAAE;AAC9B,KAAA,CAAC;AAEF;;;;;;AAMG;AACa,IAAA,WAAW,GAAG,KAAK,CAAqC,MAAM,
|
|
1
|
+
{"version":3,"file":"ngneers-controls-select-button.mjs","sources":["../../src/select-button/select-button.ts","../../src/select-button/select-button.html","../../src/select-button/ngneers-controls-select-button.ts"],"sourcesContent":["import { Component, ChangeDetectionStrategy, input } from '@angular/core';\r\nimport { NgnPt, provideSelf, ValueControlBase } from '@ngneers/controls/base';\r\nimport { NgnButtonGroup } from '@ngneers/controls/button-group';\r\nimport { NgnToggleButton } from '@ngneers/controls/toggle-button';\r\nimport { maybeCallback } from '@ngneers/controls/utils';\r\nimport { selectButtonControlTemplate } from '@ngneers/controls-themes/templates/select-button';\r\n\r\nimport type { NgnActionItemFlat, NgnItem } from '@ngneers/controls/api';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-select-button',\r\n templateUrl: './select-button.html',\r\n imports: [NgnPt, NgnButtonGroup, NgnToggleButton],\r\n providers: [provideSelf(NgnSelectButton)],\r\n})\r\nexport class NgnSelectButton<V> extends ValueControlBase<'selectButton', V> {\r\n protected readonly theme = this.injectThemeTemplate(selectButtonControlTemplate, {\r\n root: true,\r\n invalid: () => this.invalid(),\r\n });\r\n\r\n /**\r\n * Defines the orientation of the select buttons.\r\n * - 'auto' - The orientation is determined based on the available space.\r\n * - 'horizontal' - The buttons are arranged horizontally. (Default for `auto` if enough space)\r\n * - 'vertical' - The buttons are arranged vertically.\r\n * @default 'auto'\r\n */\r\n public readonly orientation = input<'auto' | 'horizontal' | 'vertical'>('auto');\r\n /**\r\n * Defines the options for the select button.\r\n */\r\n public readonly options = input.required<readonly NgnActionItemFlat<NgnItem<unknown, V>>[]>();\r\n /**\r\n * When `true`, allows unselecting the currently selected option by clicking on it again.\r\n * If `false`, clicking on the selected option will not change the selection.\r\n * @default false\r\n */\r\n public readonly allowUnselect = input<boolean>(false);\r\n\r\n protected readonly maybeCallback = maybeCallback;\r\n\r\n protected valueChange(value: V) {\r\n if (this.value() === value && !this.allowUnselect()) {\r\n return;\r\n }\r\n this.value.set(value);\r\n }\r\n}\r\n","<ngn-button-group [orientation]=\"orientation()\">\r\n @for (item of options(); track item.value) {\r\n <ngn-toggle-button\r\n [label]=\"maybeCallback(item.label)\"\r\n [icon]=\"item.icon\"\r\n [fixedWidth]=\"true\"\r\n (valueChange)=\"valueChange(item.value)\"\r\n [value]=\"value() === item.value\"\r\n [readonly]=\"readonly() || (value() === item.value && !allowUnselect())\"\r\n [attr.data-testid]=\"item.testId\"\r\n [disabled]=\"disabled()\"\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'button'\"\r\n />\r\n }\r\n</ngn-button-group>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;;;AASA;;AAEG;AAQG,MAAO,eAAmB,SAAQ,gBAAmC,CAAA;AACtD,IAAA,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,2BAA2B,EAAE;AAC/E,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,EAAE;AAC9B,KAAA,CAAC;AAEF;;;;;;AAMG;AACa,IAAA,WAAW,GAAG,KAAK,CAAqC,MAAM,kFAAC;AAC/E;;AAEG;AACa,IAAA,OAAO,GAAG,KAAK,CAAC,QAAQ,6EAAqD;AAC7F;;;;AAIG;AACa,IAAA,aAAa,GAAG,KAAK,CAAU,KAAK,oFAAC;IAElC,aAAa,GAAG,aAAa;AAEtC,IAAA,WAAW,CAAC,KAAQ,EAAA;AAC5B,QAAA,IAAI,IAAI,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,EAAE;YACnD;QACF;AACA,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;IACvB;uGAhCW,eAAe,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAf,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,eAAe,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,EAAA,WAAA,EAAA,EAAA,iBAAA,EAAA,aAAA,EAAA,UAAA,EAAA,aAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,OAAA,EAAA,EAAA,iBAAA,EAAA,SAAA,EAAA,UAAA,EAAA,SAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,aAAA,EAAA,EAAA,iBAAA,EAAA,eAAA,EAAA,UAAA,EAAA,eAAA,EAAA,QAAA,EAAA,IAAA,EAAA,UAAA,EAAA,KAAA,EAAA,iBAAA,EAAA,IAAA,EAAA,EAAA,EAAA,SAAA,EAFf,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECjB3C,mlBAgBA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDAY,KAAK,EAAA,QAAA,EAAA,SAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EAAE,cAAc,sFAAE,eAAe,EAAA,QAAA,EAAA,mBAAA,EAAA,MAAA,EAAA,CAAA,SAAA,EAAA,UAAA,EAAA,MAAA,EAAA,QAAA,EAAA,SAAA,EAAA,YAAA,CAAA,EAAA,CAAA,EAAA,eAAA,EAAA,EAAA,CAAA,uBAAA,CAAA,MAAA,EAAA,CAAA;;2FAGrC,eAAe,EAAA,UAAA,EAAA,CAAA;kBAP3B,SAAS;AACS,YAAA,IAAA,EAAA,CAAA,EAAA,eAAA,EAAA,uBAAuB,CAAC,MAAM,EAAA,QAAA,EACrC,mBAAmB,EAAA,OAAA,EAEpB,CAAC,KAAK,EAAE,cAAc,EAAE,eAAe,CAAC,EAAA,SAAA,EACtC,CAAC,WAAW,iBAAiB,CAAC,EAAA,QAAA,EAAA,mlBAAA,EAAA;;;AEjB3C;;AAEG;;;;"}
|