@ngneers/controls 0.0.1-pre1

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 (40) hide show
  1. package/api/index.d.ts +134 -0
  2. package/custom-types/index.d.ts +7 -0
  3. package/dialog/index.d.ts +43 -0
  4. package/fesm2022/ngneers-controls-api.mjs +318 -0
  5. package/fesm2022/ngneers-controls-api.mjs.map +1 -0
  6. package/fesm2022/ngneers-controls-custom-types.mjs +4 -0
  7. package/fesm2022/ngneers-controls-custom-types.mjs.map +1 -0
  8. package/fesm2022/ngneers-controls-dialog.mjs +74 -0
  9. package/fesm2022/ngneers-controls-dialog.mjs.map +1 -0
  10. package/fesm2022/ngneers-controls-form-field.mjs +33 -0
  11. package/fesm2022/ngneers-controls-form-field.mjs.map +1 -0
  12. package/fesm2022/ngneers-controls-icon.mjs +53 -0
  13. package/fesm2022/ngneers-controls-icon.mjs.map +1 -0
  14. package/fesm2022/ngneers-controls-lazy-cacher.mjs +30 -0
  15. package/fesm2022/ngneers-controls-lazy-cacher.mjs.map +1 -0
  16. package/fesm2022/ngneers-controls-list-box.mjs +119 -0
  17. package/fesm2022/ngneers-controls-list-box.mjs.map +1 -0
  18. package/fesm2022/ngneers-controls-popover.mjs +80 -0
  19. package/fesm2022/ngneers-controls-popover.mjs.map +1 -0
  20. package/fesm2022/ngneers-controls-scroller.mjs +163 -0
  21. package/fesm2022/ngneers-controls-scroller.mjs.map +1 -0
  22. package/fesm2022/ngneers-controls-select.mjs +155 -0
  23. package/fesm2022/ngneers-controls-select.mjs.map +1 -0
  24. package/fesm2022/ngneers-controls-text-field.mjs +23 -0
  25. package/fesm2022/ngneers-controls-text-field.mjs.map +1 -0
  26. package/fesm2022/ngneers-controls-utils.mjs +104 -0
  27. package/fesm2022/ngneers-controls-utils.mjs.map +1 -0
  28. package/fesm2022/ngneers-controls.mjs +6 -0
  29. package/fesm2022/ngneers-controls.mjs.map +1 -0
  30. package/form-field/index.d.ts +19 -0
  31. package/icon/index.d.ts +30 -0
  32. package/index.d.ts +2 -0
  33. package/lazy-cacher/index.d.ts +14 -0
  34. package/list-box/index.d.ts +58 -0
  35. package/package.json +78 -0
  36. package/popover/index.d.ts +41 -0
  37. package/scroller/index.d.ts +95 -0
  38. package/select/index.d.ts +86 -0
  39. package/text-field/index.d.ts +10 -0
  40. package/utils/index.d.ts +36 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-scroller.mjs","sources":["../../../packages/controls/src/scroller/scroller.ts","../../../packages/controls/src/scroller/scroller.html","../../../packages/controls/src/scroller/ngneers-controls-scroller.ts"],"sourcesContent":["import { NgTemplateOutlet } from '@angular/common';\r\nimport {\r\n Component,\r\n computed,\r\n contentChild,\r\n effect,\r\n ElementRef,\r\n inject,\r\n input,\r\n TemplateRef,\r\n untracked,\r\n viewChild,\r\n} from '@angular/core';\r\nimport { toSignal } from '@angular/core/rxjs-interop';\r\nimport { elementSizeSignal, templateTypesFn } from '@ngneers/controls/api';\r\nimport { fromEvent, map } from 'rxjs';\r\n\r\n@Component({\r\n selector: 'ngn-scroller',\r\n templateUrl: './scroller.html',\r\n imports: [NgTemplateOutlet],\r\n host: {\r\n style: 'position: relative; overflow: auto; display: block; height: 100%; width: 100%;',\r\n '[tabIndex]': 'focusable() ? 0 : -1',\r\n },\r\n})\r\nexport class Scroller<T> {\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 T.\r\n */\r\n public readonly items = input.required<readonly 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 * @defaultValue `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>(0);\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 * @defaultValue `2`\r\n */\r\n public readonly padding = input<number>(2);\r\n /**\r\n * Determines whether the scroller should have a tab index and be focusable.\r\n * @defaultValue `false`\r\n */\r\n public readonly focusable = input<boolean>(false);\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<keyof T | null>(null);\r\n\r\n private readonly _itemList = viewChild.required<ElementRef<HTMLElement>>('itemList');\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 private readonly _el = inject(ElementRef<HTMLElement>);\r\n private readonly _scrollElement: HTMLElement = this._el.nativeElement;\r\n private readonly _elementSize = elementSizeSignal(this._scrollElement);\r\n\r\n private readonly _visibleItemCount = computed(() =>\r\n this.virtual()\r\n ? Math.ceil(this._elementSize().height / this.itemHeight() + this.padding() * 2)\r\n : 0\r\n );\r\n private readonly _scrollTop = toSignal(\r\n fromEvent(this._scrollElement, 'scroll').pipe(map(e => (e.target as HTMLElement).scrollTop)),\r\n { initialValue: 0 }\r\n );\r\n private readonly _itemStartIndex = computed(() =>\r\n this.virtual()\r\n ? Math.max(0, Math.ceil(this._scrollTop() / this.itemHeight()) - this.padding())\r\n : 0\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 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 protected readonly itemsTop = computed(() => {\r\n return (this._itemStartIndex() - (this.latestStickyItem() ? 1 : 0)) * this.itemHeight();\r\n });\r\n\r\n protected readonly dummyHeight = computed(() => {\r\n return this.items().length * this.itemHeight();\r\n });\r\n\r\n constructor() {\r\n effect(() => {\r\n if (this.virtual() && !this.itemHeight()) {\r\n throw new Error('Item height 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) {\r\n untracked(() => {\r\n if (this.virtual()) {\r\n const scrollTop = this._scrollTop();\r\n const visibleHeight = this._elementSize().height;\r\n const itemTop = index * this.itemHeight();\r\n const itemBottom = itemTop + this.itemHeight();\r\n\r\n if (itemTop < scrollTop) {\r\n this._scrollElement.scrollTo({\r\n top: itemTop - 10,\r\n });\r\n } else if (itemBottom > scrollTop + visibleHeight) {\r\n this._scrollElement.scrollTo({\r\n top: itemBottom - visibleHeight + 10,\r\n });\r\n }\r\n } else {\r\n const itemElement = this._itemList().nativeElement.querySelector(\r\n `:nth-child(${index + 1})`\r\n );\r\n if (itemElement) {\r\n itemElement.scrollIntoView({ block: 'nearest' });\r\n }\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Template types for the scroller.\r\n * Can be used with the {@link @ngneers/controls/api#NgnTemplate | 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","@if (virtual()) {\r\n <div [style.height.px]=\"dummyHeight()\"></div>\r\n}\r\n<div #itemList [style.top.px]=\"itemsTop()\" [style.position]=\"virtual() ? 'absolute' : 'unset'\">\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 @for (item of visibleItems(); track item.index) {\r\n <ng-container\r\n *ngTemplateOutlet=\"itemTemplate(); context: { $implicit: item.item, index: item.index }\"\r\n ></ng-container>\r\n }\r\n</div>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,155 @@
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import * as i0 from '@angular/core';
3
+ import { viewChild, contentChild, input, computed, Component, linkedSignal, signal } from '@angular/core';
4
+ import * as i1 from '@angular/forms';
5
+ import { FormsModule } from '@angular/forms';
6
+ import { ValueControlBase, templateTypesFn, transformToNgnItems, mapToItems, filterOptions, GetElementRef, NgnTemplate, valueControlBaseProvider } from '@ngneers/controls/api';
7
+ import { FormField } from '@ngneers/controls/form-field';
8
+ import { Icon } from '@ngneers/controls/icon';
9
+ import { ListBox } from '@ngneers/controls/list-box';
10
+ import { Popover } from '@ngneers/controls/popover';
11
+ import { TextField } from '@ngneers/controls/text-field';
12
+ import { asyncComputed } from '@ngneers/controls/utils';
13
+
14
+ class SelectTemplates extends ValueControlBase {
15
+ // Item template
16
+ _defaultItemTemplate = viewChild.required('defaultItemTemplate');
17
+ _userItemTemplate = contentChild('item');
18
+ templateItem = input(null);
19
+ itemTemplate = computed(() => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate());
20
+ // Selected item template
21
+ _defaultSelectedItemTemplate = viewChild.required('defaultSelectedItemTemplate');
22
+ _userSelectedItemTemplate = contentChild('selectedItem');
23
+ templateSelectedItem = input(null);
24
+ selectedItemTemplate = computed(() => this._userSelectedItemTemplate() ??
25
+ this.templateSelectedItem() ??
26
+ this._defaultSelectedItemTemplate());
27
+ // Group template
28
+ _defaultGroupTemplate = viewChild.required('defaultGroupTemplate');
29
+ _userGroupTemplate = contentChild('group');
30
+ templateGroup = input(null);
31
+ groupTemplate = computed(() => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate());
32
+ /**
33
+ * Types for the dialog templates.
34
+ */
35
+ templateTypes = templateTypesFn();
36
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: SelectTemplates, deps: null, target: i0.ɵɵFactoryTarget.Component });
37
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "20.0.5", type: SelectTemplates, isStandalone: true, selector: "ng-component", inputs: { templateItem: { classPropertyName: "templateItem", publicName: "templateItem", isSignal: true, isRequired: false, transformFunction: null }, templateSelectedItem: { classPropertyName: "templateSelectedItem", publicName: "templateSelectedItem", isSignal: true, isRequired: false, transformFunction: null }, templateGroup: { classPropertyName: "templateGroup", publicName: "templateGroup", isSignal: true, isRequired: false, transformFunction: null } }, queries: [{ propertyName: "_userItemTemplate", first: true, predicate: ["item"], descendants: true, isSignal: true }, { propertyName: "_userSelectedItemTemplate", first: true, predicate: ["selectedItem"], descendants: true, isSignal: true }, { propertyName: "_userGroupTemplate", first: true, predicate: ["group"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "_defaultItemTemplate", first: true, predicate: ["defaultItemTemplate"], descendants: true, isSignal: true }, { propertyName: "_defaultSelectedItemTemplate", first: true, predicate: ["defaultSelectedItemTemplate"], descendants: true, isSignal: true }, { propertyName: "_defaultGroupTemplate", first: true, predicate: ["defaultGroupTemplate"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: '', isInline: true });
38
+ }
39
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: SelectTemplates, decorators: [{
40
+ type: Component,
41
+ args: [{
42
+ imports: [],
43
+ template: '',
44
+ }]
45
+ }] });
46
+
47
+ class Select extends SelectTemplates {
48
+ _popover = viewChild.required(Popover);
49
+ popoverOptions = input({});
50
+ appliedPopoverOptions = computed(() => ({
51
+ ...this.popoverOptions(),
52
+ sizeConstraints: {
53
+ width: 1,
54
+ maxWidth: 1,
55
+ ...this.popoverOptions().sizeConstraints,
56
+ },
57
+ }));
58
+ options = input([]);
59
+ fields = input();
60
+ filter = input();
61
+ filterText = input();
62
+ filterIcon = input();
63
+ virtual = input(false);
64
+ itemHeight = input();
65
+ _listbox = viewChild(ListBox);
66
+ filterTextInternal = linkedSignal(this.filterText);
67
+ currentHighlightedValue = signal(null);
68
+ _options = computed(() => {
69
+ const fields = this.fields();
70
+ const options = this.options();
71
+ if (!fields) {
72
+ return options;
73
+ }
74
+ return transformToNgnItems(options, fields);
75
+ });
76
+ _flatOptions = computed(() => mapToItems(this._options()));
77
+ _appliedFilterOptions = computed(() => {
78
+ const filter = this.filter();
79
+ if (!filter) {
80
+ return null;
81
+ }
82
+ const providedFilterArgs = typeof filter === 'boolean' ? {} : filter;
83
+ const options = {
84
+ filterFieldsCallback: item => item.label,
85
+ fieldItems: 'items',
86
+ splitWords: true,
87
+ caseSensitive: false,
88
+ clearFilterOnClose: true,
89
+ filterFn: 'contains',
90
+ ...providedFilterArgs,
91
+ };
92
+ return options;
93
+ });
94
+ // Replace with resource API when previous value persists
95
+ filteredOptions = asyncComputed(async () => {
96
+ const filter = this._appliedFilterOptions();
97
+ const filterText = this.filterTextInternal();
98
+ if (!filter || !filterText) {
99
+ return this._options();
100
+ }
101
+ return await filterOptions(this._options(), filterText, filter);
102
+ }, []);
103
+ filterIsExecuting = this.filteredOptions.isRunning;
104
+ selectedItem = computed(() => this._flatOptions().find(option => option.value === this.value()));
105
+ onKeyDown(event) {
106
+ this._listbox()?.onKeyDown(event);
107
+ // if event is not handled by the listbox, we can handle it here
108
+ if (!event.defaultPrevented) {
109
+ if (event.key === 'Enter' || event.key === ' ') {
110
+ this._popover().toggle();
111
+ event.stopPropagation();
112
+ event.preventDefault();
113
+ }
114
+ }
115
+ }
116
+ onPopoverClosed() {
117
+ this.currentHighlightedValue.set(null);
118
+ if (this._appliedFilterOptions()?.clearFilterOnClose) {
119
+ this.filterTextInternal.set('');
120
+ }
121
+ }
122
+ onSelect(value) {
123
+ if (this.value() !== value) {
124
+ this.value.set(value);
125
+ this.onChange(value);
126
+ }
127
+ this.close();
128
+ }
129
+ close() {
130
+ this._popover().close();
131
+ }
132
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: Select, deps: null, target: i0.ɵɵFactoryTarget.Component });
133
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.0.5", type: Select, isStandalone: true, selector: "ngn-select", inputs: { popoverOptions: { classPropertyName: "popoverOptions", publicName: "popoverOptions", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: false, transformFunction: null }, fields: { classPropertyName: "fields", publicName: "fields", isSignal: true, isRequired: false, transformFunction: null }, filter: { classPropertyName: "filter", publicName: "filter", isSignal: true, isRequired: false, transformFunction: null }, filterText: { classPropertyName: "filterText", publicName: "filterText", isSignal: true, isRequired: false, transformFunction: null }, filterIcon: { classPropertyName: "filterIcon", publicName: "filterIcon", 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 } }, providers: [valueControlBaseProvider(Select)], viewQueries: [{ propertyName: "_popover", first: true, predicate: Popover, descendants: true, isSignal: true }, { propertyName: "_listbox", first: true, predicate: ListBox, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<ngn-form-field\r\n (click)=\"popover.open()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n ngnElementRef\r\n #field=\"ngnElementRef\"\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n>\r\n <div class=\"ngn-select-trigger\" tabindex=\"0\">\r\n <ng-template\r\n [ngTemplateOutlet]=\"selectedItemTemplate()\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: selectedItem(),\r\n }\"\r\n ></ng-template>\r\n </div>\r\n</ngn-form-field>\r\n<ngn-popover\r\n #popover\r\n class=\"ngn-select-popover\"\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"field.nativeElement\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (closed)=\"onPopoverClosed()\"\r\n ngnElementRef\r\n #popoverElement=\"ngnElementRef\"\r\n>\r\n <ng-template #lazy>\r\n @if (filter()) {\r\n <ngn-form-field>\r\n <ngn-text-field\r\n [ngModel]=\"filterTextInternal()\"\r\n (ngModelChange)=\"filterTextInternal.set($event)\"\r\n />\r\n <ngn-icon defaultIcon=\"fa-solid fa-magnifying-glass\" [icon]=\"filterIcon()\" />\r\n @if (filterIsExecuting()) {\r\n <!-- TODO: replace with spinner -->\r\n <ngn-icon defaultIcon=\"fa-solid fa-spinner fa-spin\" />\r\n }\r\n </ngn-form-field>\r\n }\r\n <ngn-list-box\r\n [highlightable]=\"false\"\r\n [selectable]=\"true\"\r\n [items]=\"filteredOptions()\"\r\n [itemHeight]=\"itemHeight()\"\r\n [virtual]=\"virtual()\"\r\n [templateItem]=\"itemTemplate()\"\r\n [templateGroup]=\"groupTemplate()\"\r\n [fields]=\"{\r\n groupItems: 'items',\r\n value: 'value',\r\n label: 'label',\r\n testId: 'testId',\r\n }\"\r\n [ngModel]=\"selectedItem()?.value\"\r\n (ngModelChange)=\"onSelect($event)\"\r\n />\r\n </ng-template>\r\n</ngn-popover>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate [ngnTemplate]=\"templateTypes.item\" let-group>\r\n <span [attr.data-testid]=\"group?.testId\">{{ group?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultSelectedItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n", dependencies: [{ kind: "component", type: FormField, selector: "ngn-form-field", inputs: ["label", "inputId"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ListBox, selector: "ngn-list-box", inputs: ["items", "fields", "selectable", "highlightable", "virtual", "itemHeight"] }, { kind: "component", type: TextField, selector: "ngn-text-field" }, { kind: "component", type: Popover, selector: "ngn-popover", inputs: ["anchor", "options"], outputs: ["opened", "closed"] }, { kind: "directive", type: GetElementRef, selector: "[ngnElementRef]", exportAs: ["ngnElementRef"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: NgnTemplate, selector: "ng-template[ngnTemplate]", inputs: ["ngnTemplate"] }, { kind: "component", type: Icon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }] });
134
+ }
135
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: Select, decorators: [{
136
+ type: Component,
137
+ args: [{ selector: 'ngn-select', imports: [
138
+ FormField,
139
+ FormsModule,
140
+ ListBox,
141
+ TextField,
142
+ Popover,
143
+ GetElementRef,
144
+ NgTemplateOutlet,
145
+ NgnTemplate,
146
+ Icon,
147
+ ], providers: [valueControlBaseProvider(Select)], template: "<ngn-form-field\r\n (click)=\"popover.open()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n ngnElementRef\r\n #field=\"ngnElementRef\"\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n>\r\n <div class=\"ngn-select-trigger\" tabindex=\"0\">\r\n <ng-template\r\n [ngTemplateOutlet]=\"selectedItemTemplate()\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: selectedItem(),\r\n }\"\r\n ></ng-template>\r\n </div>\r\n</ngn-form-field>\r\n<ngn-popover\r\n #popover\r\n class=\"ngn-select-popover\"\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"field.nativeElement\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (closed)=\"onPopoverClosed()\"\r\n ngnElementRef\r\n #popoverElement=\"ngnElementRef\"\r\n>\r\n <ng-template #lazy>\r\n @if (filter()) {\r\n <ngn-form-field>\r\n <ngn-text-field\r\n [ngModel]=\"filterTextInternal()\"\r\n (ngModelChange)=\"filterTextInternal.set($event)\"\r\n />\r\n <ngn-icon defaultIcon=\"fa-solid fa-magnifying-glass\" [icon]=\"filterIcon()\" />\r\n @if (filterIsExecuting()) {\r\n <!-- TODO: replace with spinner -->\r\n <ngn-icon defaultIcon=\"fa-solid fa-spinner fa-spin\" />\r\n }\r\n </ngn-form-field>\r\n }\r\n <ngn-list-box\r\n [highlightable]=\"false\"\r\n [selectable]=\"true\"\r\n [items]=\"filteredOptions()\"\r\n [itemHeight]=\"itemHeight()\"\r\n [virtual]=\"virtual()\"\r\n [templateItem]=\"itemTemplate()\"\r\n [templateGroup]=\"groupTemplate()\"\r\n [fields]=\"{\r\n groupItems: 'items',\r\n value: 'value',\r\n label: 'label',\r\n testId: 'testId',\r\n }\"\r\n [ngModel]=\"selectedItem()?.value\"\r\n (ngModelChange)=\"onSelect($event)\"\r\n />\r\n </ng-template>\r\n</ngn-popover>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate [ngnTemplate]=\"templateTypes.item\" let-group>\r\n <span [attr.data-testid]=\"group?.testId\">{{ group?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultSelectedItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n" }]
148
+ }] });
149
+
150
+ /**
151
+ * Generated bundle index. Do not edit.
152
+ */
153
+
154
+ export { Select };
155
+ //# sourceMappingURL=ngneers-controls-select.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-select.mjs","sources":["../../../packages/controls/src/select/select-templates.ts","../../../packages/controls/src/select/select.ts","../../../packages/controls/src/select/select.html","../../../packages/controls/src/select/ngneers-controls-select.ts"],"sourcesContent":["import { Component, computed, contentChild, input, TemplateRef, viewChild } from '@angular/core';\r\nimport { NgnItem, templateTypesFn, ValueControlBase } from '@ngneers/controls/api';\r\n\r\n@Component({\r\n imports: [],\r\n template: '',\r\n})\r\nexport abstract class SelectTemplates<T, K extends keyof T> extends ValueControlBase<T[K]> {\r\n // Item template\r\n private readonly _defaultItemTemplate =\r\n viewChild.required<TemplateRef<typeof this.templateTypes.item>>('defaultItemTemplate');\r\n private readonly _userItemTemplate =\r\n contentChild<TemplateRef<typeof this.templateTypes.item>>('item');\r\n public readonly templateItem = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\r\n protected readonly itemTemplate = computed(\r\n () => this._userItemTemplate() ?? this.templateItem() ?? this._defaultItemTemplate()\r\n );\r\n\r\n // Selected item template\r\n private readonly _defaultSelectedItemTemplate = viewChild.required<TemplateRef<unknown>>(\r\n 'defaultSelectedItemTemplate'\r\n );\r\n private readonly _userSelectedItemTemplate = contentChild<TemplateRef<unknown>>('selectedItem');\r\n public readonly templateSelectedItem = input<TemplateRef<unknown> | null>(null);\r\n protected readonly selectedItemTemplate = computed(\r\n () =>\r\n this._userSelectedItemTemplate() ??\r\n this.templateSelectedItem() ??\r\n this._defaultSelectedItemTemplate()\r\n );\r\n\r\n // Group template\r\n private readonly _defaultGroupTemplate =\r\n viewChild.required<TemplateRef<typeof this.templateTypes.item>>('defaultGroupTemplate');\r\n private readonly _userGroupTemplate =\r\n contentChild<TemplateRef<typeof this.templateTypes.item>>('group');\r\n public readonly templateGroup = input<TemplateRef<typeof this.templateTypes.item> | null>(null);\r\n protected readonly groupTemplate = computed(\r\n () => this._userGroupTemplate() ?? this.templateGroup() ?? this._defaultGroupTemplate()\r\n );\r\n\r\n /**\r\n * Types for the dialog templates.\r\n */\r\n public readonly templateTypes = templateTypesFn<{\r\n item: {\r\n $implicit: NgnItem<T, K> | undefined;\r\n };\r\n }>();\r\n}\r\n","import { NgTemplateOutlet } from '@angular/common';\r\nimport { Component, computed, input, linkedSignal, signal, viewChild } from '@angular/core';\r\nimport { FormsModule } from '@angular/forms';\r\nimport {\r\n filterOptions,\r\n GetElementRef,\r\n NgnTemplate,\r\n valueControlBaseProvider,\r\n mapToItems,\r\n NgnItem,\r\n NgnItemFields,\r\n transformToNgnItems,\r\n} from '@ngneers/controls/api';\r\nimport { IconType } from '@ngneers/controls/custom-types';\r\nimport { FormField } from '@ngneers/controls/form-field';\r\nimport { Icon } from '@ngneers/controls/icon';\r\nimport { ListBox } from '@ngneers/controls/list-box';\r\nimport { Popover, PopoverOptions } from '@ngneers/controls/popover';\r\nimport { TextField } from '@ngneers/controls/text-field';\r\nimport { asyncComputed } from '@ngneers/controls/utils';\r\n\r\nimport { SelectTemplates } from './select-templates';\r\nimport { SelectFilterOptions, SelectFilterOptionsInternal } from './types';\r\n\r\n@Component({\r\n selector: 'ngn-select',\r\n templateUrl: './select.html',\r\n imports: [\r\n FormField,\r\n FormsModule,\r\n ListBox,\r\n TextField,\r\n Popover,\r\n GetElementRef,\r\n NgTemplateOutlet,\r\n NgnTemplate,\r\n Icon,\r\n ],\r\n providers: [valueControlBaseProvider(Select)],\r\n})\r\nexport class Select<T extends object, K extends keyof T> extends SelectTemplates<T, K> {\r\n private readonly _popover = viewChild.required<Popover>(Popover);\r\n\r\n public readonly popoverOptions = input<PopoverOptions>({});\r\n protected readonly appliedPopoverOptions = computed(() => ({\r\n ...this.popoverOptions(),\r\n sizeConstraints: {\r\n width: 1,\r\n maxWidth: 1,\r\n ...this.popoverOptions().sizeConstraints,\r\n },\r\n }));\r\n public readonly options = input<readonly NgnItem<T, K>[] | readonly T[]>([]);\r\n public readonly fields = input<NgnItemFields<T, K>>();\r\n public readonly filter = input<SelectFilterOptions<NgnItem<T, K>> | boolean>();\r\n public readonly filterText = input<string>();\r\n public readonly filterIcon = input<IconType>();\r\n public readonly virtual = input<boolean>(false);\r\n public readonly itemHeight = input<number>();\r\n private readonly _listbox = viewChild(ListBox);\r\n\r\n protected readonly filterTextInternal = linkedSignal(this.filterText);\r\n\r\n protected readonly currentHighlightedValue = signal<T[K] | null>(null);\r\n\r\n private readonly _options = computed(() => {\r\n const fields = this.fields();\r\n const options = this.options();\r\n if (!fields) {\r\n return options as NgnItem<T, K>[];\r\n }\r\n return transformToNgnItems(options as T[], fields);\r\n });\r\n\r\n private readonly _flatOptions = computed(() => mapToItems(this._options()));\r\n\r\n private readonly _appliedFilterOptions = computed(() => {\r\n const filter = this.filter();\r\n if (!filter) {\r\n return null;\r\n }\r\n const providedFilterArgs = typeof filter === 'boolean' ? {} : filter;\r\n const options: SelectFilterOptionsInternal<NgnItem> = {\r\n filterFieldsCallback: item => item.label,\r\n fieldItems: 'items',\r\n splitWords: true,\r\n caseSensitive: false,\r\n clearFilterOnClose: true,\r\n filterFn: 'contains',\r\n ...providedFilterArgs,\r\n };\r\n return options;\r\n });\r\n\r\n // Replace with resource API when previous value persists\r\n protected readonly filteredOptions = asyncComputed(async () => {\r\n const filter = this._appliedFilterOptions();\r\n const filterText = this.filterTextInternal();\r\n if (!filter || !filterText) {\r\n return this._options();\r\n }\r\n return await filterOptions<NgnItem>(this._options(), filterText, filter);\r\n }, []);\r\n\r\n protected readonly filterIsExecuting = this.filteredOptions.isRunning;\r\n\r\n protected readonly selectedItem = computed(() =>\r\n this._flatOptions().find(option => option.value === this.value())\r\n );\r\n\r\n protected onKeyDown(event: KeyboardEvent) {\r\n this._listbox()?.onKeyDown(event);\r\n // if event is not handled by the listbox, we can handle it here\r\n if (!event.defaultPrevented) {\r\n if (event.key === 'Enter' || event.key === ' ') {\r\n this._popover().toggle();\r\n event.stopPropagation();\r\n event.preventDefault();\r\n }\r\n }\r\n }\r\n\r\n protected onPopoverClosed() {\r\n this.currentHighlightedValue.set(null);\r\n if (this._appliedFilterOptions()?.clearFilterOnClose) {\r\n this.filterTextInternal.set('');\r\n }\r\n }\r\n\r\n public onSelect(value: T[K]) {\r\n if (this.value() !== value) {\r\n this.value.set(value);\r\n this.onChange(value);\r\n }\r\n this.close();\r\n }\r\n\r\n public close() {\r\n this._popover().close();\r\n }\r\n}\r\n","<ngn-form-field\r\n (click)=\"popover.open()\"\r\n (keydown)=\"onKeyDown($event)\"\r\n ngnElementRef\r\n #field=\"ngnElementRef\"\r\n [label]=\"label()\"\r\n [inputId]=\"inputId()\"\r\n>\r\n <div class=\"ngn-select-trigger\" tabindex=\"0\">\r\n <ng-template\r\n [ngTemplateOutlet]=\"selectedItemTemplate()\"\r\n [ngTemplateOutletContext]=\"{\r\n $implicit: selectedItem(),\r\n }\"\r\n ></ng-template>\r\n </div>\r\n</ngn-form-field>\r\n<ngn-popover\r\n #popover\r\n class=\"ngn-select-popover\"\r\n [options]=\"appliedPopoverOptions()\"\r\n [anchor]=\"field.nativeElement\"\r\n (keydown)=\"onKeyDown($event)\"\r\n (closed)=\"onPopoverClosed()\"\r\n ngnElementRef\r\n #popoverElement=\"ngnElementRef\"\r\n>\r\n <ng-template #lazy>\r\n @if (filter()) {\r\n <ngn-form-field>\r\n <ngn-text-field\r\n [ngModel]=\"filterTextInternal()\"\r\n (ngModelChange)=\"filterTextInternal.set($event)\"\r\n />\r\n <ngn-icon defaultIcon=\"fa-solid fa-magnifying-glass\" [icon]=\"filterIcon()\" />\r\n @if (filterIsExecuting()) {\r\n <!-- TODO: replace with spinner -->\r\n <ngn-icon defaultIcon=\"fa-solid fa-spinner fa-spin\" />\r\n }\r\n </ngn-form-field>\r\n }\r\n <ngn-list-box\r\n [highlightable]=\"false\"\r\n [selectable]=\"true\"\r\n [items]=\"filteredOptions()\"\r\n [itemHeight]=\"itemHeight()\"\r\n [virtual]=\"virtual()\"\r\n [templateItem]=\"itemTemplate()\"\r\n [templateGroup]=\"groupTemplate()\"\r\n [fields]=\"{\r\n groupItems: 'items',\r\n value: 'value',\r\n label: 'label',\r\n testId: 'testId',\r\n }\"\r\n [ngModel]=\"selectedItem()?.value\"\r\n (ngModelChange)=\"onSelect($event)\"\r\n />\r\n </ng-template>\r\n</ngn-popover>\r\n\r\n<ng-template #defaultItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultGroupTemplate [ngnTemplate]=\"templateTypes.item\" let-group>\r\n <span [attr.data-testid]=\"group?.testId\">{{ group?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n\r\n<ng-template #defaultSelectedItemTemplate [ngnTemplate]=\"templateTypes.item\" let-item>\r\n <span [attr.data-testid]=\"item?.testId\">{{ item?.label }}&ZeroWidthSpace;</span>\r\n</ng-template>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Component } from '@angular/core';
3
+ import { ValueControlBase, valueControlBaseProvider } from '@ngneers/controls/api';
4
+ import { FormField } from '@ngneers/controls/form-field';
5
+
6
+ class TextField extends ValueControlBase {
7
+ onInput(value) {
8
+ this.onChange(value.target.value);
9
+ }
10
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: TextField, deps: null, target: i0.ɵɵFactoryTarget.Component });
11
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.0.5", type: TextField, isStandalone: true, selector: "ngn-text-field", providers: [valueControlBaseProvider(TextField)], usesInheritance: true, ngImport: i0, template: "<ngn-form-field [label]=\"label()\" [inputId]=\"inputId()\">\r\n <input\r\n type=\"text\"\r\n [value]=\"value()\"\r\n [id]=\"inputId()\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onTouched()\"\r\n />\r\n</ngn-form-field>\r\n", dependencies: [{ kind: "component", type: FormField, selector: "ngn-form-field", inputs: ["label", "inputId"] }] });
12
+ }
13
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: TextField, decorators: [{
14
+ type: Component,
15
+ args: [{ selector: 'ngn-text-field', imports: [FormField], providers: [valueControlBaseProvider(TextField)], template: "<ngn-form-field [label]=\"label()\" [inputId]=\"inputId()\">\r\n <input\r\n type=\"text\"\r\n [value]=\"value()\"\r\n [id]=\"inputId()\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onTouched()\"\r\n />\r\n</ngn-form-field>\r\n" }]
16
+ }] });
17
+
18
+ /**
19
+ * Generated bundle index. Do not edit.
20
+ */
21
+
22
+ export { TextField };
23
+ //# sourceMappingURL=ngneers-controls-text-field.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-text-field.mjs","sources":["../../../packages/controls/src/text-field/text-field.ts","../../../packages/controls/src/text-field/text-field.html","../../../packages/controls/src/text-field/ngneers-controls-text-field.ts"],"sourcesContent":["import { Component } from '@angular/core';\r\nimport { ValueControlBase, valueControlBaseProvider } from '@ngneers/controls/api';\r\nimport { FormField } from '@ngneers/controls/form-field';\r\n\r\n@Component({\r\n selector: 'ngn-text-field',\r\n templateUrl: './text-field.html',\r\n imports: [FormField],\r\n providers: [valueControlBaseProvider(TextField)],\r\n})\r\nexport class TextField extends ValueControlBase<string> {\r\n public onInput(value: Event) {\r\n this.onChange((value.target as HTMLInputElement).value);\r\n }\r\n}\r\n","<ngn-form-field [label]=\"label()\" [inputId]=\"inputId()\">\r\n <input\r\n type=\"text\"\r\n [value]=\"value()\"\r\n [id]=\"inputId()\"\r\n (input)=\"onInput($event)\"\r\n (blur)=\"onTouched()\"\r\n />\r\n</ngn-form-field>\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;AAUM,MAAO,SAAU,SAAQ,gBAAwB,CAAA;AAC9C,IAAA,OAAO,CAAC,KAAY,EAAA;QACzB,IAAI,CAAC,QAAQ,CAAE,KAAK,CAAC,MAA2B,CAAC,KAAK,CAAC;;uGAF9C,SAAS,EAAA,IAAA,EAAA,IAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;2FAAT,SAAS,EAAA,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,gBAAA,EAAA,SAAA,EAFT,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,ECRlD,sPASA,EAAA,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,WAAA,EAAA,IAAA,EDFY,SAAS,EAAA,QAAA,EAAA,gBAAA,EAAA,MAAA,EAAA,CAAA,OAAA,EAAA,SAAA,CAAA,EAAA,CAAA,EAAA,CAAA;;2FAGR,SAAS,EAAA,UAAA,EAAA,CAAA;kBANrB,SAAS;+BACE,gBAAgB,EAAA,OAAA,EAEjB,CAAC,SAAS,CAAC,aACT,CAAC,wBAAwB,WAAW,CAAC,EAAA,QAAA,EAAA,sPAAA,EAAA;;;AERlD;;AAEG;;;;"}
@@ -0,0 +1,104 @@
1
+ import * as i0 from '@angular/core';
2
+ import { inject, DOCUMENT, Injectable, computed, signal, effect } from '@angular/core';
3
+
4
+ function throwExp(message) {
5
+ throw new Error(message);
6
+ }
7
+
8
+ function fuzzyMatch(input, search) {
9
+ // Edge cases
10
+ const searchLen = search.length;
11
+ if (searchLen === 0)
12
+ return true;
13
+ const inputLen = input.length;
14
+ if (searchLen > inputLen)
15
+ return false;
16
+ // Micro-optimized main loop
17
+ let searchPos = 0;
18
+ for (let i = 0; i < inputLen && searchPos < searchLen; i++) {
19
+ if (input.charCodeAt(i) === search.charCodeAt(searchPos)) {
20
+ searchPos++;
21
+ // Early exit when remaining input can't contain remaining search
22
+ if (searchLen - searchPos > inputLen - i - 1)
23
+ return false;
24
+ }
25
+ // Early exit when remaining lengths match but current chars don't
26
+ else if (searchLen - searchPos === inputLen - i)
27
+ return false;
28
+ }
29
+ return searchPos === searchLen;
30
+ }
31
+
32
+ const globalPropertyName = '__ngn-controls-global__';
33
+ class NgnGlobal {
34
+ _window = inject(DOCUMENT).defaultView || window;
35
+ constructor() {
36
+ this._window[globalPropertyName] ??= {
37
+ nextElementId: 1,
38
+ };
39
+ }
40
+ get nextElementId() {
41
+ return this._window[globalPropertyName].nextElementId;
42
+ }
43
+ set nextElementId(value) {
44
+ this._window[globalPropertyName].nextElementId = value;
45
+ }
46
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: NgnGlobal, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
47
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: NgnGlobal });
48
+ }
49
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.0.5", ngImport: i0, type: NgnGlobal, decorators: [{
50
+ type: Injectable
51
+ }], ctorParameters: () => [] });
52
+
53
+ const idPrefix = 'ngn-element-id-';
54
+ function generateElementId() {
55
+ return idPrefix + inject(NgnGlobal).nextElementId++;
56
+ }
57
+
58
+ function computedWithPrevious(computeFn, previous) {
59
+ let current = previous;
60
+ return computed(() => {
61
+ const prev = current;
62
+ current = computeFn(prev);
63
+ return current;
64
+ });
65
+ }
66
+ function asyncComputed(computeFn, initial) {
67
+ let latestUpdated = 0;
68
+ let runningCounter = signal(0);
69
+ const returnSignal = signal(initial);
70
+ effect(() => {
71
+ const current = Date.now();
72
+ runningCounter.update(value => value + 1);
73
+ computeFn()
74
+ .then(value => {
75
+ runningCounter.update(value => value - 1);
76
+ // Only update the signal if this is the latest call
77
+ if (current < latestUpdated) {
78
+ console.debug('asyncComputed: ignoring stale value update');
79
+ return;
80
+ }
81
+ latestUpdated = current;
82
+ returnSignal.set(value);
83
+ })
84
+ .catch(error => {
85
+ runningCounter.update(value => value - 1);
86
+ console.error('Error in asyncComputed:', error);
87
+ });
88
+ });
89
+ const isRunning = computed(() => runningCounter() > 0);
90
+ const returnFn = returnSignal;
91
+ returnFn.isRunning = isRunning;
92
+ return returnFn;
93
+ }
94
+
95
+ function notNullish(value) {
96
+ return value !== null && value !== undefined;
97
+ }
98
+
99
+ /**
100
+ * Generated bundle index. Do not edit.
101
+ */
102
+
103
+ export { NgnGlobal, asyncComputed, computedWithPrevious, fuzzyMatch, generateElementId, notNullish, throwExp };
104
+ //# sourceMappingURL=ngneers-controls-utils.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls-utils.mjs","sources":["../../../packages/controls/src/utils/error.ts","../../../packages/controls/src/utils/fuzzy-match.ts","../../../packages/controls/src/utils/globals.ts","../../../packages/controls/src/utils/generate-id.ts","../../../packages/controls/src/utils/signals.ts","../../../packages/controls/src/utils/not-nullish.ts","../../../packages/controls/src/utils/ngneers-controls-utils.ts"],"sourcesContent":["export function throwExp(message: string): never {\r\n throw new Error(message);\r\n}\r\n","export function fuzzyMatch(input: string, search: string) {\r\n // Edge cases\r\n const searchLen = search.length;\r\n if (searchLen === 0) return true;\r\n const inputLen = input.length;\r\n if (searchLen > inputLen) return false;\r\n\r\n // Micro-optimized main loop\r\n let searchPos = 0;\r\n\r\n for (let i = 0; i < inputLen && searchPos < searchLen; i++) {\r\n if (input.charCodeAt(i) === search.charCodeAt(searchPos)) {\r\n searchPos++;\r\n // Early exit when remaining input can't contain remaining search\r\n if (searchLen - searchPos > inputLen - i - 1) return false;\r\n }\r\n // Early exit when remaining lengths match but current chars don't\r\n else if (searchLen - searchPos === inputLen - i) return false;\r\n }\r\n\r\n return searchPos === searchLen;\r\n}\r\n","import { DOCUMENT, inject, Injectable } from '@angular/core';\n\nconst globalPropertyName = '__ngn-controls-global__';\n\ninterface NgnGlobalType {\n nextElementId: number;\n}\n\ndeclare global {\n interface Window {\n [globalPropertyName]: NgnGlobalType;\n }\n}\n\n@Injectable()\nexport class NgnGlobal implements NgnGlobalType {\n private readonly _window = inject(DOCUMENT).defaultView || window;\n constructor() {\n this._window[globalPropertyName] ??= {\n nextElementId: 1,\n };\n }\n\n public get nextElementId(): number {\n return this._window[globalPropertyName].nextElementId;\n }\n public set nextElementId(value: number) {\n this._window[globalPropertyName].nextElementId = value;\n }\n}\n","import { inject } from '@angular/core';\n\nimport { NgnGlobal } from './globals';\n\nconst idPrefix = 'ngn-element-id-';\n\nexport function generateElementId() {\n return idPrefix + inject(NgnGlobal).nextElementId++;\n}\n","import { computed, effect, Signal, signal } from '@angular/core';\r\n\r\nexport function computedWithPrevious<T>(computeFn: (prev?: T) => T, previous?: T): () => T {\r\n let current = previous;\r\n\r\n return computed<T>(() => {\r\n const prev = current;\r\n current = computeFn(prev);\r\n return current;\r\n });\r\n}\r\n\r\nexport function asyncComputed<T>(\r\n computeFn: () => Promise<T>,\r\n initial: T\r\n): { (): T; isRunning: Signal<boolean> } {\r\n let latestUpdated = 0;\r\n let runningCounter = signal(0);\r\n const returnSignal = signal<T>(initial);\r\n effect(() => {\r\n const current = Date.now();\r\n runningCounter.update(value => value + 1);\r\n computeFn()\r\n .then(value => {\r\n runningCounter.update(value => value - 1);\r\n // Only update the signal if this is the latest call\r\n if (current < latestUpdated) {\r\n console.debug('asyncComputed: ignoring stale value update');\r\n return;\r\n }\r\n latestUpdated = current;\r\n returnSignal.set(value);\r\n })\r\n .catch(error => {\r\n runningCounter.update(value => value - 1);\r\n console.error('Error in asyncComputed:', error);\r\n });\r\n });\r\n const isRunning = computed(() => runningCounter() > 0);\r\n const returnFn = returnSignal as unknown as { (): T; isRunning: Signal<boolean> };\r\n returnFn.isRunning = isRunning;\r\n return returnFn;\r\n}\r\n","export function notNullish<T>(value: T | null | undefined): value is T {\r\n return value !== null && value !== undefined;\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ var index = {};
2
+
3
+ /**
4
+ * Generated bundle index. Do not edit.
5
+ */
6
+ //# sourceMappingURL=ngneers-controls.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngneers-controls.mjs","sources":["../../../packages/controls/src/index.ts","../../../packages/controls/src/ngneers-controls.ts"],"sourcesContent":["export default {};\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"AAAA,YAAe,EAAE;;ACAjB;;AAEG"}
@@ -0,0 +1,19 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { InputSignal } from '@angular/core';
3
+
4
+ interface FormFieldBase {
5
+ label: InputSignal<string | null>;
6
+ inputId: InputSignal<string | null> | InputSignal<string>;
7
+ }
8
+
9
+ declare class FormField implements FormFieldBase {
10
+ private readonly _parentFormField;
11
+ protected readonly hasParentFormField: boolean;
12
+ readonly label: _angular_core.InputSignal<string | null>;
13
+ readonly inputId: _angular_core.InputSignal<string | null>;
14
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormField, never>;
15
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormField, "ngn-form-field", never, { "label": { "alias": "label"; "required": false; "isSignal": true; }; "inputId": { "alias": "inputId"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
16
+ }
17
+
18
+ export { FormField };
19
+ export type { FormFieldBase };
@@ -0,0 +1,30 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { IconType } from '@ngneers/controls/custom-types';
4
+ import * as _ngneers_controls_icon from '@ngneers/controls/icon';
5
+
6
+ type IconTemplateData = {
7
+ $implicit: IconType;
8
+ };
9
+ type IconTemplateType = TemplateRef<IconTemplateData>;
10
+ declare class GlobalIconTemplate {
11
+ private readonly _globalIconTemplate;
12
+ readonly globalIconTemplate: _angular_core.Signal<IconTemplateType | null>;
13
+ setGlobalIconTemplate(template: IconTemplateType): void;
14
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<GlobalIconTemplate, never>;
15
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<GlobalIconTemplate>;
16
+ }
17
+
18
+ declare class Icon {
19
+ private readonly _globalIconTemplate;
20
+ readonly defaultIcon: _angular_core.InputSignal<string | undefined>;
21
+ readonly icon: _angular_core.InputSignal<string | undefined>;
22
+ private readonly _defaultIconTemplate;
23
+ protected readonly usedIconTemplate: _angular_core.Signal<_ngneers_controls_icon.IconTemplateType>;
24
+ constructor();
25
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<Icon, never>;
26
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<Icon, "ngn-icon", never, { "defaultIcon": { "alias": "defaultIcon"; "required": false; "isSignal": true; }; "icon": { "alias": "icon"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
27
+ }
28
+
29
+ export { GlobalIconTemplate, Icon };
30
+ export type { IconTemplateData, IconTemplateType };
package/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+
2
+ export { };
@@ -0,0 +1,14 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+
4
+ declare class LazyCacher {
5
+ readonly lazyContent: _angular_core.InputSignal<TemplateRef<unknown> | null | undefined>;
6
+ readonly open: _angular_core.InputSignal<boolean>;
7
+ readonly cache: _angular_core.InputSignal<boolean>;
8
+ protected readonly hasBeenOpened: _angular_core.WritableSignal<boolean>;
9
+ constructor();
10
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<LazyCacher, never>;
11
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<LazyCacher, "ngn-lazy-cacher", never, { "lazyContent": { "alias": "lazyContent"; "required": false; "isSignal": true; }; "open": { "alias": "open"; "required": false; "isSignal": true; }; "cache": { "alias": "cache"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
12
+ }
13
+
14
+ export { LazyCacher };
@@ -0,0 +1,58 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { TemplateRef } from '@angular/core';
3
+ import { ValueControlBase, NgnItem, NgnItemFields } from '@ngneers/controls/api';
4
+
5
+ declare abstract class ListBoxTemplates<T, K extends keyof T> extends ValueControlBase<T[K]> {
6
+ private readonly _defaultItemTemplate;
7
+ private readonly _userItemTemplate;
8
+ readonly templateItem: _angular_core.InputSignal<TemplateRef<{
9
+ $implicit: NgnItem<T, K> | undefined;
10
+ }> | null>;
11
+ protected readonly itemTemplate: _angular_core.Signal<TemplateRef<{
12
+ $implicit: NgnItem<T, K> | undefined;
13
+ }>>;
14
+ private readonly _defaultGroupTemplate;
15
+ private readonly _userGroupTemplate;
16
+ readonly templateGroup: _angular_core.InputSignal<TemplateRef<{
17
+ $implicit: NgnItem<T, K> | undefined;
18
+ }> | null>;
19
+ protected readonly groupTemplate: _angular_core.Signal<TemplateRef<{
20
+ $implicit: NgnItem<T, K> | undefined;
21
+ }>>;
22
+ /**
23
+ * Types for the dialog templates.
24
+ */
25
+ readonly templateTypes: {
26
+ item: {
27
+ $implicit: NgnItem<T, K> | undefined;
28
+ };
29
+ };
30
+ protected readonly templateTypesInternal: {
31
+ item: {
32
+ $implicit: NgnItem<T, K> | undefined;
33
+ index: number;
34
+ };
35
+ };
36
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ListBoxTemplates<any, any>, never>;
37
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ListBoxTemplates<any, any>, "ng-component", never, { "templateItem": { "alias": "templateItem"; "required": false; "isSignal": true; }; "templateGroup": { "alias": "templateGroup"; "required": false; "isSignal": true; }; }, {}, ["_userItemTemplate", "_userGroupTemplate"], never, true, never>;
38
+ }
39
+
40
+ declare class ListBox<T extends object, K extends keyof T> extends ListBoxTemplates<T, K> {
41
+ readonly items: _angular_core.InputSignal<readonly NgnItem<T, K>[] | readonly T[]>;
42
+ readonly fields: _angular_core.InputSignal<NgnItemFields<T, K> | undefined>;
43
+ readonly selectable: _angular_core.InputSignal<boolean>;
44
+ readonly highlightable: _angular_core.InputSignal<boolean>;
45
+ readonly virtual: _angular_core.InputSignal<boolean | undefined>;
46
+ readonly itemHeight: _angular_core.InputSignal<number | undefined>;
47
+ private readonly _scroller;
48
+ protected readonly formattedItems: _angular_core.Signal<NgnItem<T, K>[]>;
49
+ protected readonly flatItems: _angular_core.Signal<NgnItem<any, any>[]>;
50
+ protected readonly currentHighlightedValue: _angular_core.WritableSignal<T[K] | null>;
51
+ constructor();
52
+ onKeyDown(event: KeyboardEvent): void;
53
+ protected onSelect(value: T[K]): void;
54
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ListBox<any, any>, never>;
55
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ListBox<any, any>, "ngn-list-box", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "fields": { "alias": "fields"; "required": false; "isSignal": true; }; "selectable": { "alias": "selectable"; "required": false; "isSignal": true; }; "highlightable": { "alias": "highlightable"; "required": false; "isSignal": true; }; "virtual": { "alias": "virtual"; "required": false; "isSignal": true; }; "itemHeight": { "alias": "itemHeight"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
56
+ }
57
+
58
+ export { ListBox };
package/package.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "name": "@ngneers/controls",
3
+ "version": "0.0.1-pre1",
4
+ "private": false,
5
+ "dependencies": {
6
+ "tslib": "^2.8.1"
7
+ },
8
+ "peerDependencies": {
9
+ "@angular/common": "^20.0.0",
10
+ "@angular/compiler": "^20.0.0",
11
+ "@angular/core": "^20.0.0",
12
+ "@angular/forms": "^20.0.0",
13
+ "@angular/platform-browser": "^20.0.0",
14
+ "@angular/router": "^20.0.0",
15
+ "rxjs": "~7.8.0",
16
+ "@floating-ui/dom": "^1.7.1"
17
+ },
18
+ "sideEffects": false,
19
+ "module": "fesm2022/ngneers-controls.mjs",
20
+ "typings": "index.d.ts",
21
+ "exports": {
22
+ "./package.json": {
23
+ "default": "./package.json"
24
+ },
25
+ ".": {
26
+ "types": "./index.d.ts",
27
+ "default": "./fesm2022/ngneers-controls.mjs"
28
+ },
29
+ "./api": {
30
+ "types": "./api/index.d.ts",
31
+ "default": "./fesm2022/ngneers-controls-api.mjs"
32
+ },
33
+ "./custom-types": {
34
+ "types": "./custom-types/index.d.ts",
35
+ "default": "./fesm2022/ngneers-controls-custom-types.mjs"
36
+ },
37
+ "./dialog": {
38
+ "types": "./dialog/index.d.ts",
39
+ "default": "./fesm2022/ngneers-controls-dialog.mjs"
40
+ },
41
+ "./form-field": {
42
+ "types": "./form-field/index.d.ts",
43
+ "default": "./fesm2022/ngneers-controls-form-field.mjs"
44
+ },
45
+ "./icon": {
46
+ "types": "./icon/index.d.ts",
47
+ "default": "./fesm2022/ngneers-controls-icon.mjs"
48
+ },
49
+ "./list-box": {
50
+ "types": "./list-box/index.d.ts",
51
+ "default": "./fesm2022/ngneers-controls-list-box.mjs"
52
+ },
53
+ "./lazy-cacher": {
54
+ "types": "./lazy-cacher/index.d.ts",
55
+ "default": "./fesm2022/ngneers-controls-lazy-cacher.mjs"
56
+ },
57
+ "./popover": {
58
+ "types": "./popover/index.d.ts",
59
+ "default": "./fesm2022/ngneers-controls-popover.mjs"
60
+ },
61
+ "./scroller": {
62
+ "types": "./scroller/index.d.ts",
63
+ "default": "./fesm2022/ngneers-controls-scroller.mjs"
64
+ },
65
+ "./select": {
66
+ "types": "./select/index.d.ts",
67
+ "default": "./fesm2022/ngneers-controls-select.mjs"
68
+ },
69
+ "./text-field": {
70
+ "types": "./text-field/index.d.ts",
71
+ "default": "./fesm2022/ngneers-controls-text-field.mjs"
72
+ },
73
+ "./utils": {
74
+ "types": "./utils/index.d.ts",
75
+ "default": "./fesm2022/ngneers-controls-utils.mjs"
76
+ }
77
+ }
78
+ }