@ngneers/controls 0.0.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/ngneers-controls-accordion.mjs +234 -0
- package/fesm2022/ngneers-controls-accordion.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api-ng.mjs +959 -0
- package/fesm2022/ngneers-controls-api-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api-resize.mjs +712 -0
- package/fesm2022/ngneers-controls-api-resize.mjs.map +1 -0
- package/fesm2022/ngneers-controls-api.mjs +347 -0
- package/fesm2022/ngneers-controls-api.mjs.map +1 -0
- package/fesm2022/ngneers-controls-avatar.mjs +77 -0
- package/fesm2022/ngneers-controls-avatar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-base.mjs +620 -0
- package/fesm2022/ngneers-controls-base.mjs.map +1 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs +100 -0
- package/fesm2022/ngneers-controls-breadcrumb.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button-group.mjs +110 -0
- package/fesm2022/ngneers-controls-button-group.mjs.map +1 -0
- package/fesm2022/ngneers-controls-button.mjs +83 -0
- package/fesm2022/ngneers-controls-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs +74 -0
- package/fesm2022/ngneers-controls-calendar-time-CJT5AFlA.mjs.map +1 -0
- package/fesm2022/ngneers-controls-calendar.mjs +801 -0
- package/fesm2022/ngneers-controls-calendar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-checkbox.mjs +63 -0
- package/fesm2022/ngneers-controls-checkbox.mjs.map +1 -0
- package/fesm2022/ngneers-controls-chip.mjs +55 -0
- package/fesm2022/ngneers-controls-chip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-default-icons.mjs +82 -0
- package/fesm2022/ngneers-controls-default-icons.mjs.map +1 -0
- package/fesm2022/ngneers-controls-defer.mjs +72 -0
- package/fesm2022/ngneers-controls-defer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-dialog.mjs +407 -0
- package/fesm2022/ngneers-controls-dialog.mjs.map +1 -0
- package/fesm2022/ngneers-controls-directives.mjs +498 -0
- package/fesm2022/ngneers-controls-directives.mjs.map +1 -0
- package/fesm2022/ngneers-controls-drawer.mjs +271 -0
- package/fesm2022/ngneers-controls-drawer.mjs.map +1 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs +127 -0
- package/fesm2022/ngneers-controls-edit-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-errors.mjs +329 -0
- package/fesm2022/ngneers-controls-errors.mjs.map +1 -0
- package/fesm2022/ngneers-controls-filter.mjs +708 -0
- package/fesm2022/ngneers-controls-filter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-hint.mjs +153 -0
- package/fesm2022/ngneers-controls-hint.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-translations-de.mjs +170 -0
- package/fesm2022/ngneers-controls-i18n-translations-de.mjs.map +1 -0
- package/fesm2022/ngneers-controls-i18n-translations-en.mjs +170 -0
- package/fesm2022/ngneers-controls-i18n-translations-en.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.mjs +195 -0
- package/fesm2022/ngneers-controls-icon.mjs.map +1 -0
- package/fesm2022/ngneers-controls-inplace.mjs +150 -0
- package/fesm2022/ngneers-controls-inplace.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input-field.mjs +165 -0
- package/fesm2022/ngneers-controls-input-field.mjs.map +1 -0
- package/fesm2022/ngneers-controls-input.mjs +72 -0
- package/fesm2022/ngneers-controls-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-item-view.mjs +473 -0
- package/fesm2022/ngneers-controls-item-view.mjs.map +1 -0
- package/fesm2022/ngneers-controls-list-box.mjs +281 -0
- package/fesm2022/ngneers-controls-list-box.mjs.map +1 -0
- package/fesm2022/ngneers-controls-mask-input.mjs +888 -0
- package/fesm2022/ngneers-controls-mask-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-menu.mjs +371 -0
- package/fesm2022/ngneers-controls-menu.mjs.map +1 -0
- package/fesm2022/ngneers-controls-message.mjs +30 -0
- package/fesm2022/ngneers-controls-message.mjs.map +1 -0
- package/fesm2022/ngneers-controls-number-input.mjs +366 -0
- package/fesm2022/ngneers-controls-number-input.mjs.map +1 -0
- package/fesm2022/ngneers-controls-paginator.mjs +129 -0
- package/fesm2022/ngneers-controls-paginator.mjs.map +1 -0
- package/fesm2022/ngneers-controls-popover.mjs +215 -0
- package/fesm2022/ngneers-controls-popover.mjs.map +1 -0
- package/fesm2022/ngneers-controls-progress.mjs +98 -0
- package/fesm2022/ngneers-controls-progress.mjs.map +1 -0
- package/fesm2022/ngneers-controls-radio.mjs +152 -0
- package/fesm2022/ngneers-controls-radio.mjs.map +1 -0
- package/fesm2022/ngneers-controls-roving-focus.mjs +323 -0
- package/fesm2022/ngneers-controls-roving-focus.mjs.map +1 -0
- package/fesm2022/ngneers-controls-scroll-shadow.mjs +65 -0
- package/fesm2022/ngneers-controls-scroll-shadow.mjs.map +1 -0
- package/fesm2022/ngneers-controls-scroller.mjs +308 -0
- package/fesm2022/ngneers-controls-scroller.mjs.map +1 -0
- package/fesm2022/ngneers-controls-select-button.mjs +58 -0
- package/fesm2022/ngneers-controls-select-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-select.mjs +417 -0
- package/fesm2022/ngneers-controls-select.mjs.map +1 -0
- package/fesm2022/ngneers-controls-slider.mjs +167 -0
- package/fesm2022/ngneers-controls-slider.mjs.map +1 -0
- package/fesm2022/ngneers-controls-snackbar.mjs +414 -0
- package/fesm2022/ngneers-controls-snackbar.mjs.map +1 -0
- package/fesm2022/ngneers-controls-spin-buttons.mjs +126 -0
- package/fesm2022/ngneers-controls-spin-buttons.mjs.map +1 -0
- package/fesm2022/ngneers-controls-spinner.mjs +184 -0
- package/fesm2022/ngneers-controls-spinner.mjs.map +1 -0
- package/fesm2022/ngneers-controls-splitter.mjs +604 -0
- package/fesm2022/ngneers-controls-splitter.mjs.map +1 -0
- package/fesm2022/ngneers-controls-state.mjs +185 -0
- package/fesm2022/ngneers-controls-state.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 +2634 -0
- package/fesm2022/ngneers-controls-table.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tabs.mjs +336 -0
- package/fesm2022/ngneers-controls-tabs.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tag.mjs +30 -0
- package/fesm2022/ngneers-controls-tag.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toast.mjs +350 -0
- package/fesm2022/ngneers-controls-toast.mjs.map +1 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs +70 -0
- package/fesm2022/ngneers-controls-toggle-button.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tooltip.mjs +506 -0
- package/fesm2022/ngneers-controls-tooltip.mjs.map +1 -0
- package/fesm2022/ngneers-controls-tree.mjs +599 -0
- package/fesm2022/ngneers-controls-tree.mjs.map +1 -0
- package/fesm2022/ngneers-controls-upload.mjs +377 -0
- package/fesm2022/ngneers-controls-upload.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs +411 -0
- package/fesm2022/ngneers-controls-utils-ng.mjs.map +1 -0
- package/fesm2022/ngneers-controls-utils.mjs +261 -0
- package/fesm2022/ngneers-controls-utils.mjs.map +1 -0
- package/fesm2022/ngneers-controls.mjs +6 -0
- package/fesm2022/ngneers-controls.mjs.map +1 -0
- package/package.json +302 -0
- package/types/ngneers-controls-accordion.d.ts +139 -0
- package/types/ngneers-controls-api-ng.d.ts +364 -0
- package/types/ngneers-controls-api-resize.d.ts +318 -0
- package/types/ngneers-controls-api.d.ts +145 -0
- package/types/ngneers-controls-avatar.d.ts +54 -0
- package/types/ngneers-controls-base.d.ts +277 -0
- package/types/ngneers-controls-breadcrumb.d.ts +272 -0
- package/types/ngneers-controls-button-group.d.ts +46 -0
- package/types/ngneers-controls-button.d.ts +48 -0
- package/types/ngneers-controls-calendar.d.ts +466 -0
- package/types/ngneers-controls-checkbox.d.ts +40 -0
- package/types/ngneers-controls-chip.d.ts +202 -0
- package/types/ngneers-controls-default-icons.d.ts +5 -0
- package/types/ngneers-controls-defer.d.ts +48 -0
- package/types/ngneers-controls-dialog.d.ts +399 -0
- package/types/ngneers-controls-directives.d.ts +171 -0
- package/types/ngneers-controls-drawer.d.ts +308 -0
- package/types/ngneers-controls-edit-inplace.d.ts +263 -0
- package/types/ngneers-controls-errors.d.ts +155 -0
- package/types/ngneers-controls-filter.d.ts +609 -0
- package/types/ngneers-controls-hint.d.ts +88 -0
- package/types/ngneers-controls-i18n-translations-de.d.ts +164 -0
- package/types/ngneers-controls-i18n-translations-en.d.ts +164 -0
- package/types/ngneers-controls-i18n.d.ts +186 -0
- package/types/ngneers-controls-icon.d.ts +68 -0
- package/types/ngneers-controls-inplace.d.ts +98 -0
- package/types/ngneers-controls-input-field.d.ts +248 -0
- package/types/ngneers-controls-input.d.ts +30 -0
- package/types/ngneers-controls-item-view.d.ts +215 -0
- package/types/ngneers-controls-list-box.d.ts +334 -0
- package/types/ngneers-controls-mask-input.d.ts +434 -0
- package/types/ngneers-controls-menu.d.ts +192 -0
- package/types/ngneers-controls-message.d.ts +21 -0
- package/types/ngneers-controls-number-input.d.ts +146 -0
- package/types/ngneers-controls-paginator.d.ts +255 -0
- package/types/ngneers-controls-popover.d.ts +116 -0
- package/types/ngneers-controls-progress.d.ts +49 -0
- package/types/ngneers-controls-radio.d.ts +91 -0
- package/types/ngneers-controls-roving-focus.d.ts +107 -0
- package/types/ngneers-controls-scroll-shadow.d.ts +25 -0
- package/types/ngneers-controls-scroller.d.ts +151 -0
- package/types/ngneers-controls-select-button.d.ts +51 -0
- package/types/ngneers-controls-select.d.ts +409 -0
- package/types/ngneers-controls-slider.d.ts +57 -0
- package/types/ngneers-controls-snackbar.d.ts +330 -0
- package/types/ngneers-controls-spin-buttons.d.ts +69 -0
- package/types/ngneers-controls-spinner.d.ts +117 -0
- package/types/ngneers-controls-splitter.d.ts +465 -0
- package/types/ngneers-controls-state.d.ts +102 -0
- package/types/ngneers-controls-switch.d.ts +18 -0
- package/types/ngneers-controls-table.d.ts +3127 -0
- package/types/ngneers-controls-tabs.d.ts +118 -0
- package/types/ngneers-controls-tag.d.ts +21 -0
- package/types/ngneers-controls-toast.d.ts +298 -0
- package/types/ngneers-controls-toggle-button.d.ts +48 -0
- package/types/ngneers-controls-tooltip.d.ts +189 -0
- package/types/ngneers-controls-tree.d.ts +409 -0
- package/types/ngneers-controls-upload.d.ts +347 -0
- package/types/ngneers-controls-utils-ng.d.ts +129 -0
- package/types/ngneers-controls-utils.d.ts +130 -0
- package/types/ngneers-controls.d.ts +2 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-inplace.mjs","sources":["../../src/inplace/inplace-templates.ts","../../src/inplace/inplace.ts","../../src/inplace/inplace.html","../../src/inplace/ngneers-controls-inplace.ts"],"sourcesContent":["import { computed, contentChild, Directive, input, TemplateRef } from '@angular/core';\nimport { templateTypesFn } from '@ngneers/controls/api/ng';\nimport { NgnBase } from '@ngneers/controls/base';\n\nimport type { ContentTemplateType } from './types';\n\n@Directive()\nexport abstract class InplaceTemplates extends NgnBase<'inplace'> {\n // Display template\n private readonly _userDisplayTemplate = contentChild<TemplateRef<unknown>>('display');\n /**\n * Set a custom template for the display.\n * Can also be set using an `<ng-template>` element with `#display` template reference variable.\n */\n public readonly templateDisplay = input<TemplateRef<unknown> | null>(null);\n protected readonly displayTemplate = computed(\n () => this._userDisplayTemplate() ?? this.templateDisplay()\n );\n /**\n * Context for the display template.\n */\n public readonly templateDisplayContext = input<unknown>();\n\n // Content template\n private readonly _userContentTemplate =\n contentChild<TemplateRef<typeof this.templateTypes.content>>('content');\n /**\n * Set a custom template for the content.\n * Can also be set using an `<ng-template>` element with `#content` template reference variable.\n */\n public readonly templateContent = input<TemplateRef<typeof this.templateTypes.content> | null>(\n null\n );\n protected readonly contentTemplate = computed(\n () => this._userContentTemplate() ?? this.templateContent()\n );\n /**\n * Context for the content template.\n */\n public readonly templateContentContext = input<unknown>();\n\n /**\n * Types for the inplace templates.\n */\n public readonly templateTypes = templateTypesFn<{\n /**\n * Type of the template variable for the content template.\n */\n content: ContentTemplateType;\n }>();\n}\n","import { NgTemplateOutlet } from '@angular/common';\nimport {\n afterRenderEffect,\n booleanAttribute,\n Component,\n type ElementRef,\n input,\n model,\n viewChild,\n} from '@angular/core';\nimport { NgnPt, provideSelf } from '@ngneers/controls/base';\nimport { NgnDefer } from '@ngneers/controls/defer';\nimport { signalWithPrevious } from '@ngneers/controls/utils-ng';\nimport { inplaceControlTemplate } from '@ngneers/controls-themes/templates/inplace';\n\nimport { InplaceTemplates } from './inplace-templates';\n\n/**\n * @category control\n */\n@Component({\n selector: 'ngn-inplace',\n templateUrl: './inplace.html',\n imports: [NgnPt, NgTemplateOutlet, NgnDefer],\n providers: [provideSelf(NgnInplace)],\n})\nexport class NgnInplace extends InplaceTemplates {\n protected readonly theme = this.injectThemeTemplate(inplaceControlTemplate, {\n root: true,\n disabled: () => this.disabled(),\n });\n\n protected readonly closeContent = this.switchToDisplay.bind(this);\n\n private readonly _displayTrigger = viewChild<ElementRef<HTMLButtonElement>>('displayTrigger');\n private readonly _contentRef = viewChild<ElementRef<HTMLElement>>('contentRef');\n\n constructor() {\n super();\n // `contentVisible` is declared below; its field initializer has already run by\n // the time this constructor body executes, so it is safe to read here.\n const contentVisibleWithPrevious = signalWithPrevious(this.contentVisible);\n // Keep focus with the user across the display↔content swap — the outgoing view\n // is unmounted, which would otherwise drop focus to the document body. Both\n // directions only act when focus WAS dropped to the body, never when the content\n // (or something else on the page) already claimed it — so a content control that\n // autofocuses itself (e.g. edit-inplace's input) keeps focus. Runs after render\n // so the target element exists.\n afterRenderEffect(() => {\n const { current: visible, previous } = contentVisibleWithPrevious();\n const doc = this.element.nativeElement.ownerDocument;\n const active = doc.activeElement;\n const droppedToBody = active === null || active === doc.body;\n if (!droppedToBody) {\n return;\n }\n if (visible && previous === false) {\n // Opened: move focus into the content region so it is not stranded.\n this._contentRef()?.nativeElement.focus();\n } else if (!visible && previous === true) {\n // Closed: return focus to the display trigger.\n this._displayTrigger()?.nativeElement.focus();\n }\n });\n }\n\n /**\n * Controls the visibility of the content.\n */\n public readonly contentVisible = model<boolean>(false);\n /**\n * Whether the content is loaded lazily.\n * @default true\n */\n public readonly lazy = input(true, { transform: booleanAttribute });\n /**\n * Whether the content is cached when closed.\n * @default false\n */\n public readonly cache = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply disabled state styling\n * @default false\n */\n public readonly disabled = input(false, { transform: booleanAttribute });\n\n /**\n * Switches to the content view.\n */\n public switchToContent() {\n if (this.disabled()) {\n return;\n }\n this.contentVisible.set(true);\n }\n\n /**\n * Switches to the display view.\n */\n public switchToDisplay() {\n this.contentVisible.set(false);\n }\n\n /**\n * Toggles between the display and content views.\n */\n public toggle() {\n this.contentVisible.update(v => !v);\n }\n}\n","@if (contentVisible()) {\n <div #contentRef tabindex=\"-1\" [ptInt]=\"this\" [ptClass]=\"'content'\">\n <ngn-defer\n [open]=\"contentVisible()\"\n [lazyContent]=\"contentTemplate()\"\n [lazyContentContext]=\"templateContentContext() ?? { $implicit: { close: closeContent } }\"\n [lazy]=\"lazy()\"\n [cache]=\"cache()\"\n />\n </div>\n} @else {\n <button\n #displayTrigger\n type=\"button\"\n [ptInt]=\"this\"\n [ptClass]=\"'display'\"\n (click)=\"switchToContent()\"\n >\n <ng-container\n [ngTemplateOutlet]=\"displayTemplate()\"\n [ngTemplateOutletContext]=\"templateDisplayContext()\"\n />\n </button>\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, input, booleanAttribute, contentChildren, computed, effect, Component } from '@angular/core';
|
|
3
|
+
import { NgnBase, NGN_CONTROL, NgnPt, provideSelf } from '@ngneers/controls/base';
|
|
4
|
+
import { NgnButton } from '@ngneers/controls/button';
|
|
5
|
+
import { I18n } from '@ngneers/controls/i18n';
|
|
6
|
+
import { NgnIcon } from '@ngneers/controls/icon';
|
|
7
|
+
import { generateElementId } from '@ngneers/controls/utils-ng';
|
|
8
|
+
import { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/input-field';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @category control
|
|
12
|
+
*/
|
|
13
|
+
class NgnInputField extends NgnBase {
|
|
14
|
+
theme = this.injectThemeTemplate(inputFieldControlTemplate, 'host');
|
|
15
|
+
i18n = inject(I18n).translations;
|
|
16
|
+
/**
|
|
17
|
+
* Label for the input field
|
|
18
|
+
* @default null
|
|
19
|
+
*/
|
|
20
|
+
label = input(null, /* @ts-ignore */
|
|
21
|
+
...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
22
|
+
/**
|
|
23
|
+
* Sets the `aria-labelledby` attribute on the input element
|
|
24
|
+
* @default null
|
|
25
|
+
*/
|
|
26
|
+
labelledBy = input(null, /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "labelledBy" }] : /* istanbul ignore next */ []));
|
|
28
|
+
/**
|
|
29
|
+
* The kind of label presentation
|
|
30
|
+
* @todo add link to custom kind documentation subsection label
|
|
31
|
+
* @default undefined
|
|
32
|
+
*/
|
|
33
|
+
labelKind = input(undefined, /* @ts-ignore */
|
|
34
|
+
...(ngDevMode ? [{ debugName: "labelKind" }] : /* istanbul ignore next */ []));
|
|
35
|
+
/**
|
|
36
|
+
* ID for the input element. Defaults to a generated id.
|
|
37
|
+
*/
|
|
38
|
+
inputId = input(generateElementId(), /* @ts-ignore */
|
|
39
|
+
...(ngDevMode ? [{ debugName: "inputId" }] : /* istanbul ignore next */ []));
|
|
40
|
+
/**
|
|
41
|
+
* Show clear button
|
|
42
|
+
* @default false
|
|
43
|
+
*/
|
|
44
|
+
showClearButton = input(false, { ...(ngDevMode ? { debugName: "showClearButton" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
45
|
+
/**
|
|
46
|
+
* Custom icon for the clear button. Use with {@link showClearButton}.
|
|
47
|
+
* @default undefined
|
|
48
|
+
*/
|
|
49
|
+
iconClearButton = input(/* @ts-ignore */
|
|
50
|
+
...(ngDevMode ? [undefined, { debugName: "iconClearButton" }] : /* istanbul ignore next */ []));
|
|
51
|
+
/**
|
|
52
|
+
* Tabindex for the input field itself.
|
|
53
|
+
* When another focusable (input) element is present inside the input field, this should be set to -1.
|
|
54
|
+
* @default -1
|
|
55
|
+
*/
|
|
56
|
+
tabindex = input(-1, /* @ts-ignore */
|
|
57
|
+
...(ngDevMode ? [{ debugName: "tabindex" }] : /* istanbul ignore next */ []));
|
|
58
|
+
/**
|
|
59
|
+
* Explicitly apply invalid state styling
|
|
60
|
+
* @default false
|
|
61
|
+
*/
|
|
62
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
63
|
+
/**
|
|
64
|
+
* Explicitly apply readonly state styling
|
|
65
|
+
* @default false
|
|
66
|
+
*/
|
|
67
|
+
readonly = input(false, { ...(ngDevMode ? { debugName: "readonly" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
68
|
+
/**
|
|
69
|
+
* Explicitly apply disabled state styling
|
|
70
|
+
* @default false
|
|
71
|
+
*/
|
|
72
|
+
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
73
|
+
_projectedControls = contentChildren(NGN_CONTROL, { ...(ngDevMode ? { debugName: "_projectedControls" } : /* istanbul ignore next */ {}), descendants: true });
|
|
74
|
+
/**
|
|
75
|
+
* The projected primary control (input, mask, calendar, …), used to delegate
|
|
76
|
+
* pointer focus, clearing and stepping. Auxiliary controls inside the field
|
|
77
|
+
* (buttons, icons, spin buttons, …) are skipped via `isFieldControl`, so
|
|
78
|
+
* their placement/order never shadows the actual input.
|
|
79
|
+
*/
|
|
80
|
+
control = computed(() => this._projectedControls().find(c => c.isFieldControl), /* @ts-ignore */
|
|
81
|
+
...(ngDevMode ? [{ debugName: "control" }] : /* istanbul ignore next */ []));
|
|
82
|
+
/** The primary control's element when it is a native input/textarea. */
|
|
83
|
+
_inputElement = computed(() => {
|
|
84
|
+
const el = this.control()?.element.nativeElement;
|
|
85
|
+
return el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')
|
|
86
|
+
? el
|
|
87
|
+
: undefined;
|
|
88
|
+
}, /* @ts-ignore */
|
|
89
|
+
...(ngDevMode ? [{ debugName: "_inputElement" }] : /* istanbul ignore next */ []));
|
|
90
|
+
constructor() {
|
|
91
|
+
super();
|
|
92
|
+
this.initializeAutoThemeClasses('labelKind', this.labelKind);
|
|
93
|
+
effect(() => {
|
|
94
|
+
const inputElement = this._inputElement();
|
|
95
|
+
if (!inputElement) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
inputElement.id = this.inputId();
|
|
99
|
+
});
|
|
100
|
+
effect(() => {
|
|
101
|
+
const inputElement = this._inputElement();
|
|
102
|
+
if (!inputElement) {
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
const labelledBy = this.labelledBy();
|
|
106
|
+
inputElement.setAttribute('aria-labelledby', labelledBy ?? '');
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
clicked(event) {
|
|
110
|
+
// Give the projected control a chance to place focus from the pointer
|
|
111
|
+
// location (e.g. mask-input selects the section nearest the click). If it
|
|
112
|
+
// handles the event, skip the primitive focusing below.
|
|
113
|
+
if (this.control()?.focusFromPointer(event))
|
|
114
|
+
return;
|
|
115
|
+
if (!(event.target instanceof Node))
|
|
116
|
+
return;
|
|
117
|
+
const root = this.element.nativeElement;
|
|
118
|
+
const targetElement = event.target instanceof Element ? event.target : null;
|
|
119
|
+
// Controls that open/toggle on click (select combobox, calendar field) expose
|
|
120
|
+
// their interactive host as the focusable element (tabindex="0") -> redirect click there.
|
|
121
|
+
const focusable = root.querySelector('[tabindex="0"]');
|
|
122
|
+
if (focusable && !focusable.contains(event.target)) {
|
|
123
|
+
focusable.click();
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Keep real projected actions (buttons, links, explicit tab stops) in charge of their own click.
|
|
127
|
+
const interactiveTarget = targetElement?.closest('button, a[href], select, [role="button"], [tabindex]:not([tabindex="-1"])');
|
|
128
|
+
if (interactiveTarget && root.contains(interactiveTarget)) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// Plain input fields: clicking the field chrome or non-interactive adornments should focus
|
|
132
|
+
// the actual input, even when the pointer target is SVG content inside an icon/state control.
|
|
133
|
+
this._inputElement()?.focus();
|
|
134
|
+
}
|
|
135
|
+
clearButtonClicked(event) {
|
|
136
|
+
event.stopPropagation();
|
|
137
|
+
// Controls that manage their own value (e.g. mask-input) clear via the hook;
|
|
138
|
+
// the DOM fallback below only works for plain text inputs.
|
|
139
|
+
if (this.control()?.clearValue()) {
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
const inputElement = this.element.nativeElement.querySelector('input, textarea');
|
|
143
|
+
if (inputElement) {
|
|
144
|
+
inputElement.value = '';
|
|
145
|
+
inputElement.dispatchEvent(new Event('input', { bubbles: true }));
|
|
146
|
+
inputElement.dispatchEvent(new Event('change', { bubbles: true }));
|
|
147
|
+
inputElement.focus();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInputField, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
151
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.5", type: NgnInputField, isStandalone: true, selector: "ngn-input-field", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelledBy: { classPropertyName: "labelledBy", publicName: "labelledBy", isSignal: true, isRequired: false, transformFunction: null }, labelKind: { classPropertyName: "labelKind", publicName: "labelKind", isSignal: true, isRequired: false, transformFunction: null }, inputId: { classPropertyName: "inputId", publicName: "inputId", isSignal: true, isRequired: false, transformFunction: null }, showClearButton: { classPropertyName: "showClearButton", publicName: "showClearButton", isSignal: true, isRequired: false, transformFunction: null }, iconClearButton: { classPropertyName: "iconClearButton", publicName: "iconClearButton", isSignal: true, isRequired: false, transformFunction: null }, tabindex: { classPropertyName: "tabindex", publicName: "tabindex", isSignal: true, isRequired: false, transformFunction: null }, invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, readonly: { classPropertyName: "readonly", publicName: "readonly", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "inert": "disabled()" } }, providers: [provideSelf(NgnInputField)], queries: [{ propertyName: "_projectedControls", predicate: NGN_CONTROL, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (label(); as label) {\n <label [ptInt]=\"this\" [ptClass]=\"'label'\" [for]=\"inputId()\">{{ label }}</label>\n}\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n [ptInt]=\"this\"\n [ptClass]=\"{\n root: true,\n invalid: invalid(),\n readonly: readonly(),\n disabled: disabled(),\n }\"\n (click)=\"clicked($event)\"\n [tabindex]=\"tabindex()\"\n>\n <ng-content select=\"input, textarea\" />\n @if (showClearButton()) {\n <button\n tabindex=\"-1\"\n [ptInt]=\"this\"\n [ptClass]=\"'clear-button'\"\n ngnButton\n type=\"button\"\n [kind]=\"'icon'\"\n ngnButtonInline\n (click)=\"clearButtonClicked($event)\"\n [attr.aria-label]=\"i18n['inputField_clearInput']()\"\n >\n <ngn-icon defaultIcon=\"input-clear\" [icon]=\"iconClearButton()\" />\n </button>\n }\n <ng-content />\n</div>\n", dependencies: [{ kind: "directive", type: NgnPt, selector: "[ptInt]", inputs: ["ptInt", "ptClass", "ptDep"] }, { kind: "component", type: NgnIcon, selector: "ngn-icon", inputs: ["defaultIcon", "icon"] }, { kind: "directive", type: NgnButton, selector: "button[ngnButton], a[ngnButton]", inputs: ["ngnButtonInline"], exportAs: ["ngnButton"] }] });
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInputField, decorators: [{
|
|
154
|
+
type: Component,
|
|
155
|
+
args: [{ imports: [NgnPt, NgnIcon, NgnButton], selector: 'ngn-input-field', host: {
|
|
156
|
+
'[inert]': 'disabled()',
|
|
157
|
+
}, providers: [provideSelf(NgnInputField)], template: "@if (label(); as label) {\n <label [ptInt]=\"this\" [ptClass]=\"'label'\" [for]=\"inputId()\">{{ label }}</label>\n}\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n [ptInt]=\"this\"\n [ptClass]=\"{\n root: true,\n invalid: invalid(),\n readonly: readonly(),\n disabled: disabled(),\n }\"\n (click)=\"clicked($event)\"\n [tabindex]=\"tabindex()\"\n>\n <ng-content select=\"input, textarea\" />\n @if (showClearButton()) {\n <button\n tabindex=\"-1\"\n [ptInt]=\"this\"\n [ptClass]=\"'clear-button'\"\n ngnButton\n type=\"button\"\n [kind]=\"'icon'\"\n ngnButtonInline\n (click)=\"clearButtonClicked($event)\"\n [attr.aria-label]=\"i18n['inputField_clearInput']()\"\n >\n <ngn-icon defaultIcon=\"input-clear\" [icon]=\"iconClearButton()\" />\n </button>\n }\n <ng-content />\n</div>\n" }]
|
|
158
|
+
}], ctorParameters: () => [], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], labelledBy: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelledBy", required: false }] }], labelKind: [{ type: i0.Input, args: [{ isSignal: true, alias: "labelKind", required: false }] }], inputId: [{ type: i0.Input, args: [{ isSignal: true, alias: "inputId", required: false }] }], showClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "showClearButton", required: false }] }], iconClearButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "iconClearButton", required: false }] }], tabindex: [{ type: i0.Input, args: [{ isSignal: true, alias: "tabindex", required: false }] }], invalid: [{ type: i0.Input, args: [{ isSignal: true, alias: "invalid", required: false }] }], readonly: [{ type: i0.Input, args: [{ isSignal: true, alias: "readonly", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], _projectedControls: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => NGN_CONTROL), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Generated bundle index. Do not edit.
|
|
162
|
+
*/
|
|
163
|
+
|
|
164
|
+
export { NgnInputField };
|
|
165
|
+
//# sourceMappingURL=ngneers-controls-input-field.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-input-field.mjs","sources":["../../src/input-field/input-field.ts","../../src/input-field/input-field.html","../../src/input-field/ngneers-controls-input-field.ts"],"sourcesContent":["import {\n booleanAttribute,\n Component,\n computed,\n contentChildren,\n effect,\n inject,\n input,\n} from '@angular/core';\nimport { NgnBase, NGN_CONTROL, provideSelf, NgnPt } from '@ngneers/controls/base';\nimport { NgnButton } from '@ngneers/controls/button';\nimport { I18n } from '@ngneers/controls/i18n';\nimport { NgnIcon } from '@ngneers/controls/icon';\nimport { generateElementId } from '@ngneers/controls/utils-ng';\nimport { inputFieldControlTemplate } from '@ngneers/controls-themes/templates/input-field';\n\nimport type { CustomKind, IconType } from '@ngneers/controls-custom-types';\n\n/**\n * @category control\n */\n@Component({\n imports: [NgnPt, NgnIcon, NgnButton],\n selector: 'ngn-input-field',\n templateUrl: './input-field.html',\n host: {\n '[inert]': 'disabled()',\n },\n providers: [provideSelf(NgnInputField)],\n})\nexport class NgnInputField extends NgnBase<'inputField'> {\n protected readonly theme = this.injectThemeTemplate(inputFieldControlTemplate, 'host');\n protected readonly i18n = inject(I18n).translations;\n\n /**\n * Label for the input field\n * @default null\n */\n public readonly label = input<string | null>(null);\n /**\n * Sets the `aria-labelledby` attribute on the input element\n * @default null\n */\n public readonly labelledBy = input<string | null>(null);\n /**\n * The kind of label presentation\n * @todo add link to custom kind documentation subsection label\n * @default undefined\n */\n public readonly labelKind = input<CustomKind<'inputFieldLabel'>>(undefined as never);\n /**\n * ID for the input element. Defaults to a generated id.\n */\n public readonly inputId = input<string>(generateElementId());\n /**\n * Show clear button\n * @default false\n */\n public readonly showClearButton = input(false, { transform: booleanAttribute });\n /**\n * Custom icon for the clear button. Use with {@link showClearButton}.\n * @default undefined\n */\n public readonly iconClearButton = input<IconType>();\n /**\n * Tabindex for the input field itself.\n * When another focusable (input) element is present inside the input field, this should be set to -1.\n * @default -1\n */\n public readonly tabindex = input<number>(-1);\n /**\n * Explicitly apply invalid state styling\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply readonly state styling\n * @default false\n */\n public readonly readonly = input(false, { transform: booleanAttribute });\n /**\n * Explicitly apply disabled state styling\n * @default false\n */\n public readonly disabled = input(false, { transform: booleanAttribute });\n\n private readonly _projectedControls = contentChildren(NGN_CONTROL, { descendants: true });\n /**\n * The projected primary control (input, mask, calendar, …), used to delegate\n * pointer focus, clearing and stepping. Auxiliary controls inside the field\n * (buttons, icons, spin buttons, …) are skipped via `isFieldControl`, so\n * their placement/order never shadows the actual input.\n */\n public readonly control = computed(() => this._projectedControls().find(c => c.isFieldControl));\n\n /** The primary control's element when it is a native input/textarea. */\n private readonly _inputElement = computed(() => {\n const el = this.control()?.element.nativeElement;\n return el && (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA')\n ? (el as HTMLInputElement | HTMLTextAreaElement)\n : undefined;\n });\n\n constructor() {\n super();\n this.initializeAutoThemeClasses('labelKind', this.labelKind);\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n inputElement.id = this.inputId();\n });\n effect(() => {\n const inputElement = this._inputElement();\n if (!inputElement) {\n return;\n }\n const labelledBy = this.labelledBy();\n inputElement.setAttribute('aria-labelledby', labelledBy ?? '');\n });\n }\n\n protected clicked(event: MouseEvent) {\n // Give the projected control a chance to place focus from the pointer\n // location (e.g. mask-input selects the section nearest the click). If it\n // handles the event, skip the primitive focusing below.\n if (this.control()?.focusFromPointer(event)) return;\n\n if (!(event.target instanceof Node)) return;\n\n const root = this.element.nativeElement;\n const targetElement = event.target instanceof Element ? event.target : null;\n\n // Controls that open/toggle on click (select combobox, calendar field) expose\n // their interactive host as the focusable element (tabindex=\"0\") -> redirect click there.\n const focusable = root.querySelector<HTMLElement>('[tabindex=\"0\"]');\n if (focusable && !focusable.contains(event.target)) {\n focusable.click();\n return;\n }\n\n // Keep real projected actions (buttons, links, explicit tab stops) in charge of their own click.\n const interactiveTarget = targetElement?.closest(\n 'button, a[href], select, [role=\"button\"], [tabindex]:not([tabindex=\"-1\"])'\n );\n if (interactiveTarget && root.contains(interactiveTarget)) {\n return;\n }\n\n // Plain input fields: clicking the field chrome or non-interactive adornments should focus\n // the actual input, even when the pointer target is SVG content inside an icon/state control.\n this._inputElement()?.focus();\n }\n\n protected clearButtonClicked(event: MouseEvent) {\n event.stopPropagation();\n // Controls that manage their own value (e.g. mask-input) clear via the hook;\n // the DOM fallback below only works for plain text inputs.\n if (this.control()?.clearValue()) {\n return;\n }\n const inputElement = this.element.nativeElement.querySelector('input, textarea');\n if (inputElement) {\n (inputElement as HTMLInputElement | HTMLTextAreaElement).value = '';\n inputElement.dispatchEvent(new Event('input', { bubbles: true }));\n inputElement.dispatchEvent(new Event('change', { bubbles: true }));\n (inputElement as HTMLInputElement | HTMLTextAreaElement).focus();\n }\n }\n}\n","@if (label(); as label) {\n <label [ptInt]=\"this\" [ptClass]=\"'label'\" [for]=\"inputId()\">{{ label }}</label>\n}\n<!-- eslint-disable-next-line @angular-eslint/template/click-events-have-key-events -->\n<div\n [ptInt]=\"this\"\n [ptClass]=\"{\n root: true,\n invalid: invalid(),\n readonly: readonly(),\n disabled: disabled(),\n }\"\n (click)=\"clicked($event)\"\n [tabindex]=\"tabindex()\"\n>\n <ng-content select=\"input, textarea\" />\n @if (showClearButton()) {\n <button\n tabindex=\"-1\"\n [ptInt]=\"this\"\n [ptClass]=\"'clear-button'\"\n ngnButton\n type=\"button\"\n [kind]=\"'icon'\"\n ngnButtonInline\n (click)=\"clearButtonClicked($event)\"\n [attr.aria-label]=\"i18n['inputField_clearInput']()\"\n >\n <ngn-icon defaultIcon=\"input-clear\" [icon]=\"iconClearButton()\" />\n </button>\n }\n <ng-content />\n</div>\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { input, booleanAttribute, model, runInInjectionContext, effect, Directive } from '@angular/core';
|
|
3
|
+
import { domEventSignal } from '@ngneers/controls/api/ng';
|
|
4
|
+
import { NgnBase, provideSelf } from '@ngneers/controls/base';
|
|
5
|
+
import { inputControlTemplate } from '@ngneers/controls-themes/templates/input';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @category control
|
|
9
|
+
*/
|
|
10
|
+
class NgnInput extends NgnBase {
|
|
11
|
+
isFieldControl = true;
|
|
12
|
+
theme = this.injectThemeTemplate(inputControlTemplate, {
|
|
13
|
+
root: true,
|
|
14
|
+
invalid: () => this.invalid(),
|
|
15
|
+
empty: () => !this.value(),
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Explicitly apply invalid state styling
|
|
19
|
+
* @default false
|
|
20
|
+
*/
|
|
21
|
+
invalid = input(false, { ...(ngDevMode ? { debugName: "invalid" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
22
|
+
/**
|
|
23
|
+
* The current value of the input, kept in sync with the native element in both directions.
|
|
24
|
+
* @default ''
|
|
25
|
+
*/
|
|
26
|
+
value = model('', /* @ts-ignore */
|
|
27
|
+
...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
28
|
+
_input = this.element.nativeElement;
|
|
29
|
+
ngAfterViewInit() {
|
|
30
|
+
const changeEvent = domEventSignal(this.element.nativeElement, 'change', this.injector);
|
|
31
|
+
const inputEvent = domEventSignal(this.element.nativeElement, 'input', this.injector);
|
|
32
|
+
runInInjectionContext(this.injector, () => {
|
|
33
|
+
effect(() => {
|
|
34
|
+
const _changeEvent = changeEvent();
|
|
35
|
+
const _inputEvent = inputEvent();
|
|
36
|
+
if (!_changeEvent && !_inputEvent) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const val = this._input.value;
|
|
40
|
+
this.value.set(val ?? '');
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
constructor() {
|
|
45
|
+
super();
|
|
46
|
+
effect(() => {
|
|
47
|
+
if (this._input.value !== this.value()) {
|
|
48
|
+
this._input.value = this.value() || '';
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInput, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
53
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "22.0.5", type: NgnInput, isStandalone: true, selector: "input[ngnInput], textarea[ngnInput]", inputs: { invalid: { classPropertyName: "invalid", publicName: "invalid", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange" }, host: { properties: { "attr.aria-invalid": "invalid() ? \"true\" : null" } }, providers: [provideSelf(NgnInput)], exportAs: ["ngnInput"], usesInheritance: true, ngImport: i0 });
|
|
54
|
+
}
|
|
55
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.5", ngImport: i0, type: NgnInput, decorators: [{
|
|
56
|
+
type: Directive,
|
|
57
|
+
args: [{
|
|
58
|
+
selector: 'input[ngnInput], textarea[ngnInput]',
|
|
59
|
+
providers: [provideSelf(NgnInput)],
|
|
60
|
+
exportAs: 'ngnInput',
|
|
61
|
+
host: {
|
|
62
|
+
'[attr.aria-invalid]': 'invalid() ? "true" : null',
|
|
63
|
+
},
|
|
64
|
+
}]
|
|
65
|
+
}], ctorParameters: () => [], propDecorators: { 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"] }] } });
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Generated bundle index. Do not edit.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
export { NgnInput };
|
|
72
|
+
//# sourceMappingURL=ngneers-controls-input.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ngneers-controls-input.mjs","sources":["../../src/input/input.ts","../../src/input/ngneers-controls-input.ts"],"sourcesContent":["import {\n type AfterViewInit,\n booleanAttribute,\n Directive,\n effect,\n input,\n model,\n runInInjectionContext,\n} from '@angular/core';\nimport { domEventSignal } from '@ngneers/controls/api/ng';\nimport { NgnBase, provideSelf } from '@ngneers/controls/base';\nimport { inputControlTemplate } from '@ngneers/controls-themes/templates/input';\n\n/**\n * @category control\n */\n@Directive({\n selector: 'input[ngnInput], textarea[ngnInput]',\n providers: [provideSelf(NgnInput)],\n exportAs: 'ngnInput',\n host: {\n '[attr.aria-invalid]': 'invalid() ? \"true\" : null',\n },\n})\nexport class NgnInput extends NgnBase<'input'> implements AfterViewInit {\n public override readonly isFieldControl = true;\n protected readonly theme = this.injectThemeTemplate(inputControlTemplate, {\n root: true,\n invalid: () => this.invalid(),\n empty: () => !this.value(),\n });\n /**\n * Explicitly apply invalid state styling\n * @default false\n */\n public readonly invalid = input(false, { transform: booleanAttribute });\n\n /**\n * The current value of the input, kept in sync with the native element in both directions.\n * @default ''\n */\n public readonly value = model<string | null>('');\n\n private readonly _input = this.element.nativeElement as HTMLInputElement;\n\n public ngAfterViewInit() {\n const changeEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'change',\n this.injector\n );\n const inputEvent = domEventSignal(\n this.element.nativeElement as HTMLInputElement,\n 'input',\n this.injector\n );\n\n runInInjectionContext(this.injector, () => {\n effect(() => {\n const _changeEvent = changeEvent();\n const _inputEvent = inputEvent();\n if (!_changeEvent && !_inputEvent) {\n return;\n }\n const val = this._input.value;\n this.value.set(val ?? '');\n });\n });\n }\n\n constructor() {\n super();\n effect(() => {\n if (this._input.value !== this.value()) {\n this._input.value = this.value() || '';\n }\n });\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;;;;;AAaA;;AAEG;AASG,MAAO,QAAS,SAAQ,OAAgB,CAAA;IACnB,cAAc,GAAG,IAAI;AAC3B,IAAA,KAAK,GAAG,IAAI,CAAC,mBAAmB,CAAC,oBAAoB,EAAE;AACxE,QAAA,IAAI,EAAE,IAAI;AACV,QAAA,OAAO,EAAE,MAAM,IAAI,CAAC,OAAO,EAAE;QAC7B,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE;AAC3B,KAAA,CAAC;AACF;;;AAGG;IACa,OAAO,GAAG,KAAK,CAAC,KAAK,+EAAI,SAAS,EAAE,gBAAgB,EAAA,CAAG;AAEvE;;;AAGG;IACa,KAAK,GAAG,KAAK,CAAgB,EAAE;8EAAC;AAE/B,IAAA,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,aAAiC;IAEjE,eAAe,GAAA;AACpB,QAAA,MAAM,WAAW,GAAG,cAAc,CAChC,IAAI,CAAC,OAAO,CAAC,aAAiC,EAC9C,QAAQ,EACR,IAAI,CAAC,QAAQ,CACd;AACD,QAAA,MAAM,UAAU,GAAG,cAAc,CAC/B,IAAI,CAAC,OAAO,CAAC,aAAiC,EAC9C,OAAO,EACP,IAAI,CAAC,QAAQ,CACd;AAED,QAAA,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAK;YACxC,MAAM,CAAC,MAAK;AACV,gBAAA,MAAM,YAAY,GAAG,WAAW,EAAE;AAClC,gBAAA,MAAM,WAAW,GAAG,UAAU,EAAE;AAChC,gBAAA,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE;oBACjC;gBACF;AACA,gBAAA,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK;gBAC7B,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC;AAC3B,YAAA,CAAC,CAAC;AACJ,QAAA,CAAC,CAAC;IACJ;AAEA,IAAA,WAAA,GAAA;AACE,QAAA,KAAK,EAAE;QACP,MAAM,CAAC,MAAK;YACV,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,EAAE;gBACtC,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE;YACxC;AACF,QAAA,CAAC,CAAC;IACJ;uGArDW,QAAQ,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA;AAAR,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,QAAA,EAAA,IAAA,EAAA,QAAQ,qcANR,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,EAAA,QAAA,EAAA,CAAA,UAAA,CAAA,EAAA,eAAA,EAAA,IAAA,EAAA,QAAA,EAAA,EAAA,EAAA,CAAA;;2FAMvB,QAAQ,EAAA,UAAA,EAAA,CAAA;kBARpB,SAAS;AAAC,YAAA,IAAA,EAAA,CAAA;AACT,oBAAA,QAAQ,EAAE,qCAAqC;AAC/C,oBAAA,SAAS,EAAE,CAAC,WAAW,CAAA,QAAA,CAAU,CAAC;AAClC,oBAAA,QAAQ,EAAE,UAAU;AACpB,oBAAA,IAAI,EAAE;AACJ,wBAAA,qBAAqB,EAAE,2BAA2B;AACnD,qBAAA;AACF,iBAAA;;;ACvBD;;AAEG;;;;"}
|