fn-input 0.0.15 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  - **Unified Solution**: Combines label, input, icons, and validation messages.
10
10
  - **Standalone**: No project-level modules required.
11
11
  - **Dynamic Icons**: Supports SVG icons with variant and size configurations via `@arpudhabotupload/fn-icon-angular`.
12
- - **Intelligent Validation**: Automatic error and helper message rendering based on `FormControl` status.
12
+ - **Intelligent Validation**: Automatic error and helper message rendering managed by the `fn-field-message` component.
13
13
  - **Advanced Input Types**:
14
14
  - **Text & Textarea**:
15
15
  - **Alphanumeric Filtering**: Restrict input to alphanumeric characters with custom patterns (e.g., address lines).
@@ -35,7 +35,7 @@
35
35
  Install the library and its peer dependencies:
36
36
 
37
37
  ```bash
38
- npm install fn-input fn-label fn-toast @arpudhabotupload/fn-icon-angular @ngx-translate/core rxjs
38
+ npm install fn-input fn-label fn-toast fn-field-message @arpudhabotupload/fn-icon-angular @ngx-translate/core rxjs
39
39
  ```
40
40
 
41
41
  ---
@@ -9,6 +9,7 @@ import { TranslateService, TranslateModule } from '@ngx-translate/core';
9
9
  import { Subscription, merge } from 'rxjs';
10
10
  import { startWith } from 'rxjs/operators';
11
11
  import { FNLabel } from 'fn-label';
12
+ import { FNFieldMessage } from 'fn-field-message';
12
13
  import { FNIconComponent } from '@arpudhabotupload/fn-icon-angular';
13
14
  import { ToastService, FNToast } from 'fn-toast';
14
15
 
@@ -149,28 +150,28 @@ class FNInput {
149
150
  */
150
151
  handleEmailInput(event) {
151
152
  const input = event.target;
152
- const cursorPosition = input.selectionStart || 0;
153
153
  const originalValue = input.value;
154
+ const cursorPosition = input.selectionStart || 0;
154
155
  // 1. Convert to lowercase
155
- const lowerValue = originalValue.toLowerCase();
156
+ let filteredValue = originalValue.toLowerCase();
156
157
  // 2. Split at the first @ to handle local and domain parts separately
157
- const parts = lowerValue.split('@');
158
+ const parts = filteredValue.split('@');
158
159
  let localPart = parts[0];
159
160
  let domainPart = parts.length > 1 ? parts.slice(1).join('') : null;
160
- // 3. Filter local part: a-z, 0-9, ., _, +, -
161
+ // 3. Filter local part: a-z, 0-9, ., _, +, -, space
161
162
  // Rule: Cannot start with a dot (.)
162
- localPart = localPart.replaceAll(/[^a-z0-9._+-]/g, '');
163
+ localPart = localPart.replaceAll(/[^a-z0-9._+\-\s]/g, '');
163
164
  while (localPart.startsWith('.')) {
164
165
  localPart = localPart.substring(1);
165
166
  }
166
167
  while (localPart.includes('..')) {
167
168
  localPart = localPart.replaceAll('..', '.');
168
169
  }
169
- // 4. Filter domain part: a-z, 0-9, ., -
170
+ // 4. Filter domain part: a-z, 0-9, ., -, space
170
171
  // Rule: No underscores (_), no plus signs (+), cannot start with a hyphen (-)
171
- let filteredValue = localPart;
172
+ filteredValue = localPart;
172
173
  if (domainPart !== null) {
173
- domainPart = domainPart.replaceAll(/[^a-z0-9.-]/g, '');
174
+ domainPart = domainPart.replaceAll(/[^a-z0-9.\-\s]/g, '');
174
175
  while (domainPart.startsWith('-')) {
175
176
  domainPart = domainPart.substring(1);
176
177
  }
@@ -179,24 +180,16 @@ class FNInput {
179
180
  }
180
181
  filteredValue += '@' + domainPart;
181
182
  }
183
+ // 5. Sync with DOM if changed
182
184
  if (originalValue !== filteredValue) {
183
- const charsRemovedBeforeCursor = this.countRemovedCharsBeforeCursor(originalValue.toLowerCase(), filteredValue, cursorPosition);
184
- input.value = filteredValue;
185
- this.control.setValue(filteredValue, { emitEvent: false });
186
- const newCursorPos = Math.max(0, cursorPosition - charsRemovedBeforeCursor);
187
- input.setSelectionRange(newCursorPos, newCursorPos);
188
- }
189
- else if (originalValue !== lowerValue) {
190
- // If only case changed (e.g., typed Uppercase)
191
185
  input.value = filteredValue;
192
- this.control.setValue(filteredValue, { emitEvent: false });
193
186
  input.setSelectionRange(cursorPosition, cursorPosition);
194
187
  }
195
- if (this.field.type === 'password' && this.field.feedback) {
196
- this.checkPasswordStrength(filteredValue);
197
- }
198
- this.valueChange.emit({ name: this.field.name, value: filteredValue });
188
+ // 6. Always sync with control to ensure validation runs (including spaces)
189
+ this.control.setValue(filteredValue);
199
190
  this.control.markAsTouched();
191
+ this.cdr.markForCheck();
192
+ this.valueChange.emit({ name: this.field.name, value: filteredValue });
200
193
  }
201
194
  onFocus() {
202
195
  this.hasFocus.set(true);
@@ -277,7 +270,6 @@ class FNInput {
277
270
  let filteredValue = originalValue;
278
271
  // Strict filtering if !isAlphanumeric
279
272
  if (!this.isAlphanumeric) {
280
- console.log('isAlphanumeric', this.isAlphanumeric);
281
273
  const allowedPattern = /[^a-zA-Z0-9\s(){}[\];,."='+\-*/<>!&|%_@$?:]/g;
282
274
  filteredValue = filteredValue.replaceAll(allowedPattern, '');
283
275
  }
@@ -310,30 +302,7 @@ class FNInput {
310
302
  const cursorPosition = target.selectionStart;
311
303
  const originalValue = target.value;
312
304
  let filteredValue = originalValue;
313
- // IF NOT alphanumeric, user wants strict filtering:
314
- // "only accept tihs.) {} [] ; , . " ' = + - * / < > ! & | % &_( )-/.;@!, $% : dont allow emoji"
315
- // Interpretation: Allow alphanumeric + specified special chars. Ban emojis.
316
- // Actually, the user said: "if isAlphanumeric false only accept..."
317
- // So if isAlphanumeric is TRUE, we use the existing handleAlphanumericInput logic (or similar).
318
- // The current logic in handleInput is generic.
319
- // The existing code has a separate `handleAlphanumericInput` method but it's not called here?
320
- // Wait, the template likely calls `handleAlphanumericInput` if `isAlphanumeric` is true, or `handleInput` otherwise?
321
- // Let's check the template.
322
- // BUT assuming `handleInput` is the generic handler:
323
305
  if (!this.isAlphanumeric) {
324
- // Regex to allow: a-z, A-Z, 0-9, and: ) {} [] ; , . " ' = + - * / < > ! & | % _ ( - @ $ ? :
325
- // Note: User list: `.` `"` `'` `?` (wait, ? not in list?)
326
- // User list: `) {} [] ; , . " ' = + - * / < > ! & | % &_( )-/.;@!, $%`
327
- // Uniques: ) { } [ ] ; , . " ' = + - * / < > ! & | % _ ( @ $
328
- // (The `&` is repeated, `.` repeated, `,` repeated etc.)
329
- // I will create a regex that matches anything NOT in this list and replace with empty string.
330
- // [^a-zA-Z0-9\s(){}[\];,."='+\-*/<>!&|%_@$]
331
- // Note: `*`, `+`, `?` etc need escaping in regex if outside [], but inside [] they are literals mostly.
332
- // `-` needs to be last or escaped. `]` needs escape. `^` needs escape if first? No, invalid here.
333
- // Let's verify valid chars:
334
- // a-z A-Z 0-9
335
- // space
336
- // ) { } [ ] ; , . " ' = + - * / < > ! & | % _ ( @ $ :
337
306
  const allowedPattern = /[^a-zA-Z0-9\s(){}[\];,."='+\-*/<>!&|%_@$?:]/g;
338
307
  filteredValue = filteredValue.replaceAll(allowedPattern, '');
339
308
  }
@@ -353,9 +322,6 @@ class FNInput {
353
322
  target.setSelectionRange(newCursorPos, newCursorPos);
354
323
  }
355
324
  // Trailing spaces will be trimmed on blur, not during input
356
- if (this.field.type === 'password' && this.field.feedback) {
357
- this.checkPasswordStrength(filteredValue);
358
- }
359
325
  this.valueChange.emit({ name: this.field.name, value: filteredValue });
360
326
  this.control.markAsTouched();
361
327
  }
@@ -941,9 +907,7 @@ class FNInput {
941
907
  if (this.helperHandle) {
942
908
  return this.helperHandle.showFormFieldMessage(control, helperText);
943
909
  }
944
- const isError = control?.touched && !!control?.errors;
945
- const isHelper = !isError && Boolean(helperText ?? '');
946
- return isError || isHelper;
910
+ return true;
947
911
  }
948
912
  getTranslatedLabel(label) {
949
913
  if (!label)
@@ -967,34 +931,8 @@ class FNInput {
967
931
  ? '.'
968
932
  : '';
969
933
  }
970
- // Removed getIconPath as HTTP loading is disabled
971
- // --- MESSAGE LOGIC ---
972
- getFieldMessage() {
973
- if (!this.control)
974
- return this.field?.helperText || '';
975
- if (this.control.touched && this.control.errors) {
976
- for (const key of Object.keys(this.control.errors)) {
977
- const errorValue = this.control.errors[key];
978
- if (errorValue && typeof errorValue === 'object' && errorValue.message) {
979
- return errorValue.message;
980
- }
981
- if (this.field?.errors?.[key]) {
982
- return this.field.errors[key];
983
- }
984
- }
985
- return (this.field?.errors?.['default'] ||
986
- 'Please enter ' + this.translateService.instant(this.field?.label));
987
- }
988
- return this.field?.helperText || '';
989
- }
990
- get isError() {
991
- return !!(this.control?.touched && this.control?.errors);
992
- }
993
- get isSuccess() {
994
- return !!(this.control?.valid && this.control?.touched);
995
- }
996
934
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: FNInput, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
997
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: FNInput, isStandalone: true, selector: "fn-input", inputs: { field: "field", helperHandle: "helperHandle", toastService: "toastService", currencyMeta: "currencyMeta", defaultLocale: "defaultLocale", form: "form" }, outputs: { valueChange: "valueChange", fieldBlur: "fieldBlur" }, viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["fnTextarea"], descendants: true }], ngImport: i0, template: "@if (field.name && isVisible() && !field.hidden) {\r\n <div class=\"fn-input-container\">\r\n @if (field.type! !== 'hidden') {\r\n <fn-label\r\n [for]=\"uniqueId\"\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n [color]=\"field.color || '#03182b'\"\r\n [variant]=\"field.labelVariant || 'p1'\"\r\n [statusLabel]=\"field.statusLabel\"\r\n ></fn-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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n ></textarea>\r\n }\r\n\r\n <!-- Password Field -->\r\n @case ('password') {\r\n <div class=\"relative w-full\">\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\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=\"fn-input-field overflow-hidden text-ellipsis\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-12':\r\n (field.toggleMask && !field.isCopyText) ||\r\n (!field.toggleMask && field.isCopyText),\r\n 'pr-24': field.toggleMask && field.isCopyText && !field.hasGenerateKey,\r\n 'pr-32': field.toggleMask && field.isCopyText && field.hasGenerateKey,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.toggleMask && !field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n } @else if (field.isCopyText && !field.toggleMask) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon\r\n [name]=\"'round-arrow-top-left'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n }\r\n } @else if (field.toggleMask && field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n [ngClass]=\"{ 'opacity-50 cursor-not-allowed': !control.value }\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (field.feedback && isPasswordFocused) {\r\n <div class=\"mt-2 space-y-1\">\r\n <div class=\"flex items-center justify-between text-xs\">\r\n <span class=\"font-medium\" [ngClass]=\"strengthClass\">\r\n {{ passwordStrengthLabel | translate }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <fn-icon\r\n [name]=\"passwordStrengthPercent > 50 ? 'check-circle' : 'info-circle'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'extrasmall'\"\r\n [color]=\"\r\n passwordStrengthPercent <= 25\r\n ? '#ef3e42'\r\n : passwordStrengthPercent <= 75\r\n ? '#ff9f00'\r\n : '#6cc24a'\r\n \"\r\n ></fn-icon>\r\n </div>\r\n </div>\r\n <div class=\"h-1.5 w-full bg-[#eef0f2] rounded-full overflow-hidden\">\r\n <div\r\n class=\"h-full transition-all duration-300 rounded-full\"\r\n [ngClass]=\"{\r\n 'bg-[#ef3e42]': passwordStrengthPercent <= 25,\r\n 'bg-[#ff9f00]': passwordStrengthPercent > 25 && passwordStrengthPercent <= 75,\r\n 'bg-[#6cc24a]': passwordStrengthPercent > 75,\r\n }\"\r\n [style.width.%]=\"passwordStrengthPercent\"\r\n ></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Number Field -->\r\n @case ('number') {\r\n <div class=\"relative w-full\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10': field.suffix?.icon && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'text-[24px] font-bold': field.isCurrency,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Default Input Field (text, email, etc.) -->\r\n @default {\r\n <div class=\"relative z-0\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10':\r\n (field.icon || field.suffix?.icon) && !field.isCopyText && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'pr-20':\r\n field.isCopyText && !field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-30':\r\n field.isCopyText && field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-32':\r\n field.isCopyText && field.hasGenerateKey && (field.icon || field.suffix?.icon),\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n\r\n @if (field.icon || field.suffix?.icon || field.suffix?.text) {\r\n @if (field.suffix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"suffixClick($event)\"\r\n (keydown.enter)=\"suffixClick($event)\"\r\n [attr.tabindex]=\"field.suffix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.suffix?.onClick\"\r\n >{{ field.suffix!.text }}</span\r\n >\r\n }\r\n @if (field.icon || field.suffix?.icon) {\r\n <fn-icon\r\n [name]=\"field.suffix?.icon || field.icon?.name || ''\"\r\n [variant]=\"field.icon?.variant || 'Line'\"\r\n [size]=\"field.icon ? getIconSizeName(field.icon.size) : 'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n }\r\n </div>\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 <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n", styles: [".fn-input-container{display:flex;flex-direction:column;width:100%}.fn-label{font-family:Outfit,sans-serif;font-weight:500;margin-bottom:8px;display:flex;align-items:center}.fn-label span{color:#c4cdd2;font-size:14px;font-weight:400}.fn-input-field{width:100%;height:48px;padding:0 16px;background-color:#f7f8f9;border-bottom:1.5px solid #c4cdd2;font-family:Outfit,sans-serif;font-size:16px;color:#03182b;transition:all .2s ease;border-radius:4px 4px 0 0}.fn-input-field::placeholder{color:#c4cdd2}.fn-input-field:focus{outline:none;background-color:#fff;border-bottom-color:#03182b}.fn-input-field.error{border-bottom-color:#ef3e42}.fn-input-field.success{border-bottom-color:#6cc24a}.fn-input-field.disabled{background-color:#eef0f2;color:#c4cdd2;cursor:not-allowed}.fn-input-field.pl-10{padding-left:40px!important}.fn-input-field.has-prefix-text{padding-left:100px!important}.fn-input-field.pr-10{padding-right:40px!important}.fn-input-field.has-suffix-text{padding-right:120px!important}.fn-input-field.pr-12{padding-right:44px!important}.fn-input-field.pr-20{padding-right:72px!important}.fn-input-field.pr-24{padding-right:88px!important}.fn-input-field.pr-30{padding-right:104px!important}.fn-input-field.pr-32{padding-right:120px!important}.fn-field-message-container{margin-top:4px}.fn-field-message-text{font-family:Outfit,sans-serif;font-size:12px;color:#c4cdd2}.fn-field-message-text.error{color:#ef3e42}.fn-field-message-text.success{color:#6cc24a}.icon-container{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px}.relative{position:relative}.absolute{position:absolute}.right-0{right:0}.left-0{left:0}.top-1\\/2{top:50%}.-translate-y-1\\/2{transform:translateY(-50%)}.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.pr-3{padding-right:.75rem}.pl-3{padding-left:.75rem}.mt-2{margin-top:.5rem}.space-y-1>:not([hidden])~:not([hidden]){margin-top:.25rem}.text-xs{font-size:.75rem}.font-medium{font-weight:500}.h-1\\.5{height:.375rem}.w-full{width:100%}.bg-\\[\\#eef0f2\\]{background-color:#eef0f2}.rounded-full{border-radius:9999px}.overflow-hidden{overflow:hidden}.transition-all{transition-property:all}.duration-300{transition-duration:.3s}.cursor-pointer{cursor:pointer}.opacity-50{opacity:.5}.cursor-not-allowed{cursor:not-allowed}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: FNLabel, selector: "fn-label", inputs: ["field", "label", "required", "className", "class", "for", "color", "variant", "statusLabel", "ngClass", "hideOptional"] }, { kind: "component", type: FNIconComponent, selector: "fn-icon", inputs: ["name", "variant", "size", "color", "strokeWidth", "disabled", "className", "basePath"] }, { kind: "component", type: FNToast, selector: "fn-toast" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
935
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.19", type: FNInput, isStandalone: true, selector: "fn-input", inputs: { field: "field", helperHandle: "helperHandle", toastService: "toastService", currencyMeta: "currencyMeta", defaultLocale: "defaultLocale", form: "form" }, outputs: { valueChange: "valueChange", fieldBlur: "fieldBlur" }, viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["fnTextarea"], descendants: true }], ngImport: i0, template: "@if (field.name && isVisible() && !field.hidden) {\r\n <div class=\"flex flex-col gap-2\">\r\n @if (field.type! !== 'hidden') {\r\n <fn-label\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [class]=\"'!text-[var(--Base-70)]'\"\r\n [variant]=\"'p4'\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n ></fn-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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"two-square\" variant=\"Line\" size=\"large\"></fn-icon>\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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"round-arrow-top-left\" color=\"var(--Base-100)\"></fn-icon>\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]=\"isEmailField ? 'text' : 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 <fn-icon\r\n class=\"bg-white\"\r\n [name]=\"field.icon.name\"\r\n [variant]=\"field.icon.variant\"\r\n [size]=\"getIconSizeName(field.icon.size)\"\r\n [color]=\"control.disabled ? 'var(--Base-30)' : ''\"\r\n ></fn-icon>\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 <fn-field-message\r\n [control]=\"control\"\r\n [field]=\"field\"\r\n [hasFocus]=\"hasFocus()\"\r\n ></fn-field-message>\r\n }\r\n </div>\r\n\r\n <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n", styles: [":host{--RHB-Premier-Blue-100: #002353;--RHB-Premier-Silver-100: #c1cdd8;--RHB-Blue-10: #ebf7ff;--RHB-Blue-20: #def1ff;--RHB-Blue-30: #bbe3ff;--RHB-Blue-40: #99d4ff;--RHB-Blue-50: #78c5ff;--RHB-Blue-60: #5cb5f9;--RHB-Blue-70: #3d9ee9;--RHB-Blue-80: #258bdd;--RHB-Blue-90: #0b77ca;--RHB-Blue-100: #0067b1;--RHB-Blue-200: #0158a0;--RHB-Blue-300: #004b90;--RHB-Blue-400: #003d75;--RHB-Blue-500: #003362;--RHB-Light-Blue-10: #eff9fd;--RHB-Light-Blue-100: #5bc2e7;--RHB-Red-10: #ffeeee;--RHB-Red-20: #fed7db;--RHB-Red-30: #fec0c9;--RHB-Red-40: #fda9b6;--RHB-Red-50: #fc91a3;--RHB-Red-60: #fc7a91;--RHB-Red-70: #fb637e;--RHB-Red-80: #f85a6f;--RHB-Red-90: #f55160;--RHB-Red-100: #ef3e42;--RHB-Red-200: #d72f32;--RHB-Red-300: #bf1f21;--RHB-Red-400: #a61011;--RHB-Red-500: #860000;--Green-10: #f0f9ed;--Green-20: #e2f3db;--Green-30: #d3edc9;--Green-40: #c4e7b7;--Green-50: #b5e1a4;--Green-60: #a7da92;--Green-70: #98d480;--Green-80: #89ce6e;--Green-90: #7bc85c;--Green-100: #6cc24a;--Green-200: #54af30;--Green-300: #2b8809;--Green-400: #065c00;--Green-500: #004300;--Green-600: #519c66;--Orange-10: #fff4eb;--Orange-20: #fdebda;--Orange-30: #fbe2c9;--Orange-40: #f9d8b9;--Orange-50: #f7cfa8;--Orange-60: #f4c697;--Orange-70: #f2bd86;--Orange-80: #f0b376;--Orange-90: #eeaa65;--Orange-100: #eca154;--Orange-200: #eb8a22;--Orange-300: #ed6c1c;--Orange-400: #de4e01;--Orange-500: #c0410b;--Purple-10: #f9f7ff;--Purple-20: #e7e4f4;--Purple-30: #d7d3e9;--Purple-40: #c6c3df;--Purple-50: #b6b3d4;--Purple-60: #a6a3c9;--Purple-70: #9692be;--Purple-80: #8682b3;--Purple-90: #7572a9;--Purple-100: #615e9b;--Purple-200: #555193;--Purple-300: #48448b;--Purple-400: #3c3782;--Purple-500: #2f2a7a;--Base-0: #ffffff;--Base-10: #eef0f2;--Base-20: #e0e4e9;--Base-30: #c4cdd2;--Base-40: #9aa3aa;--Base-50: #818c95;--Base-60: #687480;--Base-70: #4f5d6b;--Base-80: #354655;--Base-90: #1c2f40;--Base-100: #03182b;--Gradient-top: #91d6ef}.fn-input-container{display:flex;flex-direction:column;width:100%;gap:.5rem}.peer{appearance:none}.fn-input-field,.peer{width:100%;line-height:1.5rem;border-radius:0;border:0;border-bottom:1px solid var(--Base-30);padding-bottom:.4375rem;background-color:transparent;font-size:1rem;color:var(--Base-100);font-family:Outfit,sans-serif;transition:all .2s ease}.fn-input-field::placeholder,.peer::placeholder{color:var(--Base-50)!important;font-size:1rem!important}.fn-input-field:focus,.peer:focus{outline:none;box-shadow:none;caret-color:var(--RHB-Blue-100);border-bottom-color:var(--RHB-Blue-100)!important}.fn-input-field.opacity-100,.peer.opacity-100{opacity:1}.fn-input-field.\\!text-\\[var\\(--Base-30\\)\\],.peer.\\!text-\\[var\\(--Base-30\\)\\]{color:var(--Base-30)!important}.fn-input-field.\\!border-\\[var\\(--RHB-Blue-100\\)\\],.peer.\\!border-\\[var\\(--RHB-Blue-100\\)\\]{border-bottom-color:var(--RHB-Blue-100)!important}.fn-input-field.\\!border-\\[var\\(--RHB-Red-100\\)\\],.peer.\\!border-\\[var\\(--RHB-Red-100\\)\\]{border-bottom-color:var(--RHB-Red-100)!important}.fn-input-field.\\!border-\\[var\\(--Green-100\\)\\],.peer.\\!border-\\[var\\(--Green-100\\)\\]{border-bottom-color:var(--Green-100)!important}.fn-input-field.pr-12,.peer.pr-12{padding-right:3rem!important}.fn-input-field.pr-16,.peer.pr-16{padding-right:4rem!important}.fn-input-field.pr-24,.peer.pr-24{padding-right:6rem!important}.fn-input-field.pr-32,.peer.pr-32{padding-right:8rem!important}.fn-input-field.pr-8,.peer.pr-8{padding-right:2rem!important}.font-bold{font-weight:700}.leading-\\[32px\\]{line-height:32px}.text-\\[24px\\]{font-size:24px}.relative{position:relative}.absolute{position:absolute}.right-0{right:0}.right-4{right:1rem}.right-12{right:3rem}.right-20{right:5rem}.top-0{top:0}.bottom-2{bottom:.5rem}.right-0\\.5{right:.125rem}.cursor-pointer{cursor:pointer}.cursor-not-allowed{cursor:not-allowed}.opacity-50{opacity:.5}.text-\\[var\\(--Base-10\\)\\]{color:var(--Base-10)}.hover\\:text-\\[var\\(--RHB-Blue-100\\)\\]:hover{color:var(--RHB-Blue-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.items-center{align-items:center}.bg-white{background-color:var(--Base-0)}.z-0{z-index:0}.\\!text-\\[var\\(--Base-70\\)\\]{color:var(--Base-70)!important}.text-\\[var\\(--RHB-Red-100\\)\\]{color:var(--RHB-Red-100)}.text-\\[var\\(--Orange-100\\)\\]{color:var(--Orange-100)}.text-\\[var\\(--Green-100\\)\\]{color:var(--Green-100)}.overflow-hidden{overflow:hidden}.text-ellipsis{text-overflow:ellipsis}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "component", type: FNLabel, selector: "fn-label", inputs: ["field", "label", "required", "className", "class", "for", "color", "variant", "statusLabel", "ngClass", "hideOptional"] }, { kind: "component", type: FNFieldMessage, selector: "fn-field-message", inputs: ["field", "control", "hasFocus"] }, { kind: "component", type: FNIconComponent, selector: "fn-icon", inputs: ["name", "variant", "size", "color", "strokeWidth", "disabled", "className", "basePath"] }, { kind: "component", type: FNToast, selector: "fn-toast" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
998
936
  }
999
937
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImport: i0, type: FNInput, decorators: [{
1000
938
  type: Component,
@@ -1004,9 +942,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.19", ngImpo
1004
942
  ReactiveFormsModule,
1005
943
  TranslateModule,
1006
944
  FNLabel,
945
+ FNFieldMessage,
1007
946
  FNIconComponent,
1008
947
  FNToast,
1009
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field.name && isVisible() && !field.hidden) {\r\n <div class=\"fn-input-container\">\r\n @if (field.type! !== 'hidden') {\r\n <fn-label\r\n [for]=\"uniqueId\"\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n [color]=\"field.color || '#03182b'\"\r\n [variant]=\"field.labelVariant || 'p1'\"\r\n [statusLabel]=\"field.statusLabel\"\r\n ></fn-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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n ></textarea>\r\n }\r\n\r\n <!-- Password Field -->\r\n @case ('password') {\r\n <div class=\"relative w-full\">\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\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=\"fn-input-field overflow-hidden text-ellipsis\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-12':\r\n (field.toggleMask && !field.isCopyText) ||\r\n (!field.toggleMask && field.isCopyText),\r\n 'pr-24': field.toggleMask && field.isCopyText && !field.hasGenerateKey,\r\n 'pr-32': field.toggleMask && field.isCopyText && field.hasGenerateKey,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.toggleMask && !field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n } @else if (field.isCopyText && !field.toggleMask) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon\r\n [name]=\"'round-arrow-top-left'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n }\r\n } @else if (field.toggleMask && field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n [ngClass]=\"{ 'opacity-50 cursor-not-allowed': !control.value }\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (field.feedback && isPasswordFocused) {\r\n <div class=\"mt-2 space-y-1\">\r\n <div class=\"flex items-center justify-between text-xs\">\r\n <span class=\"font-medium\" [ngClass]=\"strengthClass\">\r\n {{ passwordStrengthLabel | translate }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <fn-icon\r\n [name]=\"passwordStrengthPercent > 50 ? 'check-circle' : 'info-circle'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'extrasmall'\"\r\n [color]=\"\r\n passwordStrengthPercent <= 25\r\n ? '#ef3e42'\r\n : passwordStrengthPercent <= 75\r\n ? '#ff9f00'\r\n : '#6cc24a'\r\n \"\r\n ></fn-icon>\r\n </div>\r\n </div>\r\n <div class=\"h-1.5 w-full bg-[#eef0f2] rounded-full overflow-hidden\">\r\n <div\r\n class=\"h-full transition-all duration-300 rounded-full\"\r\n [ngClass]=\"{\r\n 'bg-[#ef3e42]': passwordStrengthPercent <= 25,\r\n 'bg-[#ff9f00]': passwordStrengthPercent > 25 && passwordStrengthPercent <= 75,\r\n 'bg-[#6cc24a]': passwordStrengthPercent > 75,\r\n }\"\r\n [style.width.%]=\"passwordStrengthPercent\"\r\n ></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Number Field -->\r\n @case ('number') {\r\n <div class=\"relative w-full\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10': field.suffix?.icon && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'text-[24px] font-bold': field.isCurrency,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Default Input Field (text, email, etc.) -->\r\n @default {\r\n <div class=\"relative z-0\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10':\r\n (field.icon || field.suffix?.icon) && !field.isCopyText && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'pr-20':\r\n field.isCopyText && !field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-30':\r\n field.isCopyText && field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-32':\r\n field.isCopyText && field.hasGenerateKey && (field.icon || field.suffix?.icon),\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n\r\n @if (field.icon || field.suffix?.icon || field.suffix?.text) {\r\n @if (field.suffix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"suffixClick($event)\"\r\n (keydown.enter)=\"suffixClick($event)\"\r\n [attr.tabindex]=\"field.suffix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.suffix?.onClick\"\r\n >{{ field.suffix!.text }}</span\r\n >\r\n }\r\n @if (field.icon || field.suffix?.icon) {\r\n <fn-icon\r\n [name]=\"field.suffix?.icon || field.icon?.name || ''\"\r\n [variant]=\"field.icon?.variant || 'Line'\"\r\n [size]=\"field.icon ? getIconSizeName(field.icon.size) : 'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n }\r\n </div>\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 <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n", styles: [".fn-input-container{display:flex;flex-direction:column;width:100%}.fn-label{font-family:Outfit,sans-serif;font-weight:500;margin-bottom:8px;display:flex;align-items:center}.fn-label span{color:#c4cdd2;font-size:14px;font-weight:400}.fn-input-field{width:100%;height:48px;padding:0 16px;background-color:#f7f8f9;border-bottom:1.5px solid #c4cdd2;font-family:Outfit,sans-serif;font-size:16px;color:#03182b;transition:all .2s ease;border-radius:4px 4px 0 0}.fn-input-field::placeholder{color:#c4cdd2}.fn-input-field:focus{outline:none;background-color:#fff;border-bottom-color:#03182b}.fn-input-field.error{border-bottom-color:#ef3e42}.fn-input-field.success{border-bottom-color:#6cc24a}.fn-input-field.disabled{background-color:#eef0f2;color:#c4cdd2;cursor:not-allowed}.fn-input-field.pl-10{padding-left:40px!important}.fn-input-field.has-prefix-text{padding-left:100px!important}.fn-input-field.pr-10{padding-right:40px!important}.fn-input-field.has-suffix-text{padding-right:120px!important}.fn-input-field.pr-12{padding-right:44px!important}.fn-input-field.pr-20{padding-right:72px!important}.fn-input-field.pr-24{padding-right:88px!important}.fn-input-field.pr-30{padding-right:104px!important}.fn-input-field.pr-32{padding-right:120px!important}.fn-field-message-container{margin-top:4px}.fn-field-message-text{font-family:Outfit,sans-serif;font-size:12px;color:#c4cdd2}.fn-field-message-text.error{color:#ef3e42}.fn-field-message-text.success{color:#6cc24a}.icon-container{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px}.relative{position:relative}.absolute{position:absolute}.right-0{right:0}.left-0{left:0}.top-1\\/2{top:50%}.-translate-y-1\\/2{transform:translateY(-50%)}.flex{display:flex}.items-center{align-items:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-2{gap:.5rem}.pr-3{padding-right:.75rem}.pl-3{padding-left:.75rem}.mt-2{margin-top:.5rem}.space-y-1>:not([hidden])~:not([hidden]){margin-top:.25rem}.text-xs{font-size:.75rem}.font-medium{font-weight:500}.h-1\\.5{height:.375rem}.w-full{width:100%}.bg-\\[\\#eef0f2\\]{background-color:#eef0f2}.rounded-full{border-radius:9999px}.overflow-hidden{overflow:hidden}.transition-all{transition-property:all}.duration-300{transition-duration:.3s}.cursor-pointer{cursor:pointer}.opacity-50{opacity:.5}.cursor-not-allowed{cursor:not-allowed}.text-ellipsis{text-overflow:ellipsis}.whitespace-nowrap{white-space:nowrap}\n"] }]
948
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (field.name && isVisible() && !field.hidden) {\r\n <div class=\"flex flex-col gap-2\">\r\n @if (field.type! !== 'hidden') {\r\n <fn-label\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [class]=\"'!text-[var(--Base-70)]'\"\r\n [variant]=\"'p4'\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n ></fn-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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"two-square\" variant=\"Line\" size=\"large\"></fn-icon>\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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"round-arrow-top-left\" color=\"var(--Base-100)\"></fn-icon>\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]=\"isEmailField ? 'text' : 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 <fn-icon\r\n class=\"bg-white\"\r\n [name]=\"field.icon.name\"\r\n [variant]=\"field.icon.variant\"\r\n [size]=\"getIconSizeName(field.icon.size)\"\r\n [color]=\"control.disabled ? 'var(--Base-30)' : ''\"\r\n ></fn-icon>\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 <fn-field-message\r\n [control]=\"control\"\r\n [field]=\"field\"\r\n [hasFocus]=\"hasFocus()\"\r\n ></fn-field-message>\r\n }\r\n </div>\r\n\r\n <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n", styles: [":host{--RHB-Premier-Blue-100: #002353;--RHB-Premier-Silver-100: #c1cdd8;--RHB-Blue-10: #ebf7ff;--RHB-Blue-20: #def1ff;--RHB-Blue-30: #bbe3ff;--RHB-Blue-40: #99d4ff;--RHB-Blue-50: #78c5ff;--RHB-Blue-60: #5cb5f9;--RHB-Blue-70: #3d9ee9;--RHB-Blue-80: #258bdd;--RHB-Blue-90: #0b77ca;--RHB-Blue-100: #0067b1;--RHB-Blue-200: #0158a0;--RHB-Blue-300: #004b90;--RHB-Blue-400: #003d75;--RHB-Blue-500: #003362;--RHB-Light-Blue-10: #eff9fd;--RHB-Light-Blue-100: #5bc2e7;--RHB-Red-10: #ffeeee;--RHB-Red-20: #fed7db;--RHB-Red-30: #fec0c9;--RHB-Red-40: #fda9b6;--RHB-Red-50: #fc91a3;--RHB-Red-60: #fc7a91;--RHB-Red-70: #fb637e;--RHB-Red-80: #f85a6f;--RHB-Red-90: #f55160;--RHB-Red-100: #ef3e42;--RHB-Red-200: #d72f32;--RHB-Red-300: #bf1f21;--RHB-Red-400: #a61011;--RHB-Red-500: #860000;--Green-10: #f0f9ed;--Green-20: #e2f3db;--Green-30: #d3edc9;--Green-40: #c4e7b7;--Green-50: #b5e1a4;--Green-60: #a7da92;--Green-70: #98d480;--Green-80: #89ce6e;--Green-90: #7bc85c;--Green-100: #6cc24a;--Green-200: #54af30;--Green-300: #2b8809;--Green-400: #065c00;--Green-500: #004300;--Green-600: #519c66;--Orange-10: #fff4eb;--Orange-20: #fdebda;--Orange-30: #fbe2c9;--Orange-40: #f9d8b9;--Orange-50: #f7cfa8;--Orange-60: #f4c697;--Orange-70: #f2bd86;--Orange-80: #f0b376;--Orange-90: #eeaa65;--Orange-100: #eca154;--Orange-200: #eb8a22;--Orange-300: #ed6c1c;--Orange-400: #de4e01;--Orange-500: #c0410b;--Purple-10: #f9f7ff;--Purple-20: #e7e4f4;--Purple-30: #d7d3e9;--Purple-40: #c6c3df;--Purple-50: #b6b3d4;--Purple-60: #a6a3c9;--Purple-70: #9692be;--Purple-80: #8682b3;--Purple-90: #7572a9;--Purple-100: #615e9b;--Purple-200: #555193;--Purple-300: #48448b;--Purple-400: #3c3782;--Purple-500: #2f2a7a;--Base-0: #ffffff;--Base-10: #eef0f2;--Base-20: #e0e4e9;--Base-30: #c4cdd2;--Base-40: #9aa3aa;--Base-50: #818c95;--Base-60: #687480;--Base-70: #4f5d6b;--Base-80: #354655;--Base-90: #1c2f40;--Base-100: #03182b;--Gradient-top: #91d6ef}.fn-input-container{display:flex;flex-direction:column;width:100%;gap:.5rem}.peer{appearance:none}.fn-input-field,.peer{width:100%;line-height:1.5rem;border-radius:0;border:0;border-bottom:1px solid var(--Base-30);padding-bottom:.4375rem;background-color:transparent;font-size:1rem;color:var(--Base-100);font-family:Outfit,sans-serif;transition:all .2s ease}.fn-input-field::placeholder,.peer::placeholder{color:var(--Base-50)!important;font-size:1rem!important}.fn-input-field:focus,.peer:focus{outline:none;box-shadow:none;caret-color:var(--RHB-Blue-100);border-bottom-color:var(--RHB-Blue-100)!important}.fn-input-field.opacity-100,.peer.opacity-100{opacity:1}.fn-input-field.\\!text-\\[var\\(--Base-30\\)\\],.peer.\\!text-\\[var\\(--Base-30\\)\\]{color:var(--Base-30)!important}.fn-input-field.\\!border-\\[var\\(--RHB-Blue-100\\)\\],.peer.\\!border-\\[var\\(--RHB-Blue-100\\)\\]{border-bottom-color:var(--RHB-Blue-100)!important}.fn-input-field.\\!border-\\[var\\(--RHB-Red-100\\)\\],.peer.\\!border-\\[var\\(--RHB-Red-100\\)\\]{border-bottom-color:var(--RHB-Red-100)!important}.fn-input-field.\\!border-\\[var\\(--Green-100\\)\\],.peer.\\!border-\\[var\\(--Green-100\\)\\]{border-bottom-color:var(--Green-100)!important}.fn-input-field.pr-12,.peer.pr-12{padding-right:3rem!important}.fn-input-field.pr-16,.peer.pr-16{padding-right:4rem!important}.fn-input-field.pr-24,.peer.pr-24{padding-right:6rem!important}.fn-input-field.pr-32,.peer.pr-32{padding-right:8rem!important}.fn-input-field.pr-8,.peer.pr-8{padding-right:2rem!important}.font-bold{font-weight:700}.leading-\\[32px\\]{line-height:32px}.text-\\[24px\\]{font-size:24px}.relative{position:relative}.absolute{position:absolute}.right-0{right:0}.right-4{right:1rem}.right-12{right:3rem}.right-20{right:5rem}.top-0{top:0}.bottom-2{bottom:.5rem}.right-0\\.5{right:.125rem}.cursor-pointer{cursor:pointer}.cursor-not-allowed{cursor:not-allowed}.opacity-50{opacity:.5}.text-\\[var\\(--Base-10\\)\\]{color:var(--Base-10)}.hover\\:text-\\[var\\(--RHB-Blue-100\\)\\]:hover{color:var(--RHB-Blue-100)}.flex{display:flex}.flex-col{flex-direction:column}.gap-2{gap:.5rem}.items-center{align-items:center}.bg-white{background-color:var(--Base-0)}.z-0{z-index:0}.\\!text-\\[var\\(--Base-70\\)\\]{color:var(--Base-70)!important}.text-\\[var\\(--RHB-Red-100\\)\\]{color:var(--RHB-Red-100)}.text-\\[var\\(--Orange-100\\)\\]{color:var(--Orange-100)}.text-\\[var\\(--Green-100\\)\\]{color:var(--Green-100)}.overflow-hidden{overflow:hidden}.text-ellipsis{text-overflow:ellipsis}\n"] }]
1010
949
  }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { field: [{
1011
950
  type: Input
1012
951
  }], helperHandle: [{
@@ -1 +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 { InjectionToken } from '@angular/core';\r\nimport { ValidatorFn } from '@angular/forms';\r\nimport { Observable } from 'rxjs';\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;\r\n hideWhen?: 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 labelSize?: string;\r\n valueColor?: string;\r\n valueSize?: string;\r\n isCopyText?: boolean;\r\n hasGenerateKey?: boolean;\r\n onGenerateKey?: () => void;\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}\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 translate: (key: string) => string;\r\n}\r\n\r\nimport { Toast, ToastService } from 'fn-toast';\r\n\r\nexport interface FNInputToast extends ToastService {}\r\n\r\nexport const FN_TOAST_SERVICE = new InjectionToken<FNInputToast>('FN_TOAST_SERVICE');\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} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n// Removed HttpClient import\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 { FNLabel } from 'fn-label';\r\nimport { FNIconComponent } from '@arpudhabotupload/fn-icon-angular';\r\nimport { FNToast, ToastService } from 'fn-toast';\r\nimport {\r\n FNInputBase,\r\n FNInputHelper,\r\n FNInputToast,\r\n DEFAULT_CURRENCY_META,\r\n TypeIconSize,\r\n FN_TOAST_SERVICE,\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: [\r\n FormsModule,\r\n CommonModule,\r\n ReactiveFormsModule,\r\n TranslateModule,\r\n FNLabel,\r\n FNIconComponent,\r\n FNToast,\r\n ],\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 {\r\n @Input() field = {} as FNInputBase;\r\n @Input() helperHandle?: FNInputHelper;\r\n @Input() toastService?: FNInputToast;\r\n private readonly fallbackToastService = inject(ToastService, { optional: true });\r\n private readonly injectedToastService = inject(FN_TOAST_SERVICE, { optional: true });\r\n\r\n get effectiveToastService(): FNInputToast | undefined {\r\n return this.toastService || this.injectedToastService || this.fallbackToastService || undefined;\r\n }\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 translateService = inject(TranslateService);\r\n hasFocus = signal(false);\r\n @ViewChild('fnTextarea') textareaElement!: ElementRef<HTMLTextAreaElement>;\r\n\r\n // Removed local Toast State\r\n\r\n // Removed HttpClient injection\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 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 if (this.field.type === 'password' && this.field.feedback) {\r\n this.checkPasswordStrength(filteredValue);\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 togglePasswordVisibility(): void {\r\n this.showPassword = !this.showPassword;\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: `.` `\"` `'` `?` (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 if (this.field.type === 'password' && this.field.feedback) {\r\n this.checkPasswordStrength(filteredValue);\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 /**\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 if (this.field.type === 'password' && this.field.feedback) {\r\n this.checkPasswordStrength(filteredValue);\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 const service = this.effectiveToastService;\r\n if (service) {\r\n // Position set to top as requested\r\n service.success('Copied to clipboard', 'Success', 2000);\r\n }\r\n });\r\n }\r\n\r\n prefixClick(e: Event): void {\r\n if (this.field.prefix?.onClick) {\r\n this.field.prefix.onClick(e);\r\n }\r\n }\r\n\r\n suffixClick(e: Event): void {\r\n if (this.field.suffix?.onClick) {\r\n this.field.suffix.onClick(e);\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 // Removed local toast helpers\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.translateService.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 // Removed getIconPath as HTTP loading is disabled\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.translateService.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=\"fn-input-container\">\r\n @if (field.type! !== 'hidden') {\r\n <fn-label\r\n [for]=\"uniqueId\"\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n [color]=\"field.color || '#03182b'\"\r\n [variant]=\"field.labelVariant || 'p1'\"\r\n [statusLabel]=\"field.statusLabel\"\r\n ></fn-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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n ></textarea>\r\n }\r\n\r\n <!-- Password Field -->\r\n @case ('password') {\r\n <div class=\"relative w-full\">\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\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=\"fn-input-field overflow-hidden text-ellipsis\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-12':\r\n (field.toggleMask && !field.isCopyText) ||\r\n (!field.toggleMask && field.isCopyText),\r\n 'pr-24': field.toggleMask && field.isCopyText && !field.hasGenerateKey,\r\n 'pr-32': field.toggleMask && field.isCopyText && field.hasGenerateKey,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.toggleMask && !field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n } @else if (field.isCopyText && !field.toggleMask) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon\r\n [name]=\"'round-arrow-top-left'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n }\r\n } @else if (field.toggleMask && field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"togglePasswordVisibility()\"\r\n (keydown)=\"togglePasswordVisibility()\"\r\n >\r\n <fn-icon\r\n [name]=\"showPassword ? 'eye-open' : 'eye-close'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'large'\"\r\n [color]=\"'#03182b'\"\r\n ></fn-icon>\r\n </span>\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n [ngClass]=\"{ 'opacity-50 cursor-not-allowed': !control.value }\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n </div>\r\n </div>\r\n\r\n @if (field.feedback && isPasswordFocused) {\r\n <div class=\"mt-2 space-y-1\">\r\n <div class=\"flex items-center justify-between text-xs\">\r\n <span class=\"font-medium\" [ngClass]=\"strengthClass\">\r\n {{ passwordStrengthLabel | translate }}\r\n </span>\r\n <div class=\"flex items-center gap-1\">\r\n <fn-icon\r\n [name]=\"passwordStrengthPercent > 50 ? 'check-circle' : 'info-circle'\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'extrasmall'\"\r\n [color]=\"\r\n passwordStrengthPercent <= 25\r\n ? '#ef3e42'\r\n : passwordStrengthPercent <= 75\r\n ? '#ff9f00'\r\n : '#6cc24a'\r\n \"\r\n ></fn-icon>\r\n </div>\r\n </div>\r\n <div class=\"h-1.5 w-full bg-[#eef0f2] rounded-full overflow-hidden\">\r\n <div\r\n class=\"h-full transition-all duration-300 rounded-full\"\r\n [ngClass]=\"{\r\n 'bg-[#ef3e42]': passwordStrengthPercent <= 25,\r\n 'bg-[#ff9f00]': passwordStrengthPercent > 25 && passwordStrengthPercent <= 75,\r\n 'bg-[#6cc24a]': passwordStrengthPercent > 75,\r\n }\"\r\n [style.width.%]=\"passwordStrengthPercent\"\r\n ></div>\r\n </div>\r\n </div>\r\n }\r\n }\r\n\r\n <!-- Number Field -->\r\n @case ('number') {\r\n <div class=\"relative w-full\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10': field.suffix?.icon && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'text-[24px] font-bold': field.isCurrency,\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n </div>\r\n }\r\n\r\n <!-- Default Input Field (text, email, etc.) -->\r\n @default {\r\n <div class=\"relative z-0\">\r\n @if (field.prefix?.icon || field.prefix?.text) {\r\n <div\r\n class=\"absolute left-0 top-1/2 -translate-y-1/2 pl-3 flex items-center gap-2\"\r\n style=\"z-index: 1\"\r\n >\r\n @if (field.prefix?.icon) {\r\n <fn-icon\r\n [name]=\"field.prefix?.icon || ''\"\r\n [variant]=\"'Line'\"\r\n [size]=\"'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n @if (field.prefix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"prefixClick($event)\"\r\n (keydown.enter)=\"prefixClick($event)\"\r\n [attr.tabindex]=\"field.prefix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.prefix?.onClick\"\r\n >{{ field.prefix!.text }}</span\r\n >\r\n }\r\n </div>\r\n }\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=\"fn-input-field\"\r\n [ngClass]=\"{\r\n disabled: control.disabled || field.readOnly,\r\n error: control.touched && control.errors,\r\n success: field['hasSuccessBorder'] && control.valid && !control.errors,\r\n 'pl-10': field.prefix?.icon && !field.prefix?.text,\r\n 'has-prefix-text': !!field.prefix?.text,\r\n 'pr-10':\r\n (field.icon || field.suffix?.icon) && !field.isCopyText && !field.suffix?.text,\r\n 'has-suffix-text': !!field.suffix?.text,\r\n 'pr-20':\r\n field.isCopyText && !field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-30':\r\n field.isCopyText && field.hasGenerateKey && !(field.icon || field.suffix?.icon),\r\n 'pr-32':\r\n field.isCopyText && field.hasGenerateKey && (field.icon || field.suffix?.icon),\r\n }\"\r\n [ngStyle]=\"{\r\n color: field.valueColor || 'inherit',\r\n 'font-size': field.valueSize || '',\r\n }\"\r\n (focus)=\"onFocus()\"\r\n />\r\n\r\n <div class=\"absolute right-0 top-1/2 -translate-y-1/2 flex items-center pr-3 gap-2\">\r\n @if (field.isCopyText) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"copyText($event)\"\r\n (keydown)=\"copyText($event)\"\r\n >\r\n <fn-icon [name]=\"'two-square'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n @if (field.hasGenerateKey) {\r\n <span\r\n class=\"cursor-pointer\"\r\n (click)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n (keydown)=\"field.onGenerateKey && field.onGenerateKey()\"\r\n >\r\n <fn-icon [name]=\"'round-arrow-top-left'\" [color]=\"'#03182b'\"></fn-icon>\r\n </span>\r\n }\r\n }\r\n\r\n @if (field.icon || field.suffix?.icon || field.suffix?.text) {\r\n @if (field.suffix?.text) {\r\n <span\r\n class=\"text-sm font-medium whitespace-nowrap\"\r\n [ngStyle]=\"{ color: control.disabled ? '#c4cdd2' : '#03182b' }\"\r\n (click)=\"suffixClick($event)\"\r\n (keydown.enter)=\"suffixClick($event)\"\r\n [attr.tabindex]=\"field.suffix?.onClick ? 0 : null\"\r\n [class.cursor-pointer]=\"!!field.suffix?.onClick\"\r\n >{{ field.suffix!.text }}</span\r\n >\r\n }\r\n @if (field.icon || field.suffix?.icon) {\r\n <fn-icon\r\n [name]=\"field.suffix?.icon || field.icon?.name || ''\"\r\n [variant]=\"field.icon?.variant || 'Line'\"\r\n [size]=\"field.icon ? getIconSizeName(field.icon.size) : 'medium'\"\r\n [color]=\"control.disabled ? '#c4cdd2' : '#03182b'\"\r\n ></fn-icon>\r\n }\r\n }\r\n </div>\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 <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
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 { InjectionToken } from '@angular/core';\r\nimport { ValidatorFn } from '@angular/forms';\r\nimport { Observable } from 'rxjs';\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;\r\n hideWhen?: 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 labelSize?: string;\r\n valueColor?: string;\r\n valueSize?: string;\r\n isCopyText?: boolean;\r\n hasGenerateKey?: boolean;\r\n onGenerateKey?: () => void;\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}\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 translate: (key: string) => string;\r\n}\r\n\r\nimport { Toast, ToastService } from 'fn-toast';\r\n\r\nexport interface FNInputToast extends ToastService {}\r\n\r\nexport const FN_TOAST_SERVICE = new InjectionToken<FNInputToast>('FN_TOAST_SERVICE');\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} from '@angular/core';\r\nimport { CommonModule } from '@angular/common';\r\n// Removed HttpClient import\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 { FNLabel } from 'fn-label';\r\nimport { FNFieldMessage } from 'fn-field-message';\r\nimport { FNIconComponent } from '@arpudhabotupload/fn-icon-angular';\r\nimport { FNToast, ToastService } from 'fn-toast';\r\nimport {\r\n FNInputBase,\r\n FNInputHelper,\r\n FNInputToast,\r\n DEFAULT_CURRENCY_META,\r\n TypeIconSize,\r\n FN_TOAST_SERVICE,\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: [\r\n FormsModule,\r\n CommonModule,\r\n ReactiveFormsModule,\r\n TranslateModule,\r\n FNLabel,\r\n FNFieldMessage,\r\n FNIconComponent,\r\n FNToast,\r\n ],\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 {\r\n @Input() field = {} as FNInputBase;\r\n @Input() helperHandle?: FNInputHelper;\r\n @Input() toastService?: FNInputToast;\r\n private readonly fallbackToastService = inject(ToastService, { optional: true });\r\n private readonly injectedToastService = inject(FN_TOAST_SERVICE, { optional: true });\r\n\r\n get effectiveToastService(): FNInputToast | undefined {\r\n return this.toastService || this.injectedToastService || this.fallbackToastService || undefined;\r\n }\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 translateService = inject(TranslateService);\r\n hasFocus = signal(false);\r\n @ViewChild('fnTextarea') textareaElement!: ElementRef<HTMLTextAreaElement>;\r\n\r\n // Removed local Toast State\r\n\r\n // Removed HttpClient injection\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 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 originalValue = input.value;\r\n const cursorPosition = input.selectionStart || 0;\r\n\r\n // 1. Convert to lowercase\r\n let filteredValue = originalValue.toLowerCase();\r\n\r\n // 2. Split at the first @ to handle local and domain parts separately\r\n const parts = filteredValue.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, ., _, +, -, space\r\n // Rule: Cannot start with a dot (.)\r\n localPart = localPart.replaceAll(/[^a-z0-9._+\\-\\s]/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, ., -, space\r\n // Rule: No underscores (_), no plus signs (+), cannot start with a hyphen (-)\r\n filteredValue = localPart;\r\n if (domainPart !== null) {\r\n domainPart = domainPart.replaceAll(/[^a-z0-9.\\-\\s]/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 // 5. Sync with DOM if changed\r\n if (originalValue !== filteredValue) {\r\n input.value = filteredValue;\r\n input.setSelectionRange(cursorPosition, cursorPosition);\r\n }\r\n\r\n // 6. Always sync with control to ensure validation runs (including spaces)\r\n this.control.setValue(filteredValue);\r\n this.control.markAsTouched();\r\n this.cdr.markForCheck();\r\n\r\n this.valueChange.emit({ name: this.field.name, value: filteredValue });\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 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 togglePasswordVisibility(): void {\r\n this.showPassword = !this.showPassword;\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 (!this.isAlphanumeric) {\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 if (this.field.type === 'password' && this.field.feedback) {\r\n this.checkPasswordStrength(filteredValue);\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 const service = this.effectiveToastService;\r\n if (service) {\r\n // Position set to top as requested\r\n service.success('Copied to clipboard', 'Success', 2000);\r\n }\r\n });\r\n }\r\n\r\n prefixClick(e: Event): void {\r\n if (this.field.prefix?.onClick) {\r\n this.field.prefix.onClick(e);\r\n }\r\n }\r\n\r\n suffixClick(e: Event): void {\r\n if (this.field.suffix?.onClick) {\r\n this.field.suffix.onClick(e);\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 // Removed local toast helpers\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 return true;\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.translateService.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 // Removed getIconPath as HTTP loading is disabled\r\n\r\n // Removed getFieldMessage, isError, isSuccess as they are now handled by FNFieldMessage\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 <fn-label\r\n [label]=\"field.label\"\r\n [required]=\"field.required || false\"\r\n [class]=\"'!text-[var(--Base-70)]'\"\r\n [variant]=\"'p4'\"\r\n [hideOptional]=\"field.hideOptional || false\"\r\n ></fn-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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"two-square\" variant=\"Line\" size=\"large\"></fn-icon>\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 <fn-icon\r\n name=\"eye-close\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\r\n } @else {\r\n <fn-icon\r\n name=\"eye-open\"\r\n variant=\"Line\"\r\n size=\"large\"\r\n color=\"var(--Base-100)\"\r\n ></fn-icon>\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 <fn-icon name=\"two-square\"></fn-icon>\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 <fn-icon name=\"round-arrow-top-left\" color=\"var(--Base-100)\"></fn-icon>\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]=\"isEmailField ? 'text' : 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 <fn-icon\r\n class=\"bg-white\"\r\n [name]=\"field.icon.name\"\r\n [variant]=\"field.icon.variant\"\r\n [size]=\"getIconSizeName(field.icon.size)\"\r\n [color]=\"control.disabled ? 'var(--Base-30)' : ''\"\r\n ></fn-icon>\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 <fn-field-message\r\n [control]=\"control\"\r\n [field]=\"field\"\r\n [hasFocus]=\"hasFocus()\"\r\n ></fn-field-message>\r\n }\r\n </div>\r\n\r\n <!-- Integrated Toast Notifications -->\r\n <fn-toast></fn-toast>\r\n}\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
@@ -179,9 +179,6 @@ export declare class FNInput implements OnInit, AfterViewInit, OnDestroy {
179
179
  showFormFieldMessage(control: any, helperText: string): boolean;
180
180
  getTranslatedLabel(label: string): string;
181
181
  getEndSymbol(label: string): string;
182
- getFieldMessage(): string;
183
- get isError(): boolean;
184
- get isSuccess(): boolean;
185
182
  static ɵfac: i0.ɵɵFactoryDeclaration<FNInput, never>;
186
183
  static ɵcmp: i0.ɵɵ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>;
187
184
  }
@@ -1 +1 @@
1
- {"version":3,"file":"fn-input.component.d.ts","sourceRoot":"","sources":["../../../projects/fn-input/src/lib/fn-input.component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fn-input.component.d.ts","sourceRoot":"","sources":["../../../projects/fn-input/src/lib/fn-input.component.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fn-input",
3
- "version": "0.0.15",
3
+ "version": "0.0.17",
4
4
  "description": "Reusable Angular standalone component for rendering field validation and helper messages.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^17.0.0 || ^18.0.0 || ^19.0.0 || ^20.0.0 || ^21.0.0",
@@ -10,6 +10,7 @@
10
10
  "@arpudhabotupload/fn-icon-angular": "^1.0.0",
11
11
  "fn-label": "^0.0.16",
12
12
  "fn-toast": "^0.0.9",
13
+ "fn-field-message": "^0.0.2",
13
14
  "rxjs": "^6.6.0 || ^7.0.0"
14
15
  },
15
16
  "dependencies": {