npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@libs-ui/components-inputs-input

v0.2.357-4

Published

> Universal input component hỗ trợ text, number, textarea và iframe-textarea với validation, formatting và customization đầy đủ.

Readme

@libs-ui/components-inputs-input

Universal input component hỗ trợ text, number, textarea và iframe-textarea với validation, formatting và customization đầy đủ.

Giới thiệu

LibsUiComponentsInputsInputComponent là Angular standalone component đa năng cho việc nhập liệu. Component hỗ trợ 4 kiểu dữ liệu (string, int, float, bigint), 3 loại tag (input, textarea, iframe-textarea), tự động format number theo locale (VI/EN), auto-resize textarea, và cung cấp API điều khiển ngoài qua FunctionsControl. Tích hợp sẵn OnPush Change Detection và Angular Signals.

Tính năng

  • ✅ Hỗ trợ 4 kiểu dữ liệu: string, int, float, bigint
  • ✅ Hỗ trợ 3 loại tag: input, textarea, iframe-textarea
  • ✅ Tự động format number theo ngôn ngữ (VI dùng . phân cách nghìn, EN dùng ,)
  • ✅ Auto-resize textarea theo nội dung (min/max height có thể cấu hình)
  • ✅ Validation min/max value cho number input
  • ✅ Hiển thị character count (showCount)
  • ✅ Icon left/right kèm popover tooltip
  • ✅ Template slot tùy chỉnh dưới input (trái/phải)
  • ✅ Nút tăng/giảm (up/down) cho number input
  • ✅ Drag & drop file vào input
  • ✅ Điều khiển từ bên ngoài qua FunctionsControl (focus, blur, insert, reset, selectAll)
  • iframe-textarea: cô lập CSS toàn cục, style riêng qua iframeTextareaCustomStyle
  • ✅ OnPush Change Detection + Angular Signals

Khi nào sử dụng

  • Cần input field cơ bản cho text hoặc number
  • Cần textarea tự động co giãn theo nội dung
  • Cần format number theo locale VI/EN
  • Cần validation min/max cho number input
  • Cần hiển thị số ký tự đã nhập
  • Cần custom icon trái/phải với popover tooltip
  • Cần điều khiển input từ component cha (focus, insert text, reset)
  • Cần drag & drop file vào vùng input
  • Cần cô lập editor content khỏi CSS toàn cục (dùng iframe-textarea)

Cài đặt

npm install @libs-ui/components-inputs-input

Import

import { LibsUiComponentsInputsInputComponent } from '@libs-ui/components-inputs-input';

@Component({
  standalone: true,
  imports: [LibsUiComponentsInputsInputComponent],
})
export class YourComponent {}

Import thêm types/interfaces khi cần:

import {
  LibsUiComponentsInputsInputComponent,
  IInputFunctionControlEvent,
  IFocusAndBlurEvent,
  IIframeTextareaCustomStyle,
  TYPE_DATA_TYPE_INPUT,
  TYPE_TAG_INPUT,
  TYPE_INPUT,
  TYPE_INPUT_RESIZE_MODE,
  TYPE_MODE_INPUT,
} from '@libs-ui/components-inputs-input';

Ví dụ sử dụng

Basic Text Input

<libs_ui-components-inputs-input
  [(value)]="textValue"
  [placeholder]="'Nhập nội dung'"
  (outChange)="handlerTextChange($event)" />
protected textValue = signal('');

handlerTextChange(value: string): void {
  // value đã được emit
}

Number Input với Min/Max

<libs_ui-components-inputs-input
  [dataType]="'int'"
  [(value)]="numberValue"
  [minValueNumber]="0"
  [maxValueNumber]="100"
  [placeholder]="'Nhập số 0-100'"
  (outChange)="handlerNumberChange($event)" />
protected numberValue = signal<number>(0);

handlerNumberChange(value: number): void {
  // value là number đã được parse
}

Float Input với Fixed Decimal và Giá trị âm

<libs_ui-components-inputs-input
  [dataType]="'float'"
  [(value)]="floatValue"
  [fixedFloat]="2"
  [acceptNegativeValue]="true"
  [placeholder]="'Nhập số thực (vd: -99.99)'"
  (outChange)="handlerFloatChange($event)" />
protected floatValue = signal<number>(0);

handlerFloatChange(value: number): void {
  // value là số thực, tối đa 2 chữ số thập phân
}

Bigint Input với Precision tùy chỉnh

<libs_ui-components-inputs-input
  [dataType]="'bigint'"
  [(value)]="bigintValue"
  [maxLengthNumberCount]="19"
  [fixedFloat]="4"
  [placeholder]="'Nhập giá trị lớn'"
  (outChange)="handlerBigintChange($event)" />
protected bigintValue = signal('');

handlerBigintChange(value: string): void {
  // bigint trả về string thay vì number
}

Textarea với Auto-resize và Character Count

<libs_ui-components-inputs-input
  [tagInput]="'textarea'"
  [(value)]="textareaValue"
  [defaultHeight]="80"
  [minHeightTextArea]="80"
  [maxHeightTextArea]="300"
  [maxLength]="500"
  [showCount]="true"
  [placeholder]="'Nhập mô tả...'"
  (outChange)="handlerTextareaChange($event)"
  (outHeightAreaChange)="handlerHeightChange($event)" />
protected textareaValue = signal('');

handlerTextareaChange(value: string): void {
  // value là chuỗi text
}

handlerHeightChange(data: { isChange: boolean; height: number }): void {
  // data.height là chiều cao mới của textarea
}

Password Input

<libs_ui-components-inputs-input
  [typeInput]="'password'"
  [(value)]="passwordValue"
  [resetAutoCompletePassword]="true"
  [placeholder]="'Nhập mật khẩu'"
  (outChange)="handlerPasswordChange($event)" />
protected passwordValue = signal('');

handlerPasswordChange(value: string): void {
  // xử lý password
}

Input với Icon Left/Right và Popover

<libs_ui-components-inputs-input
  [(value)]="searchValue"
  [iconLeftClass]="'libs-ui-icon-search'"
  [iconRightClass]="'libs-ui-icon-close'"
  [popoverContentIconLeft]="'Tìm kiếm'"
  [popoverContentIconRight]="'Xóa nội dung'"
  [placeholder]="'Tìm kiếm...'"
  (outChange)="handlerSearchChange($event)"
  (outIconLeft)="handlerIconLeftClick($event)"
  (outIconRight)="handlerIconRightClick($event)" />
protected searchValue = signal('');

handlerSearchChange(value: string): void {
  // xử lý tìm kiếm
}

handlerIconLeftClick(eventName: string): void {
  // eventName = 'click'
}

handlerIconRightClick(eventName: string): void {
  this.searchValue.set('');
}

External Control qua FunctionsControl

<libs_ui-components-inputs-input
  [(value)]="controlledValue"
  [placeholder]="'Điều khiển từ bên ngoài'"
  (outFunctionsControl)="handlerFunctionsControl($event)" />

<button (click)="handlerFocusInput()">Focus</button>
<button (click)="handlerInsertText()">Insert "Hello"</button>
<button (click)="handlerResetInput()">Reset</button>
<button (click)="handlerSelectAll()">Select All</button>
import { signal } from '@angular/core';
import { IInputFunctionControlEvent } from '@libs-ui/components-inputs-input';

protected controlledValue = signal('');
private functionControl = signal<IInputFunctionControlEvent | null>(null);

handlerFunctionsControl(control: IInputFunctionControlEvent): void {
  this.functionControl.set(control);
}

async handlerFocusInput(): Promise<void> {
  await this.functionControl()?.focus();
}

async handlerInsertText(): Promise<void> {
  await this.functionControl()?.insertContent('Hello');
}

async handlerResetInput(): Promise<void> {
  await this.functionControl()?.resetValue();
}

async handlerSelectAll(): Promise<void> {
  await this.functionControl()?.selectAllContent();
}

IFrame Textarea với Custom Style

<libs_ui-components-inputs-input
  [tagInput]="'iframe-textarea'"
  [(value)]="iframeValue"
  [iframeTextareaCustomStyle]="iframeStyle"
  [defaultHeight]="120"
  [maxHeightTextArea]="400"
  [placeholder]="'Nhập nội dung (cô lập CSS)'"
  (outChange)="handlerIframeChange($event)"
  (outFunctionsControl)="handlerIframeFunctionsControl($event)" />
import { IIframeTextareaCustomStyle, IInputFunctionControlEvent } from '@libs-ui/components-inputs-input';

protected iframeValue = signal('');
protected iframeStyle: IIframeTextareaCustomStyle = {
  fontSize: '14px',
  lineHeight: '1.6',
  padding: '8px 12px',
  color: '#333333',
  backgroundColor: '#ffffff',
  borderColor: '#e2e8f0',
  borderRadius: '6px',
};

handlerIframeChange(value: string): void {
  // value là nội dung textarea bên trong iframe
}

handlerIframeFunctionsControl(control: IInputFunctionControlEvent): void {
  // lưu control để điều khiển từ bên ngoài
}

Number Input với Nút Up/Down

<libs_ui-components-inputs-input
  [dataType]="'int'"
  [(value)]="stepValue"
  [minValueNumber]="0"
  [maxValueNumber]="10"
  [valueUpDownNumber]="1"
  [placeholder]="'0'"
  (outChange)="handlerStepChange($event)"
  (outChangeValueByButtonUpDown)="handlerUpDownClick()" />
protected stepValue = signal<number>(0);

handlerStepChange(value: number): void {
  // value thay đổi
}

handlerUpDownClick(): void {
  // được gọi khi click nút tăng/giảm
}

Textarea không xuống dòng khi Enter

<libs_ui-components-inputs-input
  [tagInput]="'textarea'"
  [(value)]="singleLineValue"
  [textAreaEnterNotNewLine]="true"
  [placeholder]="'Enter để submit, Shift+Enter xuống dòng'"
  (outChange)="handlerChange($event)"
  (outEnterEvent)="handlerEnter($event)" />
import { IEvent } from '@libs-ui/interfaces-types';

protected singleLineValue = signal('');

handlerChange(value: string): void {
  // xử lý thay đổi
}

handlerEnter(event: IEvent): void {
  event.stopPropagation();
  // xử lý submit khi nhấn Enter
}

Drag & Drop File vào Input

<libs_ui-components-inputs-input
  [(value)]="fileDropValue"
  [placeholder]="'Kéo file vào đây hoặc nhập text'"
  (outChange)="handlerChange($event)"
  (outFilesDrop)="handlerFilesDrop($event)"
  (outFileDrop)="handlerFileDrop($event)" />
protected fileDropValue = signal('');

handlerChange(value: string): void {
  // xử lý text thay đổi
}

handlerFilesDrop(files: File[]): void {
  // xử lý nhiều file drop
  files.forEach(file => console.log(file.name));
}

handlerFileDrop(file: File): void {
  // xử lý từng file riêng lẻ
}

@Input()

| Input | Type | Default | Mô tả | Ví dụ | |---|---|---|---|---| | [acceptNegativeValue] | boolean | false | Cho phép nhập giá trị âm | [acceptNegativeValue]="true" | | [acceptOnlyClickIcon] | boolean | false | Cho phép click icon kể cả khi disable/readonly | [acceptOnlyClickIcon]="true" | | [autoAddZeroLessThan10InTypeInt] | boolean | false | Tự động thêm số 0 trước nếu giá trị < 10 (dataType=int) | [autoAddZeroLessThan10InTypeInt]="true" | | [autoRemoveEmoji] | boolean | false | Tự động loại bỏ emoji khỏi chuỗi nhập | [autoRemoveEmoji]="true" | | [backgroundNone] | boolean | false | Làm trong suốt background của input | [backgroundNone]="true" | | [blurTimeOut] | number | 32 | Delay (ms) trước khi blur được thực thi | [blurTimeOut]="50" | | [borderError] | boolean | false | Hiển thị border màu đỏ báo lỗi | [borderError]="hasError()" | | [classContainerBottomInput] | string | ' ' | CSS class cho container bên dưới input | [classContainerBottomInput]="'flex gap-2'" | | [classContainerInput] | string | 'w-full' | CSS class cho container bọc input | [classContainerInput]="'w-64'" | | [classInclude] | string | ' w-full ' | CSS class bổ sung cho element input | [classInclude]="'text-right'" | | [dataType] | TYPE_DATA_TYPE_INPUT | 'string' | Kiểu dữ liệu: 'string' | 'int' | 'float' | 'bigint' | [dataType]="'int'" | | [defaultHeight] | number | 32 | Chiều cao mặc định (px) | [defaultHeight]="40" | | [disable] | boolean | false | Vô hiệu hóa input | [disable]="isLoading()" | | [emitEmptyInDataTypeNumber] | boolean | false | Emit undefined khi xóa hết giá trị number | [emitEmptyInDataTypeNumber]="true" | | [(fixedFloat)] | number | undefined | Số chữ số thập phân tối đa (dùng với float/bigint) | [(fixedFloat)]="2" | | [focusInput] | boolean | false | Tự động focus input khi render | [focusInput]="true" | | [focusTimeOut] | number | 600 | Delay (ms) trước khi focus được thực thi | [focusTimeOut]="300" | | [iconLeftClass] | string | '' | CSS class cho icon bên trái | [iconLeftClass]="'libs-ui-icon-search'" | | [iconRightClass] | string | undefined | CSS class cho icon bên phải | [iconRightClass]="'libs-ui-icon-close'" | | [iframeTextareaCustomStyle] | IIframeTextareaCustomStyle | undefined | Custom style cho nội dung bên trong iframe-textarea | [iframeTextareaCustomStyle]="myStyle" | | [ignoreBlockInputMaxValue] | boolean | undefined | Không chặn nhập khi vượt quá maxValueNumber | [ignoreBlockInputMaxValue]="true" | | [ignoreStopPropagationEvent] | boolean | undefined | Không gọi stopPropagation trên sự kiện native | [ignoreStopPropagationEvent]="true" | | [ignoreWidthInput100] | boolean | undefined | Không áp dụng w-full cho element input | [ignoreWidthInput100]="true" | | [keepPlaceholderOnly] | boolean | false | Chỉ hiển thị placeholder, ẩn giá trị thực | [keepPlaceholderOnly]="true" | | [keepZeroInTypeInt] | boolean | false | Giữ số 0 ở đầu khi nhập (dataType=int) | [keepZeroInTypeInt]="true" | | [(maxLength)] | number | undefined | Số ký tự tối đa được nhập | [(maxLength)]="100" | | [(maxLengthNumberCount)] | number | undefined | Số chữ số tối đa phần nguyên (dataType=bigint) | [(maxLengthNumberCount)]="19" | | [maxHeightTextArea] | number | 250 | Chiều cao tối đa textarea (px) | [maxHeightTextArea]="400" | | [(maxValueNumber)] | number | undefined | Giá trị tối đa cho number input | [(maxValueNumber)]="100" | | [minHeightTextArea] | number | undefined | Chiều cao tối thiểu textarea (px) | [minHeightTextArea]="80" | | [(minValueNumber)] | number | undefined | Giá trị tối thiểu cho number input | [(minValueNumber)]="0" | | [modeInput] | TYPE_MODE_INPUT | 'text' | inputmode cho mobile keyboard: 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal' | [modeInput]="'numeric'" | | [noBorder] | boolean | false | Ẩn border của input | [noBorder]="true" | | [onlyAcceptNegativeValue] | boolean | false | Chỉ chấp nhận số âm (tự động set acceptNegativeValue=true) | [onlyAcceptNegativeValue]="true" | | [placeholder] | string | ' ' | Placeholder text (hỗ trợ i18n key) | [placeholder]="'i18n_enter_value'" | | [popoverContentIconLeft] | string | '' | Nội dung popover khi hover icon trái | [popoverContentIconLeft]="'Tìm kiếm'" | | [popoverContentIconRight] | string | '' | Nội dung popover khi hover icon phải | [popoverContentIconRight]="'Xóa'" | | [readonly] | boolean | false | Chỉ đọc, không cho phép chỉnh sửa | [readonly]="isViewing()" | | [resetAutoCompletePassword] | boolean | false | Tắt autocomplete của browser (dùng cho password) | [resetAutoCompletePassword]="true" | | [resize] | TYPE_INPUT_RESIZE_MODE | 'vertical' | Chế độ resize textarea: 'auto' | 'vertical' | 'horizontal' | 'none' | [resize]="'none'" | | [selectAllTimeOut] | number | 600 | Delay (ms) trước khi selectAll được thực thi | [selectAllTimeOut]="300" | | [setIconRightColorSameColorDisableReadOnly] | boolean | false | Icon phải có màu giống màu text disable/readonly | [setIconRightColorSameColorDisableReadOnly]="true" | | [showCount] | boolean | false | Hiển thị số ký tự đã nhập (dataType=string) | [showCount]="true" | | [tabInsertContentTagInput] | boolean | false | Cho phép dùng phím Tab để chèn ký tự tab vào input | [tabInsertContentTagInput]="true" | | [tagInput] | TYPE_TAG_INPUT | 'input' | Loại element: 'input' | 'textarea' | 'iframe-textarea' | [tagInput]="'textarea'" | | [templateLeftBottomInput] | TemplateRef | undefined | Template tùy chỉnh ở góc dưới trái | [templateLeftBottomInput]="myLeftTpl" | | [templateRightBottomInput] | TemplateRef | undefined | Template tùy chỉnh ở góc dưới phải | [templateRightBottomInput]="myRightTpl" | | [textAreaEnterNotNewLine] | boolean | false | Enter không xuống dòng trong textarea (dùng Shift+Enter để xuống dòng) | [textAreaEnterNotNewLine]="true" | | [typeInput] | TYPE_INPUT | 'text' | HTML input type: 'text' | 'number' | 'password' | [typeInput]="'password'" | | [useColorModeExist] | boolean | false | Áp dụng màu text theo color mode của hệ thống | [useColorModeExist]="true" | | [(value)] | string \| number | '' | Giá trị input (two-way binding qua model) | [(value)]="myValue" | | [valueUpDownNumber] | number | undefined | Bước nhảy mỗi lần nhấn nút tăng/giảm | [valueUpDownNumber]="5" | | [zIndexPopoverContent] | number | 10 | Z-index của popover content | [zIndexPopoverContent]="100" |

@Output()

| Output | Type | Mô tả | Handler TS | Binding HTML | |---|---|---|---|---| | (outChange) | string \| number \| undefined | Emit khi value thay đổi, đã được parse theo dataType | handlerChange(value: string \| number): void { /* xử lý */ } | (outChange)="handlerChange($event)" | | (outChangeValueByButtonUpDown) | void | Emit khi người dùng click nút tăng hoặc giảm | handlerUpDownClick(): void { /* xử lý */ } | (outChangeValueByButtonUpDown)="handlerUpDownClick()" | | (outEnterEvent) | IEvent | Emit khi nhấn phím Enter (trong textarea nếu textAreaEnterNotNewLine=true thì chỉ Enter không Shift) | handlerEnter(event: IEvent): void { event.stopPropagation(); /* xử lý submit */ } | (outEnterEvent)="handlerEnter($event)" | | (outFileDrop) | File | Emit từng file riêng lẻ khi drop hoặc paste file vào input | handlerFileDrop(file: File): void { event.stopPropagation(); /* xử lý file */ } | (outFileDrop)="handlerFileDrop($event)" | | (outFilesDrop) | Array<File> | Emit toàn bộ danh sách file khi drop hoặc paste vào input | handlerFilesDrop(files: File[]): void { event.stopPropagation(); /* xử lý danh sách */ } | (outFilesDrop)="handlerFilesDrop($event)" | | (outFocusAndBlurEvent) | IFocusAndBlurEvent | Emit khi input được focus hoặc blur, kèm name: 'focus' \| 'blur' | handlerFocusBlur(e: IFocusAndBlurEvent): void { e.event.stopPropagation(); /* xử lý */ } | (outFocusAndBlurEvent)="handlerFocusBlur($event)" | | (outFunctionsControl) | IInputFunctionControlEvent | Emit API điều khiển: focus, blur, insert, reset, selectAll | handlerFunctionsControl(ctrl: IInputFunctionControlEvent): void { this.ctrl.set(ctrl); } | (outFunctionsControl)="handlerFunctionsControl($event)" | | (outHeightAreaChange) | { isChange: boolean; height: number } | Emit khi chiều cao textarea thay đổi do auto-resize | handlerHeightChange(data: { isChange: boolean; height: number }): void { /* xử lý */ } | (outHeightAreaChange)="handlerHeightChange($event)" | | (outIconLeft) | string | Emit khi click icon trái, giá trị là tên event ('click') | handlerIconLeft(eventName: string): void { eventName; /* 'click' */ } | (outIconLeft)="handlerIconLeft($event)" | | (outIconRight) | string | Emit khi click icon phải, giá trị là tên event ('click') | handlerIconRight(eventName: string): void { eventName; /* 'click' */ } | (outIconRight)="handlerIconRight($event)" | | (outInputEvent) | IEvent | Emit native input event gốc (mỗi lần DOM input event xảy ra) | handlerInputEvent(e: IEvent): void { e.stopPropagation(); /* xử lý native event */ } | (outInputEvent)="handlerInputEvent($event)" |

FunctionsControl API

Nhận instance IInputFunctionControlEvent qua output (outFunctionsControl). Tất cả methods là async.

| Method | Signature | Mô tả | |---|---|---| | focus | (emitEvent?: boolean) => Promise<void> | Focus vào input. Nếu emitEvent=true thì emit outFocusAndBlurEvent | | blur | (emitEvent?: boolean) => Promise<void> | Blur khỏi input. Nếu emitEvent=true thì emit outFocusAndBlurEvent | | insertContent | (data: string \| number) => Promise<void> | Chèn nội dung vào vị trí con trỏ hiện tại | | resetValue | () => Promise<void> | Reset value về chuỗi rỗng và emit outChange | | getElementValue | () => Promise<string> \| undefined | Lấy giá trị raw từ DOM element | | checkAndDisableUpDownButton | (value: number) => Promise<void> | Kiểm tra và cập nhật trạng thái disable của nút tăng/giảm | | selectAllContent | () => Promise<void> | Chọn toàn bộ nội dung trong input |

Types & Interfaces

import {
  TYPE_INPUT,
  TYPE_DATA_TYPE_INPUT,
  TYPE_TAG_INPUT,
  TYPE_MODE_INPUT,
  TYPE_INPUT_RESIZE_MODE,
  IInputFunctionControlEvent,
  IFocusAndBlurEvent,
  IIframeTextareaCustomStyle,
} from '@libs-ui/components-inputs-input';

// Loại HTML element
type TYPE_TAG_INPUT = 'input' | 'textarea' | 'iframe-textarea';

// Kiểu dữ liệu
type TYPE_DATA_TYPE_INPUT = 'string' | 'int' | 'float' | 'bigint';

// HTML input type attribute
type TYPE_INPUT = 'text' | 'number' | 'password';

// inputmode attribute (mobile keyboard)
type TYPE_MODE_INPUT = 'none' | 'text' | 'tel' | 'url' | 'email' | 'numeric' | 'decimal';

// Chế độ resize textarea
type TYPE_INPUT_RESIZE_MODE = 'auto' | 'vertical' | 'horizontal' | 'none' | undefined;

// API điều khiển từ component cha
interface IInputFunctionControlEvent {
  focus: (emitEvent?: boolean) => Promise<void>;
  blur: (emitEvent?: boolean) => Promise<void>;
  insertContent: (data: string | number) => Promise<void>;
  resetValue: () => Promise<void>;
  getElementValue: () => Promise<string> | undefined;
  checkAndDisableUpDownButton: (value: number) => Promise<void>;
  selectAllContent: () => Promise<void>;
}

// Event focus/blur
interface IFocusAndBlurEvent {
  name: 'focus' | 'blur';
  event: Event;
}

// Custom style cho iframe-textarea
interface IIframeTextareaCustomStyle {
  borderRadius?: string;
  borderColor?: string;
  padding?: string;
  lineHeight?: string;
  fontSize?: string;
  height?: string;
  color?: string;
  backgroundColor?: string;
}

Lưu ý quan trọng

⚠️ Number Formatting theo Locale: Component tự động format number theo ngôn ngữ hiện tại. Tiếng Việt (VI) dùng dấu . phân cách nghìn và , phân cách thập phân. Tiếng Anh (EN) dùng , phân cách nghìn và . phân cách thập phân.

⚠️ Giới hạn độ chính xác số: int tối đa 16-17 chữ số, float tối đa 15 chữ số phần nguyên + phần thập phân, bigint cấu hình được qua maxLengthNumberCount (default 19) và fixedFloat (default 4).

⚠️ value là model (two-way binding): Dùng [(value)]="mySignal" để binding hai chiều. Output (outChange) emit giá trị đã được parse theo dataType — với bigint trả về string, các loại khác trả về number hoặc string.

⚠️ iframe-textarea CSS isolation: Khi dùng tagInput="iframe-textarea", content được render bên trong <iframe> — CSS của trang cha không áp dụng vào bên trong. Dùng [iframeTextareaCustomStyle] để tùy chỉnh giao diện bên trong iframe (fontSize, padding, color, borderColor...).

⚠️ FunctionsControl timing: Output (outFunctionsControl) emit sau khi DOM element được khởi tạo xong. Lưu instance vào signal để dùng sau: private ctrl = signal<IInputFunctionControlEvent | null>(null).

⚠️ textAreaEnterNotNewLine với Shift+Enter: Khi [textAreaEnterNotNewLine]="true", nhấn Enter không xuống dòng và emit outEnterEvent. Dùng Shift+Enter để xuống dòng bình thường.

⚠️ emitEmptyInDataTypeNumber: Mặc định khi xóa hết giá trị number, component emit 0. Bật [emitEmptyInDataTypeNumber]="true" để emit undefined thay vì 0.

Demo

npx nx serve core-ui

Truy cập: http://localhost:4500/inputs/input