@tolle_/tolle-ui 0.0.15-beta → 0.0.18-beta

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.
@@ -18,10 +18,7 @@ function cn(...inputs) {
18
18
  return twMerge(clsx(inputs));
19
19
  }
20
20
 
21
- // 1. Define Component Variants (The "Recipe")
22
- const buttonVariants = cva(
23
- // Base styles applied to ALL buttons
24
- "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background", {
21
+ const buttonVariants = cva("inline-flex items-center justify-center rounded-md text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background active:scale-[0.98]", {
25
22
  variants: {
26
23
  variant: {
27
24
  default: "bg-primary text-primary-foreground hover:bg-primary/90",
@@ -36,62 +33,79 @@ const buttonVariants = cva(
36
33
  xs: "h-8 px-2 py-1 text-xs",
37
34
  sm: "h-9 rounded-md px-3",
38
35
  lg: "h-11 rounded-md px-8",
36
+ // RESTORED: Square icon button variants
39
37
  "icon-xs": "h-8 w-8",
40
38
  "icon-sm": "h-9 w-9",
41
39
  icon: "h-10 w-10",
42
40
  "icon-lg": "h-11 w-11",
43
41
  },
44
- // Added block variant
45
- block: {
46
- true: "w-full flex",
47
- },
48
- // Added readonly variant
49
- readonly: {
50
- true: "pointer-events-none opacity-80",
51
- },
52
- disabled: {
53
- true: "pointer-events-none",
54
- }
42
+ block: { true: "w-full flex" },
43
+ busy: { true: "relative !cursor-wait !pointer-events-none" }
55
44
  },
56
45
  defaultVariants: {
57
46
  variant: "default",
58
47
  size: "default",
59
48
  block: false,
60
- readonly: false,
61
49
  },
62
50
  });
63
51
  class ButtonComponent {
64
- // Allow consumers to pass a custom class to override styles
65
52
  class = '';
66
- // Expose the variants as Inputs
67
53
  variant = 'default';
68
54
  size = 'default';
69
- // Added new inputs
70
55
  block = false;
71
- readonly = false;
72
56
  disabled = false;
73
- // Calculate the final string of classes
57
+ busy = false;
58
+ readonly = false;
74
59
  get computedClass() {
75
- return cn(buttonVariants({ variant: this.variant, size: this.size, block: this.block, disabled: this.disabled }), this.class);
60
+ return cn(buttonVariants({
61
+ variant: this.variant,
62
+ size: this.size,
63
+ block: this.block,
64
+ busy: this.busy
65
+ }),
66
+ // Adds 'size-icon-sm', 'size-xs', etc. for the CSS selectors to work
67
+ 'size-' + this.size, this.class);
76
68
  }
77
69
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
78
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ButtonComponent, isStandalone: true, selector: "tolle-button", inputs: { class: "class", variant: "variant", size: "size", block: "block", readonly: "readonly", disabled: "disabled" }, ngImport: i0, template: `
79
- <button [class]="computedClass" [disabled]="disabled" [attr.aria-readonly]="readonly">
80
- <span class="flex items-center justify-center gap-2 w-full h-full">
70
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ButtonComponent, isStandalone: true, selector: "tolle-button", inputs: { class: "class", variant: "variant", size: "size", block: "block", disabled: "disabled", busy: "busy", readonly: "readonly" }, ngImport: i0, template: `
71
+ <button
72
+ [class]="computedClass"
73
+ [disabled]="disabled || busy"
74
+ [attr.aria-busy]="busy"
75
+ >
76
+ <div *ngIf="busy" class="absolute inset-0 flex items-center justify-center">
77
+ <svg class="animate-spin h-5 w-5 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
78
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
79
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
80
+ </svg>
81
+ </div>
82
+
83
+ <span class="flex items-center justify-center w-full h-full" [class.invisible]="busy">
81
84
  <ng-content></ng-content>
82
85
  </span>
83
86
  </button>
84
- `, isInline: true, styles: [":host ::ng-deep i{display:inline-flex;align-items:center;line-height:1;font-size:1.25em}:host ::ng-deep i:not(:only-child){margin-right:.5rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }] });
87
+ `, isInline: true, styles: [":host{display:inline-block}:host(.w-full){display:block}:host ::ng-deep i{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host-context(.size-xs) ::ng-deep i,:host-context(.size-icon-xs) ::ng-deep i,:host-context(.size-sm) ::ng-deep i,:host-context(.size-icon-sm) ::ng-deep i{font-size:1rem}:host-context(.size-default) ::ng-deep i,:host-context(.size-icon) ::ng-deep i,:host-context(.size-lg) ::ng-deep i,:host-context(.size-icon-lg) ::ng-deep i{font-size:1.2rem}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
85
88
  }
86
89
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
87
90
  type: Component,
88
91
  args: [{ selector: 'tolle-button', standalone: true, imports: [CommonModule], template: `
89
- <button [class]="computedClass" [disabled]="disabled" [attr.aria-readonly]="readonly">
90
- <span class="flex items-center justify-center gap-2 w-full h-full">
92
+ <button
93
+ [class]="computedClass"
94
+ [disabled]="disabled || busy"
95
+ [attr.aria-busy]="busy"
96
+ >
97
+ <div *ngIf="busy" class="absolute inset-0 flex items-center justify-center">
98
+ <svg class="animate-spin h-5 w-5 text-current" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
99
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
100
+ <path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
101
+ </svg>
102
+ </div>
103
+
104
+ <span class="flex items-center justify-center w-full h-full" [class.invisible]="busy">
91
105
  <ng-content></ng-content>
92
106
  </span>
93
107
  </button>
94
- `, styles: [":host ::ng-deep i{display:inline-flex;align-items:center;line-height:1;font-size:1.25em}:host ::ng-deep i:not(:only-child){margin-right:.5rem}\n"] }]
108
+ `, styles: [":host{display:inline-block}:host(.w-full){display:block}:host ::ng-deep i{display:inline-flex;align-items:center;justify-content:center;line-height:1}:host-context(.size-xs) ::ng-deep i,:host-context(.size-icon-xs) ::ng-deep i,:host-context(.size-sm) ::ng-deep i,:host-context(.size-icon-sm) ::ng-deep i{font-size:1rem}:host-context(.size-default) ::ng-deep i,:host-context(.size-icon) ::ng-deep i,:host-context(.size-lg) ::ng-deep i,:host-context(.size-icon-lg) ::ng-deep i{font-size:1.2rem}\n"] }]
95
109
  }], propDecorators: { class: [{
96
110
  type: Input
97
111
  }], variant: [{
@@ -100,86 +114,117 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
100
114
  type: Input
101
115
  }], block: [{
102
116
  type: Input
103
- }], readonly: [{
104
- type: Input
105
117
  }], disabled: [{
106
118
  type: Input
119
+ }], busy: [{
120
+ type: Input
121
+ }], readonly: [{
122
+ type: Input
107
123
  }] } });
108
124
 
109
125
  class InputComponent {
110
126
  cdr;
127
+ id = `input-${Math.random().toString(36).substr(2, 9)}`;
128
+ label = '';
129
+ hint = '';
130
+ errorMessage = '';
111
131
  type = 'text';
112
132
  placeholder = '';
113
- disabled = false;
114
- error = false;
115
133
  size = 'default';
116
134
  containerClass = '';
117
135
  class = '';
118
- // Internal State
136
+ // New States
137
+ disabled = false;
138
+ readonly = false;
139
+ error = false;
119
140
  value = '';
120
- // CVA Callbacks
121
141
  onChange = () => { };
122
142
  onTouched = () => { };
123
143
  constructor(cdr) {
124
144
  this.cdr = cdr;
125
145
  }
126
- // --- ControlValueAccessor Implementation ---
127
146
  writeValue(value) {
128
147
  this.value = value;
129
148
  this.cdr.markForCheck();
130
149
  }
131
- registerOnChange(fn) {
132
- this.onChange = fn;
133
- }
134
- registerOnTouched(fn) {
135
- this.onTouched = fn;
136
- }
150
+ registerOnChange(fn) { this.onChange = fn; }
151
+ registerOnTouched(fn) { this.onTouched = fn; }
137
152
  setDisabledState(isDisabled) {
138
153
  this.disabled = isDisabled;
139
154
  this.cdr.markForCheck();
140
155
  }
141
156
  onInputChange(event) {
157
+ if (this.readonly || this.disabled)
158
+ return;
142
159
  const val = event.target.value;
143
160
  this.value = val;
144
161
  this.onChange(val);
145
162
  }
146
- // --- Styling Logic ---
147
163
  cn = cn;
148
164
  get computedContainerClass() {
149
- return cn("group relative flex items-center w-full rounded-md border border-input bg-background ring-offset-background transition-all focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-1 shadow-sm", this.size === 'xs' && "h-8 px-2 gap-1.5", this.size === 'sm' && "h-9 px-3 gap-2", this.size === 'default' && "h-10 px-3 gap-2", this.size === 'lg' && "h-11 px-4 gap-3", this.disabled && "cursor-not-allowed opacity-50", this.error && "border-destructive focus-within:ring-destructive", this.containerClass);
165
+ return cn("group relative flex items-center w-full rounded-md border transition-all shadow-sm", "bg-background ring-offset-background",
166
+ // Sizing
167
+ this.size === 'xs' && "h-8 px-2 gap-1.5", this.size === 'sm' && "h-9 px-3 gap-2", this.size === 'default' && "h-10 px-3 gap-2", this.size === 'lg' && "h-11 px-4 gap-3",
168
+ // Interaction States (Focus ring disabled for Readonly/Disabled)
169
+ !(this.readonly || this.disabled) && "focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-1",
170
+ // Colors & Borders
171
+ this.error ? "border-destructive focus-within:ring-destructive" : "border-input",
172
+ // Disabled vs Readonly styling
173
+ this.disabled && "cursor-not-allowed opacity-50 bg-muted/30", this.readonly && "cursor-default bg-muted/10 border-dashed focus-within:ring-0", this.containerClass);
150
174
  }
151
175
  get computedInputClass() {
152
- return cn("flex-1 bg-transparent border-none p-0 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-0 disabled:cursor-not-allowed", this.size === 'xs' && "text-xs", this.size === 'lg' && "text-base", this.class);
176
+ return cn("flex-1 bg-transparent border-none p-0 text-sm placeholder:text-muted-foreground focus:outline-none focus:ring-0", this.size === 'xs' && "text-xs", this.size === 'lg' && "text-base", this.disabled && "cursor-not-allowed", this.readonly && "cursor-default", this.class);
153
177
  }
154
178
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
155
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: InputComponent, isStandalone: true, selector: "tolle-input", inputs: { type: "type", placeholder: "placeholder", disabled: "disabled", error: "error", size: "size", containerClass: "containerClass", class: "class" }, providers: [
179
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: InputComponent, isStandalone: true, selector: "tolle-input", inputs: { id: "id", label: "label", hint: "hint", errorMessage: "errorMessage", type: "type", placeholder: "placeholder", size: "size", containerClass: "containerClass", class: "class", disabled: "disabled", readonly: "readonly", error: "error" }, providers: [
156
180
  {
157
181
  provide: NG_VALUE_ACCESSOR,
158
182
  useExisting: forwardRef(() => InputComponent),
159
183
  multi: true
160
184
  }
161
185
  ], ngImport: i0, template: `
162
- <div [class]="computedContainerClass">
186
+ <div class="flex flex-col gap-1.5 w-full">
187
+ <label
188
+ *ngIf="label"
189
+ [for]="id"
190
+ [class.opacity-50]="disabled"
191
+ class="text-sm font-medium text-foreground leading-none transition-opacity"
192
+ >
193
+ {{ label }}
194
+ </label>
163
195
 
164
- <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
165
- <ng-content select="[prefix]"></ng-content>
166
- </div>
196
+ <div [class]="computedContainerClass">
197
+ <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
198
+ <ng-content select="[prefix]"></ng-content>
199
+ </div>
167
200
 
168
- <input
169
- [type]="type"
170
- [placeholder]="placeholder"
171
- [disabled]="disabled"
172
- [(ngModel)]="value"
173
- (blur)="onTouched()"
174
- (input)="onInputChange($event)"
175
- [class]="computedInputClass"
176
- />
201
+ <input
202
+ [id]="id"
203
+ [type]="type"
204
+ [placeholder]="placeholder"
205
+ [disabled]="disabled"
206
+ [readOnly]="readonly"
207
+ [(ngModel)]="value"
208
+ (blur)="onTouched()"
209
+ (input)="onInputChange($event)"
210
+ [class]="computedInputClass"
211
+ />
177
212
 
178
- <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
179
- <ng-content select="[suffix]"></ng-content>
213
+ <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
214
+ <ng-content select="[suffix]"></ng-content>
215
+ </div>
180
216
  </div>
217
+
218
+ <ng-container *ngIf="!disabled">
219
+ <p *ngIf="hint && !error" class="text-xs text-muted-foreground px-1">
220
+ {{ hint }}
221
+ </p>
222
+ <p *ngIf="error && errorMessage" class="text-xs text-destructive px-1">
223
+ {{ errorMessage }}
224
+ </p>
225
+ </ng-container>
181
226
  </div>
182
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i2.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: 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"] }] });
227
+ `, 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.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: 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"] }] });
183
228
  }
184
229
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputComponent, decorators: [{
185
230
  type: Component,
@@ -195,35 +240,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
195
240
  }
196
241
  ],
197
242
  template: `
198
- <div [class]="computedContainerClass">
243
+ <div class="flex flex-col gap-1.5 w-full">
244
+ <label
245
+ *ngIf="label"
246
+ [for]="id"
247
+ [class.opacity-50]="disabled"
248
+ class="text-sm font-medium text-foreground leading-none transition-opacity"
249
+ >
250
+ {{ label }}
251
+ </label>
199
252
 
200
- <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
201
- <ng-content select="[prefix]"></ng-content>
202
- </div>
253
+ <div [class]="computedContainerClass">
254
+ <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
255
+ <ng-content select="[prefix]"></ng-content>
256
+ </div>
203
257
 
204
- <input
205
- [type]="type"
206
- [placeholder]="placeholder"
207
- [disabled]="disabled"
208
- [(ngModel)]="value"
209
- (blur)="onTouched()"
210
- (input)="onInputChange($event)"
211
- [class]="computedInputClass"
212
- />
258
+ <input
259
+ [id]="id"
260
+ [type]="type"
261
+ [placeholder]="placeholder"
262
+ [disabled]="disabled"
263
+ [readOnly]="readonly"
264
+ [(ngModel)]="value"
265
+ (blur)="onTouched()"
266
+ (input)="onInputChange($event)"
267
+ [class]="computedInputClass"
268
+ />
213
269
 
214
- <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
215
- <ng-content select="[suffix]"></ng-content>
270
+ <div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
271
+ <ng-content select="[suffix]"></ng-content>
272
+ </div>
216
273
  </div>
274
+
275
+ <ng-container *ngIf="!disabled">
276
+ <p *ngIf="hint && !error" class="text-xs text-muted-foreground px-1">
277
+ {{ hint }}
278
+ </p>
279
+ <p *ngIf="error && errorMessage" class="text-xs text-destructive px-1">
280
+ {{ errorMessage }}
281
+ </p>
282
+ </ng-container>
217
283
  </div>
218
284
  `,
219
285
  }]
220
- }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { type: [{
286
+ }], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { id: [{
221
287
  type: Input
222
- }], placeholder: [{
288
+ }], label: [{
223
289
  type: Input
224
- }], disabled: [{
290
+ }], hint: [{
225
291
  type: Input
226
- }], error: [{
292
+ }], errorMessage: [{
293
+ type: Input
294
+ }], type: [{
295
+ type: Input
296
+ }], placeholder: [{
227
297
  type: Input
228
298
  }], size: [{
229
299
  type: Input
@@ -231,6 +301,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
231
301
  type: Input
232
302
  }], class: [{
233
303
  type: Input
304
+ }], disabled: [{
305
+ type: Input
306
+ }], readonly: [{
307
+ type: Input
308
+ }], error: [{
309
+ type: Input
234
310
  }] } });
235
311
 
236
312
  class CardComponent {
@@ -426,6 +502,7 @@ class SelectComponent {
426
502
  disabled = false;
427
503
  searchable = false;
428
504
  size = 'default';
505
+ readonly = false;
429
506
  trigger;
430
507
  popover;
431
508
  items;
@@ -453,11 +530,19 @@ class SelectComponent {
453
530
  }
454
531
  // UPDATED: Centralized sizing logic for the trigger
455
532
  get computedTriggerClass() {
456
- return cn('flex w-full items-center justify-between rounded-md border border-input bg-background ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring focus:ring-ring focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 transition-all', 'disabled:opacity-50 shadow-sm transition-shadow', 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.class);
533
+ return cn('flex w-full items-center justify-between rounded-md border transition-all shadow-sm', 'bg-background ring-offset-background placeholder:text-muted-foreground',
534
+ // Sizing
535
+ 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',
536
+ // Interaction States (Focus ring disabled for Readonly/Disabled)
537
+ !(this.readonly || this.disabled) && 'focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1',
538
+ // Colors & Borders (Matching your Hex-based theme logic)
539
+ this.disabled && 'cursor-not-allowed opacity-50 bg-muted/30 border-input', this.readonly && 'cursor-default bg-muted/10 border-dashed border-input focus:ring-0', !this.disabled && !this.readonly && 'border-input hover:border-accent cursor-pointer', this.class);
457
540
  }
458
541
  // UPDATED: Dynamic icon sizing relative to the trigger size
459
542
  get iconClass() {
460
- return cn('ri-arrow-down-s-line text-muted-foreground ml-2 transition-transform duration-200', this.isOpen ? 'rotate-180' : '', (this.size === 'xs' || this.size === 'sm') ? 'text-[14px]' : 'text-[18px]');
543
+ return cn('ri-arrow-down-s-line text-muted-foreground ml-2 transition-transform duration-200', this.isOpen ? 'rotate-180' : '', (this.size === 'xs' || this.size === 'sm') ? 'text-[14px]' : 'text-[18px]',
544
+ // Hide or fade icon when interaction is blocked
545
+ (this.disabled || this.readonly) && 'opacity-30');
461
546
  }
462
547
  ngAfterContentInit() {
463
548
  this.updateItemSelection();
@@ -471,7 +556,7 @@ class SelectComponent {
471
556
  }
472
557
  }
473
558
  toggle() {
474
- if (this.disabled)
559
+ if (this.disabled || this.readonly)
475
560
  return;
476
561
  this.isOpen ? this.close() : this.open();
477
562
  }
@@ -538,7 +623,7 @@ class SelectComponent {
538
623
  this.cleanupAutoUpdate();
539
624
  }
540
625
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, deps: [{ token: SelectService }], target: i0.ɵɵFactoryTarget.Component });
541
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "tolle-select", inputs: { placeholder: "placeholder", class: "class", disabled: "disabled", searchable: "searchable", size: "size" }, host: { listeners: { "document:mousedown": "onDocumentClick($event)" } }, providers: [
626
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: SelectComponent, isStandalone: true, selector: "tolle-select", inputs: { placeholder: "placeholder", class: "class", disabled: "disabled", searchable: "searchable", size: "size", readonly: "readonly" }, host: { listeners: { "document:mousedown": "onDocumentClick($event)" } }, providers: [
542
627
  SelectService,
543
628
  {
544
629
  provide: NG_VALUE_ACCESSOR,
@@ -585,7 +670,7 @@ class SelectComponent {
585
670
  </div>
586
671
  </div>
587
672
  </div>
588
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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: InputComponent, selector: "tolle-input", inputs: ["type", "placeholder", "disabled", "error", "size", "containerClass", "class"] }] });
673
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { 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: InputComponent, selector: "tolle-input", inputs: ["id", "label", "hint", "errorMessage", "type", "placeholder", "size", "containerClass", "class", "disabled", "readonly", "error"] }] });
589
674
  }
590
675
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, decorators: [{
591
676
  type: Component,
@@ -653,6 +738,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
653
738
  type: Input
654
739
  }], size: [{
655
740
  type: Input
741
+ }], readonly: [{
742
+ type: Input
656
743
  }], trigger: [{
657
744
  type: ViewChild,
658
745
  args: ['trigger']
@@ -1568,7 +1655,7 @@ class MultiSelectComponent {
1568
1655
  </div>
1569
1656
  </div>
1570
1657
  </div>
1571
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: BadgeComponent, selector: "tolle-badge", inputs: ["variant", "size", "removable", "class"], outputs: ["onRemove"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["type", "placeholder", "disabled", "error", "size", "containerClass", "class"] }] });
1658
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: BadgeComponent, selector: "tolle-badge", inputs: ["variant", "size", "removable", "class"], outputs: ["onRemove"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["id", "label", "hint", "errorMessage", "type", "placeholder", "size", "containerClass", "class", "disabled", "readonly", "error"] }] });
1572
1659
  }
1573
1660
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectComponent, decorators: [{
1574
1661
  type: Component,
@@ -2513,7 +2600,7 @@ class PaginationComponent {
2513
2600
  </div>
2514
2601
  </div>
2515
2602
  </div>
2516
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: SelectComponent, selector: "tolle-select", inputs: ["placeholder", "class", "disabled", "searchable", "size"] }, { kind: "component", type: SelectItemComponent, selector: "tolle-select-item", inputs: ["value", "class", "selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2603
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { 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: SelectComponent, selector: "tolle-select", inputs: ["placeholder", "class", "disabled", "searchable", "size", "readonly"] }, { kind: "component", type: SelectItemComponent, selector: "tolle-select-item", inputs: ["value", "class", "selected"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2517
2604
  }
2518
2605
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, decorators: [{
2519
2606
  type: Component,
@@ -2642,6 +2729,16 @@ class DataTableComponent {
2642
2729
  pageSize = 10;
2643
2730
  expandable = false;
2644
2731
  size = 'default';
2732
+ // --- NEW INPUTS FOR COLUMN HIDING ---
2733
+ allowColumnHiding = true;
2734
+ showSettings = true; // Set to false to hide the gear icon/menu entirely
2735
+ // Track visibility state: { 'columnKey': true/false }
2736
+ columnVisibility = {};
2737
+ showColumnMenu = false;
2738
+ // Filter columns based on visibility state
2739
+ get activeColumns() {
2740
+ return this.columns.filter(col => this.columnVisibility[col.key]);
2741
+ }
2645
2742
  // Track which rows are open
2646
2743
  expandedRows = new Set();
2647
2744
  // Use ContentChildren to grab the tolleCell templates from the user's HTML
@@ -2687,11 +2784,25 @@ class DataTableComponent {
2687
2784
  if (changes['data']) {
2688
2785
  this.refreshTable();
2689
2786
  }
2787
+ if (changes['columns']) {
2788
+ this.initializeVisibility();
2789
+ }
2790
+ }
2791
+ initializeVisibility() {
2792
+ // Default all columns to visible if not already set
2793
+ this.columns.forEach(col => {
2794
+ if (this.columnVisibility[col.key] === undefined) {
2795
+ this.columnVisibility[col.key] = true;
2796
+ }
2797
+ });
2690
2798
  }
2691
2799
  // --- Search & Sort & Page Logic ---
2692
2800
  // (Your existing implementation of applySearch, applySort, and updatePage goes here)
2693
2801
  refreshTable() { this.applySearch(); this.applySort(); this.updatePage(); }
2694
2802
  onSearch() { this.currentPage = 1; this.refreshTable(); }
2803
+ toggleColumn(key) {
2804
+ this.columnVisibility[key] = !this.columnVisibility[key];
2805
+ }
2695
2806
  applySearch() {
2696
2807
  if (!this.searchTerm) {
2697
2808
  this.filteredData = [...this.data];
@@ -2749,7 +2860,7 @@ class DataTableComponent {
2749
2860
  return this.cellTemplates?.find(t => t.name === key);
2750
2861
  }
2751
2862
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2752
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DataTableComponent, isStandalone: true, selector: "tolle-data-table", inputs: { data: "data", columns: "columns", searchable: "searchable", paginate: "paginate", pageSize: "pageSize", expandable: "expandable", size: "size", expandedTemplate: "expandedTemplate" }, queries: [{ propertyName: "cellTemplates", predicate: TolleCellDirective }], usesOnChanges: true, ngImport: i0, template: `
2863
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: DataTableComponent, isStandalone: true, selector: "tolle-data-table", inputs: { data: "data", columns: "columns", searchable: "searchable", paginate: "paginate", pageSize: "pageSize", expandable: "expandable", size: "size", allowColumnHiding: "allowColumnHiding", showSettings: "showSettings", expandedTemplate: "expandedTemplate" }, queries: [{ propertyName: "cellTemplates", predicate: TolleCellDirective }], usesOnChanges: true, ngImport: i0, template: `
2753
2864
  <div class="space-y-4">
2754
2865
  <div *ngIf="searchable" class="flex items-center py-2">
2755
2866
  <tolle-input
@@ -2837,7 +2948,7 @@ class DataTableComponent {
2837
2948
  (onPageSizeChange)="updatePage()"
2838
2949
  ></tolle-pagination>
2839
2950
  </div>
2840
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: PaginationComponent, selector: "tolle-pagination", inputs: ["class", "showPageLinks", "showPageOptions", "showCurrentPageInfo", "currentPageInfoTemplate", "totalRecords", "currentPageSize", "currentPage", "pageSizeOptions"], outputs: ["onPageNumberChange", "onPageSizeChange"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["type", "placeholder", "disabled", "error", "size", "containerClass", "class"] }] });
2951
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { 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: PaginationComponent, selector: "tolle-pagination", inputs: ["class", "showPageLinks", "showPageOptions", "showCurrentPageInfo", "currentPageInfoTemplate", "totalRecords", "currentPageSize", "currentPage", "pageSizeOptions"], outputs: ["onPageNumberChange", "onPageSizeChange"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["id", "label", "hint", "errorMessage", "type", "placeholder", "size", "containerClass", "class", "disabled", "readonly", "error"] }] });
2841
2952
  }
2842
2953
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataTableComponent, decorators: [{
2843
2954
  type: Component,
@@ -2949,6 +3060,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2949
3060
  type: Input
2950
3061
  }], size: [{
2951
3062
  type: Input
3063
+ }], allowColumnHiding: [{
3064
+ type: Input
3065
+ }], showSettings: [{
3066
+ type: Input
2952
3067
  }], cellTemplates: [{
2953
3068
  type: ContentChildren,
2954
3069
  args: [TolleCellDirective]
@@ -3743,7 +3858,7 @@ class DateRangePickerComponent {
3743
3858
  ></tolle-range-calendar>
3744
3859
  </div>
3745
3860
  </div>
3746
- `, 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: RangeCalendarComponent, selector: "tolle-range-calendar", inputs: ["class", "disablePastDates"], outputs: ["rangeSelect"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["type", "placeholder", "disabled", "error", "size", "containerClass", "class"] }] });
3861
+ `, 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: RangeCalendarComponent, selector: "tolle-range-calendar", inputs: ["class", "disablePastDates"], outputs: ["rangeSelect"] }, { kind: "component", type: InputComponent, selector: "tolle-input", inputs: ["id", "label", "hint", "errorMessage", "type", "placeholder", "size", "containerClass", "class", "disabled", "readonly", "error"] }] });
3747
3862
  }
3748
3863
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateRangePickerComponent, decorators: [{
3749
3864
  type: Component,
@@ -3955,6 +4070,176 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3955
4070
  args: ['click']
3956
4071
  }] } });
3957
4072
 
4073
+ class TextareaComponent {
4074
+ textareaElement;
4075
+ id = `textarea-${Math.random().toString(36).substr(2, 9)}`;
4076
+ label = '';
4077
+ placeholder = '';
4078
+ hint = '';
4079
+ rows = 3;
4080
+ maxLength;
4081
+ showCharacterCount = false;
4082
+ autoGrow = false;
4083
+ error = false;
4084
+ className = '';
4085
+ // New States
4086
+ disabled = false;
4087
+ readonly = false;
4088
+ value = '';
4089
+ onChange = () => { };
4090
+ onTouched = () => { };
4091
+ ngAfterViewInit() {
4092
+ if (this.autoGrow)
4093
+ this.resize();
4094
+ }
4095
+ get textareaClasses() {
4096
+ return cn('flex w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background transition-all duration-200 shadow-sm', 'placeholder:text-muted-foreground focus-visible:outline-none',
4097
+ // Focus States (Disabled only when readonly or disabled is true)
4098
+ !(this.readonly || this.disabled) && 'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-1',
4099
+ // Border colors
4100
+ this.error ? 'border-destructive' : 'border-input',
4101
+ // Disabled vs Readonly styles
4102
+ this.disabled && 'cursor-not-allowed opacity-50 bg-muted/30', this.readonly && 'cursor-default bg-muted/10 border-dashed focus-visible:ring-0', 'scrollbar-thin scrollbar-thumb-muted scrollbar-track-transparent', 'min-h-[80px]', this.className);
4103
+ }
4104
+ handleInput(event) {
4105
+ if (this.readonly || this.disabled)
4106
+ return;
4107
+ const val = event.target.value;
4108
+ this.value = val;
4109
+ this.onChange(val);
4110
+ if (this.autoGrow)
4111
+ this.resize();
4112
+ }
4113
+ resize() {
4114
+ const textarea = this.textareaElement.nativeElement;
4115
+ textarea.style.height = 'auto';
4116
+ textarea.style.height = `${textarea.scrollHeight}px`;
4117
+ }
4118
+ writeValue(value) {
4119
+ this.value = value;
4120
+ if (this.autoGrow)
4121
+ setTimeout(() => this.resize());
4122
+ }
4123
+ registerOnChange(fn) { this.onChange = fn; }
4124
+ registerOnTouched(fn) { this.onTouched = fn; }
4125
+ setDisabledState(isDisabled) { this.disabled = isDisabled; }
4126
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4127
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: TextareaComponent, isStandalone: true, selector: "tolle-textarea", inputs: { id: "id", label: "label", placeholder: "placeholder", hint: "hint", rows: "rows", maxLength: "maxLength", showCharacterCount: "showCharacterCount", autoGrow: "autoGrow", error: "error", className: "className", disabled: "disabled", readonly: "readonly" }, providers: [
4128
+ {
4129
+ provide: NG_VALUE_ACCESSOR,
4130
+ useExisting: forwardRef(() => TextareaComponent),
4131
+ multi: true
4132
+ }
4133
+ ], viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["textareaElement"], descendants: true }], ngImport: i0, template: `
4134
+ <div class="flex flex-col gap-1.5 w-full">
4135
+ <label *ngIf="label" [for]="id"
4136
+ [class.opacity-50]="disabled"
4137
+ class="text-sm font-medium text-foreground leading-none transition-opacity">
4138
+ {{ label }}
4139
+ </label>
4140
+
4141
+ <div class="relative">
4142
+ <textarea
4143
+ #textareaElement
4144
+ [id]="id"
4145
+ [placeholder]="placeholder"
4146
+ [disabled]="disabled"
4147
+ [readOnly]="readonly"
4148
+ [rows]="rows"
4149
+ [(ngModel)]="value"
4150
+ (input)="handleInput($event)"
4151
+ (blur)="onTouched()"
4152
+ [class]="textareaClasses"
4153
+ [style.resize]="(autoGrow || readonly || disabled) ? 'none' : 'vertical'"
4154
+ [style.overflow]="autoGrow ? 'hidden' : 'auto'"
4155
+ ></textarea>
4156
+ </div>
4157
+
4158
+ <div *ngIf="(showCharacterCount || hint) && !disabled" class="flex justify-between items-center px-1">
4159
+ <p *ngIf="hint" class="text-xs text-muted-foreground">{{ hint }}</p>
4160
+ <p *ngIf="showCharacterCount" class="text-[10px] uppercase tracking-wider text-muted-foreground ml-auto font-medium">
4161
+ {{ value.length || 0 }}{{ maxLength ? ' / ' + maxLength : '' }}
4162
+ </p>
4163
+ </div>
4164
+ </div>
4165
+ `, 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.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: 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"] }] });
4166
+ }
4167
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextareaComponent, decorators: [{
4168
+ type: Component,
4169
+ args: [{
4170
+ selector: 'tolle-textarea',
4171
+ standalone: true,
4172
+ imports: [CommonModule, FormsModule],
4173
+ providers: [
4174
+ {
4175
+ provide: NG_VALUE_ACCESSOR,
4176
+ useExisting: forwardRef(() => TextareaComponent),
4177
+ multi: true
4178
+ }
4179
+ ],
4180
+ template: `
4181
+ <div class="flex flex-col gap-1.5 w-full">
4182
+ <label *ngIf="label" [for]="id"
4183
+ [class.opacity-50]="disabled"
4184
+ class="text-sm font-medium text-foreground leading-none transition-opacity">
4185
+ {{ label }}
4186
+ </label>
4187
+
4188
+ <div class="relative">
4189
+ <textarea
4190
+ #textareaElement
4191
+ [id]="id"
4192
+ [placeholder]="placeholder"
4193
+ [disabled]="disabled"
4194
+ [readOnly]="readonly"
4195
+ [rows]="rows"
4196
+ [(ngModel)]="value"
4197
+ (input)="handleInput($event)"
4198
+ (blur)="onTouched()"
4199
+ [class]="textareaClasses"
4200
+ [style.resize]="(autoGrow || readonly || disabled) ? 'none' : 'vertical'"
4201
+ [style.overflow]="autoGrow ? 'hidden' : 'auto'"
4202
+ ></textarea>
4203
+ </div>
4204
+
4205
+ <div *ngIf="(showCharacterCount || hint) && !disabled" class="flex justify-between items-center px-1">
4206
+ <p *ngIf="hint" class="text-xs text-muted-foreground">{{ hint }}</p>
4207
+ <p *ngIf="showCharacterCount" class="text-[10px] uppercase tracking-wider text-muted-foreground ml-auto font-medium">
4208
+ {{ value.length || 0 }}{{ maxLength ? ' / ' + maxLength : '' }}
4209
+ </p>
4210
+ </div>
4211
+ </div>
4212
+ `
4213
+ }]
4214
+ }], propDecorators: { textareaElement: [{
4215
+ type: ViewChild,
4216
+ args: ['textareaElement']
4217
+ }], id: [{
4218
+ type: Input
4219
+ }], label: [{
4220
+ type: Input
4221
+ }], placeholder: [{
4222
+ type: Input
4223
+ }], hint: [{
4224
+ type: Input
4225
+ }], rows: [{
4226
+ type: Input
4227
+ }], maxLength: [{
4228
+ type: Input
4229
+ }], showCharacterCount: [{
4230
+ type: Input
4231
+ }], autoGrow: [{
4232
+ type: Input
4233
+ }], error: [{
4234
+ type: Input
4235
+ }], className: [{
4236
+ type: Input
4237
+ }], disabled: [{
4238
+ type: Input
4239
+ }], readonly: [{
4240
+ type: Input
4241
+ }] } });
4242
+
3958
4243
  /*
3959
4244
  * Public API Surface of tolle
3960
4245
  */
@@ -3963,5 +4248,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3963
4248
  * Generated bundle index. Do not edit.
3964
4249
  */
3965
4250
 
3966
- export { AccordionComponent, AccordionItemComponent, BadgeComponent, ButtonComponent, ButtonGroupComponent, CalendarComponent, CardComponent, CardContentComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CheckboxComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, InputComponent, MaskedInputComponent, Modal, ModalComponent, ModalRef, ModalService, ModalStackService, MultiSelectComponent, PaginationComponent, RangeCalendarComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SkeletonComponent, SwitchComponent, TOLLE_CONFIG, ThemeService, ToastContainerComponent, ToastService, TolleCellDirective, TooltipDirective, cn, provideTolleConfig };
4251
+ export { AccordionComponent, AccordionItemComponent, BadgeComponent, ButtonComponent, ButtonGroupComponent, CalendarComponent, CardComponent, CardContentComponent, CardFooterComponent, CardHeaderComponent, CardTitleComponent, CheckboxComponent, DataTableComponent, DatePickerComponent, DateRangePickerComponent, DropdownItemComponent, DropdownLabelComponent, DropdownMenuComponent, DropdownSeparatorComponent, DropdownTriggerDirective, InputComponent, MaskedInputComponent, Modal, ModalComponent, ModalRef, ModalService, ModalStackService, MultiSelectComponent, PaginationComponent, RangeCalendarComponent, SelectComponent, SelectGroupComponent, SelectItemComponent, SelectSeparatorComponent, SkeletonComponent, SwitchComponent, TOLLE_CONFIG, TextareaComponent, ThemeService, ToastContainerComponent, ToastService, TolleCellDirective, TooltipDirective, cn, provideTolleConfig };
3967
4252
  //# sourceMappingURL=tolle_-tolle-ui.mjs.map