fn-input 0.0.1

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.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fn-input.mjs","sources":["../../../projects/fn-input/src/lib/fn-input.types.ts","../../../projects/fn-input/src/lib/fn-input.component.ts","../../../projects/fn-input/src/lib/fn-input.component.html","../../../projects/fn-input/src/fn-input.ts"],"sourcesContent":["import { ValidatorFn } from '@angular/forms';\r\n\r\nexport type TypeIconVariant = 'Colour' | 'Duotone' | 'Fill' | 'Line';\r\nexport type TypeIconSize = 10 | 16 | 20 | 24 | 32 | 48;\r\n\r\nexport type TypeLabelVariant =\r\n | 'h1'\r\n | 'h1Bold'\r\n | 'h2'\r\n | 'h2Bold'\r\n | 'h3'\r\n | 'h3Bold'\r\n | 'p1'\r\n | 'p1Bold'\r\n | 'p2'\r\n | 'p2Bold'\r\n | 'p3'\r\n | 'p3Bold'\r\n | 'p4'\r\n | 'p4Bold'\r\n | 'interactionLarge'\r\n | 'interactionLargeBold'\r\n | 'interactionMedium'\r\n | 'interactionMediumBold'\r\n | 'interactionSmall'\r\n | 'interactionSmallBold'\r\n | 'avatarLabel';\r\n\r\nexport type TypeStatusLabel =\r\n | 'Standard'\r\n | 'Success'\r\n | 'Hot'\r\n | 'Warning'\r\n | 'Disabled'\r\n | 'RHBPremierBanking';\r\n\r\nexport interface FNInputAffix {\r\n icon?: string;\r\n text?: string;\r\n onClick?: (e: Event) => void;\r\n}\r\n\r\nexport interface FNInputVisibilityCondition {\r\n dependsOn: string;\r\n showWhen: any | any[];\r\n hideWhen?: any | any[];\r\n}\r\n\r\nexport interface FNInputCommonProps<T = any> {\r\n fieldType: 'FNInput';\r\n name: string;\r\n label: string;\r\n placeholder?: string;\r\n className?: string;\r\n required?: boolean;\r\n value?: T;\r\n disabled?: boolean;\r\n hidden?: boolean;\r\n readOnly?: boolean;\r\n floatLabelVariant?: 'in' | 'over' | 'on';\r\n validators?: ValidatorFn[];\r\n errors?: { [key: string]: string };\r\n rows?: number;\r\n prefix?: FNInputAffix;\r\n suffix?: FNInputAffix;\r\n hasSuccessBorder?: boolean;\r\n visibilityCondition?: FNInputVisibilityCondition;\r\n helperText?: string;\r\n isAlphanumeric?: boolean;\r\n hideOptional?: boolean;\r\n isAddressLine?: boolean;\r\n color?: string;\r\n labelVariant?: TypeLabelVariant;\r\n statusLabel?: TypeStatusLabel;\r\n}\r\n\r\nexport interface FNTextInputProps<T = any> extends FNInputCommonProps<T> {\r\n type: 'text' | 'email' | 'textarea' | 'hidden';\r\n cols?: number;\r\n maxLength?: number;\r\n icon?: {\r\n name: string;\r\n variant: TypeIconVariant;\r\n size: TypeIconSize;\r\n };\r\n}\r\n\r\nexport interface FNPasswordProps extends FNInputCommonProps<string> {\r\n type: 'password';\r\n toggleMask?: boolean;\r\n feedback?: boolean;\r\n weakLabel?: string;\r\n mediumLabel?: string;\r\n strongLabel?: string;\r\n isCopyText?: boolean;\r\n hasGenerateKey?: boolean;\r\n onGenerateKey?: () => void;\r\n}\r\n\r\nexport interface FNInputNumberProps extends FNInputCommonProps<number> {\r\n type: 'number';\r\n min?: number;\r\n max?: number;\r\n step?: number;\r\n minFractionDigits?: number;\r\n maxFractionDigits?: number;\r\n currency?: string;\r\n currencyDisplay?: 'symbol' | 'code' | 'name';\r\n locale?: string;\r\n useGrouping?: boolean;\r\n mode?: 'decimal' | 'currency';\r\n showButtons?: boolean;\r\n buttonLayout?: 'stacked' | 'horizontal' | 'vertical';\r\n incrementButtonIcon?: string;\r\n decrementButtonIcon?: string;\r\n isCurrency?: boolean;\r\n maxIntegerDigits?: number;\r\n}\r\n\r\nexport type FNInputBase = FNTextInputProps | FNPasswordProps | FNInputNumberProps;\r\n\r\nexport interface FNInputHelper {\r\n showFormFieldMessage: (control: any, helperText: string) => boolean;\r\n}\r\n\r\nexport interface FNInputToast {\r\n success: (message: string, title?: string, duration?: number) => string;\r\n error: (message: string, title?: string, duration?: number) => string;\r\n}\r\n\r\nexport const DEFAULT_CURRENCY_META = [\r\n { code: 'USD', locale: 'en-US', symbol: '$', digit: '1.2-2' },\r\n { code: 'MYR', locale: 'en-MY', symbol: 'RM', digit: '1.2-2' },\r\n { code: 'EUR', locale: 'en-US', symbol: '€', digit: '1.2-2' },\r\n { code: 'GBP', locale: 'en-US', symbol: '£', digit: '1.2-2' },\r\n { code: 'JPY', locale: 'ja-JP', symbol: '¥', digit: '1.0-0' },\r\n { code: 'CNY', locale: 'zh-CN', symbol: '¥', digit: '1.2-2' },\r\n { code: 'INR', locale: 'en-IN', symbol: '₹', digit: '1.2-2' },\r\n];\r\n","import {\r\n AfterViewInit,\r\n ChangeDetectionStrategy,\r\n ChangeDetectorRef,\r\n Component,\r\n ElementRef,\r\n EventEmitter,\r\n inject,\r\n Input,\r\n OnInit,\r\n Output,\r\n signal,\r\n ViewChild,\r\n OnDestroy,\r\n OnChanges,\r\n SimpleChanges,\r\n ViewChildren,\r\n QueryList,\r\n} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { FormControl, FormGroup, FormsModule, ReactiveFormsModule } from '@angular/forms';\r\nimport { TranslateModule, TranslateService } from '@ngx-translate/core';\r\nimport { Subscription, merge } from 'rxjs';\r\nimport { startWith } from 'rxjs/operators';\r\nimport {\r\n FNInputBase,\r\n FNInputHelper,\r\n FNInputToast,\r\n DEFAULT_CURRENCY_META,\r\n TypeIconVariant,\r\n TypeIconSize,\r\n} from './fn-input.types';\r\n\r\nexport type TypeIconSizeName = 'extrasmall' | 'small' | 'medium' | 'large' | 'x-large' | 'xxlarge';\r\n\r\n@Component({\r\n selector: 'fn-input',\r\n standalone: true,\r\n imports: [FormsModule, CommonModule, ReactiveFormsModule, TranslateModule],\r\n templateUrl: './fn-input.component.html',\r\n styleUrls: ['./fn-input.component.scss'],\r\n changeDetection: ChangeDetectionStrategy.OnPush,\r\n})\r\nexport class FNInput implements OnInit, AfterViewInit, OnDestroy, OnChanges {\r\n @Input() field = {} as FNInputBase;\r\n @Input() helperHandle?: FNInputHelper;\r\n @Input() toastService?: FNInputToast;\r\n @Input() currencyMeta = DEFAULT_CURRENCY_META;\r\n @Input() defaultLocale = 'en-US';\r\n @Input() form!: FormGroup;\r\n @Output() valueChange = new EventEmitter();\r\n @Output() fieldBlur = new EventEmitter();\r\n\r\n translate = inject(TranslateService);\r\n hasFocus = signal(false);\r\n @ViewChild('fnTextarea') textareaElement!: ElementRef<HTMLTextAreaElement>;\r\n @ViewChildren('iconContainer') iconContainers!: QueryList<ElementRef<HTMLElement>>;\r\n\r\n http = inject(HttpClient);\r\n private readonly subs = new Subscription();\r\n\r\n private readonly sizeMap: Record<TypeIconSizeName, TypeIconSize> = {\r\n extrasmall: 10,\r\n small: 16,\r\n medium: 20,\r\n large: 24,\r\n 'x-large': 32,\r\n xxlarge: 48,\r\n };\r\n\r\n getIconSizeName(size: number): 'small' | 'medium' | 'large' | 'x-large' {\r\n switch (size) {\r\n case 16:\r\n return 'small';\r\n case 20:\r\n return 'medium';\r\n case 24:\r\n return 'large';\r\n case 32:\r\n return 'x-large';\r\n default:\r\n return 'medium';\r\n }\r\n }\r\n\r\n get isAlphanumeric(): boolean {\r\n return this.field.isAlphanumeric !== false;\r\n }\r\n\r\n get isEmailField(): boolean {\r\n return this.field.type === 'email' || this.field.name?.toLowerCase().includes('email');\r\n }\r\n\r\n private get alphanumericPattern(): RegExp {\r\n if (this.field.isAddressLine) {\r\n return /[^A-Za-z0-9 \\-_&(),/]/g;\r\n }\r\n\r\n return /[^A-Za-z0-9 \\-_&()]/g;\r\n }\r\n\r\n isDisabled = false;\r\n control!: FormControl;\r\n isVisible = signal(true); // Track visibility state\r\n helperText = '';\r\n\r\n // Use a counter-based approach for unique IDs (safer than Math.random())\r\n private static idCounter = 0;\r\n uniqueId = `fn-input-${++FNInput.idCounter}`;\r\n\r\n constructor(private readonly cdr: ChangeDetectorRef) {}\r\n\r\n ngOnInit(): void {\r\n if (this.field.hidden) return;\r\n this.helperText = this.field.helperText ?? '';\r\n this.initFormControl();\r\n\r\n if (this.field.value) this.control.setValue(this.field.value);\r\n this.setupVisibilityCondition();\r\n this.setupFieldMessageListener();\r\n }\r\n\r\n ngOnDestroy(): void {\r\n this.subs.unsubscribe();\r\n }\r\n\r\n ngOnChanges(changes: SimpleChanges): void {\r\n if (changes['field'] || changes['form']) {\r\n this.updateAllIcons();\r\n }\r\n }\r\n\r\n private setupFieldMessageListener(): void {\r\n if (!this.control) return;\r\n\r\n const val$ = this.control.valueChanges.pipe(startWith(this.control.value));\r\n const status$ = this.control.statusChanges.pipe(startWith(this.control.status));\r\n\r\n this.subs.add(\r\n merge(val$, status$).subscribe(() => {\r\n try {\r\n this.cdr.detectChanges();\r\n } catch (e) {\r\n console.warn('CDR detectChanges failed during field message update:', e);\r\n this.cdr.markForCheck();\r\n }\r\n }),\r\n );\r\n }\r\n\r\n ngAfterViewInit(): void {\r\n // Access the textarea element by ViewChild or native element reference\r\n this.autoResizeInitial();\r\n if (this.field.type === 'textarea' && this.control?.value) {\r\n setTimeout(() => this.autoResizeInitial(), 30);\r\n }\r\n // Apply initial formatting after view is initialized\r\n if (this.field.type === 'number' && this.field.isCurrency && this.control?.value) {\r\n this.formatInitialCurrencyValue();\r\n }\r\n }\r\n\r\n enforceLowercase(event: Event) {\r\n const input = event.target as HTMLInputElement;\r\n const start = input.selectionStart;\r\n const end = input.selectionEnd;\r\n\r\n input.value = input.value.toLowerCase();\r\n if (this.control) {\r\n this.control.setValue(input.value, { emitEvent: false });\r\n }\r\n this.valueChange.emit({ name: this.field.name, value: input.value });\r\n\r\n // restore cursor position so typing is smooth\r\n input.setSelectionRange(start, end);\r\n }\r\n\r\n /**\r\n * Handle email input - allows only valid email characters and enforces lowercase.\r\n * Allowed: a-z, 0-9, . _ + - @\r\n * Rules:\r\n * - Only one @ allowed\r\n * - No consecutive dots (..)\r\n * - Automatic lowercase\r\n */\r\n handleEmailInput(event: Event): void {\r\n const input = event.target as HTMLInputElement;\r\n const cursorPosition = input.selectionStart || 0;\r\n const originalValue = input.value;\r\n\r\n // 1. Convert to lowercase\r\n const lowerValue = originalValue.toLowerCase();\r\n\r\n // 2. Split at the first @ to handle local and domain parts separately\r\n const parts = lowerValue.split('@');\r\n let localPart = parts[0];\r\n let domainPart = parts.length > 1 ? parts.slice(1).join('') : null;\r\n\r\n // 3. Filter local part: a-z, 0-9, ., _, +, -\r\n // Rule: Cannot start with a dot (.)\r\n localPart = localPart.replaceAll(/[^a-z0-9._+-]/g, '');\r\n while (localPart.startsWith('.')) {\r\n localPart = localPart.substring(1);\r\n }\r\n while (localPart.includes('..')) {\r\n localPart = localPart.replaceAll('..', '.');\r\n }\r\n\r\n // 4. Filter domain part: a-z, 0-9, ., -\r\n // Rule: No underscores (_), no plus signs (+), cannot start with a hyphen (-)\r\n let filteredValue = localPart;\r\n if (domainPart !== null) {\r\n domainPart = domainPart.replaceAll(/[^a-z0-9.-]/g, '');\r\n while (domainPart.startsWith('-')) {\r\n domainPart = domainPart.substring(1);\r\n }\r\n while (domainPart.includes('..')) {\r\n domainPart = domainPart.replaceAll('..', '.');\r\n }\r\n filteredValue += '@' + domainPart;\r\n }\r\n\r\n if (originalValue !== filteredValue) {\r\n const charsRemovedBeforeCursor = this.countRemovedCharsBeforeCursor(\r\n originalValue.toLowerCase(),\r\n filteredValue,\r\n cursorPosition,\r\n );\r\n input.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n const newCursorPos = Math.max(0, cursorPosition - charsRemovedBeforeCursor);\r\n input.setSelectionRange(newCursorPos, newCursorPos);\r\n } else if (originalValue !== lowerValue) {\r\n // If only case changed (e.g., typed Uppercase)\r\n input.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n input.setSelectionRange(cursorPosition, cursorPosition);\r\n }\r\n\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\r\n this.control.markAsTouched();\r\n }\r\n\r\n onFocus(): void {\r\n this.hasFocus.set(true);\r\n }\r\n\r\n private formatInitialCurrencyValue(): void {\r\n const numericValue = Number(this.control.value);\r\n if (!Number.isNaN(numericValue)) {\r\n setTimeout(() => {\r\n const inputElement = document.getElementById(this.uniqueId) as HTMLInputElement;\r\n if (inputElement) {\r\n inputElement.value = this.formatCurrencyWithCommas(numericValue);\r\n }\r\n }, 50);\r\n }\r\n }\r\n\r\n initFormControl() {\r\n const controller = this.form.controls?.[this.field.name];\r\n this.control = controller as FormControl;\r\n if (this.field.value) this.control.setValue(this.field.value);\r\n\r\n if (this.control) {\r\n // Handle disabled state\r\n if (this.field.disabled ?? false) {\r\n this.control?.disable();\r\n } else {\r\n this.control?.enable();\r\n }\r\n }\r\n }\r\n\r\n autoResizeInitial() {\r\n const textarea = this.textareaElement?.nativeElement;\r\n if (textarea) {\r\n // Get the number of rows (default to 2 if not specified)\r\n const rows = this.field.rows || 1;\r\n\r\n // Calculate line height from computed styles\r\n const computedStyle = globalThis.getComputedStyle(textarea);\r\n const lineHeight = Number.parseFloat(computedStyle.lineHeight) || 32; // Default to 24px if not set\r\n\r\n // Calculate minimum height based on rows\r\n const minHeight = rows * lineHeight;\r\n\r\n // Reset height to auto to get accurate scrollHeight\r\n textarea.style.height = 'auto';\r\n\r\n // Use the larger of scrollHeight or minHeight\r\n const newHeight = Math.max(textarea.scrollHeight, minHeight);\r\n textarea.style.height = newHeight + 'px';\r\n textarea.style.overflow = 'hidden';\r\n }\r\n }\r\n\r\n handleTextArea(event: Event): void {\r\n const element = event.target as HTMLTextAreaElement;\r\n const cursorPosition = element.selectionStart;\r\n const originalValue = element.value;\r\n\r\n // Apply alphanumeric filtering if enabled\r\n if (this.field.type === 'textarea' && this.isAlphanumeric) {\r\n // Only allow characters based on the selected pattern\r\n const alphanumericPattern = this.alphanumericPattern;\r\n let filteredValue = originalValue.replaceAll(alphanumericPattern, '');\r\n\r\n // Prevent leading spaces\r\n if (filteredValue.startsWith(' ')) {\r\n filteredValue = filteredValue.trimStart();\r\n }\r\n\r\n // Replace multiple consecutive spaces with single space\r\n filteredValue = filteredValue.replaceAll(/\\s{2,}/g, ' ');\r\n\r\n if (originalValue !== filteredValue) {\r\n // Calculate the number of characters removed before the cursor position\r\n const charsRemovedBeforeCursor = originalValue.length - filteredValue.length;\r\n element.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n // Restore cursor position - account for removed characters\r\n const newCursorPos = Math.max(0, (cursorPosition || 0) - charsRemovedBeforeCursor);\r\n element.setSelectionRange(newCursorPos, newCursorPos);\r\n }\r\n\r\n // increase height\r\n this.autoResizeInitial();\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\r\n } else {\r\n let filteredValue = originalValue;\r\n\r\n // Strict filtering if !isAlphanumeric\r\n if (!this.isAlphanumeric) {\r\n console.log('isAlphanumeric', this.isAlphanumeric);\r\n\r\n const allowedPattern = /[^a-zA-Z0-9\\s(){}[\\];,.\"='+\\-*/<>!&|%_@$?:]/g;\r\n filteredValue = filteredValue.replaceAll(allowedPattern, '');\r\n }\r\n\r\n // Prevent leading spaces\r\n if (filteredValue.startsWith(' ')) {\r\n filteredValue = filteredValue.trimStart();\r\n }\r\n\r\n // Replace multiple consecutive spaces with single space\r\n filteredValue = filteredValue.replaceAll(/\\s{2,}/g, ' ');\r\n\r\n if (originalValue !== filteredValue) {\r\n // Calculate the number of characters removed before the cursor position\r\n const charsRemovedBeforeCursor = originalValue.length - filteredValue.length;\r\n element.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n // Restore cursor position - account for removed characters\r\n const newCursorPos = Math.max(0, (cursorPosition || 0) - charsRemovedBeforeCursor);\r\n element.setSelectionRange(newCursorPos, newCursorPos);\r\n }\r\n\r\n // increase height\r\n this.autoResizeInitial();\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\r\n }\r\n\r\n this.control.markAsTouched();\r\n }\r\n\r\n handleInput(event: Event): void {\r\n const target = event.target as HTMLInputElement;\r\n const cursorPosition = target.selectionStart;\r\n const originalValue = target.value;\r\n\r\n let filteredValue = originalValue;\r\n\r\n // IF NOT alphanumeric, user wants strict filtering:\r\n // \"only accept tihs.) {} [] ; , . \" ' = + - * / < > ! & | % &_( )-/.;@!, $% : dont allow emoji\"\r\n // Interpretation: Allow alphanumeric + specified special chars. Ban emojis.\r\n // Actually, the user said: \"if isAlphanumeric false only accept...\"\r\n // So if isAlphanumeric is TRUE, we use the existing handleAlphanumericInput logic (or similar).\r\n // The current logic in handleInput is generic.\r\n // The existing code has a separate `handleAlphanumericInput` method but it's not called here?\r\n // Wait, the template likely calls `handleAlphanumericInput` if `isAlphanumeric` is true, or `handleInput` otherwise?\r\n // Let's check the template.\r\n // BUT assuming `handleInput` is the generic handler:\r\n\r\n if (!this.isAlphanumeric) {\r\n // Regex to allow: a-z, A-Z, 0-9, and: ) {} [] ; , . \" ' = + - * / < > ! & | % _ ( - @ $ ? :\r\n // Note: User list: ) {} [] ; , . \" ' = + - * / < > ! & | % &_( )-/.;@!, $%\r\n // Combined unique special chars: ) { } [ ] ; , . \" ' = + - * / < > ! & | % _ ( @ $ ? :\r\n // Also space is implied? usually yes.\r\n // And NO EMOJIS.\r\n // easier to just replace anything NOT in the allowed set.\r\n\r\n // Allowed chars regex pattern:\r\n // A-Za-z0-9\r\n // Space: \\s\r\n // Special: (){}[\\];,.\"='+\\-*/<>!&|%_@$?:\r\n // Note: - inside [] needs to be escaped or at end. ] needs escape. \\ needs escape? (not in list).\r\n // User list has: `.` `\"` `'` `?` (wait, ? not in list?)\r\n // User list: `) {} [] ; , . \" ' = + - * / < > ! & | % &_( )-/.;@!, $%`\r\n // Uniques: ) { } [ ] ; , . \" ' = + - * / < > ! & | % _ ( @ $\r\n // (The `&` is repeated, `.` repeated, `,` repeated etc.)\r\n // I will create a regex that matches anything NOT in this list and replace with empty string.\r\n\r\n // [^a-zA-Z0-9\\s(){}[\\];,.\"='+\\-*/<>!&|%_@$]\r\n // Note: `*`, `+`, `?` etc need escaping in regex if outside [], but inside [] they are literals mostly.\r\n // `-` needs to be last or escaped. `]` needs escape. `^` needs escape if first? No, invalid here.\r\n // Let's verify valid chars:\r\n // a-z A-Z 0-9\r\n // space\r\n // ) { } [ ] ; , . \" ' = + - * / < > ! & | % _ ( @ $ :\r\n\r\n const allowedPattern = /[^a-zA-Z0-9\\s(){}[\\];,.\"='+\\-*/<>!&|%_@$?:]/g;\r\n filteredValue = filteredValue.replaceAll(allowedPattern, '');\r\n }\r\n\r\n // Prevent leading spaces\r\n if (filteredValue.startsWith(' ')) {\r\n filteredValue = filteredValue.trimStart();\r\n }\r\n\r\n // replaceAll multiple consecutive spaces with single space\r\n filteredValue = filteredValue.replaceAll(/\\s{2,}/g, ' ');\r\n\r\n if (originalValue !== filteredValue) {\r\n // Calculate the number of characters removed before the cursor position\r\n const charsRemovedBeforeCursor = originalValue.length - filteredValue.length;\r\n target.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n // Restore cursor position - account for removed characters\r\n const newCursorPos = Math.max(0, (cursorPosition || 0) - charsRemovedBeforeCursor);\r\n target.setSelectionRange(newCursorPos, newCursorPos);\r\n }\r\n\r\n // Trailing spaces will be trimmed on blur, not during input\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\r\n this.control.markAsTouched();\r\n }\r\n\r\n /**\r\n * Handle alphanumeric input - allows only letters, numbers, and specific special characters\r\n * Allowed: A-Z, a-z, 0-9, space, hyphen, underscore, ampersand, and parentheses\r\n * Also prevents leading spaces and multiple consecutive spaces\r\n */\r\n handleAlphanumericInput(event: Event): void {\r\n const target = event.target as HTMLInputElement;\r\n const cursorPosition = target.selectionStart;\r\n const originalValue = target.value;\r\n\r\n // Only allow characters based on the selected pattern\r\n const alphanumericPattern = this.alphanumericPattern;\r\n let filteredValue = originalValue.replaceAll(alphanumericPattern, '');\r\n\r\n // Prevent leading spaces\r\n if (filteredValue.startsWith(' ')) {\r\n filteredValue = filteredValue.trimStart();\r\n }\r\n\r\n // Replace multiple consecutive spaces with single space\r\n filteredValue = filteredValue.replaceAll(/\\s{2,}/g, ' ');\r\n\r\n if (originalValue !== filteredValue) {\r\n // Calculate the number of characters removed before the cursor position\r\n const charsRemovedBeforeCursor = originalValue.length - filteredValue.length;\r\n target.value = filteredValue;\r\n this.control.setValue(filteredValue, { emitEvent: false });\r\n // Restore cursor position - account for removed characters\r\n const newCursorPos = Math.max(0, (cursorPosition || 0) - charsRemovedBeforeCursor);\r\n target.setSelectionRange(newCursorPos, newCursorPos);\r\n }\r\n\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\r\n this.control.markAsTouched();\r\n }\r\n\r\n handleBlur(e: Event, maxDecimals: number = 2): void {\r\n this.hasFocus.set(false);\r\n const target = e.target as HTMLInputElement | HTMLTextAreaElement;\r\n const cleanValueString = target.value;\r\n\r\n if (!cleanValueString) {\r\n this.fieldBlur.emit({ name: this.field.name, value: '' });\r\n this.cdr.detectChanges();\r\n return;\r\n }\r\n\r\n // Delegate to type-specific handlers\r\n if (this.field.type === 'text' || this.field.type === 'textarea') {\r\n this.handleTextFieldBlur(target, cleanValueString);\r\n } else if (this.field.type === 'number') {\r\n this.handleNumberFieldBlur(target, cleanValueString, maxDecimals);\r\n }\r\n\r\n // Emit final value\r\n this.fieldBlur.emit({\r\n name: this.field.name,\r\n value: target.value,\r\n });\r\n this.cdr.detectChanges();\r\n }\r\n\r\n /**\r\n * Handle blur for text and textarea fields - trim trailing spaces\r\n */\r\n private handleTextFieldBlur(\r\n target: HTMLInputElement | HTMLTextAreaElement,\r\n cleanValueString: string,\r\n ): void {\r\n const trimmed = cleanValueString.trim();\r\n if (cleanValueString !== trimmed) {\r\n target.value = trimmed;\r\n this.control.setValue(trimmed, { emitEvent: false });\r\n }\r\n }\r\n\r\n /**\r\n * Handle blur for number fields - validate and format\r\n */\r\n private handleNumberFieldBlur(\r\n target: HTMLInputElement | HTMLTextAreaElement,\r\n cleanValueString: string,\r\n maxDecimals: number,\r\n ): void {\r\n // Remove commas for parsing/validation\r\n const numString = cleanValueString.replaceAll(',', '');\r\n\r\n // Check if the string is a valid number format\r\n const isValidNumberFormat = /^-?\\d+(\\.\\d+)?$/.test(numString);\r\n\r\n // If not a valid number format, clear the field\r\n if (!isValidNumberFormat) {\r\n target.value = '';\r\n this.control.setValue('');\r\n return;\r\n }\r\n\r\n // Format currency fields or set raw value for non-currency\r\n if (this.field.type === 'number' && this.field.isCurrency) {\r\n this.processCurrencyValue(target, numString, maxDecimals);\r\n } else {\r\n // Non-currency: preserve the raw string value\r\n target.value = numString;\r\n }\r\n }\r\n\r\n /**\r\n * Process currency value - handle formatting and decimal places\r\n */\r\n private processCurrencyValue(\r\n target: HTMLInputElement | HTMLTextAreaElement,\r\n numString: string,\r\n maxDecimals: number,\r\n ): void {\r\n // Handle negative values - convert to positive\r\n let processedValue = numString.startsWith('-') ? numString.substring(1) : numString;\r\n\r\n // Handle edge case of \"-0\" or just \"-\"\r\n if (processedValue === '' || processedValue === '0') {\r\n processedValue = '0';\r\n }\r\n\r\n // Format the value with proper decimal places\r\n const cleanValueString = this.formatDecimalPlaces(processedValue, maxDecimals);\r\n\r\n const formattedValue = this.formatCurrencyWithCommas(cleanValueString, maxDecimals);\r\n\r\n // Update the control value with the numeric string (not formatted)\r\n this.control.setValue(cleanValueString, { emitEvent: false });\r\n\r\n // Trigger validators and mark as touched\r\n this.control.updateValueAndValidity();\r\n this.control.markAsTouched();\r\n\r\n // Set display value with commas after Angular's form control update\r\n setTimeout(() => {\r\n target.value = formattedValue;\r\n }, 0);\r\n }\r\n\r\n /**\r\n * Format decimal places - pad or truncate to maxDecimals\r\n */\r\n private formatDecimalPlaces(value: string, maxDecimals: number): string {\r\n let [intPart, decPart] = value.includes('.') ? value.split('.') : [value, ''];\r\n\r\n // Pad or truncate decimal part to maxDecimals\r\n if (decPart.length < maxDecimals) {\r\n decPart = decPart.padEnd(maxDecimals, '0');\r\n } else if (decPart.length > maxDecimals) {\r\n decPart = decPart.slice(0, maxDecimals);\r\n }\r\n\r\n // Build the clean value string (without commas)\r\n return maxDecimals > 0 ? `${intPart}.${decPart}` : intPart;\r\n }\r\n\r\n handleNumberInput(event: Event, maxDecimals: number = 2): void {\r\n const target = event.target as HTMLInputElement;\r\n const originalValue = target.value;\r\n const cursorPosition = target.selectionStart ?? 0;\r\n\r\n // Step 1: Filter and format the input value\r\n let value = this.filterNumericInput(target.value, maxDecimals);\r\n\r\n // Step 2: Update cursor position if value changed\r\n this.updateCursorPositionAfterFilter(target, originalValue, value, cursorPosition);\r\n\r\n // Step 3: Update form control and validate\r\n this.updateFormControlValue(value, maxDecimals);\r\n\r\n // Step 4: Emit changes\r\n this.valueChange.emit({ name: this.field.name, value: target.value });\r\n this.control.markAsTouched();\r\n }\r\n\r\n /**\r\n * Filter numeric input to only allow digits and decimal point\r\n * Ensures only one decimal point and enforces max decimal places\r\n */\r\n private filterNumericInput(value: string, maxDecimals: number): string {\r\n // Remove ALL non-numeric characters except decimal point\r\n let filtered = value.replaceAll(/[^0-9.]/g, '');\r\n\r\n // Ensure only one decimal point\r\n filtered = this.filterDecimalPoints(filtered);\r\n\r\n // Restrict to maxDecimals decimal places if decimal exists\r\n filtered = this.enforceDecimalLimit(filtered, maxDecimals);\r\n\r\n return filtered;\r\n }\r\n\r\n /**\r\n * Ensure only one decimal point exists in the value\r\n */\r\n private filterDecimalPoints(value: string): string {\r\n const parts = value.split('.');\r\n if (parts.length > 2) {\r\n return parts[0] + '.' + parts.slice(1).join('');\r\n }\r\n return value;\r\n }\r\n\r\n /**\r\n * Enforce maximum decimal places limit\r\n */\r\n private enforceDecimalLimit(value: string, maxDecimals: number): string {\r\n if (!value.includes('.')) {\r\n return value;\r\n }\r\n\r\n const [integerPart, decimalPart] = value.split('.');\r\n if (decimalPart && decimalPart.length > maxDecimals) {\r\n return integerPart + '.' + decimalPart.slice(0, maxDecimals);\r\n }\r\n return value;\r\n }\r\n\r\n /**\r\n * Update cursor position after filtering input\r\n */\r\n private updateCursorPositionAfterFilter(\r\n target: HTMLInputElement,\r\n originalValue: string,\r\n newValue: string,\r\n cursorPosition: number,\r\n ): void {\r\n if (target.value === newValue) {\r\n return;\r\n }\r\n\r\n const charsRemovedBeforeCursor = this.countRemovedCharsBeforeCursor(\r\n originalValue,\r\n newValue,\r\n cursorPosition,\r\n );\r\n target.value = newValue;\r\n const newPosition = Math.max(0, cursorPosition - charsRemovedBeforeCursor);\r\n target.setSelectionRange(newPosition, newPosition);\r\n }\r\n\r\n /**\r\n * Update form control value and perform validation\r\n */\r\n private updateFormControlValue(value: string, maxDecimals: number): void {\r\n this.control.setValue(value, { emitEvent: false });\r\n this.validateIntegerDigits(value, maxDecimals);\r\n this.clearNumericError();\r\n }\r\n\r\n /**\r\n * Count how many characters were removed before the cursor position\r\n * This helps maintain correct cursor position after filtering input\r\n */\r\n private countRemovedCharsBeforeCursor(\r\n original: string,\r\n filtered: string,\r\n cursorPos: number,\r\n ): number {\r\n let removedCount = 0;\r\n let filteredIndex = 0;\r\n\r\n for (let i = 0; i < cursorPos && i < original.length; i++) {\r\n if (filteredIndex < filtered.length && original[i] === filtered[filteredIndex]) {\r\n filteredIndex++;\r\n } else {\r\n removedCount++;\r\n }\r\n }\r\n\r\n return removedCount;\r\n }\r\n\r\n /**\r\n * Handle paste event for number inputs\r\n * Prevents pasting of non-numeric characters and enforces digit limits\r\n */\r\n handleNumberPaste(event: ClipboardEvent, maxDecimals: number = 2): void {\r\n event.preventDefault();\r\n const target = event.target as HTMLInputElement;\r\n const pastedText = event.clipboardData?.getData('text') || '';\r\n const isCurrency = this.field.type === 'number' && !!this.field.isCurrency;\r\n\r\n const filteredText = isCurrency\r\n ? this.getFilteredCurrencyPastedText(pastedText)\r\n : this.getFilteredIntegerPastedText(pastedText);\r\n const finalValue = this.buildFinalPasteValue(target, filteredText, isCurrency, maxDecimals);\r\n\r\n // Update the input\r\n target.value = finalValue;\r\n this.control.setValue(finalValue, { emitEvent: false });\r\n\r\n this.validateIntegerDigits(finalValue, maxDecimals);\r\n this.clearNumericError();\r\n\r\n this.valueChange.emit({ name: this.field.name, value: finalValue });\r\n this.control.markAsTouched();\r\n\r\n this.setCursorAfterPaste(target, filteredText, finalValue);\r\n }\r\n\r\n /**\r\n * Filter pasted text for currency input (allows digits and decimal point)\r\n */\r\n private getFilteredCurrencyPastedText(pastedText: string): string {\r\n return pastedText.replaceAll(/[^0-9.]/g, '');\r\n }\r\n\r\n /**\r\n * Filter pasted text for integer-only input (allows digits only)\r\n */\r\n private getFilteredIntegerPastedText(pastedText: string): string {\r\n return pastedText.replaceAll(/\\D/g, '');\r\n }\r\n\r\n /**\r\n * Build final value after paste operation\r\n */\r\n private buildFinalPasteValue(\r\n target: HTMLInputElement,\r\n filteredText: string,\r\n isCurrency: boolean,\r\n maxDecimals: number,\r\n ): string {\r\n const currentValue = target.value;\r\n const start = target.selectionStart;\r\n const end = target.selectionEnd;\r\n\r\n let finalValue: string;\r\n\r\n // If selection API is not supported or no selection, replace entire content\r\n if (start === null || end === null || (start === 0 && end === 0)) {\r\n finalValue = filteredText;\r\n } else {\r\n finalValue = currentValue.substring(0, start) + filteredText + currentValue.substring(end);\r\n }\r\n\r\n return isCurrency ? this.applyDecimalRestrictions(finalValue, maxDecimals) : finalValue;\r\n }\r\n\r\n /**\r\n * Apply decimal restrictions for currency fields\r\n */\r\n private applyDecimalRestrictions(value: string, maxDecimals: number): string {\r\n let result = value;\r\n\r\n // Ensure only one decimal point\r\n const parts = result.split('.');\r\n if (parts.length > 2) {\r\n result = parts[0] + '.' + parts.slice(1).join('');\r\n }\r\n\r\n // Restrict to maxDecimals decimal places\r\n if (result.includes('.')) {\r\n const [intPart, decPart] = result.split('.');\r\n if (decPart.length > maxDecimals) {\r\n result = intPart + '.' + decPart.slice(0, maxDecimals);\r\n }\r\n }\r\n\r\n return result;\r\n }\r\n\r\n /**\r\n * Validate integer digit limit and set/clear errors\r\n */\r\n private validateIntegerDigits(value: string, maxDecimals: number): void {\r\n if (this.field.type !== 'number' || !this.field.maxIntegerDigits) {\r\n return;\r\n }\r\n\r\n const maxIntDigits = this.field.maxIntegerDigits ?? 15;\r\n const [intPart] = value.includes('.') ? value.split('.') : [value];\r\n\r\n if (intPart.length > maxIntDigits) {\r\n this.setMaxIntegerDigitsError(intPart.length, maxIntDigits, maxDecimals);\r\n } else {\r\n this.clearMaxIntegerDigitsError();\r\n }\r\n }\r\n\r\n /**\r\n * Set max integer digits error\r\n */\r\n private setMaxIntegerDigitsError(actual: number, max: number, maxDecimals: number): void {\r\n const currentErrors = this.control.errors || {};\r\n this.control.setErrors({\r\n ...currentErrors,\r\n maxIntegerDigits: {\r\n actual,\r\n max,\r\n maxDecimals,\r\n message: `Please shorten your input to ${max} whole digits and ${maxDecimals} decimal or fewer.`,\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Clear max integer digits error if present\r\n */\r\n private clearMaxIntegerDigitsError(): void {\r\n if (!this.control.hasError('maxIntegerDigits')) {\r\n return;\r\n }\r\n\r\n const errors = { ...this.control.errors };\r\n delete errors['maxIntegerDigits'];\r\n this.control.setErrors(Object.keys(errors).length ? errors : null);\r\n }\r\n\r\n /**\r\n * Clear numeric error if present\r\n */\r\n private clearNumericError(): void {\r\n if (!this.control.hasError('numeric')) {\r\n return;\r\n }\r\n\r\n const errors = { ...this.control.errors };\r\n delete errors['numeric'];\r\n this.control.setErrors(Object.keys(errors).length ? errors : null);\r\n }\r\n\r\n /**\r\n * Set cursor position after paste operation\r\n */\r\n private setCursorAfterPaste(\r\n target: HTMLInputElement,\r\n filteredText: string,\r\n finalValue: string,\r\n ): void {\r\n // Input type=\"number\" does not support selection APIs\r\n if (target.type === 'number') {\r\n return;\r\n }\r\n\r\n const start = target.selectionStart || 0;\r\n const newCursorPos = start + filteredText.length;\r\n const actualPos = Math.min(newCursorPos, finalValue.length);\r\n target.setSelectionRange(actualPos, actualPos);\r\n }\r\n\r\n // Format number with comma separators\r\n // Uses string-based formatting for large numbers to preserve precision\r\n formatCurrencyWithCommas(value: number | string, maxDecimals: number = 2): string {\r\n if (this.field.type !== 'number' || !this.field.isCurrency) return value.toString();\r\n\r\n const strValue = value.toString();\r\n\r\n // Return original value for empty or invalid inputs\r\n if (!strValue || strValue === 'NaN') return '';\r\n\r\n // Use string-based formatting to preserve precision for large numbers\r\n const [integerPart, decimalPart] = strValue.includes('.')\r\n ? strValue.split('.')\r\n : [strValue, ''];\r\n\r\n // Format integer part with comma separators (every 3 digits from right)\r\n // Using iterative approach instead of regex to avoid ReDoS concerns\r\n let formattedInteger = '';\r\n const len = integerPart.length;\r\n for (let i = 0; i < len; i++) {\r\n if (i > 0 && (len - i) % 3 === 0) {\r\n formattedInteger += ',';\r\n }\r\n formattedInteger += integerPart[i];\r\n }\r\n // Format decimal part (pad or truncate to maxDecimals)\r\n let formattedDecimal = decimalPart || '';\r\n if (formattedDecimal.length < maxDecimals) {\r\n formattedDecimal = formattedDecimal.padEnd(maxDecimals, '0');\r\n } else if (formattedDecimal.length > maxDecimals) {\r\n formattedDecimal = formattedDecimal.slice(0, maxDecimals);\r\n }\r\n\r\n return maxDecimals > 0 ? `${formattedInteger}.${formattedDecimal}` : formattedInteger;\r\n }\r\n\r\n handleNumberKeydown(event: KeyboardEvent, isCurrency: boolean) {\r\n if (isCurrency) return;\r\n\r\n // Allow: Backspace, Delete, Tab, Arrow keys\r\n if (['Backspace', 'Delete', 'Tab', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {\r\n return;\r\n }\r\n\r\n // Allow clipboard operations (Ctrl+V, Ctrl+C, Ctrl+X, Cmd+V, Cmd+C, Cmd+X)\r\n // and selection (Ctrl+A, Cmd+A)\r\n if (event.ctrlKey || event.metaKey) {\r\n return;\r\n }\r\n\r\n // Block everything that is not 0-9\r\n if (!/^\\d$/.test(event.key)) {\r\n event.preventDefault();\r\n }\r\n }\r\n\r\n // Get locale from currency code using currencyMeta\r\n getLocaleFromCurrency(currencyCode?: string): string {\r\n const currencyObj = this.currencyMeta.find(\r\n (c: { code: string; locale: string }) => c.code === currencyCode,\r\n );\r\n\r\n return currencyObj?.locale || this.defaultLocale;\r\n }\r\n\r\n showPassword = false;\r\n passwordStrengthLabel = '';\r\n strengthClass = '';\r\n passwordStrengthPercent = 0;\r\n isPasswordFocused = false;\r\n onPasswordFocus(): void {\r\n this.hasFocus.set(true);\r\n this.isPasswordFocused = true;\r\n this.cdr.detectChanges();\r\n }\r\n\r\n onPasswordBlur(): void {\r\n this.isPasswordFocused = false;\r\n this.cdr.detectChanges();\r\n }\r\n\r\n handlePasswordBlur(e: Event): void {\r\n this.handleBlur(e); // Original blur functionality (sets hasFocus to false)\r\n this.onPasswordBlur(); // Hide password feedback\r\n }\r\n\r\n checkPasswordStrength(value: string) {\r\n if (!value || this.field.type !== 'password') {\r\n this.passwordStrengthLabel = '';\r\n this.strengthClass = '';\r\n this.passwordStrengthPercent = 0;\r\n\r\n return;\r\n }\r\n let score = 0;\r\n if (value.length >= 8) score++;\r\n if (/[A-Z]/.test(value)) score++;\r\n if (/\\d/.test(value)) score++;\r\n if (/[\\W_]/.test(value)) score++;\r\n\r\n if (score <= 1) {\r\n this.passwordStrengthLabel = this.field.weakLabel || 'Weak';\r\n this.strengthClass = 'text-[var(--RHB-Red-100)]';\r\n this.passwordStrengthPercent = 25;\r\n } else if (score === 2 || score === 3) {\r\n this.passwordStrengthLabel = this.field.mediumLabel || 'Medium';\r\n this.strengthClass = 'text-[var(--Orange-100)]';\r\n this.passwordStrengthPercent = score === 2 ? 50 : 75;\r\n } else {\r\n this.passwordStrengthLabel = this.field.strongLabel || 'Strong';\r\n this.strengthClass = 'text-[var(--Green-100)]';\r\n this.passwordStrengthPercent = 100;\r\n }\r\n }\r\n\r\n increment(): void {\r\n if (this.field.type !== 'number') return;\r\n const step = this.field.step || 1;\r\n const current = Number(this.control.value) || 0;\r\n let nextValue = current + step;\r\n\r\n if (typeof this.field.max === 'number') {\r\n nextValue = Math.min(nextValue, this.field.max);\r\n }\r\n\r\n this.control.setValue(nextValue);\r\n this.control.markAsTouched();\r\n this.valueChange.emit({ name: this.field.name, value: nextValue });\r\n\r\n // Update display value for currency inputs\r\n if (this.field.isCurrency) {\r\n setTimeout(() => {\r\n const inputElement = document.getElementById(this.uniqueId) as HTMLInputElement;\r\n if (inputElement) {\r\n inputElement.value = this.formatCurrencyWithCommas(nextValue);\r\n }\r\n });\r\n }\r\n }\r\n\r\n decrement(): void {\r\n if (this.field.type !== 'number') return;\r\n const step = this.field.step || 1;\r\n const current = Number(this.control.value) || 0;\r\n let nextValue = current - step;\r\n\r\n // Ensure minimum value is 0 (no negative values)\r\n const minValue = Math.max(this.field.min || 0, 0);\r\n nextValue = Math.max(nextValue, minValue);\r\n\r\n this.control.setValue(nextValue);\r\n this.control.markAsTouched();\r\n this.valueChange.emit({ name: this.field.name, value: nextValue });\r\n\r\n // Update display value for currency inputs\r\n if (this.field.isCurrency) {\r\n setTimeout(() => {\r\n const inputElement = document.getElementById(this.uniqueId) as HTMLInputElement;\r\n if (inputElement) {\r\n inputElement.value = this.formatCurrencyWithCommas(nextValue);\r\n }\r\n });\r\n }\r\n }\r\n\r\n copyText(e: Event): void {\r\n e.stopPropagation();\r\n if (!this.control.value) return;\r\n navigator.clipboard.writeText(this.control.value).then(() => {\r\n if (this.toastService) {\r\n this.toastService.success('Copied to clipboard', 'Success', 1000);\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * Set up visibility condition listener\r\n * Watches the dependent field and shows/hides this field based on conditions\r\n */\r\n setupVisibilityCondition(): void {\r\n if (!this.field.visibilityCondition || !this.form) return;\r\n\r\n const { dependsOn } = this.field.visibilityCondition;\r\n const dependentControl = this.form.get(dependsOn);\r\n\r\n if (!dependentControl) {\r\n return;\r\n }\r\n\r\n // Initial visibility check\r\n this.updateVisibility(dependentControl.value);\r\n\r\n // Subscribe to value changes\r\n dependentControl.valueChanges.subscribe((value) => {\r\n this.updateVisibility(value);\r\n });\r\n }\r\n\r\n /**\r\n * Update field visibility based on dependent field value\r\n */\r\n private updateVisibility(dependentValue: any): void {\r\n if (!this.field.visibilityCondition) return;\r\n\r\n const { showWhen, hideWhen } = this.field.visibilityCondition;\r\n let shouldBeVisible = false;\r\n\r\n // Check showWhen condition\r\n if (showWhen !== undefined) {\r\n if (Array.isArray(showWhen)) {\r\n shouldBeVisible = showWhen.includes(dependentValue);\r\n } else {\r\n shouldBeVisible = dependentValue === showWhen;\r\n }\r\n }\r\n\r\n // Check hideWhen condition (overrides showWhen)\r\n if (hideWhen !== undefined) {\r\n const shouldHide = Array.isArray(hideWhen)\r\n ? hideWhen.includes(dependentValue)\r\n : dependentValue === hideWhen;\r\n\r\n if (shouldHide) {\r\n shouldBeVisible = false;\r\n }\r\n }\r\n\r\n // Update visibility\r\n this.isVisible.set(shouldBeVisible);\r\n\r\n // Only clear value when hiding if there's no initial value\r\n // This preserves data when editing existing records\r\n if (!shouldBeVisible && this.control && !this.control.value) {\r\n this.control.setValue(null);\r\n this.control.markAsUntouched();\r\n this.control.updateValueAndValidity();\r\n }\r\n\r\n this.cdr.detectChanges();\r\n }\r\n\r\n showFormFieldMessage(control: any, helperText: string): boolean {\r\n if (this.helperHandle) {\r\n return this.helperHandle.showFormFieldMessage(control, helperText);\r\n }\r\n const isError = control?.touched && !!control?.errors;\r\n const isHelper = !isError && Boolean(helperText ?? '');\r\n return isError || isHelper;\r\n }\r\n\r\n getTranslatedLabel(label: string): string {\r\n if (!label) return '';\r\n try {\r\n const labelStr = label.toString();\r\n return (\r\n labelStr\r\n .split('::')\r\n .map((part) => part.trim())\r\n .filter((part) => !!part)\r\n .map((part) => this.translate.instant(part))\r\n .join(' ') + this.getEndSymbol(labelStr)\r\n );\r\n } catch (e) {\r\n console.warn('Translation failed in getTranslatedLabel:', label, e);\r\n return label;\r\n }\r\n }\r\n\r\n getEndSymbol(label: string): string {\r\n return label.toString().includes('required') && label.toString().includes('FNFieldMessage')\r\n ? '.'\r\n : '';\r\n }\r\n\r\n // --- ICON LOGIC ---\r\n private updateAllIcons(): void {\r\n // We'll call this after ViewInit or when inputs change\r\n setTimeout(() => {\r\n this.iconContainers?.forEach((container) => {\r\n const name = container.nativeElement.getAttribute('data-icon-name');\r\n const variant =\r\n (container.nativeElement.getAttribute('data-icon-variant') as TypeIconVariant) || 'Line';\r\n const size = (container.nativeElement.getAttribute('data-icon-size') ||\r\n 'medium') as TypeIconSizeName;\r\n const color = container.nativeElement.getAttribute('data-icon-color');\r\n const disabled = container.nativeElement.getAttribute('data-icon-disabled') === 'true';\r\n\r\n if (name) {\r\n this.loadIconToContainer(container.nativeElement, name, variant, size, color, disabled);\r\n }\r\n });\r\n }, 0);\r\n }\r\n\r\n private loadIconToContainer(\r\n container: HTMLElement,\r\n name: string,\r\n variant: TypeIconVariant,\r\n sizeName: TypeIconSizeName,\r\n color?: string | null,\r\n disabled?: boolean,\r\n ): void {\r\n const size = this.sizeMap[sizeName];\r\n const iconPath = this.getIconPath(name, variant, size);\r\n\r\n if (!iconPath) {\r\n container.innerHTML = '';\r\n return;\r\n }\r\n\r\n this.http.get(iconPath, { responseType: 'text' }).subscribe({\r\n next: (raw) => {\r\n try {\r\n const parser = new DOMParser();\r\n const doc = parser.parseFromString(raw, 'image/svg+xml');\r\n const svg = doc.querySelector('svg') as unknown as SVGSVGElement;\r\n\r\n if (!svg) {\r\n container.innerHTML = '';\r\n return;\r\n }\r\n\r\n // SVG Normalization logic\r\n for (const s of svg.querySelectorAll('style')) s.remove();\r\n\r\n if (color) {\r\n for (const el of svg.querySelectorAll<SVGElement>('*')) {\r\n const style = el.getAttribute('style');\r\n if (style) {\r\n const cleaned = style\r\n .replaceAll(/fill\\s*:\\s*[^;]+;?/gi, '')\r\n .replaceAll(/stroke\\s*:\\s*[^;]+;?/gi, '');\r\n if (cleaned) el.setAttribute('style', cleaned);\r\n else el.removeAttribute('style');\r\n }\r\n\r\n const fill = el.getAttribute('fill');\r\n if (fill && fill !== 'none' && !fill.startsWith('url(')) {\r\n el.setAttribute('fill', 'currentColor');\r\n }\r\n\r\n const stroke = el.getAttribute('stroke');\r\n if (stroke && stroke !== 'none' && !stroke.startsWith('url(')) {\r\n el.setAttribute('stroke', 'currentColor');\r\n }\r\n }\r\n }\r\n\r\n svg.removeAttribute('width');\r\n svg.removeAttribute('height');\r\n if (!svg.getAttribute('viewBox')) {\r\n svg.setAttribute('viewBox', `0 0 ${size} ${size}`);\r\n }\r\n svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');\r\n svg.setAttribute('focusable', 'false');\r\n svg.setAttribute('aria-hidden', 'true');\r\n svg.setAttribute('width', '100%');\r\n svg.setAttribute('height', '100%');\r\n\r\n const style = `;display:block;max-width:100%;max-height:100%;${disabled ? 'opacity:0.5;cursor:not-allowed;' : ''}`;\r\n svg.setAttribute('style', (svg.getAttribute('style') || '') + style);\r\n\r\n container.innerHTML = '';\r\n container.appendChild(svg);\r\n this.cdr.detectChanges();\r\n } catch (error) {\r\n console.error(`[fn-input] Error parsing SVG for icon \"${name}\":`, error);\r\n container.innerHTML = '';\r\n }\r\n },\r\n error: () => {\r\n container.innerHTML = '';\r\n this.cdr.detectChanges();\r\n },\r\n });\r\n }\r\n\r\n private getIconPath(icon: string, variant: TypeIconVariant, size: TypeIconSize): string | null {\r\n if (!icon) return null;\r\n if (size === 16 || size === 10) {\r\n return `assets/icons/${variant}/${size}px/${icon}.svg`;\r\n }\r\n return `assets/icons/${variant}/${size}px/${icon}--${size}.svg`;\r\n }\r\n\r\n // --- MESSAGE LOGIC ---\r\n getFieldMessage(): string {\r\n if (!this.control) return this.field?.helperText || '';\r\n\r\n if (this.control.touched && this.control.errors) {\r\n for (const key of Object.keys(this.control.errors)) {\r\n const errorValue = this.control.errors[key];\r\n if (errorValue && typeof errorValue === 'object' && errorValue.message) {\r\n return errorValue.message;\r\n }\r\n if (this.field?.errors?.[key]) {\r\n return this.field.errors[key];\r\n }\r\n }\r\n return (\r\n this.field?.errors?.['default'] ||\r\n 'Please enter ' + this.translate.instant(this.field?.label)\r\n );\r\n }\r\n\r\n return this.field?.helperText || '';\r\n }\r\n\r\n get isError(): boolean {\r\n return !!(this.control?.touched && this.control?.errors);\r\n }\r\n\r\n get isSuccess(): boolean {\r\n return !!(this.control?.valid && this.control?.touched);\r\n }\r\n}\r\n","@if (field.name && isVisible() && !field.hidden) {\r\n <div class=\"flex flex-col gap-2\">\r\n @if (field.type! !== 'hidden') {\r\n <label\r\n [for]=\"uniqueId\"\r\n class=\"fn-label !whitespace-normal\"\r\n [ngClass]=\"\r\n (field.statusLabel ? field.statusLabel : field.labelVariant || 'p4') +\r\n ' ' +\r\n (field.className || '')\r\n \"\r\n [style.color]=\"field.color || null\"\r\n >\r\n {{ getTranslatedLabel(field.label) }}\r\n @if (!field.required && !field.hideOptional) {\r\n <span>&nbsp;(Optional)</span>\r\n }\r\n </label>\r\n }\r\n\r\n <ng-container>\r\n @switch (field.type) {\r\n <!-- Textarea Field -->\r\n @case ('textarea') {\r\n <textarea\r\n #fnTextarea\r\n style=\"resize: none\"\r\n [name]=\"field.name\"\r\n [id]=\"uniqueId\"\r\n [required]=\"field.required || false\"\r\n [placeholder]=\"field.placeholder || '' | translate\"\r\n [disabled]=\"field.disabled || false\"\r\n [rows]=\"field.rows || 1\"\r\n [readonly]=\"field.readOnly || false\"\r\n [formControl]=\"control\"\r\n (input)=\"handleTextArea($event)\"\r\n (blur)=\"handleBlur($event)\"\r\n class=\"peer w-full leading-6 rounded-none border-0 border-b border-[var(--Base-30)] pb-1.75 bg-transparent text-base text-[var(--Base-100)] focus:outline-none focus:ring-0 placeholder:!text-[var(--Base-50)] placeholder:!text-base focus:[caret-color:var(--RHB-Blue-100)]\"\r\n [ngClass]=\"{\r\n 'opacity-100': control.disabled || field.readOnly,\r\n '!text-[var(--Base-30)]': control.disabled || field.readOnly,\r\n '!border-[var(--RHB-Blue-100)]': hasFocus(),\r\n '!border-[var(--RHB-Red-100)]': control.touched && control.errors,\r\n '!border-[var(--Green-100)]':\r\n field['hasSuccessBorder'] && control.valid && !control.errors,\r\n }\"\r\n (focus)=\"onFocus()\"\r\n ></textarea>\r\n }\r\n\r\n <!-- Password Field -->\r\n\r\n @case ('password') {\r\n <div class=\"relative w-full\">\r\n <input\r\n [type]=\"showPassword ? 'text' : 'password'\"\r\n [id]=\"uniqueId\"\r\n [required]=\"field.required || false\"\r\n [disabled]=\"field.disabled || false\"\r\n [formControl]=\"control\"\r\n [placeholder]=\"field.placeholder || '' | translate\"\r\n [readonly]=\"field.readOnly || false\"\r\n (input)=\"isAlphanumeric ? handleAlphanumericInput($event) : handleInput($event)\"\r\n (focus)=\"onPasswordFocus()\"\r\n (blur)=\"handlePasswordBlur($event)\"\r\n class=\"peer h-8 w-full leading-6 rounded-none border-0 border-b border-[var(--Base-30)] pb-1.75 bg-transparent text-base text-[var(--Base-100)] focus:outline-none focus:ring-0 placeholder:!text-[var(--Base-50)] placeholder:!text-base focus:[caret-color:var(--RHB-Blue-100)] overflow-hidden text-ellipsis\"\r\n [ngClass]=\"{\r\n 'opacity-100': control.disabled || field.readOnly,\r\n '!text-[var(--Base-30)]': control.disabled || field.readOnly,\r\n '!border-[var(--RHB-Blue-100)]': hasFocus() && !control.disabled,\r\n '!border-[var(--RHB-Red-100)]': control.touched && control.errors,\r\n '!border-[var(--Green-100)]': field['hasSuccessBorder'] && control.valid,\r\n 'pr-12': field.toggleMask && !field.isCopyText,\r\n 'pr-16': field.isCopyText && !field.toggleMask,\r\n 'pr-24': field.toggleMask && field.isCopyText && !field.hasGenerateKey,\r\n 'pr-32': field.toggleMask && field.isCopyText && field.hasGenerateKey,\r\n }\"\r\n />\r\n @if (field.toggleMask && !field.isCopyText) {\r\n <!-- Only Eye Icon -->\r\n <span\r\n class=\"absolute right-0 top-0 cursor-pointer text-[var(--Base-10)] hover:text-[var(--RHB-Blue-100)]\"\r\n (click)=\"showPassword = !showPassword\"\r\n (keydown)=\"showPassword = !showPassword\"\r\n >\r\n @if (!showPassword) {\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"eye-close\"\r\n data-icon-variant=\"Line\"\r\n data-icon-size=\"large\"\r\n data-icon-color=\"var(--Base-100)\"\r\n ></div>\r\n } @else {\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"eye-open\"\r\n data-icon-variant=\"Line\"\r\n data-icon-size=\"large\"\r\n data-icon-color=\"var(--Base-100)\"\r\n ></div>\r\n }\r\n </span>\r\n } @else if (field.isCopyText && !field.toggleMask) {\r\n <!-- Only Copy Icon -->\r\n <span\r\n class=\"absolute right-12 top-0 cursor-pointer text-[var(--Base-10)] hover:text-[var(--RHB-Blue-100)]\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <div #iconContainer class=\"icon-container\" data-icon-name=\"two-square\"></div>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"absolute right-4 top-0 cursor-pointer text-[var(--Base-10)] hover:text-[var(--RHB-Blue-100)]\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"two-square\"\r\n data-icon-variant=\"Line\"\r\n data-icon-size=\"large\"\r\n ></div>\r\n </span>\r\n }\r\n } @else if (field.toggleMask && field.isCopyText) {\r\n <!-- Both Eye + Copy Icons -->\r\n <span\r\n class=\"absolute right-20 top-0 cursor-pointer text-[var(--Base-10)] hover:text-[var(--RHB-Blue-100)]\"\r\n (click)=\"showPassword = !showPassword\"\r\n (keydown)=\"showPassword = !showPassword\"\r\n >\r\n @if (!showPassword) {\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"eye-close\"\r\n data-icon-variant=\"Line\"\r\n data-icon-size=\"large\"\r\n data-icon-color=\"var(--Base-100)\"\r\n ></div>\r\n } @else {\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"eye-open\"\r\n data-icon-variant=\"Line\"\r\n data-icon-size=\"large\"\r\n data-icon-color=\"var(--Base-100)\"\r\n ></div>\r\n }\r\n </span>\r\n\r\n <span\r\n class=\"absolute right-12 top-0 cursor-pointer text-[var(--Base-10)] hover:text-[var(--RHB-Blue-100)]\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <div #iconContainer class=\"icon-container\" data-icon-name=\"two-square\"></div>\r\n </span>\r\n\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"absolute right-4 top-0 text-[var(--Base-10)]\"\r\n [ngClass]=\"{\r\n 'cursor-pointer hover:text-[var(--RHB-Blue-100)]':\r\n control.value && control.value.length > 0,\r\n 'cursor-not-allowed opacity-50': !control.value || control.value.length === 0,\r\n }\"\r\n (click)=\"\r\n control.value &&\r\n control.value.length > 0 &&\r\n field.onGenerateKey &&\r\n field.onGenerateKey()\r\n \"\r\n (keydown)=\"\r\n control.value &&\r\n control.value.length > 0 &&\r\n field.onGenerateKey &&\r\n field.onGenerateKey()\r\n \"\r\n >\r\n <div\r\n #iconContainer\r\n class=\"icon-container\"\r\n data-icon-name=\"round-arrow-top-left\"\r\n ></div>\r\n </span>\r\n }\r\n }\r\n </div>\r\n }\r\n\r\n <!-- Number Field -->\r\n @case ('number') {\r\n <input\r\n [type]=\"field.type === 'number' && field.isCurrency ? 'text' : 'number'\"\r\n [name]=\"field.name\"\r\n [id]=\"uniqueId\"\r\n [required]=\"field.required || false\"\r\n [placeholder]=\"field.placeholder || '' | translate\"\r\n [disabled]=\"isDisabled || false\"\r\n [readOnly]=\"field.readOnly || false\"\r\n [formControl]=\"control\"\r\n [min]=\"field.type === 'number' && !field.isCurrency ? 0 : null\"\r\n [max]=\"field.type === 'number' && !field.isCurrency ? field.max : null\"\r\n [step]=\"field.type === 'number' && !field.isCurrency ? field.step || 1 : null\"\r\n (input)=\"handleNumberInput($event, field?.minFractionDigits || 2)\"\r\n (paste)=\"handleNumberPaste($event, field?.minFractionDigits || 2)\"\r\n (blur)=\"handleBlur($event, field?.minFractionDigits || 2)\"\r\n (keydown)=\"handleNumberKeydown($event, field?.isCurrency || false)\"\r\n class=\"peer h-8 w-full leading-6 rounded-none border-0 border-b border-[var(--Base-30)] pb-1.75 bg-transparent text-base text-[var(--Base-100)] focus:outline-none focus:ring-0 placeholder:!text-[var(--Base-50)] placeholder:!text-base focus:[caret-color:var(--RHB-Blue-100)]\"\r\n [ngClass]=\"{\r\n 'opacity-100': control.disabled || field.readOnly,\r\n '!text-[var(--Base-30)]': control.disabled || field.readOnly,\r\n '!border-[var(--RHB-Blue-100)]': hasFocus(),\r\n '!border-[var(--RHB-Red-100)]': control.touched && control.errors,\r\n '!border-[var(--Green-100)]':\r\n field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'text-[24px] font-bold leading-[32px]': field.isCurrency,\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n }\r\n\r\n <!-- Default Input Field (text, email, etc.) -->\r\n @default {\r\n <div class=\"relative z-0\">\r\n <input\r\n [type]=\"field.type\"\r\n [name]=\"field.name\"\r\n [id]=\"uniqueId\"\r\n [required]=\"field.required || false\"\r\n [placeholder]=\"field.placeholder || '' | translate\"\r\n [disabled]=\"field.disabled || false\"\r\n [readOnly]=\"field.readOnly || false\"\r\n [formControl]=\"control\"\r\n (input)=\"\r\n isEmailField\r\n ? handleEmailInput($event)\r\n : field.type === 'text' && isAlphanumeric\r\n ? handleAlphanumericInput($event)\r\n : handleInput($event)\r\n \"\r\n (blur)=\"handleBlur($event)\"\r\n class=\"peer h-8 w-full leading-6 rounded-none border-0 border-b border-[var(--Base-30)] pb-1.75 bg-transparent text-base text-[var(--Base-100)] focus:outline-none focus:ring-0 placeholder:!text-[var(--Base-50)] placeholder:!text-base focus:[caret-color:var(--RHB-Blue-100)]\"\r\n [ngClass]=\"{\r\n 'opacity-100': control.disabled || field.readOnly,\r\n '!text-[var(--Base-30)]': control.disabled || field.readOnly,\r\n '!border-[var(--RHB-Blue-100)]': hasFocus(),\r\n '!border-[var(--RHB-Red-100)]': control.touched && control.errors,\r\n '!border-[var(--Green-100)]':\r\n field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pr-8': field.icon,\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n @if (field.icon) {\r\n <span class=\"absolute bottom-2 right-0.5 flex items-center\">\r\n <div\r\n #iconContainer\r\n class=\"bg-white\"\r\n [attr.data-icon-name]=\"field.icon.name\"\r\n [attr.data-icon-variant]=\"field.icon.variant\"\r\n [attr.data-icon-size]=\"getIconSizeName(field.icon.size)\"\r\n [attr.data-icon-color]=\"control.disabled ? 'var(--Base-30)' : ''\"\r\n ></div>\r\n </span>\r\n }\r\n </div>\r\n }\r\n }\r\n </ng-container>\r\n\r\n @if (showFormFieldMessage(control, helperText)) {\r\n <div class=\"fn-field-message-container\">\r\n <span\r\n class=\"fn-field-message-text\"\r\n [ngClass]=\"{\r\n error: isError,\r\n success: isSuccess,\r\n }\"\r\n >\r\n {{ getFieldMessage() | translate }}\r\n </span>\r\n </div>\r\n }\r\n </div>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "fn-input",
3
+ "version": "0.0.1",
4
+ "description": "Reusable Angular standalone component for rendering field validation and helper messages.",
5
+ "peerDependencies": {
6
+ "@angular/common": ">=17.0.0",
7
+ "@angular/core": ">=17.0.0",
8
+ "@ngx-translate/core": ">=17.0.0"
9
+ },
10
+ "dependencies": {
11
+ "tslib": "^2.3.0"
12
+ },
13
+ "sideEffects": false,
14
+ "module": "fesm2022/fn-input.mjs",
15
+ "typings": "types/fn-input.d.ts",
16
+ "exports": {
17
+ "./package.json": {
18
+ "default": "./package.json"
19
+ },
20
+ ".": {
21
+ "types": "./types/fn-input.d.ts",
22
+ "default": "./fesm2022/fn-input.mjs"
23
+ }
24
+ }
25
+ }
@@ -0,0 +1,290 @@
1
+ import * as _angular_core from '@angular/core';
2
+ import { OnInit, AfterViewInit, OnDestroy, OnChanges, EventEmitter, ElementRef, QueryList, ChangeDetectorRef, SimpleChanges } from '@angular/core';
3
+ import { HttpClient } from '@angular/common/http';
4
+ import { ValidatorFn, FormGroup, FormControl } from '@angular/forms';
5
+ import { TranslateService } from '@ngx-translate/core';
6
+
7
+ type TypeIconVariant = 'Colour' | 'Duotone' | 'Fill' | 'Line';
8
+ type TypeIconSize = 10 | 16 | 20 | 24 | 32 | 48;
9
+ type TypeLabelVariant = 'h1' | 'h1Bold' | 'h2' | 'h2Bold' | 'h3' | 'h3Bold' | 'p1' | 'p1Bold' | 'p2' | 'p2Bold' | 'p3' | 'p3Bold' | 'p4' | 'p4Bold' | 'interactionLarge' | 'interactionLargeBold' | 'interactionMedium' | 'interactionMediumBold' | 'interactionSmall' | 'interactionSmallBold' | 'avatarLabel';
10
+ type TypeStatusLabel = 'Standard' | 'Success' | 'Hot' | 'Warning' | 'Disabled' | 'RHBPremierBanking';
11
+ interface FNInputAffix {
12
+ icon?: string;
13
+ text?: string;
14
+ onClick?: (e: Event) => void;
15
+ }
16
+ interface FNInputVisibilityCondition {
17
+ dependsOn: string;
18
+ showWhen: any | any[];
19
+ hideWhen?: any | any[];
20
+ }
21
+ interface FNInputCommonProps<T = any> {
22
+ fieldType: 'FNInput';
23
+ name: string;
24
+ label: string;
25
+ placeholder?: string;
26
+ className?: string;
27
+ required?: boolean;
28
+ value?: T;
29
+ disabled?: boolean;
30
+ hidden?: boolean;
31
+ readOnly?: boolean;
32
+ floatLabelVariant?: 'in' | 'over' | 'on';
33
+ validators?: ValidatorFn[];
34
+ errors?: {
35
+ [key: string]: string;
36
+ };
37
+ rows?: number;
38
+ prefix?: FNInputAffix;
39
+ suffix?: FNInputAffix;
40
+ hasSuccessBorder?: boolean;
41
+ visibilityCondition?: FNInputVisibilityCondition;
42
+ helperText?: string;
43
+ isAlphanumeric?: boolean;
44
+ hideOptional?: boolean;
45
+ isAddressLine?: boolean;
46
+ color?: string;
47
+ labelVariant?: TypeLabelVariant;
48
+ statusLabel?: TypeStatusLabel;
49
+ }
50
+ interface FNTextInputProps<T = any> extends FNInputCommonProps<T> {
51
+ type: 'text' | 'email' | 'textarea' | 'hidden';
52
+ cols?: number;
53
+ maxLength?: number;
54
+ icon?: {
55
+ name: string;
56
+ variant: TypeIconVariant;
57
+ size: TypeIconSize;
58
+ };
59
+ }
60
+ interface FNPasswordProps extends FNInputCommonProps<string> {
61
+ type: 'password';
62
+ toggleMask?: boolean;
63
+ feedback?: boolean;
64
+ weakLabel?: string;
65
+ mediumLabel?: string;
66
+ strongLabel?: string;
67
+ isCopyText?: boolean;
68
+ hasGenerateKey?: boolean;
69
+ onGenerateKey?: () => void;
70
+ }
71
+ interface FNInputNumberProps extends FNInputCommonProps<number> {
72
+ type: 'number';
73
+ min?: number;
74
+ max?: number;
75
+ step?: number;
76
+ minFractionDigits?: number;
77
+ maxFractionDigits?: number;
78
+ currency?: string;
79
+ currencyDisplay?: 'symbol' | 'code' | 'name';
80
+ locale?: string;
81
+ useGrouping?: boolean;
82
+ mode?: 'decimal' | 'currency';
83
+ showButtons?: boolean;
84
+ buttonLayout?: 'stacked' | 'horizontal' | 'vertical';
85
+ incrementButtonIcon?: string;
86
+ decrementButtonIcon?: string;
87
+ isCurrency?: boolean;
88
+ maxIntegerDigits?: number;
89
+ }
90
+ type FNInputBase = FNTextInputProps | FNPasswordProps | FNInputNumberProps;
91
+ interface FNInputHelper {
92
+ showFormFieldMessage: (control: any, helperText: string) => boolean;
93
+ }
94
+ interface FNInputToast {
95
+ success: (message: string, title?: string, duration?: number) => string;
96
+ error: (message: string, title?: string, duration?: number) => string;
97
+ }
98
+ declare const DEFAULT_CURRENCY_META: {
99
+ code: string;
100
+ locale: string;
101
+ symbol: string;
102
+ digit: string;
103
+ }[];
104
+
105
+ type TypeIconSizeName = 'extrasmall' | 'small' | 'medium' | 'large' | 'x-large' | 'xxlarge';
106
+ declare class FNInput implements OnInit, AfterViewInit, OnDestroy, OnChanges {
107
+ private readonly cdr;
108
+ field: FNInputBase;
109
+ helperHandle?: FNInputHelper;
110
+ toastService?: FNInputToast;
111
+ currencyMeta: {
112
+ code: string;
113
+ locale: string;
114
+ symbol: string;
115
+ digit: string;
116
+ }[];
117
+ defaultLocale: string;
118
+ form: FormGroup;
119
+ valueChange: EventEmitter<any>;
120
+ fieldBlur: EventEmitter<any>;
121
+ translate: TranslateService;
122
+ hasFocus: _angular_core.WritableSignal<boolean>;
123
+ textareaElement: ElementRef<HTMLTextAreaElement>;
124
+ iconContainers: QueryList<ElementRef<HTMLElement>>;
125
+ http: HttpClient;
126
+ private readonly subs;
127
+ private readonly sizeMap;
128
+ getIconSizeName(size: number): 'small' | 'medium' | 'large' | 'x-large';
129
+ get isAlphanumeric(): boolean;
130
+ get isEmailField(): boolean;
131
+ private get alphanumericPattern();
132
+ isDisabled: boolean;
133
+ control: FormControl;
134
+ isVisible: _angular_core.WritableSignal<boolean>;
135
+ helperText: string;
136
+ private static idCounter;
137
+ uniqueId: string;
138
+ constructor(cdr: ChangeDetectorRef);
139
+ ngOnInit(): void;
140
+ ngOnDestroy(): void;
141
+ ngOnChanges(changes: SimpleChanges): void;
142
+ private setupFieldMessageListener;
143
+ ngAfterViewInit(): void;
144
+ enforceLowercase(event: Event): void;
145
+ /**
146
+ * Handle email input - allows only valid email characters and enforces lowercase.
147
+ * Allowed: a-z, 0-9, . _ + - @
148
+ * Rules:
149
+ * - Only one @ allowed
150
+ * - No consecutive dots (..)
151
+ * - Automatic lowercase
152
+ */
153
+ handleEmailInput(event: Event): void;
154
+ onFocus(): void;
155
+ private formatInitialCurrencyValue;
156
+ initFormControl(): void;
157
+ autoResizeInitial(): void;
158
+ handleTextArea(event: Event): void;
159
+ handleInput(event: Event): void;
160
+ /**
161
+ * Handle alphanumeric input - allows only letters, numbers, and specific special characters
162
+ * Allowed: A-Z, a-z, 0-9, space, hyphen, underscore, ampersand, and parentheses
163
+ * Also prevents leading spaces and multiple consecutive spaces
164
+ */
165
+ handleAlphanumericInput(event: Event): void;
166
+ handleBlur(e: Event, maxDecimals?: number): void;
167
+ /**
168
+ * Handle blur for text and textarea fields - trim trailing spaces
169
+ */
170
+ private handleTextFieldBlur;
171
+ /**
172
+ * Handle blur for number fields - validate and format
173
+ */
174
+ private handleNumberFieldBlur;
175
+ /**
176
+ * Process currency value - handle formatting and decimal places
177
+ */
178
+ private processCurrencyValue;
179
+ /**
180
+ * Format decimal places - pad or truncate to maxDecimals
181
+ */
182
+ private formatDecimalPlaces;
183
+ handleNumberInput(event: Event, maxDecimals?: number): void;
184
+ /**
185
+ * Filter numeric input to only allow digits and decimal point
186
+ * Ensures only one decimal point and enforces max decimal places
187
+ */
188
+ private filterNumericInput;
189
+ /**
190
+ * Ensure only one decimal point exists in the value
191
+ */
192
+ private filterDecimalPoints;
193
+ /**
194
+ * Enforce maximum decimal places limit
195
+ */
196
+ private enforceDecimalLimit;
197
+ /**
198
+ * Update cursor position after filtering input
199
+ */
200
+ private updateCursorPositionAfterFilter;
201
+ /**
202
+ * Update form control value and perform validation
203
+ */
204
+ private updateFormControlValue;
205
+ /**
206
+ * Count how many characters were removed before the cursor position
207
+ * This helps maintain correct cursor position after filtering input
208
+ */
209
+ private countRemovedCharsBeforeCursor;
210
+ /**
211
+ * Handle paste event for number inputs
212
+ * Prevents pasting of non-numeric characters and enforces digit limits
213
+ */
214
+ handleNumberPaste(event: ClipboardEvent, maxDecimals?: number): void;
215
+ /**
216
+ * Filter pasted text for currency input (allows digits and decimal point)
217
+ */
218
+ private getFilteredCurrencyPastedText;
219
+ /**
220
+ * Filter pasted text for integer-only input (allows digits only)
221
+ */
222
+ private getFilteredIntegerPastedText;
223
+ /**
224
+ * Build final value after paste operation
225
+ */
226
+ private buildFinalPasteValue;
227
+ /**
228
+ * Apply decimal restrictions for currency fields
229
+ */
230
+ private applyDecimalRestrictions;
231
+ /**
232
+ * Validate integer digit limit and set/clear errors
233
+ */
234
+ private validateIntegerDigits;
235
+ /**
236
+ * Set max integer digits error
237
+ */
238
+ private setMaxIntegerDigitsError;
239
+ /**
240
+ * Clear max integer digits error if present
241
+ */
242
+ private clearMaxIntegerDigitsError;
243
+ /**
244
+ * Clear numeric error if present
245
+ */
246
+ private clearNumericError;
247
+ /**
248
+ * Set cursor position after paste operation
249
+ */
250
+ private setCursorAfterPaste;
251
+ formatCurrencyWithCommas(value: number | string, maxDecimals?: number): string;
252
+ handleNumberKeydown(event: KeyboardEvent, isCurrency: boolean): void;
253
+ getLocaleFromCurrency(currencyCode?: string): string;
254
+ showPassword: boolean;
255
+ passwordStrengthLabel: string;
256
+ strengthClass: string;
257
+ passwordStrengthPercent: number;
258
+ isPasswordFocused: boolean;
259
+ onPasswordFocus(): void;
260
+ onPasswordBlur(): void;
261
+ handlePasswordBlur(e: Event): void;
262
+ checkPasswordStrength(value: string): void;
263
+ increment(): void;
264
+ decrement(): void;
265
+ copyText(e: Event): void;
266
+ /**
267
+ * Set up visibility condition listener
268
+ * Watches the dependent field and shows/hides this field based on conditions
269
+ */
270
+ setupVisibilityCondition(): void;
271
+ /**
272
+ * Update field visibility based on dependent field value
273
+ */
274
+ private updateVisibility;
275
+ showFormFieldMessage(control: any, helperText: string): boolean;
276
+ getTranslatedLabel(label: string): string;
277
+ getEndSymbol(label: string): string;
278
+ private updateAllIcons;
279
+ private loadIconToContainer;
280
+ private getIconPath;
281
+ getFieldMessage(): string;
282
+ get isError(): boolean;
283
+ get isSuccess(): boolean;
284
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<FNInput, never>;
285
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<FNInput, "fn-input", never, { "field": { "alias": "field"; "required": false; }; "helperHandle": { "alias": "helperHandle"; "required": false; }; "toastService": { "alias": "toastService"; "required": false; }; "currencyMeta": { "alias": "currencyMeta"; "required": false; }; "defaultLocale": { "alias": "defaultLocale"; "required": false; }; "form": { "alias": "form"; "required": false; }; }, { "valueChange": "valueChange"; "fieldBlur": "fieldBlur"; }, never, never, true, never>;
286
+ }
287
+
288
+ export { DEFAULT_CURRENCY_META, FNInput };
289
+ export type { FNInputAffix, FNInputBase, FNInputCommonProps, FNInputHelper, FNInputNumberProps, FNInputToast, FNInputVisibilityCondition, FNPasswordProps, FNTextInputProps, TypeIconSize, TypeIconSizeName, TypeIconVariant, TypeLabelVariant, TypeStatusLabel };
290
+ //# sourceMappingURL=fn-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fn-input.d.ts","sources":["../../../projects/fn-input/src/lib/fn-input.types.ts","../../../projects/fn-input/src/lib/fn-input.component.ts"],"sourcesContent":[null,null],"names":[],"mappings":";;;;;;AAEM,KAAA,eAAA;AACA,KAAA,YAAA;AAEA,KAAA,gBAAA;AAuBA,KAAA,eAAA;;;;;AAYL;;;AAIC;AACA;AACD;AAEK,UAAA,kBAAA;;;;;;;;;;;AAWJ;AACA,iBAAA,WAAA;AACA;AAAW;;;;;;;;;;;;;;AAaZ;AAEK,UAAA,gBAAA,kBAAA,kBAAA;;;;AAIJ;;;;;AAKD;;;;;;;;;;AAWC;AACD;;;;;;;;;AAUC;;;AAGA;;AAEA;;;;;AAKD;AAEK,KAAA,WAAA,GAAA,gBAAA,GAAA,eAAA,GAAA,kBAAA;;;AAIL;;AAGC;AACA;AACD;AAED,cAAA,qBAAA;;;;;;;AChGM,KAAA,gBAAA;AAEN,cAAA,OAAA,YAAA,MAAA,EAAA,aAAA,EAAA,SAAA,EAAA,SAAA;;;;;;;;;;AAYgD;AACrC;;AAEC,iBAAA,YAAA;AACA,eAAA,YAAA;AAEV,eAAA,gBAAA;AACA,cAAQ,aAAA,CAAA,cAAA;AACiB,qBAAA,UAAA,CAAA,mBAAA;;AAGzB,UAAA,UAAA;AACA;AAEA;;;;;AAwCA;;AAEA,eAAS,aAAA,CAAA,cAAA;AACT;AAGA;AACA;AAE6B,qBAAA,iBAAA;AAE7B;AAUA;AAIA,yBAAA,aAAA;AAMA;AAkBA;;AA2BA;;;;;;;AAOG;AACH,4BAAA,KAAA;AA0DA;AAIA;;;AAkDA,0BAAA,KAAA;AAqEA,uBAAA,KAAA;AAwEA;;;;AAIG;AACH,mCAAA,KAAA;;AAyDA;;AAEG;AACH;AAWA;;AAEG;AACH;AA2BA;;AAEG;AACH;AA+BA;;AAEG;AACH;;AAiCA;;;AAGG;AACH;AAaA;;AAEG;AACH;AAQA;;AAEG;AACH;AAYA;;AAEG;AACH;AAoBA;;AAEG;AACH;AAMA;;;AAGG;AACH;AAmBA;;;AAGG;;AAyBH;;AAEG;AACH;AAIA;;AAEG;AACH;AAIA;;AAEG;AACH;AAsBA;;AAEG;AACH;AAoBA;;AAEG;AACH;AAeA;;AAEG;AACH;AAaA;;AAEG;AACH;AAUA;;AAEG;AACH;AAUA;;AAEG;AACH;;AAoDA,+BAAA,aAAA;AAqBA;AAQA;AACA;AACA;AACA;AACA;AACA;AAMA;AAKA,0BAAA,KAAA;;AAkCA;AAyBA;AAyBA,gBAAA,KAAA;AAUA;;;AAGG;AACH;AAmBA;;AAEG;AACH;;AAiDA;AAkBA;AAOA;AAmBA;AAmFA;AASA;;;;;AA6BD;;;;"}