@ngneers/controls 0.0.1-pre1 → 0.0.1-pre3
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/LICENSE +21 -0
- package/fesm2022/ngneers-controls-accordion.mjs +194 -0
- package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api-ng.mjs +668 -0
- package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api.mjs +256 -227
- package/fesm2022/ngneers-controls-api.mjs.map +1 -1
- package/fesm2022/ngneers-controls-avatar.mjs +70 -0
- package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-base.mjs +397 -0
- package/fesm2022/ngneers-controls-base.mjs.map +1 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs +74 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button-group.mjs +51 -0
- package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button.mjs +62 -0
- package/fesm2022/ngneers-controls-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs +63 -0
- package/fesm2022/ngneers-controls-calendar-time-C7UnIFzU.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar.mjs +468 -0
- package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-checkbox.mjs +58 -0
- package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
- package/fesm2022/ngneers-controls-chip.mjs +52 -0
- package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-defer.mjs +43 -0
- package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-dialog.mjs +329 -33
- package/fesm2022/ngneers-controls-dialog.mjs.map +1 -1
- package/fesm2022/ngneers-controls-directives.mjs +443 -0
- package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
- package/fesm2022/ngneers-controls-drawer.mjs +232 -0
- package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs +120 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-filter.mjs +516 -0
- package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs +87 -0
- package/fesm2022/ngneers-controls-i18n-de-CdTPeBiR.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs +87 -0
- package/fesm2022/ngneers-controls-i18n-en-Cfp2pOLY.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n.mjs +57 -0
- package/fesm2022/ngneers-controls-i18n.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-calendar-z5xA9wTT.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-check-DdAQ9k-T.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-chevron_down-HO-z-xOr.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-chevron_left-CC5psi16.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-chevron_right-BRxlzx4G.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-chevron_up-cqhPO7g2.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-ellipsis-DXIGA1sk.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-filter-oU7E6Xgr.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-filter_solid-CqIKuR4N.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-magnifying_glass-T4Hzbkig.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-minus-oGDEFO4E.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-sort-CRD4tafz.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-sort_down-DiFB1P6R.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-sort_up-Bq_q3hIi.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs +4 -0
- package/fesm2022/ngneers-controls-icon-xmark-BZKZORiu.mjs.map +1 -0
- package/fesm2022/ngneers-controls-icon.mjs +60 -18
- package/fesm2022/ngneers-controls-icon.mjs.map +1 -1
- package/fesm2022/ngneers-controls-inplace.mjs +107 -0
- package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input-field.mjs +141 -0
- package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input-mask.mjs +282 -0
- package/fesm2022/ngneers-controls-input-mask.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input.mjs +69 -0
- package/fesm2022/ngneers-controls-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-item-view.mjs +441 -0
- package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
- package/fesm2022/ngneers-controls-list-box.mjs +157 -53
- package/fesm2022/ngneers-controls-list-box.mjs.map +1 -1
- package/fesm2022/ngneers-controls-menu.mjs +332 -0
- package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
- package/fesm2022/ngneers-controls-message.mjs +29 -0
- package/fesm2022/ngneers-controls-message.mjs.map +1 -0
- package/fesm2022/ngneers-controls-paginator.mjs +111 -0
- package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
- package/fesm2022/ngneers-controls-popover.mjs +129 -40
- package/fesm2022/ngneers-controls-popover.mjs.map +1 -1
- package/fesm2022/ngneers-controls-progress.mjs +82 -0
- package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
- package/fesm2022/ngneers-controls-scroller.mjs +162 -78
- package/fesm2022/ngneers-controls-scroller.mjs.map +1 -1
- package/fesm2022/ngneers-controls-select-button.mjs +55 -0
- package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-select.mjs +313 -103
- package/fesm2022/ngneers-controls-select.mjs.map +1 -1
- package/fesm2022/ngneers-controls-slider.mjs +155 -0
- package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
- package/fesm2022/ngneers-controls-spinner.mjs +169 -0
- package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
- package/fesm2022/ngneers-controls-splitter.mjs +717 -0
- package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-switch.mjs +39 -0
- package/fesm2022/ngneers-controls-switch.mjs.map +1 -0
- package/fesm2022/ngneers-controls-table.mjs +379 -0
- package/fesm2022/ngneers-controls-table.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tabs.mjs +287 -0
- package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tag.mjs +29 -0
- package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toast.mjs +184 -0
- package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs +65 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tooltip.mjs +454 -0
- package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs +227 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils.mjs +217 -60
- package/fesm2022/ngneers-controls-utils.mjs.map +1 -1
- package/fesm2022/ngneers-controls.mjs.map +1 -1
- package/package.json +167 -32
- package/types/ngneers-controls-accordion.d.ts +114 -0
- package/types/ngneers-controls-api-ng.d.ts +291 -0
- package/types/ngneers-controls-api.d.ts +99 -0
- package/types/ngneers-controls-avatar.d.ts +50 -0
- package/types/ngneers-controls-base.d.ts +166 -0
- package/types/ngneers-controls-breadcrumb.d.ts +86 -0
- package/types/ngneers-controls-button-group.d.ts +30 -0
- package/types/ngneers-controls-button.d.ts +34 -0
- package/types/ngneers-controls-calendar.d.ts +275 -0
- package/types/ngneers-controls-checkbox.d.ts +38 -0
- package/types/ngneers-controls-chip.d.ts +37 -0
- package/types/ngneers-controls-defer.d.ts +22 -0
- package/types/ngneers-controls-dialog.d.ts +218 -0
- package/types/ngneers-controls-directives.d.ts +146 -0
- package/types/ngneers-controls-drawer.d.ts +220 -0
- package/types/ngneers-controls-edit-inplace.d.ts +182 -0
- package/types/ngneers-controls-filter.d.ts +304 -0
- package/types/ngneers-controls-i18n.d.ts +108 -0
- package/types/ngneers-controls-icon.d.ts +74 -0
- package/types/ngneers-controls-inplace.d.ts +95 -0
- package/types/ngneers-controls-input-field.d.ts +159 -0
- package/types/ngneers-controls-input-mask.d.ts +83 -0
- package/types/ngneers-controls-input.d.ts +27 -0
- package/types/ngneers-controls-item-view.d.ts +211 -0
- package/types/ngneers-controls-list-box.d.ts +216 -0
- package/types/ngneers-controls-menu.d.ts +178 -0
- package/types/ngneers-controls-message.d.ts +19 -0
- package/types/ngneers-controls-paginator.d.ts +162 -0
- package/types/ngneers-controls-popover.d.ts +101 -0
- package/types/ngneers-controls-progress.d.ts +44 -0
- package/types/ngneers-controls-scroller.d.ts +137 -0
- package/types/ngneers-controls-select-button.d.ts +37 -0
- package/types/ngneers-controls-select.d.ts +314 -0
- package/types/ngneers-controls-slider.d.ts +53 -0
- package/types/ngneers-controls-spinner.d.ts +105 -0
- package/types/ngneers-controls-splitter.d.ts +391 -0
- package/types/ngneers-controls-switch.d.ts +18 -0
- package/types/ngneers-controls-table.d.ts +157 -0
- package/types/ngneers-controls-tabs.d.ts +106 -0
- package/types/ngneers-controls-tag.d.ts +19 -0
- package/types/ngneers-controls-toast.d.ts +70 -0
- package/types/ngneers-controls-toggle-button.d.ts +46 -0
- package/types/ngneers-controls-tooltip.d.ts +188 -0
- package/types/ngneers-controls-utils-ng.d.ts +57 -0
- package/types/ngneers-controls-utils.d.ts +130 -0
- package/api/index.d.ts +0 -134
- package/custom-types/index.d.ts +0 -7
- package/dialog/index.d.ts +0 -43
- package/fesm2022/ngneers-controls-custom-types.mjs +0 -4
- package/fesm2022/ngneers-controls-custom-types.mjs.map +0 -1
- package/fesm2022/ngneers-controls-form-field.mjs +0 -33
- package/fesm2022/ngneers-controls-form-field.mjs.map +0 -1
- package/fesm2022/ngneers-controls-lazy-cacher.mjs +0 -30
- package/fesm2022/ngneers-controls-lazy-cacher.mjs.map +0 -1
- package/fesm2022/ngneers-controls-text-field.mjs +0 -23
- package/fesm2022/ngneers-controls-text-field.mjs.map +0 -1
- package/form-field/index.d.ts +0 -19
- package/icon/index.d.ts +0 -30
- package/lazy-cacher/index.d.ts +0 -14
- package/list-box/index.d.ts +0 -58
- package/popover/index.d.ts +0 -41
- package/scroller/index.d.ts +0 -95
- package/select/index.d.ts +0 -86
- package/text-field/index.d.ts +0 -10
- package/utils/index.d.ts +0 -36
- /package/{index.d.ts → types/ngneers-controls.d.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngneers-controls-api.mjs","sources":["../../../packages/controls/src/api/dom.ts","../../../packages/controls/src/api/element-ref.ts","../../../packages/controls/src/api/filtering.ts","../../../packages/controls/src/api/value-control-base.ts","../../../packages/controls/src/api/provider.ts","../../../packages/controls/src/api/template.ts","../../../packages/controls/src/api/ngn-items.ts","../../../packages/controls/src/api/positioning.ts","../../../packages/controls/src/api/ngneers-controls-api.ts"],"sourcesContent":["import { DestroyRef, inject, signal, Signal } from '@angular/core';\r\n\r\nexport function elementSizeSignal(element: HTMLElement): Signal<{ width: number; height: number }> {\r\n const sizeSignal = signal<{ width: number; height: number }>({\r\n width: element.clientWidth,\r\n height: element.clientHeight,\r\n });\r\n\r\n const destroyRef = inject(DestroyRef);\r\n if (typeof ResizeObserver === 'undefined') {\r\n return sizeSignal; // ResizeObserver is not supported, return initial size\r\n }\r\n const resizeObserver = new ResizeObserver(entries => {\r\n const firstEntry = entries[0];\r\n sizeSignal.set({\r\n width: firstEntry.contentRect.width,\r\n height: firstEntry.contentRect.height,\r\n });\r\n });\r\n resizeObserver.observe(element);\r\n destroyRef.onDestroy(() => {\r\n resizeObserver.disconnect();\r\n });\r\n return sizeSignal;\r\n}\r\n","import { Directive, ElementRef, inject } from '@angular/core';\r\n\r\n@Directive({ selector: '[ngnElementRef]', exportAs: 'ngnElementRef' })\r\nexport class GetElementRef {\r\n public readonly elementRef = inject(ElementRef);\r\n public readonly nativeElement = this.elementRef.nativeElement;\r\n}\r\n","import { fuzzyMatch, notNullish } from '@ngneers/controls/utils';\r\n\r\nexport type PredefinedFilterFunctions = 'contains' | 'startsWith' | 'endsWith' | 'equals' | 'fuzzy';\r\n\r\nexport type FilterConfigInternal<T extends object> = FilterConfig<T> & {\r\n filterFieldsCallback: (item: T) => string | string[];\r\n fieldItems?: keyof T;\r\n};\r\n\r\nexport type FilterConfig<T extends object> = {\r\n splitWords?: boolean;\r\n caseSensitive?: boolean;\r\n filterFn?: FilterFn<T>;\r\n};\r\n\r\nexport type FilterFn<T extends object> =\r\n | PredefinedFilterFunctions\r\n | ((value: string, item: T) => Promise<boolean> | boolean);\r\n\r\nasync function filterItem<T extends object>(\r\n item: T,\r\n filterText: string,\r\n options: FilterConfigInternal<T>\r\n): Promise<T | null> {\r\n const text = options.caseSensitive ? filterText : filterText.toLowerCase();\r\n const filterFieldsCallbackResult = options.filterFieldsCallback?.(item);\r\n const fields = Array.isArray(filterFieldsCallbackResult)\r\n ? filterFieldsCallbackResult\r\n : [filterFieldsCallbackResult];\r\n const words = options.splitWords ? text.split(/\\s+/) : [text];\r\n\r\n const itemDoesMatch = (\r\n await Promise.all(\r\n fields.map(async field => {\r\n const value = String(field);\r\n const valueStr = options.caseSensitive ? value : value.toLowerCase();\r\n return await itemMatches<T>(words, options, valueStr, item);\r\n })\r\n )\r\n ).some(result => result);\r\n if (itemDoesMatch) {\r\n return item;\r\n }\r\n if (!options.fieldItems) {\r\n return null;\r\n }\r\n const childItems = item[options.fieldItems] as T[];\r\n if (!childItems || !Array.isArray(childItems) || childItems.length === 0) {\r\n return null;\r\n }\r\n const matchingChildren = await filterOptions(childItems, filterText, options);\r\n if (matchingChildren.length > 0) {\r\n return {\r\n ...item,\r\n [options.fieldItems]: matchingChildren,\r\n };\r\n }\r\n return null;\r\n}\r\n\r\nasync function itemMatches<T extends object>(\r\n words: string[],\r\n filterOptions: FilterConfigInternal<T>,\r\n itemString: string,\r\n item: T\r\n): Promise<boolean> {\r\n const results = await Promise.all(\r\n words.map(async word => {\r\n switch (filterOptions.filterFn ?? 'contains') {\r\n case 'contains':\r\n return itemString.includes(word);\r\n case 'startsWith':\r\n return itemString.startsWith(word);\r\n case 'endsWith':\r\n return itemString.endsWith(word);\r\n case 'equals':\r\n return itemString === word;\r\n case 'fuzzy':\r\n return fuzzyMatch(itemString, word);\r\n default:\r\n if (typeof filterOptions.filterFn !== 'function') {\r\n throw new Error(\r\n `Invalid filter function: ${filterOptions.filterFn}. Expected a function or one of the predefined filter functions.`\r\n );\r\n }\r\n return await filterOptions.filterFn(word, item);\r\n }\r\n })\r\n );\r\n return results.some(result => result);\r\n}\r\n\r\nexport async function filterOptions<T extends object>(\r\n options: T[],\r\n filterText: string,\r\n filterOptions: FilterConfigInternal<T>\r\n): Promise<readonly T[]> {\r\n if (!filterText) {\r\n return options;\r\n }\r\n return (\r\n await Promise.all(\r\n options.map(async option => await filterItem(option, filterText, filterOptions))\r\n )\r\n ).filter(notNullish);\r\n}\r\n","import { Component, input, signal, Type } from '@angular/core';\r\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\r\nimport { FormFieldBase } from '@ngneers/controls/form-field';\r\nimport { generateElementId } from '@ngneers/controls/utils';\r\n\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\nexport function valueControlBaseProvider<T extends Type<ValueControlBase<any>>>(\r\n type: T\r\n): { provide: typeof NG_VALUE_ACCESSOR; useExisting: T; multi: boolean } {\r\n return {\r\n provide: NG_VALUE_ACCESSOR,\r\n useExisting: type,\r\n multi: true,\r\n };\r\n}\r\n\r\n@Component({\r\n template: '',\r\n imports: [],\r\n})\r\nexport abstract class ValueControlBase<T> implements FormFieldBase, ControlValueAccessor {\r\n public readonly label = input<string | null>(null);\r\n public readonly inputId = input<string>(generateElementId());\r\n\r\n protected readonly value = signal<T | null>(null);\r\n\r\n public writeValue(value: T | null): void {\r\n this.value.set(value ?? null);\r\n }\r\n private _onChange: (_: T | null) => void = () => {};\r\n public registerOnChange(fn: (value: T | null) => void): void {\r\n this._onChange = fn;\r\n }\r\n private _onTouched: () => void = () => {};\r\n public registerOnTouched(fn: () => void): void {\r\n this._onTouched = fn;\r\n }\r\n\r\n protected onTouched() {\r\n this._onTouched();\r\n }\r\n\r\n protected onChange(value: T) {\r\n this._onChange(value ?? null);\r\n }\r\n}\r\n","import { Provider } from '@angular/core';\nimport { NgnGlobal } from '@ngneers/controls/utils';\n\nexport function provideNgnControls(): Provider[] {\n return [NgnGlobal];\n}\n","import { Directive, input } from '@angular/core';\n\n@Directive({\n selector: 'ng-template[ngnTemplate]',\n})\nexport class NgnTemplate<T> {\n public readonly ngnTemplate = input.required<T>();\n\n public static ngTemplateContextGuard<T>(dir: NgnTemplate<T>, ctx: unknown): ctx is T {\n return true;\n }\n}\n\n/**\n * A noop with return type T.\n * This function is used to define typed properties to use in a template.\n */\nexport function templateTypesFn<T extends Record<string, Record<string, any>>>() {\n return {} as T;\n}\n\n/**\n * A noop with return type `{ $implicit: Implicit } & Named`.\n * This function is used to define a typed property to use in a template.\n */\nexport function templateTypeFn<Implicit, Named extends Record<string, any> = object>() {\n return {} as { $implicit: Implicit } & Named;\n}\n","export type NgnItem<T = any, K extends keyof T = any> = {\r\n data?: T;\r\n label: string;\r\n value: T[K];\r\n testId?: string;\r\n items?: NgnItem<T, K>[];\r\n};\r\n\r\nexport type NgnItemFields<T, K extends keyof T> = {\r\n label: keyof T;\r\n value: K;\r\n testId?: keyof T;\r\n groupItems?: keyof T;\r\n};\r\n\r\nexport function transformToNgnItem<T extends object, K extends keyof T>(\r\n item: T,\r\n fields: NgnItemFields<T, K>\r\n): NgnItem<T, K> {\r\n const rawItems = fields.groupItems ? item[fields.groupItems] : undefined;\r\n if (rawItems && !Array.isArray(rawItems)) {\r\n throw new Error(\r\n `Expected groupItems to be an array, but got ${typeof rawItems} for item: ${JSON.stringify(item)}`\r\n );\r\n }\r\n const items = (rawItems as T[])?.length\r\n ? transformToNgnItems(rawItems as T[], fields)\r\n : undefined;\r\n return {\r\n data: item,\r\n label: item[fields.label] as string,\r\n value: item[fields.value],\r\n testId: fields.testId ? (item[fields.testId] as string) : undefined,\r\n items: items,\r\n };\r\n}\r\n\r\nexport function transformToNgnItems<T extends object, K extends keyof T>(\r\n items: readonly T[],\r\n fields: {\r\n label: keyof T;\r\n value: K;\r\n testId?: keyof T;\r\n groupItems?: keyof T;\r\n }\r\n): NgnItem<T, K>[] {\r\n return items.map(item => transformToNgnItem(item, fields));\r\n}\r\n\r\nexport function mapToItems(items: readonly NgnItem[]): NgnItem[] {\r\n return items\r\n .map(item => {\r\n if (item.items) {\r\n return item.items;\r\n }\r\n return [item];\r\n })\r\n .flat();\r\n}\r\n\r\nexport function flatItems(items: readonly NgnItem[]): NgnItem[] {\r\n return items\r\n .map(item => {\r\n if (item.items) {\r\n return [item, ...item.items];\r\n }\r\n return [item];\r\n })\r\n .flat();\r\n}\r\n","import { DestroyRef, inject, Injector } from '@angular/core';\r\nimport { autoUpdate, computePosition, flip, offset, shift, size } from '@floating-ui/dom';\r\n\r\nexport type PositioningSizeConstraints = {\r\n /**\r\n * The width of the floating element. When a number is provided, it is relative to the width of the reference element.\r\n * When a string is provided, it is used as the CSS width value.\r\n */\r\n width?: number | string;\r\n /**\r\n * The maximum width of the floating element. When a number is provided, it is relative to the width of the reference element.\r\n * When a string is provided, it is used as the CSS max-width value.\r\n */\r\n maxWidth?: number | string;\r\n /**\r\n * The height of the floating element. When a string is provided, it is used as the CSS height value.\r\n */\r\n height?: string;\r\n /**\r\n * The maximum height of the floating element. When a string is provided, it is used as the CSS max-height value.\r\n */\r\n maxHeight?: string;\r\n};\r\n\r\nexport type PositioningOptions = {\r\n injector?: Injector;\r\n placement?: 'top' | 'bottom' | 'left' | 'right';\r\n flip?: boolean;\r\n resize?: boolean;\r\n shift?: boolean;\r\n offset?: number;\r\n stopped?: boolean;\r\n sizeConstraints?: PositioningSizeConstraints;\r\n};\r\n\r\nexport type AutoPositioningHandle = {\r\n stop: () => void;\r\n start: () => void;\r\n isRunning: () => boolean;\r\n};\r\n\r\nfunction mergeWithDefaults(options: PositioningOptions): PositioningOptions {\r\n return {\r\n placement: 'bottom',\r\n flip: true,\r\n resize: true,\r\n shift: true,\r\n offset: 4,\r\n stopped: false,\r\n ...options,\r\n };\r\n}\r\n\r\nexport function positionElement(\r\n referenceEl: HTMLElement,\r\n floatingEl: HTMLElement,\r\n options: PositioningOptions = {}\r\n) {\r\n options = mergeWithDefaults(options);\r\n\r\n const flipMiddleware = options.flip\r\n ? flip(options.shift ? { crossAxis: 'alignment', fallbackAxisSideDirection: 'end' } : undefined)\r\n : undefined;\r\n const shiftMiddleware = options.shift ? shift() : undefined;\r\n\r\n if (options.sizeConstraints) {\r\n if (options.sizeConstraints.width || options.sizeConstraints.maxWidth) {\r\n const refWidth = referenceEl.offsetWidth;\r\n if (options.sizeConstraints.width) {\r\n if (typeof options.sizeConstraints.width === 'string') {\r\n floatingEl.style.width = options.sizeConstraints.width;\r\n } else {\r\n const widthConstraints = options.sizeConstraints.width * refWidth;\r\n floatingEl.style.width = `min(100%, ${widthConstraints}px)`;\r\n }\r\n }\r\n if (options.sizeConstraints.maxWidth) {\r\n if (typeof options.sizeConstraints.maxWidth === 'string') {\r\n floatingEl.style.maxWidth = options.sizeConstraints.maxWidth;\r\n } else {\r\n const maxWidthConstraints = options.sizeConstraints.maxWidth * refWidth;\r\n floatingEl.style.maxWidth = `min(100%, ${maxWidthConstraints}px)`;\r\n }\r\n }\r\n }\r\n if (options.sizeConstraints.height || options.sizeConstraints.maxHeight) {\r\n if (options.sizeConstraints.height) {\r\n floatingEl.style.height = options.sizeConstraints.height;\r\n }\r\n if (options.sizeConstraints.maxHeight) {\r\n floatingEl.style.maxHeight = options.sizeConstraints.maxHeight;\r\n }\r\n }\r\n }\r\n\r\n computePosition(referenceEl, floatingEl, {\r\n placement: options.placement,\r\n middleware: [\r\n options.offset ? offset(options.offset) : undefined,\r\n ...(options.placement?.includes('-')\r\n ? [flipMiddleware, shiftMiddleware]\r\n : [shiftMiddleware, flipMiddleware]),\r\n options.resize\r\n ? size({\r\n apply({ availableHeight }) {\r\n Object.assign(floatingEl.style, {\r\n maxHeight: `${Math.min(Number(options.sizeConstraints?.maxHeight ?? availableHeight), availableHeight)}px`,\r\n });\r\n },\r\n })\r\n : undefined,\r\n ].filter(Boolean),\r\n }).then(({ x, y }) => {\r\n Object.assign(floatingEl.style, {\r\n left: `${x}px`,\r\n top: `${y}px`,\r\n });\r\n });\r\n}\r\n\r\nexport function autoPositionElement(\r\n referenceEl: HTMLElement,\r\n floatingEl: HTMLElement,\r\n options: PositioningOptions = {}\r\n): AutoPositioningHandle {\r\n options = mergeWithDefaults(options);\r\n\r\n let cleanup: (() => void) | undefined;\r\n const destroyRef = options.injector?.get(DestroyRef) ?? inject(DestroyRef);\r\n\r\n function startAutoUpdate() {\r\n cleanup = autoUpdate(referenceEl, floatingEl, () => {\r\n positionElement(referenceEl, floatingEl, options);\r\n });\r\n return cleanup;\r\n }\r\n\r\n destroyRef.onDestroy(() => {\r\n cleanup?.();\r\n cleanup = undefined;\r\n });\r\n return {\r\n start: () => {\r\n cleanup?.();\r\n startAutoUpdate();\r\n },\r\n stop: () => {\r\n cleanup?.();\r\n cleanup = undefined;\r\n },\r\n isRunning: () => !!cleanup,\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-api.mjs","sources":["../../src/api/string-match.ts","../../src/api/filter-execution.ts","../../src/api/string-filter.ts","../../src/api/ngn-item.ts","../../src/api/ngneers-controls-api.ts"],"sourcesContent":["import { fuzzyMatch } from '@ngneers/controls/utils';\r\n\r\nexport type PredefinedStringMatchFunction =\r\n | 'contains'\r\n | 'startsWith'\r\n | 'endsWith'\r\n | 'equals'\r\n | 'fuzzy';\r\n\r\nexport function stringMatches(\r\n value: string,\r\n query: string,\r\n filterFn: PredefinedStringMatchFunction\r\n): boolean {\r\n switch (filterFn) {\r\n case 'contains':\r\n return value.includes(query);\r\n case 'startsWith':\r\n return value.startsWith(query);\r\n case 'endsWith':\r\n return value.endsWith(query);\r\n case 'equals':\r\n return value === query;\r\n case 'fuzzy':\r\n return fuzzyMatch(value, query);\r\n }\r\n}\r\n","import { type AllKeysOfUnion, objectEntries } from '@ngneers/controls/utils';\r\n\r\nimport { stringMatches } from './string-match';\r\n\r\ntype NgnFilterDataType = 'string' | 'number' | 'date' | 'dateTime' | 'boolean' | 'custom' | 'list';\r\n\r\ntype NgnFilterMatchMode = 'all' | 'any';\r\n\r\ntype NgnFilterOperatorId =\r\n | 'isEqual'\r\n | 'isNotEqual'\r\n | 'contains'\r\n | 'startsWith'\r\n | 'endsWith'\r\n | 'in'\r\n | 'isEmpty'\r\n | 'isNotEmpty'\r\n | 'greaterThan'\r\n | 'greaterThanOrEqual'\r\n | 'lessThan'\r\n | 'lessThanOrEqual'\r\n | 'isTrue'\r\n | 'isFalse'\r\n | 'custom';\r\n\r\ntype NgnFilterConditionConfig = {\r\n operator: NgnFilterOperatorId;\r\n rawValue: string | null;\r\n};\r\n\r\ntype NgnFilterConfig = {\r\n dataType: NgnFilterDataType;\r\n matchMode: NgnFilterMatchMode;\r\n conditions: readonly NgnFilterConditionConfig[];\r\n};\r\n\r\ntype NgnFilterCondition = {\r\n operator: NgnFilterOperatorId;\r\n value: unknown;\r\n};\r\n\r\nexport type NgnFilterValueSelector<T> = (item: T) => unknown;\r\n\r\nfunction normalizeString(value: unknown): string {\r\n return (value ?? '').toString().toLowerCase();\r\n}\r\n\r\nfunction asNumber(value: unknown): number | null {\r\n if (typeof value === 'number' && !Number.isNaN(value)) {\r\n return value;\r\n }\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const parsed = Number(value);\r\n return Number.isNaN(parsed) ? null : parsed;\r\n }\r\n return null;\r\n}\r\n\r\nfunction asDateMs(value: unknown): number | null {\r\n if (value instanceof Date && !Number.isNaN(value.getTime())) {\r\n return value.getTime();\r\n }\r\n if (typeof value === 'string' && value.trim() !== '') {\r\n const d = new Date(value);\r\n return Number.isNaN(d.getTime()) ? null : d.getTime();\r\n }\r\n return null;\r\n}\r\n\r\nfunction operatorRequiresValue(operator: NgnFilterOperatorId): boolean {\r\n switch (operator) {\r\n case 'isEmpty':\r\n case 'isNotEmpty':\r\n case 'isTrue':\r\n case 'isFalse':\r\n return false;\r\n default:\r\n return true;\r\n }\r\n}\r\n\r\nexport function parseFilterRawValue(raw: string | null, dataType: NgnFilterDataType): unknown {\r\n if (raw == null || raw === '') {\r\n return null;\r\n }\r\n\r\n switch (dataType) {\r\n case 'string':\r\n return raw;\r\n case 'list':\r\n return raw;\r\n case 'number':\r\n return asNumber(raw);\r\n case 'date':\r\n case 'dateTime': {\r\n const d = new Date(raw);\r\n return Number.isNaN(d.getTime()) ? null : d;\r\n }\r\n case 'boolean':\r\n return raw === 'true';\r\n case 'custom':\r\n return raw;\r\n }\r\n}\r\n\r\nexport function getActiveFilterConditions(config: NgnFilterConfig): readonly NgnFilterCondition[] {\r\n const dt = config.dataType;\r\n return config.conditions\r\n .map(c => {\r\n const requiresValue = operatorRequiresValue(c.operator);\r\n const parsed =\r\n c.operator === 'in' && (dt === 'string' || dt === 'list')\r\n ? (() => {\r\n if (!c.rawValue) {\r\n return null;\r\n }\r\n try {\r\n const v = JSON.parse(c.rawValue) as unknown;\r\n return Array.isArray(v) ? v.map(x => String(x)) : null;\r\n } catch {\r\n return null;\r\n }\r\n })()\r\n : parseFilterRawValue(c.rawValue, dt);\r\n if (requiresValue && (parsed == null || parsed === '')) {\r\n return null;\r\n }\r\n if (c.operator === 'in' && Array.isArray(parsed) && parsed.length === 0) {\r\n return null;\r\n }\r\n return <NgnFilterCondition>{ operator: c.operator, value: parsed };\r\n })\r\n .filter((x): x is NgnFilterCondition => x != null);\r\n}\r\n\r\nfunction matchesValue(\r\n value: unknown,\r\n dataType: NgnFilterDataType,\r\n condition: NgnFilterCondition\r\n): boolean {\r\n switch (dataType) {\r\n case 'string': {\r\n const left = normalizeString(value);\r\n switch (condition.operator) {\r\n case 'isEqual':\r\n return left === normalizeString(condition.value);\r\n case 'isNotEqual':\r\n return left !== normalizeString(condition.value);\r\n case 'contains':\r\n return stringMatches(left, normalizeString(condition.value), 'contains');\r\n case 'startsWith':\r\n return stringMatches(left, normalizeString(condition.value), 'startsWith');\r\n case 'endsWith':\r\n return stringMatches(left, normalizeString(condition.value), 'endsWith');\r\n case 'in': {\r\n const arr = Array.isArray(condition.value) ? condition.value : [];\r\n return arr.map(normalizeString).includes(left);\r\n }\r\n case 'isEmpty':\r\n return left.length === 0;\r\n case 'isNotEmpty':\r\n return left.length > 0;\r\n default:\r\n return false;\r\n }\r\n }\r\n case 'list': {\r\n const left = normalizeString(value);\r\n switch (condition.operator) {\r\n case 'in': {\r\n const arr = Array.isArray(condition.value) ? condition.value : [];\r\n return arr.map(normalizeString).includes(left);\r\n }\r\n case 'isEmpty':\r\n return left.length === 0;\r\n case 'isNotEmpty':\r\n return left.length > 0;\r\n case 'isEqual':\r\n return left === normalizeString(condition.value);\r\n case 'isNotEqual':\r\n return left !== normalizeString(condition.value);\r\n case 'contains':\r\n return stringMatches(left, normalizeString(condition.value), 'contains');\r\n case 'startsWith':\r\n return stringMatches(left, normalizeString(condition.value), 'startsWith');\r\n case 'endsWith':\r\n return stringMatches(left, normalizeString(condition.value), 'endsWith');\r\n default:\r\n return false;\r\n }\r\n }\r\n case 'number': {\r\n const left = asNumber(value);\r\n const right = asNumber(condition.value);\r\n if (left == null) {\r\n return false;\r\n }\r\n switch (condition.operator) {\r\n case 'isEqual':\r\n return right != null && left === right;\r\n case 'isNotEqual':\r\n return right != null && left !== right;\r\n case 'greaterThan':\r\n return right != null && left > right;\r\n case 'greaterThanOrEqual':\r\n return right != null && left >= right;\r\n case 'lessThan':\r\n return right != null && left < right;\r\n case 'lessThanOrEqual':\r\n return right != null && left <= right;\r\n default:\r\n return false;\r\n }\r\n }\r\n case 'date':\r\n case 'dateTime': {\r\n const left = asDateMs(value);\r\n const right = asDateMs(condition.value);\r\n if (left == null || right == null) {\r\n return false;\r\n }\r\n switch (condition.operator) {\r\n case 'isEqual':\r\n return left === right;\r\n case 'isNotEqual':\r\n return left !== right;\r\n case 'greaterThan':\r\n return left > right;\r\n case 'greaterThanOrEqual':\r\n return left >= right;\r\n case 'lessThan':\r\n return left < right;\r\n case 'lessThanOrEqual':\r\n return left <= right;\r\n default:\r\n return false;\r\n }\r\n }\r\n case 'boolean': {\r\n const b = !!value;\r\n if (condition.operator === 'isTrue') {\r\n return b === true;\r\n }\r\n if (condition.operator === 'isFalse') {\r\n return b === false;\r\n }\r\n return false;\r\n }\r\n case 'custom': {\r\n // Default behavior for custom: treat as string contains\r\n const left = normalizeString(value);\r\n const right = normalizeString(condition.value);\r\n return stringMatches(left, right, 'contains');\r\n }\r\n }\r\n}\r\n\r\nexport function executeFilter<T>(\r\n data: readonly T[],\r\n config: NgnFilterConfig,\r\n selector: NgnFilterValueSelector<T> = (item: T): unknown => item\r\n): readonly T[] {\r\n const active = getActiveFilterConditions(config);\r\n if (active.length === 0) {\r\n return data;\r\n }\r\n\r\n const mode = config.matchMode;\r\n const dt = config.dataType;\r\n return data.filter(item => {\r\n const value = selector(item);\r\n const evals = active.map(cond => matchesValue(value, dt, cond));\r\n return mode === 'any' ? evals.some(Boolean) : evals.every(Boolean);\r\n });\r\n}\r\n\r\nexport function executeMultiFilter<T extends object>(\r\n data: readonly T[],\r\n configs: {\r\n [key in Extract<AllKeysOfUnion<T>, string>]?: NgnFilterConfig;\r\n }\r\n): readonly T[] {\r\n let result: readonly T[] = data;\r\n for (const [key, config] of objectEntries(configs).filter(x => !!x[1])) {\r\n const forcedAll: NgnFilterConfig = { ...(config as NgnFilterConfig), matchMode: 'all' };\r\n result = executeFilter(result, forcedAll, (item: T): unknown => item[key]);\r\n }\r\n return result;\r\n}\r\n","import { NgnError, notNullish } from '@ngneers/controls/utils';\r\n\r\nimport { stringMatches, type PredefinedStringMatchFunction } from './string-match';\r\n\r\nexport type PredefinedFilterFunctions = PredefinedStringMatchFunction;\r\n\r\nexport type FilterConfigInternal<T extends object> = FilterConfig<T> & {\r\n filterFieldsCallback: (item: T) => string | string[] | (() => string) | (() => string[]);\r\n fieldItems?: keyof T;\r\n};\r\n\r\nexport type FilterConfig<T extends object> = {\r\n splitWords?: boolean;\r\n caseSensitive?: boolean;\r\n filterFn?: FilterFn<T>;\r\n};\r\n\r\nexport type FilterFn<T extends object> =\r\n | PredefinedFilterFunctions\r\n | ((value: string, item: T) => Promise<boolean> | boolean);\r\n\r\nasync function filterItem<T extends object>(\r\n item: T,\r\n filterText: string,\r\n options: FilterConfigInternal<T>\r\n): Promise<T | null> {\r\n const text = options.caseSensitive ? filterText : filterText.toLowerCase();\r\n const filterFieldsCallbackResultRaw = options.filterFieldsCallback?.(item);\r\n const filterFieldsCallbackResult =\r\n typeof filterFieldsCallbackResultRaw === 'function'\r\n ? filterFieldsCallbackResultRaw()\r\n : filterFieldsCallbackResultRaw;\r\n const fields = Array.isArray(filterFieldsCallbackResult)\r\n ? filterFieldsCallbackResult\r\n : [filterFieldsCallbackResult];\r\n const words = options.splitWords ? text.split(/\\s+/) : [text];\r\n\r\n const itemDoesMatch = (\r\n await Promise.all(\r\n fields.map(async field => {\r\n const value = String(field);\r\n const valueStr = options.caseSensitive ? value : value.toLowerCase();\r\n return await itemMatches<T>(words, options, valueStr, item);\r\n })\r\n )\r\n ).some(result => result);\r\n\r\n if (itemDoesMatch) {\r\n return item;\r\n }\r\n if (!options.fieldItems) {\r\n return null;\r\n }\r\n const childItems = item[options.fieldItems] as T[];\r\n if (!childItems || !Array.isArray(childItems) || childItems.length === 0) {\r\n return null;\r\n }\r\n const matchingChildren = await filterOptions(childItems, filterText, options);\r\n if (matchingChildren.length > 0) {\r\n return {\r\n ...item,\r\n [options.fieldItems]: matchingChildren,\r\n };\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * @todo fix only one word needing to match\r\n */\r\nasync function itemMatches<T extends object>(\r\n words: string[],\r\n filterOptions: FilterConfigInternal<T>,\r\n itemString: string,\r\n item: T\r\n): Promise<boolean> {\r\n const results = await Promise.all(\r\n words.map(async word => {\r\n const fn = filterOptions.filterFn ?? 'contains';\r\n if (typeof fn === 'string') {\r\n return stringMatches(itemString, word, fn);\r\n }\r\n if (typeof fn !== 'function') {\r\n throw new NgnError(\r\n 'filtering',\r\n `Invalid filter function: ${String(fn)}. Expected a function or one of the predefined filter functions.`\r\n );\r\n }\r\n return await fn(word, item);\r\n })\r\n );\r\n return results.some(result => result);\r\n}\r\n\r\nexport async function filterOptions<T extends object>(\r\n options: readonly T[],\r\n filterText: string,\r\n filterOptions: FilterConfigInternal<T>\r\n): Promise<readonly T[]> {\r\n if (!filterText) {\r\n return options;\r\n }\r\n\r\n return (\r\n await Promise.all(\r\n options.map(async option => await filterItem(option, filterText, filterOptions))\r\n )\r\n ).filter(notNullish);\r\n}\r\n","import { NgnError } from '@ngneers/controls/utils';\r\n\r\nimport type { IconType } from '@ngneers/controls-custom-types';\r\n\r\nexport type NgnItem<T = any, V = any> = {\r\n data?: T;\r\n label: string | (() => string);\r\n icon?: IconType;\r\n value: V;\r\n testId?: string;\r\n items?: NgnItem<T, V>[];\r\n};\r\n\r\nexport type NgnItemFields<T, K extends keyof T> = {\r\n label: keyof T;\r\n value: K;\r\n translate?: keyof T;\r\n testId?: keyof T;\r\n children?: keyof T;\r\n};\r\n\r\nexport type NgnItemValue<Item extends NgnItem> = Item extends { items: readonly (infer A)[] }\r\n ? A extends NgnItem\r\n ? NgnItemValue<A>\r\n : never\r\n : Item extends { value: infer T }\r\n ? T\r\n : never;\r\n\r\nexport type NgnItemsValue<Items extends readonly NgnItem[]> = Items[number] extends infer A\r\n ? A extends NgnItem\r\n ? NgnItemValue<A>\r\n : never\r\n : never;\r\n\r\nexport function transformToNgnItem<T extends object, K extends keyof T>(\r\n item: T,\r\n fields: NgnItemFields<T, K>\r\n): NgnItem<T, T[K]> {\r\n const rawItems = fields.children ? item[fields.children] : undefined;\r\n if (rawItems && !Array.isArray(rawItems)) {\r\n throw new NgnError(\r\n 'transformToNgnItem',\r\n `Expected children to be an array, but got ${typeof rawItems} for item: ${JSON.stringify(item)}`\r\n );\r\n }\r\n const items = (rawItems as T[])?.length\r\n ? transformToNgnItems(rawItems as T[], fields)\r\n : undefined;\r\n return {\r\n data: item,\r\n label: item[fields.label] as string | (() => string),\r\n value: item[fields.value],\r\n testId: fields.testId ? (item[fields.testId] as string) : undefined,\r\n items: items as NgnItem<T, T[K]>[],\r\n };\r\n}\r\n\r\nexport function transformToNgnItemPrimitive<T extends string | number>(\r\n item: T\r\n): NgnItem<unknown, T> {\r\n return transformToNgnItem({ var: item }, { label: 'var', value: 'var' });\r\n}\r\n\r\nexport function transformToNgnItems<Items extends readonly object[], K extends keyof Items[number]>(\r\n items: Items,\r\n fields: NgnItemFields<Items[number], K>\r\n): { [P in keyof Items]: NgnItem<Items[P], K> } & readonly NgnItem<Items[number], K>[] {\r\n return items.map((item: Items[number]) => transformToNgnItem(item, fields)) as {\r\n [P in keyof Items]: NgnItem<Items[P], K>;\r\n } & readonly NgnItem<Items[number], K>[];\r\n}\r\n\r\nexport function mapToItems(items: readonly NgnItem[]): readonly NgnItem[] {\r\n return items\r\n .map(item => {\r\n if (item.items) {\r\n return item.items;\r\n }\r\n return [item];\r\n })\r\n .flat();\r\n}\r\n\r\nexport function flatItems(items: readonly NgnItem[]): NgnItem[] {\r\n return items\r\n .map(item => {\r\n if (item.items) {\r\n return [item, ...item.items];\r\n }\r\n return [item];\r\n })\r\n .flat();\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,70 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, linkedSignal, computed, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { NgnBase, NgnPt, provideSelf } from '@ngneers/controls/base';
|
|
4
|
+
import { avatarControlTemplate, avatarGroupControlTemplate } from '@ngneers/controls-themes/templates/avatar';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @category control
|
|
8
|
+
*/
|
|
9
|
+
class NgnAvatar extends NgnBase {
|
|
10
|
+
theme = this.injectThemeTemplate(avatarControlTemplate, 'root');
|
|
11
|
+
/**
|
|
12
|
+
* The initials to display when no image is available.
|
|
13
|
+
* Max 4 characters.
|
|
14
|
+
*/
|
|
15
|
+
initials = input(...(ngDevMode ? [undefined, { debugName: "initials" }] : []));
|
|
16
|
+
/**
|
|
17
|
+
* The background color of the avatar, if the initials are used.
|
|
18
|
+
*/
|
|
19
|
+
bgColor = input(...(ngDevMode ? [undefined, { debugName: "bgColor" }] : []));
|
|
20
|
+
/**
|
|
21
|
+
* The image URL to display in the avatar.
|
|
22
|
+
*/
|
|
23
|
+
image = input(...(ngDevMode ? [undefined, { debugName: "image" }] : []));
|
|
24
|
+
/**
|
|
25
|
+
* The alt text for the image.
|
|
26
|
+
*/
|
|
27
|
+
alt = input(...(ngDevMode ? [undefined, { debugName: "alt" }] : []));
|
|
28
|
+
/**
|
|
29
|
+
* The size of the avatar in pixels.
|
|
30
|
+
* @default 48
|
|
31
|
+
*/
|
|
32
|
+
size = input(48, ...(ngDevMode ? [{ debugName: "size" }] : []));
|
|
33
|
+
imageLoadFailed = linkedSignal(() => !!this.image() && false, ...(ngDevMode ? [{ debugName: "imageLoadFailed" }] : []));
|
|
34
|
+
initialsLimited = computed(() => this.initials()?.slice(0, 4), ...(ngDevMode ? [{ debugName: "initialsLimited" }] : []));
|
|
35
|
+
constructor() {
|
|
36
|
+
super();
|
|
37
|
+
}
|
|
38
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnAvatar, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
39
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.0", type: NgnAvatar, isStandalone: true, selector: "ngn-avatar", inputs: { initials: { classPropertyName: "initials", publicName: "initials", isSignal: true, isRequired: false, transformFunction: null }, bgColor: { classPropertyName: "bgColor", publicName: "bgColor", isSignal: true, isRequired: false, transformFunction: null }, image: { classPropertyName: "image", publicName: "image", isSignal: true, isRequired: false, transformFunction: null }, alt: { classPropertyName: "alt", publicName: "alt", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--size.px": "size()", "style.--color": "bgColor()" } }, providers: [provideSelf(NgnAvatar)], usesInheritance: true, ngImport: i0, template: "<ng-content>\r\n @if (!image() || imageLoadFailed()) {\r\n <span\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'initials'\"\r\n [style.--letterCount]=\"initialsLimited()?.length || 1\"\r\n >\r\n {{ initialsLimited() }}\r\n </span>\r\n } @else {\r\n <img\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'image'\"\r\n [src]=\"image()\"\r\n [alt]=\"alt() ?? ''\"\r\n (error)=\"imageLoadFailed.set(true)\"\r\n />\r\n }\r\n</ng-content>\r\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
40
|
+
}
|
|
41
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnAvatar, decorators: [{
|
|
42
|
+
type: Component,
|
|
43
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-avatar', imports: [NgnPt], host: {
|
|
44
|
+
'[style.--size.px]': 'size()',
|
|
45
|
+
'[style.--color]': 'bgColor()',
|
|
46
|
+
}, providers: [provideSelf(NgnAvatar)], template: "<ng-content>\r\n @if (!image() || imageLoadFailed()) {\r\n <span\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'initials'\"\r\n [style.--letterCount]=\"initialsLimited()?.length || 1\"\r\n >\r\n {{ initialsLimited() }}\r\n </span>\r\n } @else {\r\n <img\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'image'\"\r\n [src]=\"image()\"\r\n [alt]=\"alt() ?? ''\"\r\n (error)=\"imageLoadFailed.set(true)\"\r\n />\r\n }\r\n</ng-content>\r\n" }]
|
|
47
|
+
}], ctorParameters: () => [], propDecorators: { initials: [{ type: i0.Input, args: [{ isSignal: true, alias: "initials", required: false }] }], bgColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "bgColor", required: false }] }], image: [{ type: i0.Input, args: [{ isSignal: true, alias: "image", required: false }] }], alt: [{ type: i0.Input, args: [{ isSignal: true, alias: "alt", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @category control
|
|
51
|
+
*/
|
|
52
|
+
class NgnAvatarGroup extends NgnBase {
|
|
53
|
+
theme = this.injectThemeTemplate(avatarGroupControlTemplate);
|
|
54
|
+
constructor() {
|
|
55
|
+
super();
|
|
56
|
+
}
|
|
57
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnAvatarGroup, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
58
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.0", type: NgnAvatarGroup, isStandalone: true, selector: "ngn-avatar-group", providers: [provideSelf(NgnAvatarGroup)], usesInheritance: true, ngImport: i0, template: "<div [ptInt]=\"this\" [ptClass]=\"'root'\">\r\n <ng-content></ng-content>\r\n</div>\r\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
59
|
+
}
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnAvatarGroup, decorators: [{
|
|
61
|
+
type: Component,
|
|
62
|
+
args: [{ changeDetection: ChangeDetectionStrategy.OnPush, selector: 'ngn-avatar-group', imports: [NgnPt], providers: [provideSelf(NgnAvatarGroup)], template: "<div [ptInt]=\"this\" [ptClass]=\"'root'\">\r\n <ng-content></ng-content>\r\n</div>\r\n" }]
|
|
63
|
+
}], ctorParameters: () => [] });
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Generated bundle index. Do not edit.
|
|
67
|
+
*/
|
|
68
|
+
|
|
69
|
+
export { NgnAvatar, NgnAvatarGroup };
|
|
70
|
+
//# sourceMappingURL=ngneers-controls-avatar.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-avatar.mjs","sources":["../../src/avatar/avatar.ts","../../src/avatar/avatar.html","../../src/avatar/avatar-group.ts","../../src/avatar/avatar-group.html","../../src/avatar/ngneers-controls-avatar.ts"],"sourcesContent":["import { Component, computed, input, linkedSignal, ChangeDetectionStrategy } from '@angular/core';\r\nimport { NgnBase, provideSelf, NgnPt } from '@ngneers/controls/base';\r\nimport { avatarControlTemplate } from '@ngneers/controls-themes/templates/avatar';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-avatar',\r\n templateUrl: './avatar.html',\r\n imports: [NgnPt],\r\n host: {\r\n '[style.--size.px]': 'size()',\r\n '[style.--color]': 'bgColor()',\r\n },\r\n providers: [provideSelf(NgnAvatar)],\r\n})\r\nexport class NgnAvatar extends NgnBase<'avatar'> {\r\n protected readonly theme = this.injectThemeTemplate(avatarControlTemplate, 'root');\r\n\r\n /**\r\n * The initials to display when no image is available.\r\n * Max 4 characters.\r\n */\r\n public readonly initials = input<string>();\r\n /**\r\n * The background color of the avatar, if the initials are used.\r\n */\r\n public readonly bgColor = input<string>();\r\n /**\r\n * The image URL to display in the avatar.\r\n */\r\n public readonly image = input<string>();\r\n /**\r\n * The alt text for the image.\r\n */\r\n public readonly alt = input<string>();\r\n /**\r\n * The size of the avatar in pixels.\r\n * @default 48\r\n */\r\n public readonly size = input<number>(48);\r\n\r\n protected readonly imageLoadFailed = linkedSignal<boolean>(() => !!this.image() && false);\r\n protected readonly initialsLimited = computed(() => this.initials()?.slice(0, 4));\r\n\r\n constructor() {\r\n super();\r\n }\r\n}\r\n","<ng-content>\r\n @if (!image() || imageLoadFailed()) {\r\n <span\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'initials'\"\r\n [style.--letterCount]=\"initialsLimited()?.length || 1\"\r\n >\r\n {{ initialsLimited() }}\r\n </span>\r\n } @else {\r\n <img\r\n [ptInt]=\"this\"\r\n [ptClass]=\"'image'\"\r\n [src]=\"image()\"\r\n [alt]=\"alt() ?? ''\"\r\n (error)=\"imageLoadFailed.set(true)\"\r\n />\r\n }\r\n</ng-content>\r\n","import { Component, ChangeDetectionStrategy } from '@angular/core';\r\nimport { NgnBase, provideSelf, NgnPt } from '@ngneers/controls/base';\r\nimport { avatarGroupControlTemplate } from '@ngneers/controls-themes/templates/avatar';\r\n\r\n/**\r\n * @category control\r\n */\r\n@Component({\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n selector: 'ngn-avatar-group',\r\n templateUrl: './avatar-group.html',\r\n imports: [NgnPt],\r\n providers: [provideSelf(NgnAvatarGroup)],\r\n})\r\nexport class NgnAvatarGroup extends NgnBase<'avatarGroup'> {\r\n protected readonly theme = this.injectThemeTemplate(avatarGroupControlTemplate);\r\n\r\n constructor() {\r\n super();\r\n }\r\n}\r\n","<div [ptInt]=\"this\" [ptClass]=\"'root'\">\r\n <ng-content></ng-content>\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,397 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, ElementRef, computed, signal, input, Directive, DestroyRef, afterNextRender, InjectionToken, forwardRef, Injector, booleanAttribute, viewChildren, effect, model } from '@angular/core';
|
|
3
|
+
import { getAppliedClasses, injectThemeTemplate, injectThemeControlKinds, injectThemeColors } from '@ngneers/controls/api/ng';
|
|
4
|
+
import { getPropertyIfExists, objectKeys, toggleClass } from '@ngneers/controls/utils';
|
|
5
|
+
import { classSignal, effectWithPrevious, setInputSignalValue, generateElementId } from '@ngneers/controls/utils-ng';
|
|
6
|
+
|
|
7
|
+
class NgnPtEngine {
|
|
8
|
+
pt;
|
|
9
|
+
ptClass;
|
|
10
|
+
_elementRef = inject(ElementRef);
|
|
11
|
+
classes = computed(() => {
|
|
12
|
+
const pt = this.pt();
|
|
13
|
+
if ('theme' in pt) {
|
|
14
|
+
const theme = pt['theme'];
|
|
15
|
+
const res = getAppliedClasses(this.ptClass(), theme);
|
|
16
|
+
return res;
|
|
17
|
+
}
|
|
18
|
+
return [];
|
|
19
|
+
}, ...(ngDevMode ? [{ debugName: "classes" }] : []));
|
|
20
|
+
_appliedPts = computed(() => {
|
|
21
|
+
const pt = this.pt()?.pt();
|
|
22
|
+
if (!pt) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
const classes = this.classes();
|
|
26
|
+
return classes.map(({ name: ptClass }) => {
|
|
27
|
+
const classPt = getPropertyIfExists(pt, ptClass);
|
|
28
|
+
return classPt;
|
|
29
|
+
});
|
|
30
|
+
}, ...(ngDevMode ? [{ debugName: "_appliedPts" }] : []));
|
|
31
|
+
constructor(pt, ptClass) {
|
|
32
|
+
const sigPt = typeof pt === 'function' ? pt : signal(pt);
|
|
33
|
+
const sigPtClass = typeof ptClass === 'function' ? ptClass : signal(ptClass);
|
|
34
|
+
this.pt = sigPt;
|
|
35
|
+
this.ptClass = sigPtClass;
|
|
36
|
+
const classes = computed(() => this.classes().map(c => c.class), ...(ngDevMode ? [{ debugName: "classes" }] : []));
|
|
37
|
+
classSignal(this._elementRef.nativeElement, classes);
|
|
38
|
+
effectWithPrevious(this._appliedPts, (current, previous) => {
|
|
39
|
+
if (previous) {
|
|
40
|
+
for (const classPt of previous) {
|
|
41
|
+
if (!classPt) {
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
this.removePreviousPtValues(classPt);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (current) {
|
|
48
|
+
for (const classPt of current) {
|
|
49
|
+
if (!classPt) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
this.setNewPtValues(classPt);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
setNewPtValues(classPt) {
|
|
58
|
+
if (classPt.$styles) {
|
|
59
|
+
const keys = objectKeys(classPt.$styles);
|
|
60
|
+
keys.forEach(key => {
|
|
61
|
+
this._elementRef.nativeElement.style[key] = classPt.$styles?.[key] || '';
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (classPt.$attributes) {
|
|
65
|
+
const keys = objectKeys(classPt.$attributes);
|
|
66
|
+
keys.forEach(key => {
|
|
67
|
+
this._elementRef.nativeElement.setAttribute(key, classPt.$attributes?.[key] || '');
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
if (classPt.$classes) {
|
|
71
|
+
const arrayOfClasses = Array.isArray(classPt.$classes)
|
|
72
|
+
? classPt.$classes.flatMap(c => c.split(' '))
|
|
73
|
+
: classPt.$classes.split(' ');
|
|
74
|
+
arrayOfClasses.forEach(cls => {
|
|
75
|
+
try {
|
|
76
|
+
this._elementRef.nativeElement.classList.add(cls);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
console.warn(`Could not add class '${cls}' to element`, this._elementRef.nativeElement);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
removePreviousPtValues(classPt) {
|
|
85
|
+
if (classPt.$styles) {
|
|
86
|
+
const keys = objectKeys(classPt.$styles);
|
|
87
|
+
keys.forEach(key => {
|
|
88
|
+
this._elementRef.nativeElement.style[key] = '';
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (classPt.$attributes) {
|
|
92
|
+
const keys = objectKeys(classPt.$attributes);
|
|
93
|
+
keys.forEach(key => {
|
|
94
|
+
this._elementRef.nativeElement.removeAttribute(key);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
if (classPt.$classes) {
|
|
98
|
+
const arrayOfClasses = Array.isArray(classPt.$classes)
|
|
99
|
+
? classPt.$classes.flatMap(c => c.split(' '))
|
|
100
|
+
: classPt.$classes.split(' ');
|
|
101
|
+
arrayOfClasses.forEach(cls => {
|
|
102
|
+
try {
|
|
103
|
+
this._elementRef.nativeElement.classList.remove(cls);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
console.warn(`Could not remove class '${cls}' from element`, this._elementRef.nativeElement);
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// eslint-disable-next-line @angular-eslint/directive-selector
|
|
114
|
+
class NgnPt {
|
|
115
|
+
ptInt = input.required(...(ngDevMode ? [{ debugName: "ptInt" }] : []));
|
|
116
|
+
ptClass = input.required(...(ngDevMode ? [{ debugName: "ptClass" }] : []));
|
|
117
|
+
_engine = new NgnPtEngine(this.ptInt, this.ptClass);
|
|
118
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnPt, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
119
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: NgnPt, isStandalone: true, selector: "[ptInt]", inputs: { ptInt: { classPropertyName: "ptInt", publicName: "ptInt", isSignal: true, isRequired: true, transformFunction: null }, ptClass: { classPropertyName: "ptClass", publicName: "ptClass", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0 });
|
|
120
|
+
}
|
|
121
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnPt, decorators: [{
|
|
122
|
+
type: Directive,
|
|
123
|
+
args: [{ selector: '[ptInt]' }]
|
|
124
|
+
}], propDecorators: { ptInt: [{ type: i0.Input, args: [{ isSignal: true, alias: "ptInt", required: true }] }], ptClass: [{ type: i0.Input, args: [{ isSignal: true, alias: "ptClass", required: true }] }] } });
|
|
125
|
+
|
|
126
|
+
const NGN_INSTANCE_KEY = '__ngneers_control_instance__';
|
|
127
|
+
function elementWithInstance(element) {
|
|
128
|
+
return element;
|
|
129
|
+
}
|
|
130
|
+
function setNgnInstance(element, instance) {
|
|
131
|
+
elementWithInstance(element)[NGN_INSTANCE_KEY] = instance;
|
|
132
|
+
inject(DestroyRef).onDestroy(() => {
|
|
133
|
+
delete elementWithInstance(element)[NGN_INSTANCE_KEY];
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
function getNgnInstance(element) {
|
|
137
|
+
return elementWithInstance(element)[NGN_INSTANCE_KEY];
|
|
138
|
+
}
|
|
139
|
+
function getNearestNgnInstance(element, kind) {
|
|
140
|
+
let current = element;
|
|
141
|
+
while (current) {
|
|
142
|
+
const instance = elementWithInstance(current)[NGN_INSTANCE_KEY];
|
|
143
|
+
if (instance && (!kind || instance instanceof kind)) {
|
|
144
|
+
return instance;
|
|
145
|
+
}
|
|
146
|
+
current = current.parentElement;
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
function getNearestNgnInstanceSig(element, kind) {
|
|
151
|
+
const sig = signal(null, ...(ngDevMode ? [{ debugName: "sig" }] : []));
|
|
152
|
+
afterNextRender(() => {
|
|
153
|
+
sig.set(getNearestNgnInstance(element, kind));
|
|
154
|
+
});
|
|
155
|
+
return sig;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const NGN_CONTROL = new InjectionToken('NGN_CONTROL');
|
|
159
|
+
/* eslint-enable @typescript-eslint/no-explicit-any */
|
|
160
|
+
/**
|
|
161
|
+
* @internal
|
|
162
|
+
* Provides the control itself for dependency injection.
|
|
163
|
+
* @param control - The control class to provide.
|
|
164
|
+
* @returns A provider for the control itself.
|
|
165
|
+
*/
|
|
166
|
+
function provideSelf(control) {
|
|
167
|
+
return { provide: NGN_CONTROL, useExisting: forwardRef(() => control) };
|
|
168
|
+
}
|
|
169
|
+
class NgnBase {
|
|
170
|
+
_defaultKind = signal(undefined, ...(ngDevMode ? [{ debugName: "_defaultKind" }] : []));
|
|
171
|
+
_defaultColor = signal(undefined, ...(ngDevMode ? [{ debugName: "_defaultColor" }] : []));
|
|
172
|
+
/**
|
|
173
|
+
* The element reference for the host element.
|
|
174
|
+
*/
|
|
175
|
+
element = inject(ElementRef);
|
|
176
|
+
/**
|
|
177
|
+
* The injector for the component.
|
|
178
|
+
*/
|
|
179
|
+
injector = inject(Injector);
|
|
180
|
+
/**
|
|
181
|
+
* If true, the control will not apply any theme styles.
|
|
182
|
+
* The base styles of the control will still be applied.
|
|
183
|
+
* @default false
|
|
184
|
+
*/
|
|
185
|
+
unstyled = input(false, { ...(ngDevMode ? { debugName: "unstyled" } : {}), transform: booleanAttribute });
|
|
186
|
+
/**
|
|
187
|
+
* Some controls support custom kinds for styling purposes.
|
|
188
|
+
* The available kinds depend on the control and the theme used.
|
|
189
|
+
*
|
|
190
|
+
* TODO: link to custom types documentation
|
|
191
|
+
*/
|
|
192
|
+
kind = input(undefined, ...(ngDevMode ? [{ debugName: "kind" }] : []));
|
|
193
|
+
color = input(undefined, ...(ngDevMode ? [{ debugName: "color" }] : []));
|
|
194
|
+
appliedKind = computed(() => this.kind() ?? this._defaultKind(), ...(ngDevMode ? [{ debugName: "appliedKind" }] : []));
|
|
195
|
+
appliedColor = computed(() => this.color() ?? this._defaultColor(), ...(ngDevMode ? [{ debugName: "appliedColor" }] : []));
|
|
196
|
+
/**
|
|
197
|
+
* Custom passthrough attributes to apply to the control's theme classes and its dependencies.
|
|
198
|
+
* This allows for fine-grained customization of attributes, styles and more.
|
|
199
|
+
*/
|
|
200
|
+
pt = input(...(ngDevMode ? [undefined, { debugName: "pt" }] : []));
|
|
201
|
+
_childNgnControls = viewChildren(NGN_CONTROL, ...(ngDevMode ? [{ debugName: "_childNgnControls" }] : []));
|
|
202
|
+
_afterLeaveCbs = [];
|
|
203
|
+
constructor() {
|
|
204
|
+
setNgnInstance(this.element.nativeElement, this);
|
|
205
|
+
this.prepareAfterLeaveHook();
|
|
206
|
+
effect(() => {
|
|
207
|
+
// Propagate unstyled state to direct child controls, does not affect
|
|
208
|
+
// custom user content passed into ng-content or projected templates.
|
|
209
|
+
this._childNgnControls().forEach(child => {
|
|
210
|
+
setInputSignalValue(child.unstyled, this.unstyled());
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
this.initializeKindAndColorClasses();
|
|
214
|
+
afterNextRender(() => {
|
|
215
|
+
// Remove the initializing class after the first render to prevent FOUC.
|
|
216
|
+
this.element.nativeElement.classList.remove('ngn-control-initializing');
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Prepares the after leave hook to be called when the control is destroyed
|
|
221
|
+
* and its leave animation has finished.
|
|
222
|
+
*/
|
|
223
|
+
prepareAfterLeaveHook() {
|
|
224
|
+
inject(DestroyRef).onDestroy(() => {
|
|
225
|
+
if (typeof this.element.nativeElement.getAnimations !== 'function') {
|
|
226
|
+
this.afterLeaveInternal();
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
/**
|
|
230
|
+
* Recursively searches for a leave animation on the element and its parents.
|
|
231
|
+
* @param element The element to search for leave animations.
|
|
232
|
+
* @returns The leave animation if found, otherwise null.
|
|
233
|
+
*/
|
|
234
|
+
function findLeaveAnimationRecursive(element) {
|
|
235
|
+
const animations = element.getAnimations();
|
|
236
|
+
const leaveAnimation = animations.find(a => a instanceof CSSAnimation && a.animationName.endsWith('-leave'));
|
|
237
|
+
if (leaveAnimation) {
|
|
238
|
+
return leaveAnimation;
|
|
239
|
+
}
|
|
240
|
+
if (element.parentElement) {
|
|
241
|
+
return findLeaveAnimationRecursive(element.parentElement);
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
requestAnimationFrame(() => {
|
|
246
|
+
const leaveAnimation = findLeaveAnimationRecursive(this.element.nativeElement);
|
|
247
|
+
if (!leaveAnimation) {
|
|
248
|
+
this.afterLeaveInternal();
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
leaveAnimation.finished
|
|
252
|
+
.catch(() => {
|
|
253
|
+
// ignore errors from animations being cancelled
|
|
254
|
+
})
|
|
255
|
+
.finally(() => {
|
|
256
|
+
this.afterLeaveInternal();
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
afterLeaveInternal() {
|
|
264
|
+
/**
|
|
265
|
+
* After the control is hidden/removed from the DOM,
|
|
266
|
+
* manually wipe the innerHTML to ensure no detached children remain
|
|
267
|
+
* mapped to this component's LView slots in the browser's memory.
|
|
268
|
+
* This is especially important for controls that use ng-content
|
|
269
|
+
* or dynamically render child components.
|
|
270
|
+
*/
|
|
271
|
+
this.element.nativeElement.innerHTML = '';
|
|
272
|
+
this._afterLeaveCbs.forEach(cb => cb());
|
|
273
|
+
this.afterLeave();
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Lifecycle hook that is called after the control has left (been removed from) the DOM.
|
|
277
|
+
* Can be overridden by subclasses to perform custom actions after the leave animation.
|
|
278
|
+
*/
|
|
279
|
+
afterLeave() {
|
|
280
|
+
// Can be overridden by subclasses
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* @internal
|
|
284
|
+
*/
|
|
285
|
+
injectThemeTemplate(template, hostClass) {
|
|
286
|
+
const opts = { unstyled: this.unstyled };
|
|
287
|
+
const theme = injectThemeTemplate(template, opts);
|
|
288
|
+
const kinds = injectThemeControlKinds(theme.scope);
|
|
289
|
+
if (kinds.length) {
|
|
290
|
+
this._defaultKind.set(kinds[0]);
|
|
291
|
+
}
|
|
292
|
+
const colors = injectThemeColors(theme.scope);
|
|
293
|
+
if (colors.length) {
|
|
294
|
+
this._defaultColor.set(colors[0]);
|
|
295
|
+
}
|
|
296
|
+
if (hostClass !== undefined) {
|
|
297
|
+
new NgnPtEngine(this, hostClass);
|
|
298
|
+
}
|
|
299
|
+
return theme;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Toggles the kind and color theme classes based on the current values of the kind and color inputs.
|
|
303
|
+
*/
|
|
304
|
+
initializeKindAndColorClasses() {
|
|
305
|
+
this.initializeAutoThemeClasses('kind', this.appliedKind);
|
|
306
|
+
this.initializeAutoThemeClasses('color', this.appliedColor);
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Initializes automatic theme class toggling for a given prefix based on the provided string signal.
|
|
310
|
+
*
|
|
311
|
+
* ⚠️ Caution: This method assumes that the control's theme supports classes with the given prefix.
|
|
312
|
+
*
|
|
313
|
+
* ⚠️ Caution: Make sure the signal provides only string or nullish values.
|
|
314
|
+
*
|
|
315
|
+
* @param prefix The prefix for the theme class (e.g., 'kind' or 'color').
|
|
316
|
+
* @param signal The signal that provides the current string value for the theme class.
|
|
317
|
+
*/
|
|
318
|
+
initializeAutoThemeClasses(prefix, signal) {
|
|
319
|
+
const element = this.element.nativeElement;
|
|
320
|
+
/**
|
|
321
|
+
* We can't know here whether the control has any kind or color classes,
|
|
322
|
+
* so we cast explicitly to ThemeClassToken. In practice, controls without
|
|
323
|
+
* kind or color classes will simply not toggle any classes as the input type does not allow it.
|
|
324
|
+
*/
|
|
325
|
+
const classToken = (value) => value;
|
|
326
|
+
const togglePrefixedThemeClass = (prefix, value, enabled) => {
|
|
327
|
+
if (!value) {
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const theme = this.theme;
|
|
331
|
+
if (!theme) {
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
toggleClass(element, theme.class(classToken(`${prefix}-${value}`)), enabled);
|
|
335
|
+
};
|
|
336
|
+
effectWithPrevious(signal, (current, previous) => {
|
|
337
|
+
togglePrefixedThemeClass(prefix, previous, false);
|
|
338
|
+
togglePrefixedThemeClass(prefix, current, true);
|
|
339
|
+
});
|
|
340
|
+
this._afterLeaveCbs.push(() => {
|
|
341
|
+
togglePrefixedThemeClass(prefix, signal(), false);
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnBase, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
345
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.2.0", version: "21.1.0", type: NgnBase, isStandalone: true, inputs: { unstyled: { classPropertyName: "unstyled", publicName: "unstyled", isSignal: true, isRequired: false, transformFunction: null }, kind: { classPropertyName: "kind", publicName: "kind", isSignal: true, isRequired: false, transformFunction: null }, color: { classPropertyName: "color", publicName: "color", isSignal: true, isRequired: false, transformFunction: null }, pt: { classPropertyName: "pt", publicName: "pt", isSignal: true, isRequired: false, transformFunction: null } }, host: { classAttribute: "ngn-control ngn-control-initializing" }, viewQueries: [{ propertyName: "_childNgnControls", predicate: NGN_CONTROL, descendants: true, isSignal: true }], ngImport: i0 });
|
|
346
|
+
}
|
|
347
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: NgnBase, decorators: [{
|
|
348
|
+
type: Directive,
|
|
349
|
+
args: [{
|
|
350
|
+
host: { class: 'ngn-control ngn-control-initializing' },
|
|
351
|
+
}]
|
|
352
|
+
}], ctorParameters: () => [], propDecorators: { unstyled: [{ type: i0.Input, args: [{ isSignal: true, alias: "unstyled", required: false }] }], kind: [{ type: i0.Input, args: [{ isSignal: true, alias: "kind", required: false }] }], color: [{ type: i0.Input, args: [{ isSignal: true, alias: "color", required: false }] }], pt: [{ type: i0.Input, args: [{ isSignal: true, alias: "pt", required: false }] }], _childNgnControls: [{ type: i0.ViewChildren, args: [i0.forwardRef(() => NGN_CONTROL), { isSignal: true }] }] } });
|
|
353
|
+
|
|
354
|
+
class ValueControlBase extends NgnBase {
|
|
355
|
+
/**
|
|
356
|
+
* The label for the control.
|
|
357
|
+
*/
|
|
358
|
+
label = input(null, ...(ngDevMode ? [{ debugName: "label" }] : []));
|
|
359
|
+
/**
|
|
360
|
+
* Sets the `aria-labelledby` attribute on the control.
|
|
361
|
+
* @default null
|
|
362
|
+
*/
|
|
363
|
+
labelledBy = input(null, ...(ngDevMode ? [{ debugName: "labelledBy" }] : []));
|
|
364
|
+
/**
|
|
365
|
+
* The ID for the control
|
|
366
|
+
* @default generateElementId()
|
|
367
|
+
*/
|
|
368
|
+
inputId = input(generateElementId(), ...(ngDevMode ? [{ debugName: "inputId" }] : []));
|
|
369
|
+
/**
|
|
370
|
+
* Explicitly apply invalid state styling
|
|
371
|
+
* @default false
|
|
372
|
+
*/
|
|
373
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : {}), transform: booleanAttribute });
|
|
374
|
+
/**
|
|
375
|
+
* The value of the control.
|
|
376
|
+
*/
|
|
377
|
+
value = model(undefined, ...(ngDevMode ? [{ debugName: "value" }] : []));
|
|
378
|
+
/**
|
|
379
|
+
* Set the disabled state of the control.
|
|
380
|
+
*/
|
|
381
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : {}), transform: booleanAttribute });
|
|
382
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : {}), transform: booleanAttribute });
|
|
383
|
+
touched = model(false, ...(ngDevMode ? [{ debugName: "touched" }] : []));
|
|
384
|
+
dirty = input(false, { ...(ngDevMode ? { debugName: "dirty" } : {}), transform: booleanAttribute });
|
|
385
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ValueControlBase, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
386
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.1.0", type: ValueControlBase, isStandalone: true, inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelledBy: { classPropertyName: "labelledBy", publicName: "labelledBy", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, touched: { classPropertyName: "touched", publicName: "touched", isSignal: true, isRequired: false, transformFunction: null }, dirty: { classPropertyName: "dirty", publicName: "dirty", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", touched: "touchedChange" }, usesInheritance: true, ngImport: i0 });
|
|
387
|
+
}
|
|
388
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.0", ngImport: i0, type: ValueControlBase, decorators: [{
|
|
389
|
+
type: Directive
|
|
390
|
+
}], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelledBy", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], touched: [{ type: i0.Input, args: [{ isSignal: true, alias: "touched", required: false }] }, { type: i0.Output, args: ["touchedChange"] }], dirty: [{ type: i0.Input, args: [{ isSignal: true, alias: "dirty", required: false }] }] } });
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Generated bundle index. Do not edit.
|
|
394
|
+
*/
|
|
395
|
+
|
|
396
|
+
export { NGN_CONTROL, NgnBase, NgnPt, NgnPtEngine, ValueControlBase, getNearestNgnInstance, getNearestNgnInstanceSig, getNgnInstance, provideSelf, setNgnInstance };
|
|
397
|
+
//# sourceMappingURL=ngneers-controls-base.mjs.map
|