@tolle_/tolle-ui 18.2.16 → 18.2.19

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.
@@ -2886,13 +2886,18 @@ class MaskedInputComponent {
2886
2886
  size = 'default';
2887
2887
  returnRaw = false;
2888
2888
  hideHintOnFocus = true;
2889
+ mergedPosition = 'none';
2889
2890
  inputEl;
2890
2891
  hasPrefix = false;
2891
2892
  hasSuffix = false;
2892
2893
  displayValue = '';
2893
2894
  isFocused = false;
2894
2895
  tokens = {
2895
- '0': /\d/, '9': /\d/, 'a': /[a-z]/i, 'A': /[a-z]/i, '*': /[a-z0-9]/i
2896
+ '0': /\d/,
2897
+ '9': /\d/,
2898
+ a: /[a-z]/i,
2899
+ A: /[a-z]/i,
2900
+ '*': /[a-z0-9]/i,
2896
2901
  };
2897
2902
  onChange = () => { };
2898
2903
  onTouched = () => { };
@@ -2910,58 +2915,48 @@ class MaskedInputComponent {
2910
2915
  }
2911
2916
  }
2912
2917
  get computedLabelClass() {
2913
- return cn("text-sm font-medium text-foreground leading-none transition-opacity duration-200", this.disabled && "opacity-50");
2918
+ return cn('text-sm font-medium text-foreground leading-none transition-opacity duration-200', this.disabled && 'opacity-50');
2914
2919
  }
2915
2920
  get computedContainerClass() {
2916
2921
  return cn(
2917
2922
  // Base styles
2918
- "group relative flex items-center w-full rounded-md border transition-all duration-200", "bg-background",
2919
- // Border and shadow
2920
- "border-input shadow-sm",
2923
+ 'group relative flex items-center w-full border transition-all duration-200', 'bg-background border-input shadow-sm',
2921
2924
  // Sizing
2922
- this.size === 'xs' && "h-8 px-2 gap-1.5 text-xs", this.size === 'sm' && "h-9 px-3 gap-2 text-sm", this.size === 'default' && "h-10 px-3 gap-2 text-sm", this.size === 'lg' && "h-11 px-4 gap-3 text-base",
2923
- // Focus state - SIMPLE LIKE ZARDUI
2925
+ this.size === 'xs' && 'h-8 px-2 gap-1.5 text-xs', this.size === 'sm' && 'h-9 px-3 gap-2 text-sm', this.size === 'default' && 'h-10 px-3 gap-2 text-sm', this.size === 'lg' && 'h-11 px-4 gap-3 text-base',
2926
+ // Merged position - handle border radius
2927
+ this.mergedPosition === 'left' && 'rounded-l-md rounded-r-none border-r-0 pr-0', this.mergedPosition === 'right' && 'rounded-r-md rounded-l-none border-l-0 pl-0 flex-1', this.mergedPosition === 'none' && 'rounded-md',
2928
+ // Focus state
2924
2929
  !(this.readonly || this.disabled) && [
2925
- "focus-within:border-primary/80",
2926
- "focus-within:ring-4",
2927
- "focus-within:ring-ring/30",
2928
- "focus-within:ring-offset-0",
2929
- "focus-within:shadow-none",
2930
+ 'focus-within:ring-4',
2931
+ 'focus-within:ring-ring/30',
2932
+ 'focus-within:ring-offset-0',
2933
+ 'focus-within:shadow-none',
2934
+ this.error ? 'focus-within:border-destructive/80' : 'focus-within:border-primary/80',
2930
2935
  ],
2931
2936
  // Error state
2932
2937
  this.error && [
2933
- "border-destructive",
2934
- !(this.readonly || this.disabled) && [
2935
- "focus-within:border-destructive/80",
2936
- "focus-within:ring-destructive/30"
2937
- ]
2938
+ 'border-destructive',
2939
+ !(this.readonly || this.disabled) && 'focus-within:ring-destructive/30',
2938
2940
  ],
2939
2941
  // Disabled state
2940
- this.disabled && [
2941
- "cursor-not-allowed opacity-50",
2942
- "border-opacity-50"
2943
- ],
2942
+ this.disabled && ['cursor-not-allowed opacity-50', 'border-opacity-50'],
2944
2943
  // Readonly state
2945
- this.readonly && [
2946
- "cursor-default",
2947
- "border-dashed",
2948
- !this.disabled && "focus-within:ring-0 focus-within:border-opacity-100"
2949
- ], this.containerClass);
2944
+ this.readonly && ['cursor-default', 'border-dashed'], this.containerClass);
2950
2945
  }
2951
2946
  get computedInputClass() {
2952
2947
  return cn(
2953
2948
  // Base styles
2954
- "flex-1 bg-transparent border-none p-0", "placeholder:text-muted-foreground",
2949
+ 'flex-1 bg-transparent border-none p-0', 'placeholder:text-muted-foreground',
2955
2950
  // Remove all default focus styles
2956
- "focus:outline-none focus:ring-0 focus:shadow-none",
2951
+ 'focus:outline-none focus:ring-0 focus:shadow-none',
2957
2952
  // Text sizing
2958
- this.size === 'xs' && "text-xs", this.size === 'sm' && "text-sm", this.size === 'default' && "text-sm", this.size === 'lg' && "text-base",
2953
+ this.size === 'xs' && 'text-xs', this.size === 'sm' && 'text-sm', this.size === 'default' && 'text-sm', this.size === 'lg' && 'text-base',
2959
2954
  // Cursor states
2960
- this.disabled && "cursor-not-allowed", this.readonly && "cursor-default",
2955
+ this.disabled && 'cursor-not-allowed', this.readonly && 'cursor-default',
2961
2956
  // Text color
2962
- "text-foreground",
2957
+ 'text-foreground',
2963
2958
  // Selection color
2964
- "selection:bg-primary/20 selection:text-foreground", this.class);
2959
+ 'selection:bg-primary/20 selection:text-foreground', this.class);
2965
2960
  }
2966
2961
  focusInput() {
2967
2962
  if (!this.disabled && this.inputEl) {
@@ -3031,28 +3026,22 @@ class MaskedInputComponent {
3031
3026
  }
3032
3027
  cn = cn;
3033
3028
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MaskedInputComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3034
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MaskedInputComponent, isStandalone: true, selector: "tolle-masked-input", inputs: { id: "id", label: "label", hint: "hint", errorMessage: "errorMessage", mask: "mask", placeholder: "placeholder", type: "type", disabled: "disabled", readonly: "readonly", class: "class", containerClass: "containerClass", error: "error", size: "size", returnRaw: "returnRaw", hideHintOnFocus: "hideHintOnFocus" }, providers: [
3029
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: MaskedInputComponent, isStandalone: true, selector: "tolle-masked-input", inputs: { id: "id", label: "label", hint: "hint", errorMessage: "errorMessage", mask: "mask", placeholder: "placeholder", type: "type", disabled: "disabled", readonly: "readonly", class: "class", containerClass: "containerClass", error: "error", size: "size", returnRaw: "returnRaw", hideHintOnFocus: "hideHintOnFocus", mergedPosition: "mergedPosition" }, providers: [
3035
3030
  {
3036
3031
  provide: NG_VALUE_ACCESSOR,
3037
3032
  useExisting: forwardRef(() => MaskedInputComponent),
3038
- multi: true
3039
- }
3033
+ multi: true,
3034
+ },
3040
3035
  ], viewQueries: [{ propertyName: "inputEl", first: true, predicate: ["inputEl"], descendants: true, static: true }], ngImport: i0, template: `
3041
- <div class="flex flex-col gap-1.5 w-full">
3042
- <label
3043
- *ngIf="label"
3044
- [for]="id"
3045
- [class]="computedLabelClass"
3046
- >
3036
+ <div class="flex w-full flex-col gap-1.5">
3037
+ <label *ngIf="label && mergedPosition === 'none'" [for]="id" [class]="computedLabelClass">
3047
3038
  {{ label }}
3048
3039
  </label>
3049
3040
 
3050
- <div
3051
- [class]="computedContainerClass"
3052
- (click)="focusInput()"
3053
- >
3041
+ <div [class]="computedContainerClass" (click)="focusInput()">
3054
3042
  <!-- Prefix Icon -->
3055
- <div class="h-full flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
3043
+ <div
3044
+ class="flex h-full items-center text-muted-foreground transition-colors duration-200 group-focus-within:text-primary">
3056
3045
  <ng-content select="[prefix]"></ng-content>
3057
3046
  </div>
3058
3047
 
@@ -3069,28 +3058,23 @@ class MaskedInputComponent {
3069
3058
  (focus)="onFocus()"
3070
3059
  [class]="computedInputClass"
3071
3060
  [attr.aria-invalid]="error"
3072
- [attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
3073
- />
3061
+ [attr.aria-describedby]="error && errorMessage ? id + '-error' : null" />
3074
3062
 
3075
3063
  <!-- Suffix Icon -->
3076
- <div class="h-full flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
3064
+ <div
3065
+ class="flex h-full items-center text-muted-foreground transition-colors duration-200 group-focus-within:text-primary">
3077
3066
  <ng-content select="[suffix]"></ng-content>
3078
3067
  </div>
3079
3068
  </div>
3080
3069
 
3081
- <ng-container *ngIf="!disabled">
3070
+ <ng-container *ngIf="!disabled && mergedPosition === 'none'">
3082
3071
  <p
3083
3072
  *ngIf="hint && !error"
3084
- class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
3085
- [class.opacity-0]="isFocused && hideHintOnFocus"
3086
- >
3073
+ class="px-1 text-xs text-muted-foreground transition-opacity duration-200"
3074
+ [class.opacity-0]="isFocused && hideHintOnFocus">
3087
3075
  {{ hint }}
3088
3076
  </p>
3089
- <p
3090
- *ngIf="error && errorMessage"
3091
- [id]="id + '-error'"
3092
- class="text-xs text-destructive px-1"
3093
- >
3077
+ <p *ngIf="error && errorMessage" [id]="id + '-error'" class="px-1 text-xs text-destructive">
3094
3078
  {{ errorMessage }}
3095
3079
  </p>
3096
3080
  </ng-container>
@@ -3107,25 +3091,19 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3107
3091
  {
3108
3092
  provide: NG_VALUE_ACCESSOR,
3109
3093
  useExisting: forwardRef(() => MaskedInputComponent),
3110
- multi: true
3111
- }
3094
+ multi: true,
3095
+ },
3112
3096
  ],
3113
3097
  template: `
3114
- <div class="flex flex-col gap-1.5 w-full">
3115
- <label
3116
- *ngIf="label"
3117
- [for]="id"
3118
- [class]="computedLabelClass"
3119
- >
3098
+ <div class="flex w-full flex-col gap-1.5">
3099
+ <label *ngIf="label && mergedPosition === 'none'" [for]="id" [class]="computedLabelClass">
3120
3100
  {{ label }}
3121
3101
  </label>
3122
3102
 
3123
- <div
3124
- [class]="computedContainerClass"
3125
- (click)="focusInput()"
3126
- >
3103
+ <div [class]="computedContainerClass" (click)="focusInput()">
3127
3104
  <!-- Prefix Icon -->
3128
- <div class="h-full flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
3105
+ <div
3106
+ class="flex h-full items-center text-muted-foreground transition-colors duration-200 group-focus-within:text-primary">
3129
3107
  <ng-content select="[prefix]"></ng-content>
3130
3108
  </div>
3131
3109
 
@@ -3142,33 +3120,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3142
3120
  (focus)="onFocus()"
3143
3121
  [class]="computedInputClass"
3144
3122
  [attr.aria-invalid]="error"
3145
- [attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
3146
- />
3123
+ [attr.aria-describedby]="error && errorMessage ? id + '-error' : null" />
3147
3124
 
3148
3125
  <!-- Suffix Icon -->
3149
- <div class="h-full flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
3126
+ <div
3127
+ class="flex h-full items-center text-muted-foreground transition-colors duration-200 group-focus-within:text-primary">
3150
3128
  <ng-content select="[suffix]"></ng-content>
3151
3129
  </div>
3152
3130
  </div>
3153
3131
 
3154
- <ng-container *ngIf="!disabled">
3132
+ <ng-container *ngIf="!disabled && mergedPosition === 'none'">
3155
3133
  <p
3156
3134
  *ngIf="hint && !error"
3157
- class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
3158
- [class.opacity-0]="isFocused && hideHintOnFocus"
3159
- >
3135
+ class="px-1 text-xs text-muted-foreground transition-opacity duration-200"
3136
+ [class.opacity-0]="isFocused && hideHintOnFocus">
3160
3137
  {{ hint }}
3161
3138
  </p>
3162
- <p
3163
- *ngIf="error && errorMessage"
3164
- [id]="id + '-error'"
3165
- class="text-xs text-destructive px-1"
3166
- >
3139
+ <p *ngIf="error && errorMessage" [id]="id + '-error'" class="px-1 text-xs text-destructive">
3167
3140
  {{ errorMessage }}
3168
3141
  </p>
3169
3142
  </ng-container>
3170
3143
  </div>
3171
- `
3144
+ `,
3172
3145
  }]
3173
3146
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }], propDecorators: { id: [{
3174
3147
  type: Input
@@ -3200,6 +3173,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3200
3173
  type: Input
3201
3174
  }], hideHintOnFocus: [{
3202
3175
  type: Input
3176
+ }], mergedPosition: [{
3177
+ type: Input
3203
3178
  }], inputEl: [{
3204
3179
  type: ViewChild,
3205
3180
  args: ['inputEl', { static: true }]
@@ -3430,7 +3405,7 @@ class DatePickerComponent {
3430
3405
  ></tolle-calendar>
3431
3406
  </div>
3432
3407
  </div>
3433
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MaskedInputComponent, selector: "tolle-masked-input", inputs: ["id", "label", "hint", "errorMessage", "mask", "placeholder", "type", "disabled", "readonly", "class", "containerClass", "error", "size", "returnRaw", "hideHintOnFocus"] }, { kind: "component", type: CalendarComponent, selector: "tolle-calendar", inputs: ["class", "mode", "disablePastDates", "showQuickActions", "minDate", "maxDate", "formatMonthFn", "formatYearFn", "formatDateFn"], outputs: ["dateSelect"] }] });
3408
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MaskedInputComponent, selector: "tolle-masked-input", inputs: ["id", "label", "hint", "errorMessage", "mask", "placeholder", "type", "disabled", "readonly", "class", "containerClass", "error", "size", "returnRaw", "hideHintOnFocus", "mergedPosition"] }, { kind: "component", type: CalendarComponent, selector: "tolle-calendar", inputs: ["class", "mode", "disablePastDates", "showQuickActions", "minDate", "maxDate", "formatMonthFn", "formatYearFn", "formatDateFn"], outputs: ["dateSelect"] }] });
3434
3409
  }
3435
3410
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatePickerComponent, decorators: [{
3436
3411
  type: Component,
@@ -12930,7 +12905,10 @@ class CountrySelectorComponent {
12930
12905
  defaultCountryCode = 'GH';
12931
12906
  returnValue = 'isoAlpha2';
12932
12907
  showName = true;
12908
+ mergedPosition = 'none';
12933
12909
  onSelect = new EventEmitter();
12910
+ onFocusChange = new EventEmitter();
12911
+ onBlurChange = new EventEmitter();
12934
12912
  popover;
12935
12913
  searchInput;
12936
12914
  countryCodesService = inject(CountryCodesService);
@@ -12954,19 +12932,20 @@ class CountrySelectorComponent {
12954
12932
  }
12955
12933
  }
12956
12934
  get computedTriggerClass() {
12957
- return cn('flex w-full items-center justify-between rounded-md border transition-all duration-200', 'bg-background text-foreground', 'border-input shadow-sm', this.size === 'xs' && 'h-8 px-2 text-xs', this.size === 'sm' && 'h-9 px-3 text-sm', this.size === 'default' && 'h-10 px-3 text-sm', this.size === 'lg' && 'h-11 px-4 text-base', !(this.readonly || this.disabled) && [
12958
- 'focus:outline-none',
12959
- 'focus:ring-4',
12960
- 'focus:ring-ring/30',
12961
- 'focus:ring-offset-0',
12962
- 'focus:border-primary/80',
12963
- ], !(this.readonly || this.disabled) && 'hover:border-accent', this.error && [
12964
- 'border-destructive',
12965
- !(this.readonly || this.disabled) && [
12966
- 'focus:border-destructive/80',
12967
- 'focus:ring-destructive/30',
12968
- ],
12969
- ], this.disabled && 'cursor-not-allowed opacity-50 border-opacity-50', this.readonly && 'cursor-default border-dashed', this.class);
12935
+ return cn('flex w-full items-center justify-between border transition-all duration-200', 'bg-background text-foreground', 'border-input shadow-sm', this.size === 'xs' && 'h-8 px-2 text-xs', this.size === 'sm' && 'h-9 px-3 text-sm', this.size === 'default' && 'h-10 px-3 text-sm', this.size === 'lg' && 'h-11 px-4 text-base',
12936
+ // Merged position
12937
+ this.mergedPosition === 'left' && 'rounded-l-md rounded-r-none border-r-0', this.mergedPosition === 'none' && 'rounded-md',
12938
+ // Focus state
12939
+ !(this.readonly || this.disabled) &&
12940
+ this.isFocused && [
12941
+ 'ring-4',
12942
+ 'ring-ring/30',
12943
+ 'ring-offset-0',
12944
+ 'shadow-none',
12945
+ this.error ? 'border-destructive/80' : 'border-primary/80',
12946
+ ], !(this.readonly || this.disabled) && 'hover:border-accent',
12947
+ // Error state
12948
+ this.error && ['border-destructive', this.isFocused && 'ring-destructive/30'], this.disabled && 'cursor-not-allowed opacity-50 border-opacity-50', this.readonly && 'cursor-default border-dashed', this.class);
12970
12949
  }
12971
12950
  get computedLabelClass() {
12972
12951
  return cn('text-sm font-medium text-foreground leading-none transition-opacity duration-200', this.disabled && 'opacity-50');
@@ -13010,10 +12989,12 @@ class CountrySelectorComponent {
13010
12989
  }
13011
12990
  onFocus() {
13012
12991
  this.isFocused = true;
12992
+ this.onFocusChange.emit();
13013
12993
  }
13014
12994
  onBlur() {
13015
12995
  this.isFocused = false;
13016
12996
  this.onTouched();
12997
+ this.onBlurChange.emit();
13017
12998
  }
13018
12999
  onPopoverOpen() {
13019
13000
  setTimeout(() => {
@@ -13055,7 +13036,7 @@ class CountrySelectorComponent {
13055
13036
  this.disabled = isDisabled;
13056
13037
  }
13057
13038
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CountrySelectorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
13058
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CountrySelectorComponent, isStandalone: true, selector: "tolle-country-selector", inputs: { id: "id", label: "label", hint: "hint", errorMessage: "errorMessage", error: "error", hideHintOnFocus: "hideHintOnFocus", placeholder: "placeholder", class: "class", disabled: "disabled", readonly: "readonly", size: "size", defaultCountryCode: "defaultCountryCode", returnValue: "returnValue", showName: "showName" }, outputs: { onSelect: "onSelect" }, providers: [
13039
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CountrySelectorComponent, isStandalone: true, selector: "tolle-country-selector", inputs: { id: "id", label: "label", hint: "hint", errorMessage: "errorMessage", error: "error", hideHintOnFocus: "hideHintOnFocus", placeholder: "placeholder", class: "class", disabled: "disabled", readonly: "readonly", size: "size", defaultCountryCode: "defaultCountryCode", returnValue: "returnValue", showName: "showName", mergedPosition: "mergedPosition" }, outputs: { onSelect: "onSelect", onFocusChange: "onFocusChange", onBlurChange: "onBlurChange" }, providers: [
13059
13040
  {
13060
13041
  provide: NG_VALUE_ACCESSOR,
13061
13042
  useExisting: forwardRef(() => CountrySelectorComponent),
@@ -13063,7 +13044,7 @@ class CountrySelectorComponent {
13063
13044
  },
13064
13045
  ], viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }, { propertyName: "searchInput", first: true, predicate: ["searchInput"], descendants: true }], ngImport: i0, template: `
13065
13046
  <div class="flex w-full flex-col gap-1.5">
13066
- <label *ngIf="label" [for]="id" [class]="computedLabelClass">
13047
+ <label *ngIf="label && mergedPosition === 'none'" [for]="id" [class]="computedLabelClass">
13067
13048
  {{ label }}
13068
13049
  </label>
13069
13050
 
@@ -13100,13 +13081,13 @@ class CountrySelectorComponent {
13100
13081
  </div>
13101
13082
 
13102
13083
  <div
13103
- class="flex min-w-[300px] max-w-[400px] flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md">
13084
+ class="flex min-w-[300px] max-w-[400px] flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md"
13085
+ (mousedown)="$event.stopPropagation()">
13104
13086
  <div class="sticky top-0 z-10 border-b border-border bg-popover p-2 shadow-sm">
13105
13087
  <tolle-input
13106
13088
  size="sm"
13107
13089
  placeholder="Search country..."
13108
13090
  [(ngModel)]="searchQuery"
13109
- (mousedown)="$event.stopPropagation()"
13110
13091
  (ngModelChange)="filterCountries($event)"
13111
13092
  class="w-full"
13112
13093
  #searchInput>
@@ -13140,7 +13121,7 @@ class CountrySelectorComponent {
13140
13121
  </div>
13141
13122
  </tolle-popover>
13142
13123
 
13143
- <ng-container *ngIf="!disabled">
13124
+ <ng-container *ngIf="!disabled && mergedPosition === 'none'">
13144
13125
  <p
13145
13126
  *ngIf="hint && !error"
13146
13127
  class="px-1 text-xs text-muted-foreground transition-opacity duration-200"
@@ -13172,7 +13153,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13172
13153
  ],
13173
13154
  template: `
13174
13155
  <div class="flex w-full flex-col gap-1.5">
13175
- <label *ngIf="label" [for]="id" [class]="computedLabelClass">
13156
+ <label *ngIf="label && mergedPosition === 'none'" [for]="id" [class]="computedLabelClass">
13176
13157
  {{ label }}
13177
13158
  </label>
13178
13159
 
@@ -13209,13 +13190,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13209
13190
  </div>
13210
13191
 
13211
13192
  <div
13212
- class="flex min-w-[300px] max-w-[400px] flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md">
13193
+ class="flex min-w-[300px] max-w-[400px] flex-col overflow-hidden rounded-md border border-border bg-popover shadow-md"
13194
+ (mousedown)="$event.stopPropagation()">
13213
13195
  <div class="sticky top-0 z-10 border-b border-border bg-popover p-2 shadow-sm">
13214
13196
  <tolle-input
13215
13197
  size="sm"
13216
13198
  placeholder="Search country..."
13217
13199
  [(ngModel)]="searchQuery"
13218
- (mousedown)="$event.stopPropagation()"
13219
13200
  (ngModelChange)="filterCountries($event)"
13220
13201
  class="w-full"
13221
13202
  #searchInput>
@@ -13249,7 +13230,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13249
13230
  </div>
13250
13231
  </tolle-popover>
13251
13232
 
13252
- <ng-container *ngIf="!disabled">
13233
+ <ng-container *ngIf="!disabled && mergedPosition === 'none'">
13253
13234
  <p
13254
13235
  *ngIf="hint && !error"
13255
13236
  class="px-1 text-xs text-muted-foreground transition-opacity duration-200"
@@ -13294,8 +13275,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
13294
13275
  type: Input
13295
13276
  }], showName: [{
13296
13277
  type: Input
13278
+ }], mergedPosition: [{
13279
+ type: Input
13297
13280
  }], onSelect: [{
13298
13281
  type: Output
13282
+ }], onFocusChange: [{
13283
+ type: Output
13284
+ }], onBlurChange: [{
13285
+ type: Output
13299
13286
  }], popover: [{
13300
13287
  type: ViewChild,
13301
13288
  args: ['popover']
@@ -13331,6 +13318,27 @@ class PhoneNumberInputComponent {
13331
13318
  constructor() {
13332
13319
  this.selectedIso = this.defaultCountryCode;
13333
13320
  }
13321
+ get computedLabelClass() {
13322
+ return cn('text-sm font-medium text-foreground leading-none transition-opacity duration-200', this.disabled && 'opacity-50');
13323
+ }
13324
+ get computedMergedClass() {
13325
+ return cn('group relative flex items-center w-full rounded-md border transition-all duration-200', 'bg-background border-input shadow-sm', this.size === 'xs' && 'h-8', this.size === 'sm' && 'h-9', this.size === 'default' && 'h-10', this.size === 'lg' && 'h-11',
13326
+ // Focus state
13327
+ !this.readonly &&
13328
+ !this.disabled && [
13329
+ 'focus-within:ring-4',
13330
+ 'focus-within:ring-ring/30',
13331
+ 'focus-within:ring-offset-0',
13332
+ 'focus-within:shadow-none',
13333
+ this.error ? 'focus-within:border-destructive/80' : 'focus-within:border-primary/80',
13334
+ ],
13335
+ // Error state
13336
+ this.error && 'border-destructive', this.error && !this.readonly && !this.disabled && 'focus-within:ring-destructive/30',
13337
+ // Disabled state
13338
+ this.disabled && ['cursor-not-allowed opacity-50', 'border-opacity-50'],
13339
+ // Readonly state
13340
+ this.readonly && 'cursor-default border-dashed', this.class);
13341
+ }
13334
13342
  writeValue(value) {
13335
13343
  if (value) {
13336
13344
  if (typeof value === 'object' && value.number) {
@@ -13404,75 +13412,99 @@ class PhoneNumberInputComponent {
13404
13412
  {
13405
13413
  provide: NG_VALUE_ACCESSOR,
13406
13414
  useExisting: forwardRef(() => PhoneNumberInputComponent),
13407
- multi: true
13408
- }
13415
+ multi: true,
13416
+ },
13409
13417
  ], ngImport: i0, template: `
13410
- <tolle-masked-input
13411
- [id]="id"
13412
- [label]="label"
13413
- [hint]="hint"
13414
- [error]="error"
13415
- [errorMessage]="errorMessage"
13416
- [hideHintOnFocus]="hideHintOnFocus"
13417
- [mask]="mask"
13418
- [size]="size"
13419
- [disabled]="disabled"
13420
- [readonly]="readonly"
13421
- [placeholder]="placeholder"
13422
- [(ngModel)]="displayValue"
13423
- (ngModelChange)="onMaskInputChange($event)"
13424
- [containerClass]="cn('pl-0', class)"
13425
- >
13426
- <tolle-country-selector
13427
- prefix
13428
- class="country-selector-override"
13429
- [showName]="false"
13430
- [size]="size"
13431
- [disabled]="disabled || !enableCountrySelector"
13432
- [readonly]="readonly"
13433
- [(ngModel)]="selectedIso"
13434
- (ngModelChange)="onCountryChange($event)"
13435
- ></tolle-country-selector>
13436
- </tolle-masked-input>
13437
- `, isInline: true, styles: [":host{display:block;width:100%}::ng-deep .country-selector-override{display:flex;align-items:center;border-right:1px solid var(--border, #e5e7eb)}::ng-deep .country-selector-override button{border:none!important;border-radius:0!important;border-top-left-radius:calc(var(--radius, .5rem) - 1px)!important;border-bottom-left-radius:calc(var(--radius, .5rem) - 1px)!important;background:transparent!important;box-shadow:none!important;padding-left:.75rem!important;padding-right:.5rem!important;display:flex!important;align-items:center!important;justify-content:center!important;gap:.25rem!important}::ng-deep .country-selector-override button .flex{gap:.25rem!important}::ng-deep .country-selector-override button i{margin-left:0!important;line-height:1!important;display:flex!important;align-items:center!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CountrySelectorComponent, selector: "tolle-country-selector", inputs: ["id", "label", "hint", "errorMessage", "error", "hideHintOnFocus", "placeholder", "class", "disabled", "readonly", "size", "defaultCountryCode", "returnValue", "showName"], outputs: ["onSelect"] }, { kind: "component", type: MaskedInputComponent, selector: "tolle-masked-input", inputs: ["id", "label", "hint", "errorMessage", "mask", "placeholder", "type", "disabled", "readonly", "class", "containerClass", "error", "size", "returnRaw", "hideHintOnFocus"] }] });
13418
+ <div class="flex w-full flex-col gap-1.5">
13419
+ <label *ngIf="label" [for]="id" [class]="computedLabelClass">
13420
+ {{ label }}
13421
+ </label>
13422
+
13423
+ <div [class]="computedMergedClass">
13424
+ <tolle-country-selector
13425
+ [showName]="false"
13426
+ [size]="size"
13427
+ [disabled]="disabled || !enableCountrySelector"
13428
+ [readonly]="readonly"
13429
+ [mergedPosition]="'left'"
13430
+ [(ngModel)]="selectedIso"
13431
+ (ngModelChange)="onCountryChange($event)"></tolle-country-selector>
13432
+
13433
+ <tolle-masked-input
13434
+ [id]="id"
13435
+ [mask]="mask"
13436
+ [size]="size"
13437
+ [disabled]="disabled"
13438
+ [readonly]="readonly"
13439
+ [placeholder]="placeholder"
13440
+ [error]="error"
13441
+ [mergedPosition]="'right'"
13442
+ [(ngModel)]="displayValue"
13443
+ (ngModelChange)="onMaskInputChange($event)"></tolle-masked-input>
13444
+ </div>
13445
+
13446
+ <ng-container *ngIf="!disabled">
13447
+ <p
13448
+ *ngIf="hint && !error"
13449
+ class="px-1 text-xs text-muted-foreground transition-opacity duration-200">
13450
+ {{ hint }}
13451
+ </p>
13452
+ <p *ngIf="error && errorMessage" [id]="id + '-error'" class="px-1 text-xs text-destructive">
13453
+ {{ errorMessage }}
13454
+ </p>
13455
+ </ng-container>
13456
+ </div>
13457
+ `, isInline: true, styles: [":host{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: CountrySelectorComponent, selector: "tolle-country-selector", inputs: ["id", "label", "hint", "errorMessage", "error", "hideHintOnFocus", "placeholder", "class", "disabled", "readonly", "size", "defaultCountryCode", "returnValue", "showName", "mergedPosition"], outputs: ["onSelect", "onFocusChange", "onBlurChange"] }, { kind: "component", type: MaskedInputComponent, selector: "tolle-masked-input", inputs: ["id", "label", "hint", "errorMessage", "mask", "placeholder", "type", "disabled", "readonly", "class", "containerClass", "error", "size", "returnRaw", "hideHintOnFocus", "mergedPosition"] }] });
13438
13458
  }
13439
13459
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PhoneNumberInputComponent, decorators: [{
13440
13460
  type: Component,
13441
13461
  args: [{ selector: 'tolle-phone-number-input', standalone: true, imports: [CommonModule, FormsModule, CountrySelectorComponent, MaskedInputComponent], template: `
13442
- <tolle-masked-input
13443
- [id]="id"
13444
- [label]="label"
13445
- [hint]="hint"
13446
- [error]="error"
13447
- [errorMessage]="errorMessage"
13448
- [hideHintOnFocus]="hideHintOnFocus"
13449
- [mask]="mask"
13450
- [size]="size"
13451
- [disabled]="disabled"
13452
- [readonly]="readonly"
13453
- [placeholder]="placeholder"
13454
- [(ngModel)]="displayValue"
13455
- (ngModelChange)="onMaskInputChange($event)"
13456
- [containerClass]="cn('pl-0', class)"
13457
- >
13458
- <tolle-country-selector
13459
- prefix
13460
- class="country-selector-override"
13461
- [showName]="false"
13462
- [size]="size"
13463
- [disabled]="disabled || !enableCountrySelector"
13464
- [readonly]="readonly"
13465
- [(ngModel)]="selectedIso"
13466
- (ngModelChange)="onCountryChange($event)"
13467
- ></tolle-country-selector>
13468
- </tolle-masked-input>
13462
+ <div class="flex w-full flex-col gap-1.5">
13463
+ <label *ngIf="label" [for]="id" [class]="computedLabelClass">
13464
+ {{ label }}
13465
+ </label>
13466
+
13467
+ <div [class]="computedMergedClass">
13468
+ <tolle-country-selector
13469
+ [showName]="false"
13470
+ [size]="size"
13471
+ [disabled]="disabled || !enableCountrySelector"
13472
+ [readonly]="readonly"
13473
+ [mergedPosition]="'left'"
13474
+ [(ngModel)]="selectedIso"
13475
+ (ngModelChange)="onCountryChange($event)"></tolle-country-selector>
13476
+
13477
+ <tolle-masked-input
13478
+ [id]="id"
13479
+ [mask]="mask"
13480
+ [size]="size"
13481
+ [disabled]="disabled"
13482
+ [readonly]="readonly"
13483
+ [placeholder]="placeholder"
13484
+ [error]="error"
13485
+ [mergedPosition]="'right'"
13486
+ [(ngModel)]="displayValue"
13487
+ (ngModelChange)="onMaskInputChange($event)"></tolle-masked-input>
13488
+ </div>
13489
+
13490
+ <ng-container *ngIf="!disabled">
13491
+ <p
13492
+ *ngIf="hint && !error"
13493
+ class="px-1 text-xs text-muted-foreground transition-opacity duration-200">
13494
+ {{ hint }}
13495
+ </p>
13496
+ <p *ngIf="error && errorMessage" [id]="id + '-error'" class="px-1 text-xs text-destructive">
13497
+ {{ errorMessage }}
13498
+ </p>
13499
+ </ng-container>
13500
+ </div>
13469
13501
  `, providers: [
13470
13502
  {
13471
13503
  provide: NG_VALUE_ACCESSOR,
13472
13504
  useExisting: forwardRef(() => PhoneNumberInputComponent),
13473
- multi: true
13474
- }
13475
- ], styles: [":host{display:block;width:100%}::ng-deep .country-selector-override{display:flex;align-items:center;border-right:1px solid var(--border, #e5e7eb)}::ng-deep .country-selector-override button{border:none!important;border-radius:0!important;border-top-left-radius:calc(var(--radius, .5rem) - 1px)!important;border-bottom-left-radius:calc(var(--radius, .5rem) - 1px)!important;background:transparent!important;box-shadow:none!important;padding-left:.75rem!important;padding-right:.5rem!important;display:flex!important;align-items:center!important;justify-content:center!important;gap:.25rem!important}::ng-deep .country-selector-override button .flex{gap:.25rem!important}::ng-deep .country-selector-override button i{margin-left:0!important;line-height:1!important;display:flex!important;align-items:center!important}\n"] }]
13505
+ multi: true,
13506
+ },
13507
+ ], styles: [":host{display:block;width:100%}\n"] }]
13476
13508
  }], ctorParameters: () => [], propDecorators: { id: [{
13477
13509
  type: Input
13478
13510
  }], label: [{