@tolle_/tolle-ui 0.0.19-beta → 0.0.21-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.
- package/esm2022/lib/badge.component.mjs +4 -4
- package/esm2022/lib/button.component.mjs +18 -13
- package/esm2022/lib/card.component.mjs +3 -3
- package/esm2022/lib/data-table.component.mjs +1 -1
- package/esm2022/lib/date-picker.component.mjs +2 -2
- package/esm2022/lib/date-range-picker.component.mjs +1 -1
- package/esm2022/lib/input.component.mjs +125 -32
- package/esm2022/lib/masked-input.component.mjs +118 -30
- package/esm2022/lib/multi-select.component.mjs +1 -1
- package/esm2022/lib/otp-slot.component.mjs +35 -23
- package/esm2022/lib/select.component.mjs +38 -9
- package/esm2022/lib/textarea.component.mjs +130 -26
- package/esm2022/lib/theme.service.mjs +208 -61
- package/fesm2022/tolle-ui.mjs +676 -198
- package/fesm2022/tolle-ui.mjs.map +1 -1
- package/lib/button.component.d.ts +1 -2
- package/lib/input.component.d.ts +11 -3
- package/lib/masked-input.component.d.ts +7 -1
- package/lib/otp-slot.component.d.ts +1 -0
- package/lib/select.component.d.ts +1 -0
- package/lib/textarea.component.d.ts +8 -1
- package/lib/theme.service.d.ts +35 -3
- package/package.json +1 -1
- package/preset.js +47 -33
- package/theme.css +204 -168
package/fesm2022/tolle-ui.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { clsx } from 'clsx';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Component, Input, forwardRef, Injectable, Optional, HostListener,
|
|
4
|
+
import { Component, Input, forwardRef, ViewChild, Injectable, Optional, HostListener, ContentChildren, EventEmitter, Output, Directive, inject, PLATFORM_ID, Inject, InjectionToken, APP_INITIALIZER, ChangeDetectorRef, ChangeDetectionStrategy, TemplateRef, Injector, HostBinding } from '@angular/core';
|
|
5
5
|
import * as i1 from '@angular/common';
|
|
6
6
|
import { CommonModule, isPlatformBrowser, DOCUMENT, NgIf, NgTemplateOutlet } from '@angular/common';
|
|
7
7
|
import { cva } from 'class-variance-authority';
|
|
@@ -18,15 +18,15 @@ function cn(...inputs) {
|
|
|
18
18
|
return twMerge(clsx(inputs));
|
|
19
19
|
}
|
|
20
20
|
|
|
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]", {
|
|
21
|
+
const buttonVariants = cva("tolle-button-base 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]", {
|
|
22
22
|
variants: {
|
|
23
23
|
variant: {
|
|
24
24
|
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
25
25
|
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
26
|
-
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
|
|
26
|
+
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
|
27
27
|
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
28
28
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
29
|
-
link: "underline-offset-4 hover:underline
|
|
29
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
30
30
|
},
|
|
31
31
|
size: {
|
|
32
32
|
default: "h-10 px-4 py-2",
|
|
@@ -38,7 +38,7 @@ const buttonVariants = cva("inline-flex items-center justify-center rounded-md t
|
|
|
38
38
|
icon: "h-10 w-10",
|
|
39
39
|
"icon-lg": "h-11 w-11",
|
|
40
40
|
},
|
|
41
|
-
busy: { true: "relative !cursor-wait !pointer-events-none" }
|
|
41
|
+
busy: { true: "tolle-button--busy relative !cursor-wait !pointer-events-none" }
|
|
42
42
|
},
|
|
43
43
|
defaultVariants: {
|
|
44
44
|
variant: "default",
|
|
@@ -51,16 +51,15 @@ class ButtonComponent {
|
|
|
51
51
|
size = 'default';
|
|
52
52
|
disabled = false;
|
|
53
53
|
busy = false;
|
|
54
|
-
readonly = false;
|
|
55
54
|
get computedClass() {
|
|
56
55
|
return cn(buttonVariants({
|
|
57
56
|
variant: this.variant,
|
|
58
57
|
size: this.size,
|
|
59
58
|
busy: this.busy
|
|
60
|
-
}),
|
|
59
|
+
}), this.class);
|
|
61
60
|
}
|
|
62
61
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
63
|
-
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", disabled: "disabled", busy: "busy",
|
|
62
|
+
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", disabled: "disabled", busy: "busy" }, host: { classAttribute: "tolle-button-wrapper inline-block align-middle" }, ngImport: i0, template: `
|
|
64
63
|
<button
|
|
65
64
|
[class]="computedClass"
|
|
66
65
|
[disabled]="disabled || busy"
|
|
@@ -77,11 +76,15 @@ class ButtonComponent {
|
|
|
77
76
|
<ng-content></ng-content>
|
|
78
77
|
</span>
|
|
79
78
|
</button>
|
|
80
|
-
`, isInline: true,
|
|
79
|
+
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
81
80
|
}
|
|
82
81
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ButtonComponent, decorators: [{
|
|
83
82
|
type: Component,
|
|
84
|
-
args: [{
|
|
83
|
+
args: [{
|
|
84
|
+
selector: 'tolle-button',
|
|
85
|
+
standalone: true,
|
|
86
|
+
imports: [CommonModule],
|
|
87
|
+
template: `
|
|
85
88
|
<button
|
|
86
89
|
[class]="computedClass"
|
|
87
90
|
[disabled]="disabled || busy"
|
|
@@ -98,7 +101,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
98
101
|
<ng-content></ng-content>
|
|
99
102
|
</span>
|
|
100
103
|
</button>
|
|
101
|
-
`,
|
|
104
|
+
`,
|
|
105
|
+
host: {
|
|
106
|
+
'class': 'tolle-button-wrapper inline-block align-middle'
|
|
107
|
+
}
|
|
108
|
+
}]
|
|
102
109
|
}], propDecorators: { class: [{
|
|
103
110
|
type: Input
|
|
104
111
|
}], variant: [{
|
|
@@ -109,12 +116,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
109
116
|
type: Input
|
|
110
117
|
}], busy: [{
|
|
111
118
|
type: Input
|
|
112
|
-
}], readonly: [{
|
|
113
|
-
type: Input
|
|
114
119
|
}] } });
|
|
115
120
|
|
|
116
121
|
class InputComponent {
|
|
117
122
|
cdr;
|
|
123
|
+
inputElement;
|
|
118
124
|
id = `input-${Math.random().toString(36).substr(2, 9)}`;
|
|
119
125
|
label = '';
|
|
120
126
|
hint = '';
|
|
@@ -128,12 +134,20 @@ class InputComponent {
|
|
|
128
134
|
disabled = false;
|
|
129
135
|
readonly = false;
|
|
130
136
|
error = false;
|
|
137
|
+
// Focus behavior
|
|
138
|
+
hideHintOnFocus = true;
|
|
131
139
|
value = '';
|
|
132
140
|
onChange = () => { };
|
|
133
141
|
onTouched = () => { };
|
|
142
|
+
isFocused = false;
|
|
134
143
|
constructor(cdr) {
|
|
135
144
|
this.cdr = cdr;
|
|
136
145
|
}
|
|
146
|
+
ngAfterViewInit() {
|
|
147
|
+
if (this.inputElement?.nativeElement.hasAttribute('autofocus')) {
|
|
148
|
+
setTimeout(() => this.inputElement.nativeElement.focus());
|
|
149
|
+
}
|
|
150
|
+
}
|
|
137
151
|
writeValue(value) {
|
|
138
152
|
this.value = value;
|
|
139
153
|
this.cdr.markForCheck();
|
|
@@ -151,66 +165,132 @@ class InputComponent {
|
|
|
151
165
|
this.value = val;
|
|
152
166
|
this.onChange(val);
|
|
153
167
|
}
|
|
168
|
+
onFocus() {
|
|
169
|
+
this.isFocused = true;
|
|
170
|
+
}
|
|
171
|
+
onBlur() {
|
|
172
|
+
this.isFocused = false;
|
|
173
|
+
this.onTouched();
|
|
174
|
+
}
|
|
175
|
+
focusInput() {
|
|
176
|
+
if (!this.disabled && this.inputElement) {
|
|
177
|
+
this.inputElement.nativeElement.focus();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
154
180
|
cn = cn;
|
|
181
|
+
get computedLabelClass() {
|
|
182
|
+
return cn("text-sm font-medium text-foreground leading-none transition-opacity duration-200", this.disabled && "opacity-50");
|
|
183
|
+
}
|
|
155
184
|
get computedContainerClass() {
|
|
156
|
-
return cn(
|
|
185
|
+
return cn(
|
|
186
|
+
// Base styles
|
|
187
|
+
"group relative flex items-center w-full rounded-md border transition-all duration-200", "bg-background",
|
|
188
|
+
// Border and shadow
|
|
189
|
+
"border-input shadow-sm",
|
|
157
190
|
// Sizing
|
|
158
|
-
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",
|
|
159
|
-
//
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
191
|
+
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",
|
|
192
|
+
// Focus state - SIMPLE AND ELEGANT LIKE ZARDUI
|
|
193
|
+
// The magic happens in CSS: border darkens automatically on focus
|
|
194
|
+
!(this.readonly || this.disabled) && [
|
|
195
|
+
"focus-within:border-primary/80",
|
|
196
|
+
"focus-within:ring-4",
|
|
197
|
+
"focus-within:ring-ring/30",
|
|
198
|
+
"focus-within:ring-offset-0",
|
|
199
|
+
"focus-within:shadow-none",
|
|
200
|
+
],
|
|
201
|
+
// Error state
|
|
202
|
+
this.error && [
|
|
203
|
+
"border-destructive",
|
|
204
|
+
!(this.readonly || this.disabled) && [
|
|
205
|
+
"focus-within:border-destructive/80",
|
|
206
|
+
"focus-within:ring-destructive/30"
|
|
207
|
+
]
|
|
208
|
+
],
|
|
209
|
+
// Disabled state
|
|
210
|
+
this.disabled && [
|
|
211
|
+
"cursor-not-allowed opacity-50",
|
|
212
|
+
"border-opacity-50"
|
|
213
|
+
],
|
|
214
|
+
// Readonly state
|
|
215
|
+
this.readonly && [
|
|
216
|
+
"cursor-default",
|
|
217
|
+
"border-dashed",
|
|
218
|
+
!this.disabled && "focus-within:ring-0 focus-within:border-opacity-100"
|
|
219
|
+
], this.containerClass);
|
|
165
220
|
}
|
|
166
221
|
get computedInputClass() {
|
|
167
|
-
return cn(
|
|
222
|
+
return cn(
|
|
223
|
+
// Base styles
|
|
224
|
+
"flex-1 bg-transparent border-none p-0", "placeholder:text-muted-foreground",
|
|
225
|
+
// Remove all default focus styles
|
|
226
|
+
"focus:outline-none focus:ring-0 focus:shadow-none",
|
|
227
|
+
// Text sizing
|
|
228
|
+
this.size === 'xs' && "text-xs", this.size === 'sm' && "text-sm", this.size === 'default' && "text-sm", this.size === 'lg' && "text-base",
|
|
229
|
+
// Cursor states
|
|
230
|
+
this.disabled && "cursor-not-allowed", this.readonly && "cursor-default",
|
|
231
|
+
// Text color
|
|
232
|
+
"text-foreground",
|
|
233
|
+
// Selection color
|
|
234
|
+
"selection:bg-primary/20 selection:text-foreground", this.class);
|
|
168
235
|
}
|
|
169
236
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: InputComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
170
|
-
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: [
|
|
237
|
+
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", hideHintOnFocus: "hideHintOnFocus" }, providers: [
|
|
171
238
|
{
|
|
172
239
|
provide: NG_VALUE_ACCESSOR,
|
|
173
240
|
useExisting: forwardRef(() => InputComponent),
|
|
174
241
|
multi: true
|
|
175
242
|
}
|
|
176
|
-
], ngImport: i0, template: `
|
|
243
|
+
], viewQueries: [{ propertyName: "inputElement", first: true, predicate: ["inputElement"], descendants: true }], ngImport: i0, template: `
|
|
177
244
|
<div class="flex flex-col gap-1.5 w-full">
|
|
178
245
|
<label
|
|
179
246
|
*ngIf="label"
|
|
180
247
|
[for]="id"
|
|
181
|
-
[class
|
|
182
|
-
class="text-sm font-medium text-foreground leading-none transition-opacity"
|
|
183
|
-
>
|
|
248
|
+
[class]="computedLabelClass">
|
|
184
249
|
{{ label }}
|
|
185
250
|
</label>
|
|
186
251
|
|
|
187
|
-
<div
|
|
188
|
-
|
|
252
|
+
<div
|
|
253
|
+
[class]="computedContainerClass"
|
|
254
|
+
(click)="focusInput()"
|
|
255
|
+
>
|
|
256
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
189
257
|
<ng-content select="[prefix]"></ng-content>
|
|
190
258
|
</div>
|
|
191
259
|
|
|
192
260
|
<input
|
|
261
|
+
#inputElement
|
|
193
262
|
[id]="id"
|
|
194
263
|
[type]="type"
|
|
195
264
|
[placeholder]="placeholder"
|
|
196
265
|
[disabled]="disabled"
|
|
197
266
|
[readOnly]="readonly"
|
|
198
267
|
[(ngModel)]="value"
|
|
199
|
-
(blur)="
|
|
268
|
+
(blur)="onBlur()"
|
|
269
|
+
(focus)="onFocus()"
|
|
200
270
|
(input)="onInputChange($event)"
|
|
201
271
|
[class]="computedInputClass"
|
|
272
|
+
[attr.aria-invalid]="error"
|
|
273
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
202
274
|
/>
|
|
203
275
|
|
|
204
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
276
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
205
277
|
<ng-content select="[suffix]"></ng-content>
|
|
206
278
|
</div>
|
|
207
279
|
</div>
|
|
208
280
|
|
|
209
281
|
<ng-container *ngIf="!disabled">
|
|
210
|
-
<p
|
|
282
|
+
<p
|
|
283
|
+
*ngIf="hint && !error"
|
|
284
|
+
class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
|
|
285
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
286
|
+
>
|
|
211
287
|
{{ hint }}
|
|
212
288
|
</p>
|
|
213
|
-
<p
|
|
289
|
+
<p
|
|
290
|
+
*ngIf="error && errorMessage"
|
|
291
|
+
[id]="id + '-error'"
|
|
292
|
+
class="text-xs text-destructive px-1"
|
|
293
|
+
>
|
|
214
294
|
{{ errorMessage }}
|
|
215
295
|
</p>
|
|
216
296
|
</ng-container>
|
|
@@ -235,46 +315,62 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
235
315
|
<label
|
|
236
316
|
*ngIf="label"
|
|
237
317
|
[for]="id"
|
|
238
|
-
[class
|
|
239
|
-
class="text-sm font-medium text-foreground leading-none transition-opacity"
|
|
240
|
-
>
|
|
318
|
+
[class]="computedLabelClass">
|
|
241
319
|
{{ label }}
|
|
242
320
|
</label>
|
|
243
321
|
|
|
244
|
-
<div
|
|
245
|
-
|
|
322
|
+
<div
|
|
323
|
+
[class]="computedContainerClass"
|
|
324
|
+
(click)="focusInput()"
|
|
325
|
+
>
|
|
326
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
246
327
|
<ng-content select="[prefix]"></ng-content>
|
|
247
328
|
</div>
|
|
248
329
|
|
|
249
330
|
<input
|
|
331
|
+
#inputElement
|
|
250
332
|
[id]="id"
|
|
251
333
|
[type]="type"
|
|
252
334
|
[placeholder]="placeholder"
|
|
253
335
|
[disabled]="disabled"
|
|
254
336
|
[readOnly]="readonly"
|
|
255
337
|
[(ngModel)]="value"
|
|
256
|
-
(blur)="
|
|
338
|
+
(blur)="onBlur()"
|
|
339
|
+
(focus)="onFocus()"
|
|
257
340
|
(input)="onInputChange($event)"
|
|
258
341
|
[class]="computedInputClass"
|
|
342
|
+
[attr.aria-invalid]="error"
|
|
343
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
259
344
|
/>
|
|
260
345
|
|
|
261
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
346
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
262
347
|
<ng-content select="[suffix]"></ng-content>
|
|
263
348
|
</div>
|
|
264
349
|
</div>
|
|
265
350
|
|
|
266
351
|
<ng-container *ngIf="!disabled">
|
|
267
|
-
<p
|
|
352
|
+
<p
|
|
353
|
+
*ngIf="hint && !error"
|
|
354
|
+
class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
|
|
355
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
356
|
+
>
|
|
268
357
|
{{ hint }}
|
|
269
358
|
</p>
|
|
270
|
-
<p
|
|
359
|
+
<p
|
|
360
|
+
*ngIf="error && errorMessage"
|
|
361
|
+
[id]="id + '-error'"
|
|
362
|
+
class="text-xs text-destructive px-1"
|
|
363
|
+
>
|
|
271
364
|
{{ errorMessage }}
|
|
272
365
|
</p>
|
|
273
366
|
</ng-container>
|
|
274
367
|
</div>
|
|
275
368
|
`,
|
|
276
369
|
}]
|
|
277
|
-
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: {
|
|
370
|
+
}], ctorParameters: () => [{ type: i0.ChangeDetectorRef }], propDecorators: { inputElement: [{
|
|
371
|
+
type: ViewChild,
|
|
372
|
+
args: ['inputElement']
|
|
373
|
+
}], id: [{
|
|
278
374
|
type: Input
|
|
279
375
|
}], label: [{
|
|
280
376
|
type: Input
|
|
@@ -298,6 +394,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
298
394
|
type: Input
|
|
299
395
|
}], error: [{
|
|
300
396
|
type: Input
|
|
397
|
+
}], hideHintOnFocus: [{
|
|
398
|
+
type: Input
|
|
301
399
|
}] } });
|
|
302
400
|
|
|
303
401
|
class CardComponent {
|
|
@@ -305,7 +403,7 @@ class CardComponent {
|
|
|
305
403
|
cn = cn;
|
|
306
404
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: CardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
307
405
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: CardComponent, isStandalone: true, selector: "tolle-card", inputs: { class: "class" }, ngImport: i0, template: `
|
|
308
|
-
<div [class]="cn('rounded-
|
|
406
|
+
<div [class]="cn('rounded-md border border-border bg-card text-card-foreground shadow', class)">
|
|
309
407
|
<ng-content></ng-content>
|
|
310
408
|
</div>
|
|
311
409
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }] });
|
|
@@ -317,7 +415,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
317
415
|
standalone: true,
|
|
318
416
|
imports: [CommonModule],
|
|
319
417
|
template: `
|
|
320
|
-
<div [class]="cn('rounded-
|
|
418
|
+
<div [class]="cn('rounded-md border border-border bg-card text-card-foreground shadow', class)">
|
|
321
419
|
<ng-content></ng-content>
|
|
322
420
|
</div>
|
|
323
421
|
`,
|
|
@@ -496,6 +594,7 @@ class SelectComponent {
|
|
|
496
594
|
readonly = false;
|
|
497
595
|
trigger;
|
|
498
596
|
popover;
|
|
597
|
+
container;
|
|
499
598
|
items;
|
|
500
599
|
sub = new Subscription();
|
|
501
600
|
searchQuery = '';
|
|
@@ -519,15 +618,38 @@ class SelectComponent {
|
|
|
519
618
|
this.close();
|
|
520
619
|
}));
|
|
521
620
|
}
|
|
522
|
-
//
|
|
621
|
+
// SIMPLIFIED: Zardui-inspired trigger styling
|
|
523
622
|
get computedTriggerClass() {
|
|
524
|
-
return cn(
|
|
623
|
+
return cn(
|
|
624
|
+
// Base styles
|
|
625
|
+
'flex w-full items-center justify-between rounded-md border transition-all duration-200', 'bg-background text-foreground',
|
|
626
|
+
// Border and shadow
|
|
627
|
+
'border-input shadow-sm',
|
|
525
628
|
// Sizing
|
|
526
629
|
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',
|
|
527
|
-
//
|
|
528
|
-
!(this.readonly || this.disabled) &&
|
|
529
|
-
|
|
530
|
-
|
|
630
|
+
// Focus state - SIMPLE LIKE ZARDUI
|
|
631
|
+
!(this.readonly || this.disabled) && [
|
|
632
|
+
'focus:outline-none',
|
|
633
|
+
'focus:ring-4',
|
|
634
|
+
'focus:ring-ring/30',
|
|
635
|
+
'focus:ring-offset-0',
|
|
636
|
+
'focus:shadow-none',
|
|
637
|
+
// Border darkens on focus automatically
|
|
638
|
+
'focus:border-primary/80'
|
|
639
|
+
],
|
|
640
|
+
// Hover state
|
|
641
|
+
!(this.readonly || this.disabled) && 'hover:border-accent',
|
|
642
|
+
// Disabled state
|
|
643
|
+
this.disabled && [
|
|
644
|
+
'cursor-not-allowed opacity-50',
|
|
645
|
+
'border-opacity-50'
|
|
646
|
+
],
|
|
647
|
+
// Readonly state
|
|
648
|
+
this.readonly && [
|
|
649
|
+
'cursor-default',
|
|
650
|
+
'border-dashed',
|
|
651
|
+
!this.disabled && 'focus:ring-0 focus:border-opacity-100'
|
|
652
|
+
], this.class);
|
|
531
653
|
}
|
|
532
654
|
// UPDATED: Dynamic icon sizing relative to the trigger size
|
|
533
655
|
get iconClass() {
|
|
@@ -553,6 +675,8 @@ class SelectComponent {
|
|
|
553
675
|
}
|
|
554
676
|
open() {
|
|
555
677
|
this.isOpen = true;
|
|
678
|
+
// Trigger focus on the button for focus styling
|
|
679
|
+
this.trigger.nativeElement.focus();
|
|
556
680
|
// Tick to ensure DOM is rendered before positioning
|
|
557
681
|
setTimeout(() => this.updatePosition());
|
|
558
682
|
}
|
|
@@ -621,7 +745,7 @@ class SelectComponent {
|
|
|
621
745
|
useExisting: forwardRef(() => SelectComponent),
|
|
622
746
|
multi: true
|
|
623
747
|
}
|
|
624
|
-
], queries: [{ propertyName: "items", predicate: SelectItemComponent, descendants: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], ngImport: i0, template: `
|
|
748
|
+
], queries: [{ propertyName: "items", predicate: SelectItemComponent, descendants: true }], viewQueries: [{ propertyName: "trigger", first: true, predicate: ["trigger"], descendants: true }, { propertyName: "popover", first: true, predicate: ["popover"], descendants: true }, { propertyName: "container", first: true, predicate: ["container"], descendants: true }], ngImport: i0, template: `
|
|
625
749
|
<div [class]="cn('w-full', 'size-' + size)" #container>
|
|
626
750
|
<button
|
|
627
751
|
type="button"
|
|
@@ -661,7 +785,7 @@ class SelectComponent {
|
|
|
661
785
|
</div>
|
|
662
786
|
</div>
|
|
663
787
|
</div>
|
|
664
|
-
`, 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"] }] });
|
|
788
|
+
`, 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", "hideHintOnFocus"] }] });
|
|
665
789
|
}
|
|
666
790
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SelectComponent, decorators: [{
|
|
667
791
|
type: Component,
|
|
@@ -737,6 +861,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
737
861
|
}], popover: [{
|
|
738
862
|
type: ViewChild,
|
|
739
863
|
args: ['popover']
|
|
864
|
+
}], container: [{
|
|
865
|
+
type: ViewChild,
|
|
866
|
+
args: ['container']
|
|
740
867
|
}], items: [{
|
|
741
868
|
type: ContentChildren,
|
|
742
869
|
args: [SelectItemComponent, { descendants: true }]
|
|
@@ -929,7 +1056,7 @@ class BadgeComponent {
|
|
|
929
1056
|
get computedClass() {
|
|
930
1057
|
return cn(
|
|
931
1058
|
// Base styles - Pills are always rounded-full
|
|
932
|
-
'inline-flex items-center justify-center rounded-
|
|
1059
|
+
'inline-flex items-center justify-center rounded-md border px-2 py-0.5 font-medium transition-colors gap-1',
|
|
933
1060
|
// Variants (Google Dark Mode theme)
|
|
934
1061
|
this.variant === 'default' && 'border-transparent bg-primary text-primary-foreground', this.variant === 'secondary' && 'border-transparent bg-secondary text-secondary-foreground', this.variant === 'outline' && 'text-foreground border-border bg-transparent', this.variant === 'destructive' && 'border-transparent bg-destructive text-destructive-foreground',
|
|
935
1062
|
// Sizing
|
|
@@ -947,7 +1074,7 @@ class BadgeComponent {
|
|
|
947
1074
|
<button
|
|
948
1075
|
*ngIf="removable"
|
|
949
1076
|
(click)="onRemove.emit($event)"
|
|
950
|
-
class="ml-1 -mr-1 rounded-
|
|
1077
|
+
class="ml-1 -mr-1 rounded-md p-0.5 hover:bg-foreground/20 transition-colors outline-none focus:ring-1 focus:ring-ring"
|
|
951
1078
|
>
|
|
952
1079
|
<i class="ri-close-line text-[1.1em]"></i>
|
|
953
1080
|
</button>
|
|
@@ -971,7 +1098,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
971
1098
|
<button
|
|
972
1099
|
*ngIf="removable"
|
|
973
1100
|
(click)="onRemove.emit($event)"
|
|
974
|
-
class="ml-1 -mr-1 rounded-
|
|
1101
|
+
class="ml-1 -mr-1 rounded-md p-0.5 hover:bg-foreground/20 transition-colors outline-none focus:ring-1 focus:ring-ring"
|
|
975
1102
|
>
|
|
976
1103
|
<i class="ri-close-line text-[1.1em]"></i>
|
|
977
1104
|
</button>
|
|
@@ -1363,96 +1490,205 @@ class ThemeService {
|
|
|
1363
1490
|
else if (this.config?.primaryColor) {
|
|
1364
1491
|
this.setPrimaryColor(this.config.primaryColor, false);
|
|
1365
1492
|
}
|
|
1493
|
+
// Set radius from config
|
|
1366
1494
|
if (this.config?.radius) {
|
|
1367
|
-
this.
|
|
1368
|
-
}
|
|
1369
|
-
// 2. Apply Brand Config - This will generate full palette
|
|
1370
|
-
if (this.config) {
|
|
1371
|
-
this.applyBrandConfig(this.config);
|
|
1495
|
+
this.setRadius(this.config.radius, false);
|
|
1372
1496
|
}
|
|
1373
1497
|
}
|
|
1374
1498
|
/**
|
|
1375
|
-
*
|
|
1499
|
+
* Sets the border radius for all components
|
|
1376
1500
|
*/
|
|
1377
|
-
|
|
1501
|
+
setRadius(radius, persist = true) {
|
|
1378
1502
|
if (!isPlatformBrowser(this.platformId))
|
|
1379
1503
|
return;
|
|
1380
1504
|
const root = this.document.documentElement;
|
|
1381
|
-
// Set
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1505
|
+
// Set the CSS variable
|
|
1506
|
+
this.renderer.setStyle(root, '--radius', radius);
|
|
1507
|
+
// Also update the dynamic styles to include radius calculations
|
|
1508
|
+
this.updateRadiusInDynamicStyles(radius);
|
|
1509
|
+
// Persist if needed
|
|
1510
|
+
if (persist) {
|
|
1511
|
+
localStorage.setItem('tolle-radius', radius);
|
|
1385
1512
|
}
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* Updates the radius calculations in dynamic styles
|
|
1516
|
+
*/
|
|
1517
|
+
updateRadiusInDynamicStyles(radius) {
|
|
1518
|
+
const existingStyle = this.document.getElementById(this.styleId);
|
|
1519
|
+
if (existingStyle) {
|
|
1520
|
+
let css = existingStyle.textContent || '';
|
|
1521
|
+
// Update or add radius calculations
|
|
1522
|
+
if (css.includes('--radius:')) {
|
|
1523
|
+
// Replace existing radius declarations
|
|
1524
|
+
css = css.replace(/--radius:[^;]+;/g, `--radius: ${radius};`);
|
|
1525
|
+
}
|
|
1526
|
+
else {
|
|
1527
|
+
// Add radius to the beginning of :root
|
|
1528
|
+
css = css.replace(/:root\s*{/, `:root {\n --radius: ${radius};`);
|
|
1529
|
+
}
|
|
1530
|
+
// Update the calculated radius values in the CSS
|
|
1531
|
+
const radiusCalcRegex = /calc\(var\(--radius[^)]+\)/g;
|
|
1532
|
+
css = css.replace(radiusCalcRegex, (match) => {
|
|
1533
|
+
if (match.includes('- 2px')) {
|
|
1534
|
+
return `calc(${radius} - 2px)`;
|
|
1535
|
+
}
|
|
1536
|
+
else if (match.includes('- 4px')) {
|
|
1537
|
+
return `calc(${radius} - 4px)`;
|
|
1538
|
+
}
|
|
1539
|
+
return match;
|
|
1540
|
+
});
|
|
1541
|
+
existingStyle.textContent = css;
|
|
1389
1542
|
}
|
|
1390
1543
|
}
|
|
1391
1544
|
/**
|
|
1392
1545
|
* Generates full primary color palette (50-900) based on base color
|
|
1393
|
-
* Uses color-mix() for consistency with your existing approach
|
|
1394
1546
|
*/
|
|
1395
1547
|
generatePrimaryShades(baseColor) {
|
|
1548
|
+
// Convert hex to RGB
|
|
1549
|
+
const rgb = this.hexToRgb(baseColor);
|
|
1550
|
+
const rgbString = rgb ? `${rgb.r} ${rgb.g} ${rgb.b}` : '37 99 235';
|
|
1551
|
+
// Create lighter ring colors in RGB
|
|
1552
|
+
const ringLight = this.lightenColor(baseColor, 40);
|
|
1553
|
+
const ringLightRgb = this.hexToRgb(ringLight);
|
|
1554
|
+
const ringLightRgbString = ringLightRgb ? `${ringLightRgb.r} ${ringLightRgb.g} ${ringLightRgb.b}` : '96 165 250';
|
|
1555
|
+
const ringDark = this.lightenColor(baseColor, 20);
|
|
1556
|
+
const ringDarkRgb = this.hexToRgb(ringDark);
|
|
1557
|
+
const ringDarkRgbString = ringDarkRgb ? `${ringDarkRgb.r} ${ringDarkRgb.g} ${ringDarkRgb.b}` : '147 197 253';
|
|
1558
|
+
// Get current radius or use default
|
|
1559
|
+
const root = this.document.documentElement;
|
|
1560
|
+
const currentRadius = getComputedStyle(root).getPropertyValue('--radius').trim() || '0.5rem';
|
|
1396
1561
|
const css = `
|
|
1562
|
+
/* Override primary colors - this needs to come AFTER your main CSS */
|
|
1397
1563
|
:root {
|
|
1398
|
-
/* Primary
|
|
1399
|
-
--primary
|
|
1400
|
-
--primary-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
--
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
--primary-
|
|
1407
|
-
--primary-
|
|
1408
|
-
--primary-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
--primary-
|
|
1412
|
-
--
|
|
1413
|
-
--
|
|
1414
|
-
--
|
|
1415
|
-
--
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
--ring:
|
|
1564
|
+
/* Primary in RGB format for Tailwind opacity support */
|
|
1565
|
+
--primary: ${rgbString};
|
|
1566
|
+
--primary-foreground: ${this.getContrastColorRgb(baseColor)};
|
|
1567
|
+
|
|
1568
|
+
/* Radius */
|
|
1569
|
+
--radius: ${currentRadius};
|
|
1570
|
+
|
|
1571
|
+
/* Primary shades for light mode */
|
|
1572
|
+
--primary-50: ${this.hexToRgbString(this.lightenColor(baseColor, 90))};
|
|
1573
|
+
--primary-100: ${this.hexToRgbString(this.lightenColor(baseColor, 80))};
|
|
1574
|
+
--primary-200: ${this.hexToRgbString(this.lightenColor(baseColor, 60))};
|
|
1575
|
+
--primary-300: ${this.hexToRgbString(this.lightenColor(baseColor, 40))};
|
|
1576
|
+
--primary-400: ${this.hexToRgbString(this.lightenColor(baseColor, 20))};
|
|
1577
|
+
--primary-500: ${rgbString};
|
|
1578
|
+
--primary-600: ${this.hexToRgbString(this.darkenColor(baseColor, 20))};
|
|
1579
|
+
--primary-700: ${this.hexToRgbString(this.darkenColor(baseColor, 40))};
|
|
1580
|
+
--primary-800: ${this.hexToRgbString(this.darkenColor(baseColor, 60))};
|
|
1581
|
+
--primary-900: ${this.hexToRgbString(this.darkenColor(baseColor, 80))};
|
|
1582
|
+
|
|
1583
|
+
/* Update ring color to be lighter */
|
|
1584
|
+
--ring: ${ringLightRgbString};
|
|
1419
1585
|
}
|
|
1420
1586
|
|
|
1421
1587
|
.dark {
|
|
1422
|
-
/*
|
|
1423
|
-
--primary
|
|
1424
|
-
--primary-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
--primary-
|
|
1428
|
-
--primary-
|
|
1429
|
-
--primary-
|
|
1430
|
-
--primary-
|
|
1431
|
-
--primary-
|
|
1432
|
-
--primary-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
--primary-
|
|
1436
|
-
--
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
--
|
|
1440
|
-
--accent: color-mix(in srgb, var(--primary-800), transparent 80%);
|
|
1441
|
-
--accent-foreground: var(--primary-200);
|
|
1442
|
-
--ring: color-mix(in srgb, var(--primary-600), transparent 60%);
|
|
1588
|
+
/* For dark mode, we keep the primary color but adjust shades */
|
|
1589
|
+
--primary: ${rgbString};
|
|
1590
|
+
--primary-foreground: ${this.getContrastColorRgb(baseColor)};
|
|
1591
|
+
|
|
1592
|
+
/* Dark mode shades */
|
|
1593
|
+
--primary-50: ${this.hexToRgbString(this.darkenColor(baseColor, 85))};
|
|
1594
|
+
--primary-100: ${this.hexToRgbString(this.darkenColor(baseColor, 75))};
|
|
1595
|
+
--primary-200: ${this.hexToRgbString(this.darkenColor(baseColor, 65))};
|
|
1596
|
+
--primary-300: ${this.hexToRgbString(this.darkenColor(baseColor, 55))};
|
|
1597
|
+
--primary-400: ${this.hexToRgbString(this.darkenColor(baseColor, 45))};
|
|
1598
|
+
--primary-500: ${rgbString};
|
|
1599
|
+
--primary-600: ${this.hexToRgbString(this.lightenColor(baseColor, 20))};
|
|
1600
|
+
--primary-700: ${this.hexToRgbString(this.lightenColor(baseColor, 35))};
|
|
1601
|
+
--primary-800: ${this.hexToRgbString(this.lightenColor(baseColor, 50))};
|
|
1602
|
+
--primary-900: ${this.hexToRgbString(this.lightenColor(baseColor, 65))};
|
|
1603
|
+
|
|
1604
|
+
/* Update ring color for dark mode - lighter variant */
|
|
1605
|
+
--ring: ${ringDarkRgbString};
|
|
1443
1606
|
}
|
|
1444
1607
|
`;
|
|
1445
1608
|
this.injectDynamicStyles(css);
|
|
1446
1609
|
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Convert hex color to RGB object
|
|
1612
|
+
*/
|
|
1613
|
+
hexToRgb(hex) {
|
|
1614
|
+
// Remove # if present
|
|
1615
|
+
const cleanedHex = hex.replace('#', '');
|
|
1616
|
+
let r = 0, g = 0, b = 0;
|
|
1617
|
+
if (cleanedHex.length === 3) {
|
|
1618
|
+
r = parseInt(cleanedHex[0] + cleanedHex[0], 16);
|
|
1619
|
+
g = parseInt(cleanedHex[1] + cleanedHex[1], 16);
|
|
1620
|
+
b = parseInt(cleanedHex[2] + cleanedHex[2], 16);
|
|
1621
|
+
return { r, g, b };
|
|
1622
|
+
}
|
|
1623
|
+
if (cleanedHex.length === 6) {
|
|
1624
|
+
r = parseInt(cleanedHex.substring(0, 2), 16);
|
|
1625
|
+
g = parseInt(cleanedHex.substring(2, 4), 16);
|
|
1626
|
+
b = parseInt(cleanedHex.substring(4, 6), 16);
|
|
1627
|
+
return { r, g, b };
|
|
1628
|
+
}
|
|
1629
|
+
return null;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Convert hex to RGB string format for CSS (space-separated)
|
|
1633
|
+
*/
|
|
1634
|
+
hexToRgbString(hexColor) {
|
|
1635
|
+
const rgb = this.hexToRgb(hexColor);
|
|
1636
|
+
return rgb ? `${rgb.r} ${rgb.g} ${rgb.b}` : '37 99 235';
|
|
1637
|
+
}
|
|
1638
|
+
/**
|
|
1639
|
+
* Get contrast color in RGB format
|
|
1640
|
+
*/
|
|
1641
|
+
getContrastColorRgb(hexColor) {
|
|
1642
|
+
const contrast = this.getContrastColor(hexColor);
|
|
1643
|
+
const rgb = this.hexToRgb(contrast);
|
|
1644
|
+
return rgb ? `${rgb.r} ${rgb.g} ${rgb.b}` : '255 255 255';
|
|
1645
|
+
}
|
|
1646
|
+
/**
|
|
1647
|
+
* Lighten a hex color by a percentage
|
|
1648
|
+
*/
|
|
1649
|
+
lightenColor(color, percent) {
|
|
1650
|
+
const rgb = this.hexToRgb(color);
|
|
1651
|
+
if (!rgb)
|
|
1652
|
+
return color;
|
|
1653
|
+
// Lighten by percentage
|
|
1654
|
+
const r = Math.min(255, Math.floor(rgb.r + (255 - rgb.r) * (percent / 100)));
|
|
1655
|
+
const g = Math.min(255, Math.floor(rgb.g + (255 - rgb.g) * (percent / 100)));
|
|
1656
|
+
const b = Math.min(255, Math.floor(rgb.b + (255 - rgb.b) * (percent / 100)));
|
|
1657
|
+
// Convert back to hex
|
|
1658
|
+
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1)}`;
|
|
1659
|
+
}
|
|
1660
|
+
/**
|
|
1661
|
+
* Darken a hex color by a percentage
|
|
1662
|
+
*/
|
|
1663
|
+
darkenColor(color, percent) {
|
|
1664
|
+
const rgb = this.hexToRgb(color);
|
|
1665
|
+
if (!rgb)
|
|
1666
|
+
return color;
|
|
1667
|
+
const factor = 1 - (percent / 100);
|
|
1668
|
+
const r = Math.max(0, Math.floor(rgb.r * factor));
|
|
1669
|
+
const g = Math.max(0, Math.floor(rgb.g * factor));
|
|
1670
|
+
const b = Math.max(0, Math.floor(rgb.b * factor));
|
|
1671
|
+
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
|
|
1672
|
+
}
|
|
1673
|
+
/**
|
|
1674
|
+
* Calculate contrast color (black or white) based on background color
|
|
1675
|
+
*/
|
|
1676
|
+
getContrastColor(hexColor) {
|
|
1677
|
+
const rgb = this.hexToRgb(hexColor);
|
|
1678
|
+
if (!rgb)
|
|
1679
|
+
return '#ffffff';
|
|
1680
|
+
// Calculate relative luminance
|
|
1681
|
+
const luminance = (0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b) / 255;
|
|
1682
|
+
// Return black for light colors, white for dark colors
|
|
1683
|
+
return luminance > 0.5 ? '#000000' : '#ffffff';
|
|
1684
|
+
}
|
|
1447
1685
|
injectDynamicStyles(css) {
|
|
1448
1686
|
if (!isPlatformBrowser(this.platformId))
|
|
1449
1687
|
return;
|
|
1450
|
-
// Remove existing dynamic styles
|
|
1451
1688
|
const existingStyle = this.document.getElementById(this.styleId);
|
|
1452
1689
|
if (existingStyle) {
|
|
1453
1690
|
existingStyle.remove();
|
|
1454
1691
|
}
|
|
1455
|
-
// Create and inject new styles
|
|
1456
1692
|
const styleElement = this.document.createElement('style');
|
|
1457
1693
|
styleElement.id = this.styleId;
|
|
1458
1694
|
styleElement.textContent = css;
|
|
@@ -1475,10 +1711,12 @@ class ThemeService {
|
|
|
1475
1711
|
setPrimaryColor(color, persist = true) {
|
|
1476
1712
|
if (!isPlatformBrowser(this.platformId))
|
|
1477
1713
|
return;
|
|
1478
|
-
// Update CSS variables + palette
|
|
1479
|
-
this.renderer.setStyle(this.document.documentElement, '--primary', color);
|
|
1480
1714
|
this.generatePrimaryShades(color);
|
|
1481
|
-
//
|
|
1715
|
+
// Also set inline for immediate update
|
|
1716
|
+
const rgb = this.hexToRgb(color);
|
|
1717
|
+
if (rgb) {
|
|
1718
|
+
this.renderer.setStyle(this.document.documentElement, '--primary', `${rgb.r} ${rgb.g} ${rgb.b}`);
|
|
1719
|
+
}
|
|
1482
1720
|
if (persist) {
|
|
1483
1721
|
localStorage.setItem('tolle-primary-color', color);
|
|
1484
1722
|
}
|
|
@@ -1487,8 +1725,44 @@ class ThemeService {
|
|
|
1487
1725
|
return this.isDarkSubject.value ? 'dark' : 'light';
|
|
1488
1726
|
}
|
|
1489
1727
|
get primaryColor() {
|
|
1728
|
+
if (!isPlatformBrowser(this.platformId))
|
|
1729
|
+
return null;
|
|
1730
|
+
const root = this.document.documentElement;
|
|
1731
|
+
const cssValue = getComputedStyle(root).getPropertyValue('--primary').trim();
|
|
1732
|
+
if (cssValue && cssValue !== '') {
|
|
1733
|
+
// Convert RGB string back to hex for external use
|
|
1734
|
+
const rgbParts = cssValue.split(' ').map(Number);
|
|
1735
|
+
if (rgbParts.length === 3) {
|
|
1736
|
+
return `#${rgbParts[0].toString(16).padStart(2, '0')}${rgbParts[1].toString(16).padStart(2, '0')}${rgbParts[2].toString(16).padStart(2, '0')}`;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1490
1739
|
return localStorage.getItem('tolle-primary-color');
|
|
1491
1740
|
}
|
|
1741
|
+
get radius() {
|
|
1742
|
+
if (!isPlatformBrowser(this.platformId))
|
|
1743
|
+
return null;
|
|
1744
|
+
const root = this.document.documentElement;
|
|
1745
|
+
const cssValue = getComputedStyle(root).getPropertyValue('--radius').trim();
|
|
1746
|
+
if (cssValue && cssValue !== '') {
|
|
1747
|
+
return cssValue;
|
|
1748
|
+
}
|
|
1749
|
+
return localStorage.getItem('tolle-radius') || '0.5rem';
|
|
1750
|
+
}
|
|
1751
|
+
/**
|
|
1752
|
+
* Applies the brand identity variables with full shade palette
|
|
1753
|
+
*/
|
|
1754
|
+
applyBrandConfig(config) {
|
|
1755
|
+
if (!isPlatformBrowser(this.platformId))
|
|
1756
|
+
return;
|
|
1757
|
+
// Set primary color if provided
|
|
1758
|
+
if (config.primaryColor) {
|
|
1759
|
+
this.setPrimaryColor(config.primaryColor, false);
|
|
1760
|
+
}
|
|
1761
|
+
// Set border radius if provided
|
|
1762
|
+
if (config.radius) {
|
|
1763
|
+
this.setRadius(config.radius, false);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1492
1766
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, deps: [{ token: DOCUMENT }, { token: PLATFORM_ID }, { token: TOLLE_CONFIG, optional: true }, { token: i0.RendererFactory2 }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
1493
1767
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ThemeService, providedIn: 'root' });
|
|
1494
1768
|
}
|
|
@@ -1670,7 +1944,7 @@ class MultiSelectComponent {
|
|
|
1670
1944
|
</div>
|
|
1671
1945
|
</div>
|
|
1672
1946
|
</div>
|
|
1673
|
-
`, 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"] }] });
|
|
1947
|
+
`, 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", "hideHintOnFocus"] }] });
|
|
1674
1948
|
}
|
|
1675
1949
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: MultiSelectComponent, decorators: [{
|
|
1676
1950
|
type: Component,
|
|
@@ -2067,10 +2341,12 @@ class MaskedInputComponent {
|
|
|
2067
2341
|
error = false;
|
|
2068
2342
|
size = 'default';
|
|
2069
2343
|
returnRaw = false;
|
|
2344
|
+
hideHintOnFocus = true;
|
|
2070
2345
|
inputEl;
|
|
2071
2346
|
hasPrefix = false;
|
|
2072
2347
|
hasSuffix = false;
|
|
2073
2348
|
displayValue = '';
|
|
2349
|
+
isFocused = false;
|
|
2074
2350
|
tokens = {
|
|
2075
2351
|
'0': /\d/, '9': /\d/, 'a': /[a-z]/i, 'A': /[a-z]/i, '*': /[a-z0-9]/i
|
|
2076
2352
|
};
|
|
@@ -2089,19 +2365,71 @@ class MaskedInputComponent {
|
|
|
2089
2365
|
this.cdr.detectChanges();
|
|
2090
2366
|
}
|
|
2091
2367
|
}
|
|
2368
|
+
get computedLabelClass() {
|
|
2369
|
+
return cn("text-sm font-medium text-foreground leading-none transition-opacity duration-200", this.disabled && "opacity-50");
|
|
2370
|
+
}
|
|
2092
2371
|
get computedContainerClass() {
|
|
2093
|
-
return cn(
|
|
2372
|
+
return cn(
|
|
2373
|
+
// Base styles
|
|
2374
|
+
"group relative flex items-center w-full rounded-md border transition-all duration-200", "bg-background",
|
|
2375
|
+
// Border and shadow
|
|
2376
|
+
"border-input shadow-sm",
|
|
2094
2377
|
// Sizing
|
|
2095
|
-
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",
|
|
2096
|
-
//
|
|
2097
|
-
!(this.readonly || this.disabled) &&
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2378
|
+
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",
|
|
2379
|
+
// Focus state - SIMPLE LIKE ZARDUI
|
|
2380
|
+
!(this.readonly || this.disabled) && [
|
|
2381
|
+
"focus-within:border-primary/80",
|
|
2382
|
+
"focus-within:ring-4",
|
|
2383
|
+
"focus-within:ring-ring/30",
|
|
2384
|
+
"focus-within:ring-offset-0",
|
|
2385
|
+
"focus-within:shadow-none",
|
|
2386
|
+
],
|
|
2387
|
+
// Error state
|
|
2388
|
+
this.error && [
|
|
2389
|
+
"border-destructive",
|
|
2390
|
+
!(this.readonly || this.disabled) && [
|
|
2391
|
+
"focus-within:border-destructive/80",
|
|
2392
|
+
"focus-within:ring-destructive/30"
|
|
2393
|
+
]
|
|
2394
|
+
],
|
|
2395
|
+
// Disabled state
|
|
2396
|
+
this.disabled && [
|
|
2397
|
+
"cursor-not-allowed opacity-50",
|
|
2398
|
+
"border-opacity-50"
|
|
2399
|
+
],
|
|
2400
|
+
// Readonly state
|
|
2401
|
+
this.readonly && [
|
|
2402
|
+
"cursor-default",
|
|
2403
|
+
"border-dashed",
|
|
2404
|
+
!this.disabled && "focus-within:ring-0 focus-within:border-opacity-100"
|
|
2405
|
+
], this.containerClass);
|
|
2102
2406
|
}
|
|
2103
2407
|
get computedInputClass() {
|
|
2104
|
-
return cn(
|
|
2408
|
+
return cn(
|
|
2409
|
+
// Base styles
|
|
2410
|
+
"flex-1 bg-transparent border-none p-0", "placeholder:text-muted-foreground",
|
|
2411
|
+
// Remove all default focus styles
|
|
2412
|
+
"focus:outline-none focus:ring-0 focus:shadow-none",
|
|
2413
|
+
// Text sizing
|
|
2414
|
+
this.size === 'xs' && "text-xs", this.size === 'sm' && "text-sm", this.size === 'default' && "text-sm", this.size === 'lg' && "text-base",
|
|
2415
|
+
// Cursor states
|
|
2416
|
+
this.disabled && "cursor-not-allowed", this.readonly && "cursor-default",
|
|
2417
|
+
// Text color
|
|
2418
|
+
"text-foreground",
|
|
2419
|
+
// Selection color
|
|
2420
|
+
"selection:bg-primary/20 selection:text-foreground", this.class);
|
|
2421
|
+
}
|
|
2422
|
+
focusInput() {
|
|
2423
|
+
if (!this.disabled && this.inputEl) {
|
|
2424
|
+
this.inputEl.nativeElement.focus();
|
|
2425
|
+
}
|
|
2426
|
+
}
|
|
2427
|
+
onFocus() {
|
|
2428
|
+
this.isFocused = true;
|
|
2429
|
+
}
|
|
2430
|
+
onBlur() {
|
|
2431
|
+
this.isFocused = false;
|
|
2432
|
+
this.onTouched();
|
|
2105
2433
|
}
|
|
2106
2434
|
// --- Masking Logic ---
|
|
2107
2435
|
onInput(event) {
|
|
@@ -2140,20 +2468,26 @@ class MaskedInputComponent {
|
|
|
2140
2468
|
}
|
|
2141
2469
|
return formatted;
|
|
2142
2470
|
}
|
|
2143
|
-
unmask(val) {
|
|
2471
|
+
unmask(val) {
|
|
2472
|
+
return val.replace(/[^a-zA-Z0-9]/g, '');
|
|
2473
|
+
}
|
|
2144
2474
|
writeValue(value) {
|
|
2145
2475
|
this.displayValue = value ? this.applyMask(this.unmask(value.toString())) : '';
|
|
2146
2476
|
this.cdr.markForCheck();
|
|
2147
2477
|
}
|
|
2148
|
-
registerOnChange(fn) {
|
|
2149
|
-
|
|
2478
|
+
registerOnChange(fn) {
|
|
2479
|
+
this.onChange = fn;
|
|
2480
|
+
}
|
|
2481
|
+
registerOnTouched(fn) {
|
|
2482
|
+
this.onTouched = fn;
|
|
2483
|
+
}
|
|
2150
2484
|
setDisabledState(isDisabled) {
|
|
2151
2485
|
this.disabled = isDisabled;
|
|
2152
2486
|
this.cdr.markForCheck();
|
|
2153
2487
|
}
|
|
2154
2488
|
cn = cn;
|
|
2155
2489
|
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 });
|
|
2156
|
-
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" }, providers: [
|
|
2490
|
+
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: [
|
|
2157
2491
|
{
|
|
2158
2492
|
provide: NG_VALUE_ACCESSOR,
|
|
2159
2493
|
useExisting: forwardRef(() => MaskedInputComponent),
|
|
@@ -2164,15 +2498,17 @@ class MaskedInputComponent {
|
|
|
2164
2498
|
<label
|
|
2165
2499
|
*ngIf="label"
|
|
2166
2500
|
[for]="id"
|
|
2167
|
-
[class
|
|
2168
|
-
class="text-sm font-medium text-foreground leading-none transition-opacity"
|
|
2501
|
+
[class]="computedLabelClass"
|
|
2169
2502
|
>
|
|
2170
2503
|
{{ label }}
|
|
2171
2504
|
</label>
|
|
2172
2505
|
|
|
2173
|
-
<div
|
|
2506
|
+
<div
|
|
2507
|
+
[class]="computedContainerClass"
|
|
2508
|
+
(click)="focusInput()"
|
|
2509
|
+
>
|
|
2174
2510
|
<!-- Prefix Icon -->
|
|
2175
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
2511
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
2176
2512
|
<ng-content select="[prefix]"></ng-content>
|
|
2177
2513
|
</div>
|
|
2178
2514
|
|
|
@@ -2185,21 +2521,32 @@ class MaskedInputComponent {
|
|
|
2185
2521
|
[readOnly]="readonly"
|
|
2186
2522
|
[value]="displayValue"
|
|
2187
2523
|
(input)="onInput($event)"
|
|
2188
|
-
(blur)="
|
|
2524
|
+
(blur)="onBlur()"
|
|
2525
|
+
(focus)="onFocus()"
|
|
2189
2526
|
[class]="computedInputClass"
|
|
2527
|
+
[attr.aria-invalid]="error"
|
|
2528
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
2190
2529
|
/>
|
|
2191
2530
|
|
|
2192
2531
|
<!-- Suffix Icon -->
|
|
2193
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
2532
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
2194
2533
|
<ng-content select="[suffix]"></ng-content>
|
|
2195
2534
|
</div>
|
|
2196
2535
|
</div>
|
|
2197
2536
|
|
|
2198
2537
|
<ng-container *ngIf="!disabled">
|
|
2199
|
-
<p
|
|
2538
|
+
<p
|
|
2539
|
+
*ngIf="hint && !error"
|
|
2540
|
+
class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
|
|
2541
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
2542
|
+
>
|
|
2200
2543
|
{{ hint }}
|
|
2201
2544
|
</p>
|
|
2202
|
-
<p
|
|
2545
|
+
<p
|
|
2546
|
+
*ngIf="error && errorMessage"
|
|
2547
|
+
[id]="id + '-error'"
|
|
2548
|
+
class="text-xs text-destructive px-1"
|
|
2549
|
+
>
|
|
2203
2550
|
{{ errorMessage }}
|
|
2204
2551
|
</p>
|
|
2205
2552
|
</ng-container>
|
|
@@ -2224,15 +2571,17 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
2224
2571
|
<label
|
|
2225
2572
|
*ngIf="label"
|
|
2226
2573
|
[for]="id"
|
|
2227
|
-
[class
|
|
2228
|
-
class="text-sm font-medium text-foreground leading-none transition-opacity"
|
|
2574
|
+
[class]="computedLabelClass"
|
|
2229
2575
|
>
|
|
2230
2576
|
{{ label }}
|
|
2231
2577
|
</label>
|
|
2232
2578
|
|
|
2233
|
-
<div
|
|
2579
|
+
<div
|
|
2580
|
+
[class]="computedContainerClass"
|
|
2581
|
+
(click)="focusInput()"
|
|
2582
|
+
>
|
|
2234
2583
|
<!-- Prefix Icon -->
|
|
2235
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
2584
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
2236
2585
|
<ng-content select="[prefix]"></ng-content>
|
|
2237
2586
|
</div>
|
|
2238
2587
|
|
|
@@ -2245,21 +2594,32 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
2245
2594
|
[readOnly]="readonly"
|
|
2246
2595
|
[value]="displayValue"
|
|
2247
2596
|
(input)="onInput($event)"
|
|
2248
|
-
(blur)="
|
|
2597
|
+
(blur)="onBlur()"
|
|
2598
|
+
(focus)="onFocus()"
|
|
2249
2599
|
[class]="computedInputClass"
|
|
2600
|
+
[attr.aria-invalid]="error"
|
|
2601
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
2250
2602
|
/>
|
|
2251
2603
|
|
|
2252
2604
|
<!-- Suffix Icon -->
|
|
2253
|
-
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors">
|
|
2605
|
+
<div class="flex items-center text-muted-foreground group-focus-within:text-primary transition-colors duration-200">
|
|
2254
2606
|
<ng-content select="[suffix]"></ng-content>
|
|
2255
2607
|
</div>
|
|
2256
2608
|
</div>
|
|
2257
2609
|
|
|
2258
2610
|
<ng-container *ngIf="!disabled">
|
|
2259
|
-
<p
|
|
2611
|
+
<p
|
|
2612
|
+
*ngIf="hint && !error"
|
|
2613
|
+
class="text-xs text-muted-foreground px-1 transition-opacity duration-200"
|
|
2614
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
2615
|
+
>
|
|
2260
2616
|
{{ hint }}
|
|
2261
2617
|
</p>
|
|
2262
|
-
<p
|
|
2618
|
+
<p
|
|
2619
|
+
*ngIf="error && errorMessage"
|
|
2620
|
+
[id]="id + '-error'"
|
|
2621
|
+
class="text-xs text-destructive px-1"
|
|
2622
|
+
>
|
|
2263
2623
|
{{ errorMessage }}
|
|
2264
2624
|
</p>
|
|
2265
2625
|
</ng-container>
|
|
@@ -2294,6 +2654,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
2294
2654
|
type: Input
|
|
2295
2655
|
}], returnRaw: [{
|
|
2296
2656
|
type: Input
|
|
2657
|
+
}], hideHintOnFocus: [{
|
|
2658
|
+
type: Input
|
|
2297
2659
|
}], inputEl: [{
|
|
2298
2660
|
type: ViewChild,
|
|
2299
2661
|
args: ['inputEl', { static: true }]
|
|
@@ -2446,7 +2808,7 @@ class DatePickerComponent {
|
|
|
2446
2808
|
></tolle-calendar>
|
|
2447
2809
|
</div>
|
|
2448
2810
|
</div>
|
|
2449
|
-
`, 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"] }, { kind: "component", type: CalendarComponent, selector: "tolle-calendar", inputs: ["class", "disablePastDates"] }] });
|
|
2811
|
+
`, 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", "disablePastDates"] }] });
|
|
2450
2812
|
}
|
|
2451
2813
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DatePickerComponent, decorators: [{
|
|
2452
2814
|
type: Component,
|
|
@@ -3038,7 +3400,7 @@ class DataTableComponent {
|
|
|
3038
3400
|
(onPageSizeChange)="updatePage()"
|
|
3039
3401
|
></tolle-pagination>
|
|
3040
3402
|
</div>
|
|
3041
|
-
`, 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"] }] });
|
|
3403
|
+
`, 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", "hideHintOnFocus"] }] });
|
|
3042
3404
|
}
|
|
3043
3405
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DataTableComponent, decorators: [{
|
|
3044
3406
|
type: Component,
|
|
@@ -3948,7 +4310,7 @@ class DateRangePickerComponent {
|
|
|
3948
4310
|
></tolle-range-calendar>
|
|
3949
4311
|
</div>
|
|
3950
4312
|
</div>
|
|
3951
|
-
`, 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"] }] });
|
|
4313
|
+
`, 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", "hideHintOnFocus"] }] });
|
|
3952
4314
|
}
|
|
3953
4315
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: DateRangePickerComponent, decorators: [{
|
|
3954
4316
|
type: Component,
|
|
@@ -4166,30 +4528,69 @@ class TextareaComponent {
|
|
|
4166
4528
|
label = '';
|
|
4167
4529
|
placeholder = '';
|
|
4168
4530
|
hint = '';
|
|
4531
|
+
errorMessage = '';
|
|
4169
4532
|
rows = 3;
|
|
4170
4533
|
maxLength;
|
|
4171
4534
|
showCharacterCount = false;
|
|
4172
4535
|
autoGrow = false;
|
|
4173
4536
|
error = false;
|
|
4174
4537
|
className = '';
|
|
4538
|
+
// Focus behavior
|
|
4539
|
+
hideHintOnFocus = true;
|
|
4540
|
+
hideCharacterCountOnFocus = false;
|
|
4175
4541
|
// New States
|
|
4176
4542
|
disabled = false;
|
|
4177
4543
|
readonly = false;
|
|
4178
4544
|
value = '';
|
|
4545
|
+
isFocused = false;
|
|
4179
4546
|
onChange = () => { };
|
|
4180
4547
|
onTouched = () => { };
|
|
4181
4548
|
ngAfterViewInit() {
|
|
4182
4549
|
if (this.autoGrow)
|
|
4183
4550
|
this.resize();
|
|
4184
4551
|
}
|
|
4552
|
+
get computedLabelClass() {
|
|
4553
|
+
return cn("text-sm font-medium text-foreground leading-none transition-opacity duration-200", this.disabled && "opacity-50");
|
|
4554
|
+
}
|
|
4185
4555
|
get textareaClasses() {
|
|
4186
|
-
return cn(
|
|
4187
|
-
//
|
|
4188
|
-
|
|
4189
|
-
// Border
|
|
4190
|
-
|
|
4191
|
-
//
|
|
4192
|
-
|
|
4556
|
+
return cn(
|
|
4557
|
+
// Base styles
|
|
4558
|
+
'flex w-full rounded-md border bg-background px-3 py-2 text-sm', 'ring-offset-background transition-all duration-200', 'placeholder:text-muted-foreground',
|
|
4559
|
+
// Border and shadow
|
|
4560
|
+
'border-input shadow-sm',
|
|
4561
|
+
// Minimum height
|
|
4562
|
+
'min-h-[80px]',
|
|
4563
|
+
// Focus state - SIMPLE LIKE ZARDUI
|
|
4564
|
+
!(this.readonly || this.disabled) && [
|
|
4565
|
+
'focus:outline-none',
|
|
4566
|
+
'focus:ring-4',
|
|
4567
|
+
'focus:ring-ring/30',
|
|
4568
|
+
'focus:ring-offset-0',
|
|
4569
|
+
'focus:shadow-none',
|
|
4570
|
+
// Border darkens on focus automatically
|
|
4571
|
+
'focus:border-primary/80'
|
|
4572
|
+
],
|
|
4573
|
+
// Error state
|
|
4574
|
+
this.error && [
|
|
4575
|
+
'border-destructive',
|
|
4576
|
+
!(this.readonly || this.disabled) && [
|
|
4577
|
+
'focus:border-destructive/80',
|
|
4578
|
+
'focus:ring-destructive/30'
|
|
4579
|
+
]
|
|
4580
|
+
],
|
|
4581
|
+
// Disabled state
|
|
4582
|
+
this.disabled && [
|
|
4583
|
+
'cursor-not-allowed opacity-50',
|
|
4584
|
+
'border-opacity-50'
|
|
4585
|
+
],
|
|
4586
|
+
// Readonly state
|
|
4587
|
+
this.readonly && [
|
|
4588
|
+
'cursor-default',
|
|
4589
|
+
'border-dashed',
|
|
4590
|
+
!this.disabled && 'focus:ring-0 focus:border-opacity-100'
|
|
4591
|
+
],
|
|
4592
|
+
// Scrollbar styling
|
|
4593
|
+
'scrollbar-thin scrollbar-thumb-muted scrollbar-track-transparent', this.className);
|
|
4193
4594
|
}
|
|
4194
4595
|
handleInput(event) {
|
|
4195
4596
|
if (this.readonly || this.disabled)
|
|
@@ -4200,6 +4601,13 @@ class TextareaComponent {
|
|
|
4200
4601
|
if (this.autoGrow)
|
|
4201
4602
|
this.resize();
|
|
4202
4603
|
}
|
|
4604
|
+
onFocus() {
|
|
4605
|
+
this.isFocused = true;
|
|
4606
|
+
}
|
|
4607
|
+
onBlur() {
|
|
4608
|
+
this.isFocused = false;
|
|
4609
|
+
this.onTouched();
|
|
4610
|
+
}
|
|
4203
4611
|
resize() {
|
|
4204
4612
|
const textarea = this.textareaElement.nativeElement;
|
|
4205
4613
|
textarea.style.height = 'auto';
|
|
@@ -4210,11 +4618,17 @@ class TextareaComponent {
|
|
|
4210
4618
|
if (this.autoGrow)
|
|
4211
4619
|
setTimeout(() => this.resize());
|
|
4212
4620
|
}
|
|
4213
|
-
registerOnChange(fn) {
|
|
4214
|
-
|
|
4215
|
-
|
|
4621
|
+
registerOnChange(fn) {
|
|
4622
|
+
this.onChange = fn;
|
|
4623
|
+
}
|
|
4624
|
+
registerOnTouched(fn) {
|
|
4625
|
+
this.onTouched = fn;
|
|
4626
|
+
}
|
|
4627
|
+
setDisabledState(isDisabled) {
|
|
4628
|
+
this.disabled = isDisabled;
|
|
4629
|
+
}
|
|
4216
4630
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: TextareaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4217
|
-
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: [
|
|
4631
|
+
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", errorMessage: "errorMessage", rows: "rows", maxLength: "maxLength", showCharacterCount: "showCharacterCount", autoGrow: "autoGrow", error: "error", className: "className", hideHintOnFocus: "hideHintOnFocus", hideCharacterCountOnFocus: "hideCharacterCountOnFocus", disabled: "disabled", readonly: "readonly" }, providers: [
|
|
4218
4632
|
{
|
|
4219
4633
|
provide: NG_VALUE_ACCESSOR,
|
|
4220
4634
|
useExisting: forwardRef(() => TextareaComponent),
|
|
@@ -4222,9 +4636,11 @@ class TextareaComponent {
|
|
|
4222
4636
|
}
|
|
4223
4637
|
], viewQueries: [{ propertyName: "textareaElement", first: true, predicate: ["textareaElement"], descendants: true }], ngImport: i0, template: `
|
|
4224
4638
|
<div class="flex flex-col gap-1.5 w-full">
|
|
4225
|
-
<label
|
|
4226
|
-
|
|
4227
|
-
|
|
4639
|
+
<label
|
|
4640
|
+
*ngIf="label"
|
|
4641
|
+
[for]="id"
|
|
4642
|
+
[class]="computedLabelClass"
|
|
4643
|
+
>
|
|
4228
4644
|
{{ label }}
|
|
4229
4645
|
</label>
|
|
4230
4646
|
|
|
@@ -4238,16 +4654,37 @@ class TextareaComponent {
|
|
|
4238
4654
|
[rows]="rows"
|
|
4239
4655
|
[(ngModel)]="value"
|
|
4240
4656
|
(input)="handleInput($event)"
|
|
4241
|
-
(blur)="
|
|
4657
|
+
(blur)="onBlur()"
|
|
4658
|
+
(focus)="onFocus()"
|
|
4242
4659
|
[class]="textareaClasses"
|
|
4243
4660
|
[style.resize]="(autoGrow || readonly || disabled) ? 'none' : 'vertical'"
|
|
4244
4661
|
[style.overflow]="autoGrow ? 'hidden' : 'auto'"
|
|
4662
|
+
[attr.aria-invalid]="error"
|
|
4663
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
4664
|
+
[attr.maxlength]="maxLength"
|
|
4245
4665
|
></textarea>
|
|
4246
4666
|
</div>
|
|
4247
4667
|
|
|
4248
|
-
<div *ngIf="(showCharacterCount || hint) && !disabled" class="flex justify-between items-center px-1">
|
|
4249
|
-
<p
|
|
4250
|
-
|
|
4668
|
+
<div *ngIf="(showCharacterCount || hint || errorMessage) && !disabled" class="flex justify-between items-center px-1">
|
|
4669
|
+
<p
|
|
4670
|
+
*ngIf="hint && !error"
|
|
4671
|
+
class="text-xs text-muted-foreground transition-opacity duration-200"
|
|
4672
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
4673
|
+
>
|
|
4674
|
+
{{ hint }}
|
|
4675
|
+
</p>
|
|
4676
|
+
<p
|
|
4677
|
+
*ngIf="error && errorMessage"
|
|
4678
|
+
[id]="id + '-error'"
|
|
4679
|
+
class="text-xs text-destructive"
|
|
4680
|
+
>
|
|
4681
|
+
{{ errorMessage }}
|
|
4682
|
+
</p>
|
|
4683
|
+
<p
|
|
4684
|
+
*ngIf="showCharacterCount"
|
|
4685
|
+
class="text-[10px] uppercase tracking-wider text-muted-foreground ml-auto font-medium transition-opacity duration-200"
|
|
4686
|
+
[class.opacity-0]="isFocused && hideCharacterCountOnFocus"
|
|
4687
|
+
>
|
|
4251
4688
|
{{ value.length || 0 }}{{ maxLength ? ' / ' + maxLength : '' }}
|
|
4252
4689
|
</p>
|
|
4253
4690
|
</div>
|
|
@@ -4269,9 +4706,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4269
4706
|
],
|
|
4270
4707
|
template: `
|
|
4271
4708
|
<div class="flex flex-col gap-1.5 w-full">
|
|
4272
|
-
<label
|
|
4273
|
-
|
|
4274
|
-
|
|
4709
|
+
<label
|
|
4710
|
+
*ngIf="label"
|
|
4711
|
+
[for]="id"
|
|
4712
|
+
[class]="computedLabelClass"
|
|
4713
|
+
>
|
|
4275
4714
|
{{ label }}
|
|
4276
4715
|
</label>
|
|
4277
4716
|
|
|
@@ -4285,16 +4724,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4285
4724
|
[rows]="rows"
|
|
4286
4725
|
[(ngModel)]="value"
|
|
4287
4726
|
(input)="handleInput($event)"
|
|
4288
|
-
(blur)="
|
|
4727
|
+
(blur)="onBlur()"
|
|
4728
|
+
(focus)="onFocus()"
|
|
4289
4729
|
[class]="textareaClasses"
|
|
4290
4730
|
[style.resize]="(autoGrow || readonly || disabled) ? 'none' : 'vertical'"
|
|
4291
4731
|
[style.overflow]="autoGrow ? 'hidden' : 'auto'"
|
|
4732
|
+
[attr.aria-invalid]="error"
|
|
4733
|
+
[attr.aria-describedby]="error && errorMessage ? id + '-error' : null"
|
|
4734
|
+
[attr.maxlength]="maxLength"
|
|
4292
4735
|
></textarea>
|
|
4293
4736
|
</div>
|
|
4294
4737
|
|
|
4295
|
-
<div *ngIf="(showCharacterCount || hint) && !disabled" class="flex justify-between items-center px-1">
|
|
4296
|
-
<p
|
|
4297
|
-
|
|
4738
|
+
<div *ngIf="(showCharacterCount || hint || errorMessage) && !disabled" class="flex justify-between items-center px-1">
|
|
4739
|
+
<p
|
|
4740
|
+
*ngIf="hint && !error"
|
|
4741
|
+
class="text-xs text-muted-foreground transition-opacity duration-200"
|
|
4742
|
+
[class.opacity-0]="isFocused && hideHintOnFocus"
|
|
4743
|
+
>
|
|
4744
|
+
{{ hint }}
|
|
4745
|
+
</p>
|
|
4746
|
+
<p
|
|
4747
|
+
*ngIf="error && errorMessage"
|
|
4748
|
+
[id]="id + '-error'"
|
|
4749
|
+
class="text-xs text-destructive"
|
|
4750
|
+
>
|
|
4751
|
+
{{ errorMessage }}
|
|
4752
|
+
</p>
|
|
4753
|
+
<p
|
|
4754
|
+
*ngIf="showCharacterCount"
|
|
4755
|
+
class="text-[10px] uppercase tracking-wider text-muted-foreground ml-auto font-medium transition-opacity duration-200"
|
|
4756
|
+
[class.opacity-0]="isFocused && hideCharacterCountOnFocus"
|
|
4757
|
+
>
|
|
4298
4758
|
{{ value.length || 0 }}{{ maxLength ? ' / ' + maxLength : '' }}
|
|
4299
4759
|
</p>
|
|
4300
4760
|
</div>
|
|
@@ -4312,6 +4772,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4312
4772
|
type: Input
|
|
4313
4773
|
}], hint: [{
|
|
4314
4774
|
type: Input
|
|
4775
|
+
}], errorMessage: [{
|
|
4776
|
+
type: Input
|
|
4315
4777
|
}], rows: [{
|
|
4316
4778
|
type: Input
|
|
4317
4779
|
}], maxLength: [{
|
|
@@ -4324,6 +4786,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4324
4786
|
type: Input
|
|
4325
4787
|
}], className: [{
|
|
4326
4788
|
type: Input
|
|
4789
|
+
}], hideHintOnFocus: [{
|
|
4790
|
+
type: Input
|
|
4791
|
+
}], hideCharacterCountOnFocus: [{
|
|
4792
|
+
type: Input
|
|
4327
4793
|
}], disabled: [{
|
|
4328
4794
|
type: Input
|
|
4329
4795
|
}], readonly: [{
|
|
@@ -4887,23 +5353,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4887
5353
|
class OtpSlotComponent {
|
|
4888
5354
|
char = '';
|
|
4889
5355
|
isActive = false;
|
|
4890
|
-
isFirst = false;
|
|
4891
|
-
isLast = false;
|
|
5356
|
+
isFirst = false;
|
|
5357
|
+
isLast = false;
|
|
4892
5358
|
class = '';
|
|
4893
5359
|
cn = cn;
|
|
5360
|
+
get computedClass() {
|
|
5361
|
+
return cn(
|
|
5362
|
+
// Base styles (matching input container)
|
|
5363
|
+
'relative flex h-10 w-10 items-center justify-center', 'transition-all duration-200', 'text-center font-medium select-none',
|
|
5364
|
+
// Border styling - exactly like input
|
|
5365
|
+
'border border-input shadow-sm bg-background',
|
|
5366
|
+
// FOCUS STYLING - EXACTLY LIKE INPUT COMPONENT
|
|
5367
|
+
this.isActive && [
|
|
5368
|
+
// Darker border on focus
|
|
5369
|
+
'border-primary/80',
|
|
5370
|
+
// Remove shadow on focus
|
|
5371
|
+
'shadow-none',
|
|
5372
|
+
// Focus ring with same styling as input
|
|
5373
|
+
'ring-4',
|
|
5374
|
+
'ring-ring/30',
|
|
5375
|
+
'ring-offset-0',
|
|
5376
|
+
// Ensure it's above other slots
|
|
5377
|
+
'z-10'
|
|
5378
|
+
],
|
|
5379
|
+
// Filled state
|
|
5380
|
+
this.char && !this.isActive && 'border-primary/60',
|
|
5381
|
+
// Border radius
|
|
5382
|
+
this.isFirst && 'rounded-l-md', this.isLast && 'rounded-r-md',
|
|
5383
|
+
// Remove left border for all but first slot
|
|
5384
|
+
!this.isFirst && '-ml-px', this.class);
|
|
5385
|
+
}
|
|
4894
5386
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: OtpSlotComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
4895
5387
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: OtpSlotComponent, isStandalone: true, selector: "tolle-otp-slot", inputs: { char: "char", isActive: "isActive", isFirst: "isFirst", isLast: "isLast", class: "class" }, ngImport: i0, template: `
|
|
4896
|
-
<div [class]="
|
|
4897
|
-
|
|
4898
|
-
'bg-background',
|
|
4899
|
-
isFirst ? 'rounded-l-md border-l' : '',
|
|
4900
|
-
isLast ? 'rounded-r-md' : '',
|
|
4901
|
-
isActive ? 'z-10 ring-2 ring-ring ring-offset-background' : '',
|
|
4902
|
-
class
|
|
4903
|
-
)">
|
|
4904
|
-
{{ char || '' }}
|
|
5388
|
+
<div [class]="computedClass">
|
|
5389
|
+
<span class="text-lg font-medium">{{ char || '' }}</span>
|
|
4905
5390
|
<div *ngIf="isActive && !char" class="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
4906
|
-
<div class="h-
|
|
5391
|
+
<div class="h-6 w-0.5 animate-caret-blink bg-foreground"></div>
|
|
4907
5392
|
</div>
|
|
4908
5393
|
</div>
|
|
4909
5394
|
`, isInline: true, dependencies: [{ kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
@@ -4915,17 +5400,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4915
5400
|
standalone: true,
|
|
4916
5401
|
imports: [NgIf],
|
|
4917
5402
|
template: `
|
|
4918
|
-
<div [class]="
|
|
4919
|
-
|
|
4920
|
-
'bg-background',
|
|
4921
|
-
isFirst ? 'rounded-l-md border-l' : '',
|
|
4922
|
-
isLast ? 'rounded-r-md' : '',
|
|
4923
|
-
isActive ? 'z-10 ring-2 ring-ring ring-offset-background' : '',
|
|
4924
|
-
class
|
|
4925
|
-
)">
|
|
4926
|
-
{{ char || '' }}
|
|
5403
|
+
<div [class]="computedClass">
|
|
5404
|
+
<span class="text-lg font-medium">{{ char || '' }}</span>
|
|
4927
5405
|
<div *ngIf="isActive && !char" class="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
4928
|
-
<div class="h-
|
|
5406
|
+
<div class="h-6 w-0.5 animate-caret-blink bg-foreground"></div>
|
|
4929
5407
|
</div>
|
|
4930
5408
|
</div>
|
|
4931
5409
|
`
|