@praxisui/table-rule-builder 1.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,956 @@
1
+ import * as i0 from '@angular/core';
2
+ import { Input, ChangeDetectionStrategy, Component, Injectable, EventEmitter, Output } from '@angular/core';
3
+ import * as i3$1 from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as i1 from '@angular/forms';
6
+ import { ReactiveFormsModule } from '@angular/forms';
7
+ import { Subject } from 'rxjs';
8
+ import { auditTime, takeUntil } from 'rxjs/operators';
9
+ import * as i2 from '@angular/material/form-field';
10
+ import { MatFormFieldModule } from '@angular/material/form-field';
11
+ import * as i3 from '@angular/material/input';
12
+ import { MatInputModule } from '@angular/material/input';
13
+ import * as i4$1 from '@angular/material/button';
14
+ import { MatButtonModule } from '@angular/material/button';
15
+ import * as i5 from '@angular/material/icon';
16
+ import { MatIconModule } from '@angular/material/icon';
17
+ import * as i6$1 from '@angular/material/tooltip';
18
+ import { MatTooltipModule } from '@angular/material/tooltip';
19
+ import * as i7 from '@angular/material/menu';
20
+ import { MatMenuModule } from '@angular/material/menu';
21
+ import * as i4 from '@angular/material/button-toggle';
22
+ import { MatButtonToggleModule } from '@angular/material/button-toggle';
23
+ import * as i6 from '@angular/material/slider';
24
+ import { MatSliderModule } from '@angular/material/slider';
25
+
26
+ const DEFAULT_EFFECT_PRESETS = {
27
+ aprovado: {
28
+ scope: 'row',
29
+ estilo: { color: '#eafff5', bold: true },
30
+ iconBadge: {
31
+ icon: 'check_circle',
32
+ iconColor: '#35D07F',
33
+ iconPos: 'before',
34
+ badgeText: 'Aprovado',
35
+ badgeStyle: 'soft',
36
+ badgeColor: '#2a8455',
37
+ },
38
+ background: { color: 'rgba(53,208,127,0.08)' },
39
+ layout: { border: 'left', borderColor: '#35D07F', borderWidth: 3 },
40
+ },
41
+ alerta: {
42
+ scope: 'row',
43
+ estilo: { color: '#fff8e1', bold: true },
44
+ iconBadge: {
45
+ icon: 'warning',
46
+ iconColor: '#FFC107',
47
+ iconPos: 'before',
48
+ badgeText: 'Atenção',
49
+ badgeStyle: 'outline',
50
+ badgeColor: '#FFC107',
51
+ },
52
+ background: { color: 'rgba(255,193,7,0.12)' },
53
+ },
54
+ erro: {
55
+ scope: 'row',
56
+ estilo: { color: '#ffeaea', bold: true },
57
+ iconBadge: {
58
+ icon: 'error',
59
+ iconColor: '#EF5350',
60
+ iconPos: 'before',
61
+ badgeText: 'Erro',
62
+ badgeStyle: 'solid',
63
+ badgeColor: '#EF5350',
64
+ },
65
+ background: { color: 'rgba(239,83,80,0.10)' },
66
+ },
67
+ info: {
68
+ scope: 'row',
69
+ iconBadge: { icon: 'info', iconColor: '#64B5F6', iconPos: 'before' },
70
+ background: { color: 'rgba(100,181,246,0.10)' },
71
+ },
72
+ };
73
+
74
+ class EstiloEditorComponent {
75
+ group;
76
+ // Public for template (strictTemplates): used by mat-slider
77
+ formatOpacity(v) { return (v ?? 0).toFixed(2); }
78
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EstiloEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
79
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: EstiloEditorComponent, isStandalone: true, selector: "praxis-effects-estilo-editor", inputs: { group: "group" }, ngImport: i0, template: `
80
+ <div class="estilo-grid" role="group" aria-label="Editor de estilo" [formGroup]="group">
81
+ <mat-form-field appearance="outline">
82
+ <mat-label>Cor do texto</mat-label>
83
+ <input matInput type="text" formControlName="color" placeholder="#E7ECF6" />
84
+ </mat-form-field>
85
+
86
+ <mat-form-field appearance="outline">
87
+ <mat-label>Cor de fundo do texto</mat-label>
88
+ <input matInput type="text" formControlName="bgColor" placeholder="#122033" />
89
+ </mat-form-field>
90
+
91
+ <div class="toggles">
92
+ <mat-button-toggle-group multiple>
93
+ <mat-button-toggle [checked]="group.get('bold')?.value" (change)="group.get('bold')?.setValue($event.source.checked)" aria-label="Negrito">
94
+ <mat-icon>format_bold</mat-icon>
95
+ </mat-button-toggle>
96
+ <mat-button-toggle [checked]="group.get('italic')?.value" (change)="group.get('italic')?.setValue($event.source.checked)" aria-label="Itálico">
97
+ <mat-icon>format_italic</mat-icon>
98
+ </mat-button-toggle>
99
+ <mat-button-toggle [checked]="group.get('underline')?.value" (change)="group.get('underline')?.setValue($event.source.checked)" aria-label="Sublinhado">
100
+ <mat-icon>format_underlined</mat-icon>
101
+ </mat-button-toggle>
102
+ </mat-button-toggle-group>
103
+ </div>
104
+
105
+ <mat-form-field appearance="outline">
106
+ <mat-label>Transformação</mat-label>
107
+ <select matNativeControl formControlName="transform" aria-label="Transformação do texto">
108
+ <option [ngValue]="null">Nenhuma</option>
109
+ <option value="uppercase">MAIÚSCULAS</option>
110
+ <option value="lowercase">minúsculas</option>
111
+ <option value="capitalize">Capitalizar</option>
112
+ </select>
113
+ </mat-form-field>
114
+
115
+ <div class="sliders">
116
+ <label class="slider">
117
+ <span>Opacidade</span>
118
+ <mat-slider min="0" max="1" step="0.05" [displayWith]="formatOpacity">
119
+ <input matSliderThumb formControlName="opacity" />
120
+ </mat-slider>
121
+ </label>
122
+ <label class="slider">
123
+ <span>Tamanho</span>
124
+ <mat-slider min="-2" max="2" step="1">
125
+ <input matSliderThumb formControlName="fontScale" />
126
+ </mat-slider>
127
+ </label>
128
+ </div>
129
+ </div>
130
+ `, isInline: true, styles: [".estilo-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}.toggles{display:flex;align-items:center;gap:8px}.sliders{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.slider{display:flex;flex-direction:column;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i4.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i4.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i6.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i6.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
131
+ }
132
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EstiloEditorComponent, decorators: [{
133
+ type: Component,
134
+ args: [{ selector: 'praxis-effects-estilo-editor', standalone: true, imports: [
135
+ CommonModule,
136
+ ReactiveFormsModule,
137
+ MatFormFieldModule,
138
+ MatInputModule,
139
+ MatButtonToggleModule,
140
+ MatIconModule,
141
+ MatSliderModule,
142
+ ], template: `
143
+ <div class="estilo-grid" role="group" aria-label="Editor de estilo" [formGroup]="group">
144
+ <mat-form-field appearance="outline">
145
+ <mat-label>Cor do texto</mat-label>
146
+ <input matInput type="text" formControlName="color" placeholder="#E7ECF6" />
147
+ </mat-form-field>
148
+
149
+ <mat-form-field appearance="outline">
150
+ <mat-label>Cor de fundo do texto</mat-label>
151
+ <input matInput type="text" formControlName="bgColor" placeholder="#122033" />
152
+ </mat-form-field>
153
+
154
+ <div class="toggles">
155
+ <mat-button-toggle-group multiple>
156
+ <mat-button-toggle [checked]="group.get('bold')?.value" (change)="group.get('bold')?.setValue($event.source.checked)" aria-label="Negrito">
157
+ <mat-icon>format_bold</mat-icon>
158
+ </mat-button-toggle>
159
+ <mat-button-toggle [checked]="group.get('italic')?.value" (change)="group.get('italic')?.setValue($event.source.checked)" aria-label="Itálico">
160
+ <mat-icon>format_italic</mat-icon>
161
+ </mat-button-toggle>
162
+ <mat-button-toggle [checked]="group.get('underline')?.value" (change)="group.get('underline')?.setValue($event.source.checked)" aria-label="Sublinhado">
163
+ <mat-icon>format_underlined</mat-icon>
164
+ </mat-button-toggle>
165
+ </mat-button-toggle-group>
166
+ </div>
167
+
168
+ <mat-form-field appearance="outline">
169
+ <mat-label>Transformação</mat-label>
170
+ <select matNativeControl formControlName="transform" aria-label="Transformação do texto">
171
+ <option [ngValue]="null">Nenhuma</option>
172
+ <option value="uppercase">MAIÚSCULAS</option>
173
+ <option value="lowercase">minúsculas</option>
174
+ <option value="capitalize">Capitalizar</option>
175
+ </select>
176
+ </mat-form-field>
177
+
178
+ <div class="sliders">
179
+ <label class="slider">
180
+ <span>Opacidade</span>
181
+ <mat-slider min="0" max="1" step="0.05" [displayWith]="formatOpacity">
182
+ <input matSliderThumb formControlName="opacity" />
183
+ </mat-slider>
184
+ </label>
185
+ <label class="slider">
186
+ <span>Tamanho</span>
187
+ <mat-slider min="-2" max="2" step="1">
188
+ <input matSliderThumb formControlName="fontScale" />
189
+ </mat-slider>
190
+ </label>
191
+ </div>
192
+ </div>
193
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".estilo-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:start}.toggles{display:flex;align-items:center;gap:8px}.sliders{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}.slider{display:flex;flex-direction:column;gap:6px}\n"] }]
194
+ }], propDecorators: { group: [{
195
+ type: Input
196
+ }] } });
197
+
198
+ class LayoutEditorComponent {
199
+ group;
200
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: LayoutEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
201
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: LayoutEditorComponent, isStandalone: true, selector: "praxis-effects-layout-editor", inputs: { group: "group" }, ngImport: i0, template: `
202
+ <div class="layout-grid" role="group" aria-label="Editor de layout" [formGroup]="group">
203
+ <div class="borders">
204
+ <span class="lbl">Borda</span>
205
+ <mat-button-toggle-group [value]="group.get('border')?.value" (change)="group.get('border')?.setValue($event.value)" aria-label="Borda">
206
+ <mat-button-toggle value="none"><mat-icon>crop_free</mat-icon></mat-button-toggle>
207
+ <mat-button-toggle value="left"><mat-icon>border_left</mat-icon></mat-button-toggle>
208
+ <mat-button-toggle value="right"><mat-icon>border_right</mat-icon></mat-button-toggle>
209
+ <mat-button-toggle value="top"><mat-icon>border_top</mat-icon></mat-button-toggle>
210
+ <mat-button-toggle value="bottom"><mat-icon>border_bottom</mat-icon></mat-button-toggle>
211
+ <mat-button-toggle value="all"><mat-icon>border_all</mat-icon></mat-button-toggle>
212
+ </mat-button-toggle-group>
213
+ </div>
214
+
215
+ <mat-form-field appearance="outline">
216
+ <mat-label>Cor da borda</mat-label>
217
+ <input matInput type="text" formControlName="borderColor" placeholder="#487BFF" />
218
+ </mat-form-field>
219
+ <mat-form-field appearance="outline">
220
+ <mat-label>Espessura</mat-label>
221
+ <input matInput type="number" formControlName="borderWidth" placeholder="2" />
222
+ </mat-form-field>
223
+ <mat-form-field appearance="outline">
224
+ <mat-label>Padding</mat-label>
225
+ <input matInput type="number" formControlName="padding" placeholder="6" />
226
+ </mat-form-field>
227
+
228
+ <div class="align">
229
+ <span class="lbl">Alinhamento</span>
230
+ <mat-button-toggle-group [value]="group.get('align')?.value" (change)="group.get('align')?.setValue($event.value)" aria-label="Alinhamento">
231
+ <mat-button-toggle value="start"><mat-icon>format_align_left</mat-icon></mat-button-toggle>
232
+ <mat-button-toggle value="center"><mat-icon>format_align_center</mat-icon></mat-button-toggle>
233
+ <mat-button-toggle value="end"><mat-icon>format_align_right</mat-icon></mat-button-toggle>
234
+ </mat-button-toggle-group>
235
+ </div>
236
+
237
+ <mat-form-field appearance="outline">
238
+ <mat-label>Elevação (sombra)</mat-label>
239
+ <input matInput type="number" formControlName="elevation" placeholder="6" />
240
+ </mat-form-field>
241
+ </div>
242
+ `, isInline: true, styles: [".layout-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.borders,.align{display:flex;align-items:center;gap:8px}.lbl{font-size:.85rem;opacity:.8}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i4.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i4.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
243
+ }
244
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: LayoutEditorComponent, decorators: [{
245
+ type: Component,
246
+ args: [{ selector: 'praxis-effects-layout-editor', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonToggleModule, MatIconModule], template: `
247
+ <div class="layout-grid" role="group" aria-label="Editor de layout" [formGroup]="group">
248
+ <div class="borders">
249
+ <span class="lbl">Borda</span>
250
+ <mat-button-toggle-group [value]="group.get('border')?.value" (change)="group.get('border')?.setValue($event.value)" aria-label="Borda">
251
+ <mat-button-toggle value="none"><mat-icon>crop_free</mat-icon></mat-button-toggle>
252
+ <mat-button-toggle value="left"><mat-icon>border_left</mat-icon></mat-button-toggle>
253
+ <mat-button-toggle value="right"><mat-icon>border_right</mat-icon></mat-button-toggle>
254
+ <mat-button-toggle value="top"><mat-icon>border_top</mat-icon></mat-button-toggle>
255
+ <mat-button-toggle value="bottom"><mat-icon>border_bottom</mat-icon></mat-button-toggle>
256
+ <mat-button-toggle value="all"><mat-icon>border_all</mat-icon></mat-button-toggle>
257
+ </mat-button-toggle-group>
258
+ </div>
259
+
260
+ <mat-form-field appearance="outline">
261
+ <mat-label>Cor da borda</mat-label>
262
+ <input matInput type="text" formControlName="borderColor" placeholder="#487BFF" />
263
+ </mat-form-field>
264
+ <mat-form-field appearance="outline">
265
+ <mat-label>Espessura</mat-label>
266
+ <input matInput type="number" formControlName="borderWidth" placeholder="2" />
267
+ </mat-form-field>
268
+ <mat-form-field appearance="outline">
269
+ <mat-label>Padding</mat-label>
270
+ <input matInput type="number" formControlName="padding" placeholder="6" />
271
+ </mat-form-field>
272
+
273
+ <div class="align">
274
+ <span class="lbl">Alinhamento</span>
275
+ <mat-button-toggle-group [value]="group.get('align')?.value" (change)="group.get('align')?.setValue($event.value)" aria-label="Alinhamento">
276
+ <mat-button-toggle value="start"><mat-icon>format_align_left</mat-icon></mat-button-toggle>
277
+ <mat-button-toggle value="center"><mat-icon>format_align_center</mat-icon></mat-button-toggle>
278
+ <mat-button-toggle value="end"><mat-icon>format_align_right</mat-icon></mat-button-toggle>
279
+ </mat-button-toggle-group>
280
+ </div>
281
+
282
+ <mat-form-field appearance="outline">
283
+ <mat-label>Elevação (sombra)</mat-label>
284
+ <input matInput type="number" formControlName="elevation" placeholder="6" />
285
+ </mat-form-field>
286
+ </div>
287
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".layout-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.borders,.align{display:flex;align-items:center;gap:8px}.lbl{font-size:.85rem;opacity:.8}\n"] }]
288
+ }], propDecorators: { group: [{
289
+ type: Input
290
+ }] } });
291
+
292
+ class IconeBadgeEditorComponent {
293
+ group;
294
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: IconeBadgeEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
295
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: IconeBadgeEditorComponent, isStandalone: true, selector: "praxis-effects-icone-badge-editor", inputs: { group: "group" }, ngImport: i0, template: `
296
+ <div class="icone-grid" role="group" aria-label="Editor de ícone e badge" [formGroup]="group">
297
+ <mat-form-field appearance="outline">
298
+ <mat-label>Ícone (mat-icon)</mat-label>
299
+ <input matInput type="text" formControlName="icon" placeholder="check_circle" />
300
+ </mat-form-field>
301
+ <mat-form-field appearance="outline">
302
+ <mat-label>Cor do ícone</mat-label>
303
+ <input matInput type="text" formControlName="iconColor" placeholder="#35D07F" />
304
+ </mat-form-field>
305
+
306
+ <div class="pos">
307
+ <span class="lbl">Posição do ícone</span>
308
+ <mat-button-toggle-group [value]="group.get('iconPos')?.value" (change)="group.get('iconPos')?.setValue($event.value)" aria-label="Posição do ícone">
309
+ <mat-button-toggle value="before">Antes</mat-button-toggle>
310
+ <mat-button-toggle value="after">Depois</mat-button-toggle>
311
+ <mat-button-toggle value="overlay">Sobreposto</mat-button-toggle>
312
+ </mat-button-toggle-group>
313
+ </div>
314
+
315
+ <mat-form-field appearance="outline">
316
+ <mat-label>Texto do badge</mat-label>
317
+ <input matInput type="text" formControlName="badgeText" placeholder="Aprovado" />
318
+ </mat-form-field>
319
+ <mat-form-field appearance="outline">
320
+ <mat-label>Cor do badge</mat-label>
321
+ <input matInput type="text" formControlName="badgeColor" placeholder="#2a8455" />
322
+ </mat-form-field>
323
+
324
+ <div class="variant">
325
+ <span class="lbl">Estilo</span>
326
+ <mat-button-toggle-group [value]="group.get('badgeStyle')?.value" (change)="group.get('badgeStyle')?.setValue($event.value)" aria-label="Estilo do badge">
327
+ <mat-button-toggle value="solid">Sólido</mat-button-toggle>
328
+ <mat-button-toggle value="soft">Suave</mat-button-toggle>
329
+ <mat-button-toggle value="outline">Contorno</mat-button-toggle>
330
+ </mat-button-toggle-group>
331
+ </div>
332
+ </div>
333
+ `, isInline: true, styles: [".icone-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.pos,.variant{display:flex;align-items:center;gap:8px}.lbl{font-size:.85rem;opacity:.8}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "directive", type: i4.MatButtonToggleGroup, selector: "mat-button-toggle-group", inputs: ["appearance", "name", "vertical", "value", "multiple", "disabled", "disabledInteractive", "hideSingleSelectionIndicator", "hideMultipleSelectionIndicator"], outputs: ["valueChange", "change"], exportAs: ["matButtonToggleGroup"] }, { kind: "component", type: i4.MatButtonToggle, selector: "mat-button-toggle", inputs: ["aria-label", "aria-labelledby", "id", "name", "value", "tabIndex", "disableRipple", "appearance", "checked", "disabled", "disabledInteractive"], outputs: ["change"], exportAs: ["matButtonToggle"] }, { kind: "ngmodule", type: MatIconModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
334
+ }
335
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: IconeBadgeEditorComponent, decorators: [{
336
+ type: Component,
337
+ args: [{ selector: 'praxis-effects-icone-badge-editor', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatButtonToggleModule, MatIconModule], template: `
338
+ <div class="icone-grid" role="group" aria-label="Editor de ícone e badge" [formGroup]="group">
339
+ <mat-form-field appearance="outline">
340
+ <mat-label>Ícone (mat-icon)</mat-label>
341
+ <input matInput type="text" formControlName="icon" placeholder="check_circle" />
342
+ </mat-form-field>
343
+ <mat-form-field appearance="outline">
344
+ <mat-label>Cor do ícone</mat-label>
345
+ <input matInput type="text" formControlName="iconColor" placeholder="#35D07F" />
346
+ </mat-form-field>
347
+
348
+ <div class="pos">
349
+ <span class="lbl">Posição do ícone</span>
350
+ <mat-button-toggle-group [value]="group.get('iconPos')?.value" (change)="group.get('iconPos')?.setValue($event.value)" aria-label="Posição do ícone">
351
+ <mat-button-toggle value="before">Antes</mat-button-toggle>
352
+ <mat-button-toggle value="after">Depois</mat-button-toggle>
353
+ <mat-button-toggle value="overlay">Sobreposto</mat-button-toggle>
354
+ </mat-button-toggle-group>
355
+ </div>
356
+
357
+ <mat-form-field appearance="outline">
358
+ <mat-label>Texto do badge</mat-label>
359
+ <input matInput type="text" formControlName="badgeText" placeholder="Aprovado" />
360
+ </mat-form-field>
361
+ <mat-form-field appearance="outline">
362
+ <mat-label>Cor do badge</mat-label>
363
+ <input matInput type="text" formControlName="badgeColor" placeholder="#2a8455" />
364
+ </mat-form-field>
365
+
366
+ <div class="variant">
367
+ <span class="lbl">Estilo</span>
368
+ <mat-button-toggle-group [value]="group.get('badgeStyle')?.value" (change)="group.get('badgeStyle')?.setValue($event.value)" aria-label="Estilo do badge">
369
+ <mat-button-toggle value="solid">Sólido</mat-button-toggle>
370
+ <mat-button-toggle value="soft">Suave</mat-button-toggle>
371
+ <mat-button-toggle value="outline">Contorno</mat-button-toggle>
372
+ </mat-button-toggle-group>
373
+ </div>
374
+ </div>
375
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".icone-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.pos,.variant{display:flex;align-items:center;gap:8px}.lbl{font-size:.85rem;opacity:.8}\n"] }]
376
+ }], propDecorators: { group: [{
377
+ type: Input
378
+ }] } });
379
+
380
+ class FundoEditorComponent {
381
+ group;
382
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FundoEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
383
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: FundoEditorComponent, isStandalone: true, selector: "praxis-effects-fundo-editor", inputs: { group: "group" }, ngImport: i0, template: `
384
+ <div class="fundo-grid" role="group" aria-label="Editor de fundo" [formGroup]="group">
385
+ <mat-form-field appearance="outline">
386
+ <mat-label>Cor</mat-label>
387
+ <input matInput type="text" formControlName="color" placeholder="#122033" />
388
+ </mat-form-field>
389
+ <mat-form-field appearance="outline" class="full">
390
+ <mat-label>Gradient CSS</mat-label>
391
+ <input matInput type="text" formControlName="gradient" placeholder="linear-gradient(180deg, #202637, #1c2230)" />
392
+ </mat-form-field>
393
+
394
+ <label class="slider">
395
+ <span>Transparência</span>
396
+ <mat-slider min="0" max="100" step="5">
397
+ <input matSliderThumb formControlName="alpha" />
398
+ </mat-slider>
399
+ </label>
400
+ <label class="slider">
401
+ <span>Desfoque (px)</span>
402
+ <mat-slider min="0" max="20" step="1">
403
+ <input matSliderThumb formControlName="blur" />
404
+ </mat-slider>
405
+ </label>
406
+ </div>
407
+ `, isInline: true, styles: [".fundo-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.full{grid-column:1 / -1}.slider{display:flex;flex-direction:column;gap:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }, { kind: "ngmodule", type: MatSliderModule }, { kind: "component", type: i6.MatSlider, selector: "mat-slider", inputs: ["disabled", "discrete", "showTickMarks", "min", "color", "disableRipple", "max", "step", "displayWith"], exportAs: ["matSlider"] }, { kind: "directive", type: i6.MatSliderThumb, selector: "input[matSliderThumb]", inputs: ["value"], outputs: ["valueChange", "dragStart", "dragEnd"], exportAs: ["matSliderThumb"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
408
+ }
409
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: FundoEditorComponent, decorators: [{
410
+ type: Component,
411
+ args: [{ selector: 'praxis-effects-fundo-editor', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule, MatSliderModule], template: `
412
+ <div class="fundo-grid" role="group" aria-label="Editor de fundo" [formGroup]="group">
413
+ <mat-form-field appearance="outline">
414
+ <mat-label>Cor</mat-label>
415
+ <input matInput type="text" formControlName="color" placeholder="#122033" />
416
+ </mat-form-field>
417
+ <mat-form-field appearance="outline" class="full">
418
+ <mat-label>Gradient CSS</mat-label>
419
+ <input matInput type="text" formControlName="gradient" placeholder="linear-gradient(180deg, #202637, #1c2230)" />
420
+ </mat-form-field>
421
+
422
+ <label class="slider">
423
+ <span>Transparência</span>
424
+ <mat-slider min="0" max="100" step="5">
425
+ <input matSliderThumb formControlName="alpha" />
426
+ </mat-slider>
427
+ </label>
428
+ <label class="slider">
429
+ <span>Desfoque (px)</span>
430
+ <mat-slider min="0" max="20" step="1">
431
+ <input matSliderThumb formControlName="blur" />
432
+ </mat-slider>
433
+ </label>
434
+ </div>
435
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".fundo-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.full{grid-column:1 / -1}.slider{display:flex;flex-direction:column;gap:6px}\n"] }]
436
+ }], propDecorators: { group: [{
437
+ type: Input
438
+ }] } });
439
+
440
+ class AnimacaoEditorComponent {
441
+ group;
442
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AnimacaoEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
443
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: AnimacaoEditorComponent, isStandalone: true, selector: "praxis-effects-animacao-editor", inputs: { group: "group" }, ngImport: i0, template: `
444
+ <div class="anim-grid" role="group" aria-label="Editor de animação" [formGroup]="group">
445
+ <mat-form-field appearance="outline">
446
+ <mat-label>Tipo</mat-label>
447
+ <select matNativeControl formControlName="type" aria-label="Tipo de animação">
448
+ <option value="pulse">Pulse</option>
449
+ <option value="blink">Blink</option>
450
+ <option value="grow">Grow</option>
451
+ <option value="fade">Fade</option>
452
+ <option value="slide-in">Slide In</option>
453
+ </select>
454
+ </mat-form-field>
455
+ <mat-form-field appearance="outline">
456
+ <mat-label>Duração (ms)</mat-label>
457
+ <input matInput type="number" formControlName="durationMs" placeholder="800" />
458
+ </mat-form-field>
459
+ <mat-form-field appearance="outline">
460
+ <mat-label>Delay (ms)</mat-label>
461
+ <input matInput type="number" formControlName="delayMs" placeholder="0" />
462
+ </mat-form-field>
463
+ <mat-form-field appearance="outline">
464
+ <mat-label>Disparo</mat-label>
465
+ <select matNativeControl formControlName="trigger" aria-label="Disparo da animação">
466
+ <option value="onChange">Ao mudar</option>
467
+ <option value="onAppear">Ao aparecer</option>
468
+ <option value="onHover">Ao passar o mouse</option>
469
+ </select>
470
+ </mat-form-field>
471
+ <mat-form-field appearance="outline">
472
+ <mat-label>Repetição</mat-label>
473
+ <select matNativeControl formControlName="repeat" aria-label="Repetição da animação">
474
+ <option value="once">Uma vez</option>
475
+ <option value="loop">Loop</option>
476
+ </select>
477
+ </mat-form-field>
478
+ </div>
479
+ `, isInline: true, styles: [".anim-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
480
+ }
481
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: AnimacaoEditorComponent, decorators: [{
482
+ type: Component,
483
+ args: [{ selector: 'praxis-effects-animacao-editor', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule], template: `
484
+ <div class="anim-grid" role="group" aria-label="Editor de animação" [formGroup]="group">
485
+ <mat-form-field appearance="outline">
486
+ <mat-label>Tipo</mat-label>
487
+ <select matNativeControl formControlName="type" aria-label="Tipo de animação">
488
+ <option value="pulse">Pulse</option>
489
+ <option value="blink">Blink</option>
490
+ <option value="grow">Grow</option>
491
+ <option value="fade">Fade</option>
492
+ <option value="slide-in">Slide In</option>
493
+ </select>
494
+ </mat-form-field>
495
+ <mat-form-field appearance="outline">
496
+ <mat-label>Duração (ms)</mat-label>
497
+ <input matInput type="number" formControlName="durationMs" placeholder="800" />
498
+ </mat-form-field>
499
+ <mat-form-field appearance="outline">
500
+ <mat-label>Delay (ms)</mat-label>
501
+ <input matInput type="number" formControlName="delayMs" placeholder="0" />
502
+ </mat-form-field>
503
+ <mat-form-field appearance="outline">
504
+ <mat-label>Disparo</mat-label>
505
+ <select matNativeControl formControlName="trigger" aria-label="Disparo da animação">
506
+ <option value="onChange">Ao mudar</option>
507
+ <option value="onAppear">Ao aparecer</option>
508
+ <option value="onHover">Ao passar o mouse</option>
509
+ </select>
510
+ </mat-form-field>
511
+ <mat-form-field appearance="outline">
512
+ <mat-label>Repetição</mat-label>
513
+ <select matNativeControl formControlName="repeat" aria-label="Repetição da animação">
514
+ <option value="once">Uma vez</option>
515
+ <option value="loop">Loop</option>
516
+ </select>
517
+ </mat-form-field>
518
+ </div>
519
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".anim-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}\n"] }]
520
+ }], propDecorators: { group: [{
521
+ type: Input
522
+ }] } });
523
+
524
+ class TooltipEditorComponent {
525
+ group;
526
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TooltipEditorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
527
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: TooltipEditorComponent, isStandalone: true, selector: "praxis-effects-tooltip-editor", inputs: { group: "group" }, ngImport: i0, template: `
528
+ <div class="tooltip-grid" role="group" aria-label="Editor de tooltip" [formGroup]="group">
529
+ <mat-form-field appearance="outline" class="full">
530
+ <mat-label>Texto</mat-label>
531
+ <input matInput type="text" formControlName="text" placeholder="Detalhes da célula" />
532
+ </mat-form-field>
533
+ <mat-form-field appearance="outline">
534
+ <mat-label>Posição</mat-label>
535
+ <select matNativeControl formControlName="position" aria-label="Posição do tooltip">
536
+ <option value="top">Topo</option>
537
+ <option value="right">Direita</option>
538
+ <option value="bottom">Baixo</option>
539
+ <option value="left">Esquerda</option>
540
+ </select>
541
+ </mat-form-field>
542
+ <mat-form-field appearance="outline">
543
+ <mat-label>Cor do fundo</mat-label>
544
+ <input matInput type="text" formControlName="bgColor" placeholder="#2E3142" />
545
+ </mat-form-field>
546
+ <mat-form-field appearance="outline">
547
+ <mat-label>Delay (ms)</mat-label>
548
+ <input matInput type="number" formControlName="delayMs" placeholder="300" />
549
+ </mat-form-field>
550
+ </div>
551
+ `, isInline: true, styles: [".tooltip-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.full{grid-column:1 / -1}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "component", type: i2.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i2.MatLabel, selector: "mat-label" }, { kind: "ngmodule", type: MatInputModule }, { kind: "directive", type: i3.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly", "disabledInteractive"], exportAs: ["matInput"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
552
+ }
553
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TooltipEditorComponent, decorators: [{
554
+ type: Component,
555
+ args: [{ selector: 'praxis-effects-tooltip-editor', standalone: true, imports: [CommonModule, ReactiveFormsModule, MatFormFieldModule, MatInputModule], template: `
556
+ <div class="tooltip-grid" role="group" aria-label="Editor de tooltip" [formGroup]="group">
557
+ <mat-form-field appearance="outline" class="full">
558
+ <mat-label>Texto</mat-label>
559
+ <input matInput type="text" formControlName="text" placeholder="Detalhes da célula" />
560
+ </mat-form-field>
561
+ <mat-form-field appearance="outline">
562
+ <mat-label>Posição</mat-label>
563
+ <select matNativeControl formControlName="position" aria-label="Posição do tooltip">
564
+ <option value="top">Topo</option>
565
+ <option value="right">Direita</option>
566
+ <option value="bottom">Baixo</option>
567
+ <option value="left">Esquerda</option>
568
+ </select>
569
+ </mat-form-field>
570
+ <mat-form-field appearance="outline">
571
+ <mat-label>Cor do fundo</mat-label>
572
+ <input matInput type="text" formControlName="bgColor" placeholder="#2E3142" />
573
+ </mat-form-field>
574
+ <mat-form-field appearance="outline">
575
+ <mat-label>Delay (ms)</mat-label>
576
+ <input matInput type="number" formControlName="delayMs" placeholder="300" />
577
+ </mat-form-field>
578
+ </div>
579
+ `, changeDetection: ChangeDetectionStrategy.OnPush, styles: [".tooltip-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;align-items:center}.full{grid-column:1 / -1}\n"] }]
580
+ }], propDecorators: { group: [{
581
+ type: Input
582
+ }] } });
583
+
584
+ class EffectRegistryService {
585
+ plugins = [];
586
+ register(plugin) {
587
+ if (this.plugins.find((p) => p.id === plugin.id))
588
+ return; // avoid duplicates
589
+ this.plugins.push(plugin);
590
+ this.plugins.sort((a, b) => a.order - b.order);
591
+ }
592
+ list() {
593
+ return this.plugins.slice();
594
+ }
595
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EffectRegistryService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
596
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EffectRegistryService, providedIn: 'root' });
597
+ }
598
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: EffectRegistryService, decorators: [{
599
+ type: Injectable,
600
+ args: [{ providedIn: 'root' }]
601
+ }] });
602
+
603
+ class RuleEffectsPanelComponent {
604
+ fb;
605
+ registry;
606
+ // i18n-friendly labels map
607
+ labels = {
608
+ 'panel.title': 'C. Efeitos',
609
+ 'panel.subtitle': 'Configure estilos e elementos visuais quando a regra for verdadeira',
610
+ 'tabs.estilo': 'Estilo',
611
+ 'tabs.layout': 'Layout',
612
+ 'tabs.icone': 'Ícone / Badge',
613
+ 'tabs.fundo': 'Fundo',
614
+ 'tabs.animacao': 'Animação',
615
+ 'tabs.tooltip': 'Tooltip',
616
+ 'preview.title': 'Pré-visualização',
617
+ 'preview.hint': 'As mudanças acima refletem o estilo aplicado quando a condição é verdadeira.',
618
+ 'advanced.title': 'Avançado',
619
+ 'advanced.description': 'Descrição',
620
+ 'actions.apply': 'Aplicar',
621
+ 'actions.reset': 'Redefinir',
622
+ 'presets.label': 'Presets',
623
+ };
624
+ t(key) { return this.labels[key] ?? key; }
625
+ scope = 'row';
626
+ _value;
627
+ set value(v) {
628
+ this._value = v;
629
+ if (v && this.effectsForm)
630
+ this.patchForm(v);
631
+ }
632
+ get value() { return this._value; }
633
+ valueChange = new EventEmitter();
634
+ apply = new EventEmitter();
635
+ reset = new EventEmitter();
636
+ activeTab = 'estilo';
637
+ effectsForm;
638
+ destroy$ = new Subject();
639
+ isHovering = false;
640
+ tabOrder = ['estilo', 'layout', 'icone', 'fundo', 'animacao', 'tooltip'];
641
+ constructor(fb, registry) {
642
+ this.fb = fb;
643
+ this.registry = registry;
644
+ }
645
+ ngOnInit() {
646
+ // Register built-in editors for the registry (extensible)
647
+ this.registry.register({ id: 'estilo', icon: 'text_format', label: this.t('tabs.estilo'), order: 1 });
648
+ this.registry.register({ id: 'layout', icon: 'view_quilt', label: this.t('tabs.layout'), order: 2 });
649
+ this.registry.register({ id: 'icone', icon: 'verified', label: this.t('tabs.icone'), order: 3 });
650
+ this.registry.register({ id: 'fundo', icon: 'gradient', label: this.t('tabs.fundo'), order: 4 });
651
+ this.registry.register({ id: 'animacao', icon: 'animation', label: this.t('tabs.animacao'), order: 5 });
652
+ this.registry.register({ id: 'tooltip', icon: 'info', label: this.t('tabs.tooltip'), order: 6 });
653
+ this.effectsForm = this.fb.group({
654
+ description: [''],
655
+ estilo: this.fb.group({
656
+ color: ['#ffffff'],
657
+ bgColor: [''],
658
+ bold: [false],
659
+ italic: [false],
660
+ underline: [false],
661
+ transform: [null],
662
+ opacity: [1],
663
+ fontScale: [0],
664
+ }),
665
+ layout: this.fb.group({
666
+ border: ['none'],
667
+ borderColor: ['#487BFF'],
668
+ borderWidth: [2],
669
+ padding: [6],
670
+ align: ['start'],
671
+ elevation: [6],
672
+ }),
673
+ iconBadge: this.fb.group({
674
+ icon: ['check_circle'],
675
+ iconColor: ['#35D07F'],
676
+ iconPos: ['before'],
677
+ badgeText: [''],
678
+ badgeStyle: ['soft'],
679
+ badgeColor: ['#2a8455'],
680
+ }),
681
+ background: this.fb.group({
682
+ color: ['#122033'],
683
+ gradient: [''],
684
+ alpha: [0],
685
+ blur: [0],
686
+ }),
687
+ animation: this.fb.group({
688
+ type: ['pulse'],
689
+ durationMs: [800],
690
+ trigger: ['onChange'],
691
+ repeat: ['once'],
692
+ delayMs: [0],
693
+ }),
694
+ tooltip: this.fb.group({
695
+ text: [''],
696
+ position: ['bottom'],
697
+ bgColor: ['#2E3142'],
698
+ delayMs: [300],
699
+ }),
700
+ cssClass: [''],
701
+ inlineStyle: [''],
702
+ });
703
+ this.effectsForm.valueChanges.pipe(auditTime(200), takeUntil(this.destroy$)).subscribe((formValue) => {
704
+ const value = { scope: this.scope, ...formValue };
705
+ this.valueChange.emit(value);
706
+ });
707
+ if (this._value)
708
+ this.patchForm(this._value);
709
+ }
710
+ patchForm(v) {
711
+ this.effectsForm.patchValue(v, { emitEvent: false });
712
+ }
713
+ setTab(tab) {
714
+ this.activeTab = tab;
715
+ }
716
+ applyPreset(key) {
717
+ const preset = DEFAULT_EFFECT_PRESETS[key];
718
+ if (!preset)
719
+ return;
720
+ const merged = { ...preset, scope: this.scope };
721
+ this.patchForm(merged);
722
+ this.valueChange.emit(merged);
723
+ }
724
+ onApply() {
725
+ this.apply.emit();
726
+ }
727
+ onReset() {
728
+ this.effectsForm.reset();
729
+ this.reset.emit();
730
+ }
731
+ ngOnDestroy() {
732
+ this.destroy$.next();
733
+ this.destroy$.complete();
734
+ }
735
+ // Typed subgroup getters for strict template type checking
736
+ get estiloGroup() { return this.effectsForm.get('estilo'); }
737
+ get layoutGroup() { return this.effectsForm.get('layout'); }
738
+ get iconBadgeGroup() { return this.effectsForm.get('iconBadge'); }
739
+ get backgroundGroup() { return this.effectsForm.get('background'); }
740
+ get animationGroup() { return this.effectsForm.get('animation'); }
741
+ get tooltipGroup() { return this.effectsForm.get('tooltip'); }
742
+ // Safe access for template — avoids TS casts in templates
743
+ get formValue() {
744
+ const v = (this.effectsForm?.value || {});
745
+ return { scope: this.scope, ...v };
746
+ }
747
+ // A11y: keyboard navigation for tabs
748
+ onTabsKeydown(event) {
749
+ if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight')
750
+ return;
751
+ event.preventDefault();
752
+ const idx = this.tabOrder.indexOf(this.activeTab);
753
+ const next = event.key === 'ArrowRight' ? (idx + 1) % this.tabOrder.length : (idx - 1 + this.tabOrder.length) % this.tabOrder.length;
754
+ this.activeTab = this.tabOrder[next];
755
+ }
756
+ onHoverPreview(over) {
757
+ this.isHovering = over;
758
+ }
759
+ // Preview helpers
760
+ computeTextStyle(v) {
761
+ const s = v?.estilo || {};
762
+ const size = s.fontScale ? `calc(1rem + ${s.fontScale * 0.1}rem)` : '1rem';
763
+ const transform = s.transform ?? 'none';
764
+ return {
765
+ color: s.color || null,
766
+ fontWeight: s.bold ? 600 : 400,
767
+ fontStyle: s.italic ? 'italic' : 'normal',
768
+ textDecoration: s.underline ? 'underline' : 'none',
769
+ opacity: s.opacity ?? 1,
770
+ fontSize: size,
771
+ textTransform: transform === 'uppercase'
772
+ ? 'uppercase'
773
+ : transform === 'lowercase'
774
+ ? 'lowercase'
775
+ : transform === 'capitalize'
776
+ ? 'capitalize'
777
+ : 'none',
778
+ };
779
+ }
780
+ computeCellStyle(v) {
781
+ const b = v?.background || {};
782
+ const ly = v?.layout || {};
783
+ const bg = b.gradient ? b.gradient : (b.color || 'transparent');
784
+ const alpha = (b.alpha ?? 0) / 100;
785
+ const bgWithAlpha = b.color ? `color-mix(in srgb, ${b.color} ${100 - alpha * 100}%, transparent)` : bg;
786
+ const borderColor = ly.borderColor || 'transparent';
787
+ const borderWidth = (ly.borderWidth ?? 0) + 'px';
788
+ const borderStyle = ly.border === 'none' ? 'none' : `${borderWidth} solid ${borderColor}`;
789
+ const base = {
790
+ background: bgWithAlpha,
791
+ filter: b.blur ? `blur(${b.blur}px)` : 'none',
792
+ padding: (ly.padding ?? 6) + 'px',
793
+ boxShadow: ly.elevation ? `0 ${Math.min(ly.elevation, 24)}px ${Math.min(ly.elevation, 24)}px rgba(0,0,0,.25)` : 'none',
794
+ justifyContent: ly.align === 'center' ? 'center' : ly.align === 'end' ? 'flex-end' : 'flex-start',
795
+ };
796
+ if (ly.border === 'all')
797
+ base.border = borderStyle;
798
+ if (ly.border === 'left')
799
+ base.borderLeft = borderStyle;
800
+ if (ly.border === 'right')
801
+ base.borderRight = borderStyle;
802
+ if (ly.border === 'top')
803
+ base.borderTop = borderStyle;
804
+ if (ly.border === 'bottom')
805
+ base.borderBottom = borderStyle;
806
+ return base;
807
+ }
808
+ computeCellClass(v) {
809
+ const anim = v?.animation;
810
+ const triggerHover = anim?.trigger === 'onHover';
811
+ const triggerAppear = anim?.trigger === 'onAppear';
812
+ const triggerChange = anim?.trigger === 'onChange';
813
+ const repeatClass = anim?.repeat === 'loop' ? 'anim--loop' : 'anim--once';
814
+ const active = (triggerHover && this.isHovering) ||
815
+ triggerAppear ||
816
+ triggerChange; // we don’t track changes here, preview is always ‘changed’
817
+ return {
818
+ [`anim--${anim?.type}`]: !!anim?.type && active,
819
+ [repeatClass]: !!anim?.type && active,
820
+ 'icon--overlay': v?.iconBadge?.icon && v?.iconBadge?.iconPos === 'overlay',
821
+ };
822
+ }
823
+ badgeBackground(v) {
824
+ const s = v?.iconBadge;
825
+ if (!s?.badgeText)
826
+ return null;
827
+ if (s.badgeStyle === 'solid')
828
+ return s.badgeColor || '#444';
829
+ if (s.badgeStyle === 'soft')
830
+ return `linear-gradient(180deg, ${s.badgeColor || '#444'}, #00000055)`;
831
+ if (s.badgeStyle === 'outline')
832
+ return 'transparent';
833
+ return null;
834
+ }
835
+ badgeBorder(v) {
836
+ const s = v?.iconBadge;
837
+ return s?.badgeStyle === 'outline' ? s.badgeColor || '#777' : '#0000';
838
+ }
839
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RuleEffectsPanelComponent, deps: [{ token: i1.FormBuilder }, { token: EffectRegistryService }], target: i0.ɵɵFactoryTarget.Component });
840
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.1.4", type: RuleEffectsPanelComponent, isStandalone: true, selector: "praxis-rule-effects-panel", inputs: { scope: "scope", value: "value" }, outputs: { valueChange: "valueChange", apply: "apply", reset: "reset" }, ngImport: i0, template: "<div class=\"rulefx\">\n <header class=\"rulefx__header\">\n <h3 class=\"rulefx__title\">{{ t('panel.title') }}</h3>\n <p class=\"rulefx__subtitle\">{{ t('panel.subtitle') }}</p>\n <div class=\"rulefx__actions\">\n <button mat-stroked-button [matMenuTriggerFor]=\"presetsMenu\" [attr.aria-label]=\"t('presets.label')\">\n <mat-icon>bookmarks</mat-icon>\n {{ t('presets.label') }}\n </button>\n <mat-menu #presetsMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyPreset('aprovado')\"><mat-icon>check_circle</mat-icon> Aprovado</button>\n <button mat-menu-item (click)=\"applyPreset('alerta')\"><mat-icon>warning</mat-icon> Alerta</button>\n <button mat-menu-item (click)=\"applyPreset('erro')\"><mat-icon>error</mat-icon> Erro</button>\n <button mat-menu-item (click)=\"applyPreset('info')\"><mat-icon>info</mat-icon> Info</button>\n </mat-menu>\n <button mat-flat-button color=\"primary\" (click)=\"onApply()\" [attr.aria-label]=\"t('actions.apply')\" [matTooltip]=\"t('actions.apply')\" matTooltipPosition=\"below\">\n <mat-icon>done</mat-icon>\n {{ t('actions.apply') }}\n </button>\n <button mat-stroked-button (click)=\"onReset()\" [attr.aria-label]=\"t('actions.reset')\" [matTooltip]=\"t('actions.reset')\" matTooltipPosition=\"below\">\n <mat-icon>restart_alt</mat-icon>\n {{ t('actions.reset') }}\n </button>\n </div>\n </header>\n\n <!-- Ribbon com seis categorias -->\n <nav\n class=\"rulefx__ribbon\"\n aria-label=\"Categorias de efeitos\"\n role=\"tablist\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'estilo'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'estilo'\"\n [attr.tabindex]=\"activeTab === 'estilo' ? 0 : -1\"\n (click)=\"setTab('estilo')\"\n [matTooltip]=\"t('tabs.estilo')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">text_format</span>\n <span>{{ t('tabs.estilo') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'layout'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'layout'\"\n [attr.tabindex]=\"activeTab === 'layout' ? 0 : -1\"\n (click)=\"setTab('layout')\"\n [matTooltip]=\"t('tabs.layout')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">view_quilt</span>\n <span>{{ t('tabs.layout') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'icone'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'icone'\"\n [attr.tabindex]=\"activeTab === 'icone' ? 0 : -1\"\n (click)=\"setTab('icone')\"\n [matTooltip]=\"t('tabs.icone')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">verified</span>\n <span>{{ t('tabs.icone') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'fundo'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'fundo'\"\n [attr.tabindex]=\"activeTab === 'fundo' ? 0 : -1\"\n (click)=\"setTab('fundo')\"\n [matTooltip]=\"t('tabs.fundo')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">gradient</span>\n <span>{{ t('tabs.fundo') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'animacao'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'animacao'\"\n [attr.tabindex]=\"activeTab === 'animacao' ? 0 : -1\"\n (click)=\"setTab('animacao')\"\n [matTooltip]=\"t('tabs.animacao')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">animation</span>\n <span>{{ t('tabs.animacao') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'tooltip'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tooltip'\"\n [attr.tabindex]=\"activeTab === 'tooltip' ? 0 : -1\"\n (click)=\"setTab('tooltip')\"\n [matTooltip]=\"t('tabs.tooltip')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">info</span>\n <span>{{ t('tabs.tooltip') }}</span>\n </button>\n </nav>\n\n <!-- Quickbar contextual -->\n <section class=\"rulefx__quickbar\" aria-live=\"polite\" *ngIf=\"effectsForm\">\n <ng-container [ngSwitch]=\"activeTab\">\n <ng-container *ngSwitchCase=\"'estilo'\">\n <praxis-effects-estilo-editor [group]=\"estiloGroup\"></praxis-effects-estilo-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'layout'\">\n <praxis-effects-layout-editor [group]=\"layoutGroup\"></praxis-effects-layout-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'icone'\">\n <praxis-effects-icone-badge-editor [group]=\"iconBadgeGroup\"></praxis-effects-icone-badge-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fundo'\">\n <praxis-effects-fundo-editor [group]=\"backgroundGroup\"></praxis-effects-fundo-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'animacao'\">\n <praxis-effects-animacao-editor [group]=\"animationGroup\"></praxis-effects-animacao-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'tooltip'\">\n <praxis-effects-tooltip-editor [group]=\"tooltipGroup\"></praxis-effects-tooltip-editor>\n </ng-container>\n </ng-container>\n </section>\n\n <!-- Pr\u00E9-visualiza\u00E7\u00E3o e se\u00E7\u00E3o avan\u00E7ada -->\n <section class=\"rulefx__body\">\n <div class=\"rulefx__preview\">\n <div class=\"preview__title\">{{ t('preview.title') }}</div>\n\n <div\n class=\"preview__cell\"\n [ngStyle]=\"computeCellStyle(formValue)\"\n [ngClass]=\"computeCellClass(formValue)\"\n (mouseenter)=\"onHoverPreview(true)\"\n (mouseleave)=\"onHoverPreview(false)\"\n >\n <span\n *ngIf=\"formValue.iconBadge?.icon && formValue.iconBadge?.iconPos === 'before'\"\n class=\"material-icons preview__icon\"\n [style.color]=\"formValue.iconBadge?.iconColor\"\n >\n {{ formValue.iconBadge?.icon }}\n </span>\n\n <span class=\"preview__text\" [ngStyle]=\"computeTextStyle(formValue)\">\n Joana Silva \u2014 Ativo desde 2019\n </span>\n\n <span\n *ngIf=\"formValue.iconBadge?.badgeText\"\n class=\"preview__badge\"\n [ngStyle]=\"{ 'background': badgeBackground(formValue), 'border-color': badgeBorder(formValue) }\"\n >\n {{ formValue.iconBadge?.badgeText }}\n </span>\n\n <span\n *ngIf=\"formValue.iconBadge?.icon && formValue.iconBadge?.iconPos === 'after'\"\n class=\"material-icons preview__icon\"\n [style.color]=\"formValue.iconBadge?.iconColor\"\n >\n {{ formValue.iconBadge?.icon }}\n </span>\n </div>\n\n <p class=\"preview__hint\">{{ t('preview.hint') }}</p>\n </div>\n\n <div class=\"rulefx__advanced\">\n <details class=\"advanced__section\">\n <summary>{{ t('advanced.title') }}</summary>\n <div class=\"advanced__grid\" [formGroup]=\"effectsForm\">\n <label class=\"textctl\">\n <span>{{ t('advanced.description') }}</span>\n <input type=\"text\" formControlName=\"description\" placeholder=\"ex.: Destacar pre\u00E7os altos\" />\n </label>\n <label class=\"textctl\">\n <span>Classe CSS</span>\n <input type=\"text\" formControlName=\"cssClass\" placeholder=\"ex.: praxis-cell--alert\" />\n </label>\n <label class=\"textctl\">\n <span>Estilo inline</span>\n <input type=\"text\" formControlName=\"inlineStyle\" placeholder=\"ex.: text-shadow: 0 0 8px rgba(0,255,163,.5)\" />\n </label>\n </div>\n </details>\n </div>\n </section>\n</div>\n", styles: [".rulefx{background:linear-gradient(180deg,#171b24,#1e2431);border-radius:14px;color:#e7ecf6;border:1px solid rgba(255,255,255,.08);box-shadow:0 6px 24px #00000047;padding:12px}.rulefx__header{display:grid;grid-template-columns:1fr auto;align-items:center;gap:8px;margin-bottom:8px}.rulefx__title{margin:0;font-size:1.05rem}.rulefx__subtitle{margin:0;opacity:.75;font-size:.9rem}.rulefx__actions{display:inline-flex;gap:8px;align-items:center}.rulefx__ribbon{display:flex;gap:6px;padding:8px;border-radius:10px;background:linear-gradient(180deg,#202636,#1c2230);margin-bottom:8px}.ribbon__tab{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:10px;background:transparent;color:#e7ecf6;cursor:pointer;border:none}.ribbon__tab.is-active{background:linear-gradient(180deg,#2a3550,#243149);box-shadow:inset 0 0 0 1px #ffffff0a}.rulefx__quickbar{border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:10px;background:linear-gradient(180deg,#202637,#1c2230);margin-bottom:10px}.rulefx__body{display:grid;grid-template-columns:1fr 320px;gap:12px}.rulefx__preview{border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:12px;background:linear-gradient(180deg,#202637,#1c2230)}.preview__title{font-weight:600;margin-bottom:8px}.preview__cell{display:inline-flex;align-items:center;gap:8px;padding:10px 12px;border-radius:12px;background:#35d07f14;border:1px solid rgba(53,208,127,.25)}.preview__icon{font-size:18px;line-height:1}.preview__badge{font-size:.75rem;border-radius:999px;padding:2px 8px;border:1px solid transparent}.preview__hint{opacity:.7;font-size:.85rem;margin:8px 0 0}.rulefx__advanced .advanced__grid{display:grid;grid-template-columns:1fr;gap:8px}.rulefx__advanced .textctl{display:grid;gap:6px}.rulefx__advanced input[type=text]{background:#151a24;color:#e7ecf6;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.anim--once{animation-iteration-count:1}.anim--loop{animation-iteration-count:infinite}.anim--pulse{animation-name:pfxPulse;animation-duration:.8s;animation-timing-function:ease-in-out}.anim--blink{animation-name:pfxBlink;animation-duration:.7s}.anim--grow{animation-name:pfxGrow;animation-duration:.4s}.anim--fade{animation-name:pfxFade;animation-duration:.6s}.anim--slide-in{animation-name:pfxSlideIn;animation-duration:.3s}@keyframes pfxPulse{0%{transform:scale(1)}50%{transform:scale(1.03)}to{transform:scale(1)}}@keyframes pfxBlink{0%,49%{opacity:1}50%,to{opacity:.25}}@keyframes pfxGrow{0%{transform:scale(.96)}to{transform:scale(1)}}@keyframes pfxFade{0%{opacity:0}to{opacity:1}}@keyframes pfxSlideIn{0%{transform:translateY(6px);opacity:0}to{transform:translateY(0);opacity:1}}.icon--overlay{position:relative}.icon--overlay .preview__icon{position:absolute;left:6px;top:6px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3$1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i3$1.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i3$1.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "ngmodule", type: MatFormFieldModule }, { kind: "ngmodule", type: MatInputModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i4$1.MatButton, selector: " button[matButton], a[matButton], button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button], a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button] ", inputs: ["matButton"], exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i5.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i6$1.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i7.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i7.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i7.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatButtonToggleModule }, { kind: "component", type: EstiloEditorComponent, selector: "praxis-effects-estilo-editor", inputs: ["group"] }, { kind: "component", type: LayoutEditorComponent, selector: "praxis-effects-layout-editor", inputs: ["group"] }, { kind: "component", type: IconeBadgeEditorComponent, selector: "praxis-effects-icone-badge-editor", inputs: ["group"] }, { kind: "component", type: FundoEditorComponent, selector: "praxis-effects-fundo-editor", inputs: ["group"] }, { kind: "component", type: AnimacaoEditorComponent, selector: "praxis-effects-animacao-editor", inputs: ["group"] }, { kind: "component", type: TooltipEditorComponent, selector: "praxis-effects-tooltip-editor", inputs: ["group"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
841
+ }
842
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: RuleEffectsPanelComponent, decorators: [{
843
+ type: Component,
844
+ args: [{ selector: 'praxis-rule-effects-panel', standalone: true, imports: [
845
+ CommonModule,
846
+ ReactiveFormsModule,
847
+ MatFormFieldModule,
848
+ MatInputModule,
849
+ MatButtonModule,
850
+ MatIconModule,
851
+ MatTooltipModule,
852
+ MatMenuModule,
853
+ MatButtonToggleModule,
854
+ EstiloEditorComponent,
855
+ LayoutEditorComponent,
856
+ IconeBadgeEditorComponent,
857
+ FundoEditorComponent,
858
+ AnimacaoEditorComponent,
859
+ TooltipEditorComponent,
860
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"rulefx\">\n <header class=\"rulefx__header\">\n <h3 class=\"rulefx__title\">{{ t('panel.title') }}</h3>\n <p class=\"rulefx__subtitle\">{{ t('panel.subtitle') }}</p>\n <div class=\"rulefx__actions\">\n <button mat-stroked-button [matMenuTriggerFor]=\"presetsMenu\" [attr.aria-label]=\"t('presets.label')\">\n <mat-icon>bookmarks</mat-icon>\n {{ t('presets.label') }}\n </button>\n <mat-menu #presetsMenu=\"matMenu\">\n <button mat-menu-item (click)=\"applyPreset('aprovado')\"><mat-icon>check_circle</mat-icon> Aprovado</button>\n <button mat-menu-item (click)=\"applyPreset('alerta')\"><mat-icon>warning</mat-icon> Alerta</button>\n <button mat-menu-item (click)=\"applyPreset('erro')\"><mat-icon>error</mat-icon> Erro</button>\n <button mat-menu-item (click)=\"applyPreset('info')\"><mat-icon>info</mat-icon> Info</button>\n </mat-menu>\n <button mat-flat-button color=\"primary\" (click)=\"onApply()\" [attr.aria-label]=\"t('actions.apply')\" [matTooltip]=\"t('actions.apply')\" matTooltipPosition=\"below\">\n <mat-icon>done</mat-icon>\n {{ t('actions.apply') }}\n </button>\n <button mat-stroked-button (click)=\"onReset()\" [attr.aria-label]=\"t('actions.reset')\" [matTooltip]=\"t('actions.reset')\" matTooltipPosition=\"below\">\n <mat-icon>restart_alt</mat-icon>\n {{ t('actions.reset') }}\n </button>\n </div>\n </header>\n\n <!-- Ribbon com seis categorias -->\n <nav\n class=\"rulefx__ribbon\"\n aria-label=\"Categorias de efeitos\"\n role=\"tablist\"\n (keydown)=\"onTabsKeydown($event)\"\n >\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'estilo'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'estilo'\"\n [attr.tabindex]=\"activeTab === 'estilo' ? 0 : -1\"\n (click)=\"setTab('estilo')\"\n [matTooltip]=\"t('tabs.estilo')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">text_format</span>\n <span>{{ t('tabs.estilo') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'layout'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'layout'\"\n [attr.tabindex]=\"activeTab === 'layout' ? 0 : -1\"\n (click)=\"setTab('layout')\"\n [matTooltip]=\"t('tabs.layout')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">view_quilt</span>\n <span>{{ t('tabs.layout') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'icone'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'icone'\"\n [attr.tabindex]=\"activeTab === 'icone' ? 0 : -1\"\n (click)=\"setTab('icone')\"\n [matTooltip]=\"t('tabs.icone')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">verified</span>\n <span>{{ t('tabs.icone') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'fundo'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'fundo'\"\n [attr.tabindex]=\"activeTab === 'fundo' ? 0 : -1\"\n (click)=\"setTab('fundo')\"\n [matTooltip]=\"t('tabs.fundo')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">gradient</span>\n <span>{{ t('tabs.fundo') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'animacao'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'animacao'\"\n [attr.tabindex]=\"activeTab === 'animacao' ? 0 : -1\"\n (click)=\"setTab('animacao')\"\n [matTooltip]=\"t('tabs.animacao')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">animation</span>\n <span>{{ t('tabs.animacao') }}</span>\n </button>\n <button\n class=\"ribbon__tab\"\n [class.is-active]=\"activeTab === 'tooltip'\"\n type=\"button\"\n role=\"tab\"\n [attr.aria-selected]=\"activeTab === 'tooltip'\"\n [attr.tabindex]=\"activeTab === 'tooltip' ? 0 : -1\"\n (click)=\"setTab('tooltip')\"\n [matTooltip]=\"t('tabs.tooltip')\"\n matTooltipPosition=\"below\"\n >\n <span class=\"material-icons\">info</span>\n <span>{{ t('tabs.tooltip') }}</span>\n </button>\n </nav>\n\n <!-- Quickbar contextual -->\n <section class=\"rulefx__quickbar\" aria-live=\"polite\" *ngIf=\"effectsForm\">\n <ng-container [ngSwitch]=\"activeTab\">\n <ng-container *ngSwitchCase=\"'estilo'\">\n <praxis-effects-estilo-editor [group]=\"estiloGroup\"></praxis-effects-estilo-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'layout'\">\n <praxis-effects-layout-editor [group]=\"layoutGroup\"></praxis-effects-layout-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'icone'\">\n <praxis-effects-icone-badge-editor [group]=\"iconBadgeGroup\"></praxis-effects-icone-badge-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fundo'\">\n <praxis-effects-fundo-editor [group]=\"backgroundGroup\"></praxis-effects-fundo-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'animacao'\">\n <praxis-effects-animacao-editor [group]=\"animationGroup\"></praxis-effects-animacao-editor>\n </ng-container>\n <ng-container *ngSwitchCase=\"'tooltip'\">\n <praxis-effects-tooltip-editor [group]=\"tooltipGroup\"></praxis-effects-tooltip-editor>\n </ng-container>\n </ng-container>\n </section>\n\n <!-- Pr\u00E9-visualiza\u00E7\u00E3o e se\u00E7\u00E3o avan\u00E7ada -->\n <section class=\"rulefx__body\">\n <div class=\"rulefx__preview\">\n <div class=\"preview__title\">{{ t('preview.title') }}</div>\n\n <div\n class=\"preview__cell\"\n [ngStyle]=\"computeCellStyle(formValue)\"\n [ngClass]=\"computeCellClass(formValue)\"\n (mouseenter)=\"onHoverPreview(true)\"\n (mouseleave)=\"onHoverPreview(false)\"\n >\n <span\n *ngIf=\"formValue.iconBadge?.icon && formValue.iconBadge?.iconPos === 'before'\"\n class=\"material-icons preview__icon\"\n [style.color]=\"formValue.iconBadge?.iconColor\"\n >\n {{ formValue.iconBadge?.icon }}\n </span>\n\n <span class=\"preview__text\" [ngStyle]=\"computeTextStyle(formValue)\">\n Joana Silva \u2014 Ativo desde 2019\n </span>\n\n <span\n *ngIf=\"formValue.iconBadge?.badgeText\"\n class=\"preview__badge\"\n [ngStyle]=\"{ 'background': badgeBackground(formValue), 'border-color': badgeBorder(formValue) }\"\n >\n {{ formValue.iconBadge?.badgeText }}\n </span>\n\n <span\n *ngIf=\"formValue.iconBadge?.icon && formValue.iconBadge?.iconPos === 'after'\"\n class=\"material-icons preview__icon\"\n [style.color]=\"formValue.iconBadge?.iconColor\"\n >\n {{ formValue.iconBadge?.icon }}\n </span>\n </div>\n\n <p class=\"preview__hint\">{{ t('preview.hint') }}</p>\n </div>\n\n <div class=\"rulefx__advanced\">\n <details class=\"advanced__section\">\n <summary>{{ t('advanced.title') }}</summary>\n <div class=\"advanced__grid\" [formGroup]=\"effectsForm\">\n <label class=\"textctl\">\n <span>{{ t('advanced.description') }}</span>\n <input type=\"text\" formControlName=\"description\" placeholder=\"ex.: Destacar pre\u00E7os altos\" />\n </label>\n <label class=\"textctl\">\n <span>Classe CSS</span>\n <input type=\"text\" formControlName=\"cssClass\" placeholder=\"ex.: praxis-cell--alert\" />\n </label>\n <label class=\"textctl\">\n <span>Estilo inline</span>\n <input type=\"text\" formControlName=\"inlineStyle\" placeholder=\"ex.: text-shadow: 0 0 8px rgba(0,255,163,.5)\" />\n </label>\n </div>\n </details>\n </div>\n </section>\n</div>\n", styles: [".rulefx{background:linear-gradient(180deg,#171b24,#1e2431);border-radius:14px;color:#e7ecf6;border:1px solid rgba(255,255,255,.08);box-shadow:0 6px 24px #00000047;padding:12px}.rulefx__header{display:grid;grid-template-columns:1fr auto;align-items:center;gap:8px;margin-bottom:8px}.rulefx__title{margin:0;font-size:1.05rem}.rulefx__subtitle{margin:0;opacity:.75;font-size:.9rem}.rulefx__actions{display:inline-flex;gap:8px;align-items:center}.rulefx__ribbon{display:flex;gap:6px;padding:8px;border-radius:10px;background:linear-gradient(180deg,#202636,#1c2230);margin-bottom:8px}.ribbon__tab{display:flex;align-items:center;gap:8px;padding:8px 10px;border-radius:10px;background:transparent;color:#e7ecf6;cursor:pointer;border:none}.ribbon__tab.is-active{background:linear-gradient(180deg,#2a3550,#243149);box-shadow:inset 0 0 0 1px #ffffff0a}.rulefx__quickbar{border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:10px;background:linear-gradient(180deg,#202637,#1c2230);margin-bottom:10px}.rulefx__body{display:grid;grid-template-columns:1fr 320px;gap:12px}.rulefx__preview{border:1px solid rgba(255,255,255,.08);border-radius:12px;padding:12px;background:linear-gradient(180deg,#202637,#1c2230)}.preview__title{font-weight:600;margin-bottom:8px}.preview__cell{display:inline-flex;align-items:center;gap:8px;padding:10px 12px;border-radius:12px;background:#35d07f14;border:1px solid rgba(53,208,127,.25)}.preview__icon{font-size:18px;line-height:1}.preview__badge{font-size:.75rem;border-radius:999px;padding:2px 8px;border:1px solid transparent}.preview__hint{opacity:.7;font-size:.85rem;margin:8px 0 0}.rulefx__advanced .advanced__grid{display:grid;grid-template-columns:1fr;gap:8px}.rulefx__advanced .textctl{display:grid;gap:6px}.rulefx__advanced input[type=text]{background:#151a24;color:#e7ecf6;border:1px solid rgba(255,255,255,.08);border-radius:8px;padding:8px 10px}.anim--once{animation-iteration-count:1}.anim--loop{animation-iteration-count:infinite}.anim--pulse{animation-name:pfxPulse;animation-duration:.8s;animation-timing-function:ease-in-out}.anim--blink{animation-name:pfxBlink;animation-duration:.7s}.anim--grow{animation-name:pfxGrow;animation-duration:.4s}.anim--fade{animation-name:pfxFade;animation-duration:.6s}.anim--slide-in{animation-name:pfxSlideIn;animation-duration:.3s}@keyframes pfxPulse{0%{transform:scale(1)}50%{transform:scale(1.03)}to{transform:scale(1)}}@keyframes pfxBlink{0%,49%{opacity:1}50%,to{opacity:.25}}@keyframes pfxGrow{0%{transform:scale(.96)}to{transform:scale(1)}}@keyframes pfxFade{0%{opacity:0}to{opacity:1}}@keyframes pfxSlideIn{0%{transform:translateY(6px);opacity:0}to{transform:translateY(0);opacity:1}}.icon--overlay{position:relative}.icon--overlay .preview__icon{position:absolute;left:6px;top:6px}\n"] }]
861
+ }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: EffectRegistryService }], propDecorators: { scope: [{
862
+ type: Input
863
+ }], value: [{
864
+ type: Input
865
+ }], valueChange: [{
866
+ type: Output
867
+ }], apply: [{
868
+ type: Output
869
+ }], reset: [{
870
+ type: Output
871
+ }] } });
872
+
873
+ function toCellClassAndStyle(effect) {
874
+ const classList = [];
875
+ const style = {};
876
+ // Advanced class and inline style
877
+ if (effect.cssClass)
878
+ classList.push(effect.cssClass);
879
+ if (effect.inlineStyle)
880
+ style['cssText'] = effect.inlineStyle;
881
+ // Background
882
+ const b = effect.background || {};
883
+ const ly = effect.layout || {};
884
+ const bg = b.gradient ? b.gradient : (b.color || 'transparent');
885
+ const alpha = (b.alpha ?? 0) / 100;
886
+ const bgWithAlpha = b.color ? `color-mix(in srgb, ${b.color} ${100 - alpha * 100}%, transparent)` : bg;
887
+ style['background'] = bgWithAlpha;
888
+ if (b.blur)
889
+ style['filter'] = `blur(${b.blur}px)`;
890
+ // Layout
891
+ if (ly.padding != null)
892
+ style['padding'] = `${ly.padding}px`;
893
+ if (ly.elevation)
894
+ style['box-shadow'] = `0 ${Math.min(ly.elevation, 24)}px ${Math.min(ly.elevation, 24)}px rgba(0,0,0,.25)`;
895
+ if (ly.align)
896
+ style['justify-content'] = ly.align === 'center' ? 'center' : ly.align === 'end' ? 'flex-end' : 'flex-start';
897
+ const borderColor = ly.borderColor || 'transparent';
898
+ const borderWidth = (ly.borderWidth ?? 0) + 'px';
899
+ const borderStyle = ly.border === 'none' ? 'none' : `${borderWidth} solid ${borderColor}`;
900
+ switch (ly.border) {
901
+ case 'all':
902
+ style['border'] = borderStyle;
903
+ break;
904
+ case 'left':
905
+ style['border-left'] = borderStyle;
906
+ break;
907
+ case 'right':
908
+ style['border-right'] = borderStyle;
909
+ break;
910
+ case 'top':
911
+ style['border-top'] = borderStyle;
912
+ break;
913
+ case 'bottom':
914
+ style['border-bottom'] = borderStyle;
915
+ break;
916
+ }
917
+ // Text (estilo)
918
+ const s = effect.estilo || {};
919
+ if (s.color)
920
+ style['color'] = s.color;
921
+ if (s.bgColor)
922
+ style['background-color'] = s.bgColor;
923
+ if (s.bold)
924
+ style['font-weight'] = '600';
925
+ if (s.italic)
926
+ style['font-style'] = 'italic';
927
+ if (s.underline)
928
+ style['text-decoration'] = 'underline';
929
+ if (s.opacity != null)
930
+ style['opacity'] = String(s.opacity);
931
+ if (s.transform)
932
+ style['text-transform'] = s.transform;
933
+ if (s.fontScale && s.fontScale !== 0)
934
+ style['font-size'] = `calc(1rem + ${s.fontScale * 0.1}rem)`;
935
+ // Icon overlay class
936
+ if (effect.iconBadge?.iconPos === 'overlay')
937
+ classList.push('icon--overlay');
938
+ // Animation
939
+ const anim = effect.animation;
940
+ if (anim?.type) {
941
+ classList.push(`anim--${anim.type}`);
942
+ classList.push(anim.repeat === 'loop' ? 'anim--loop' : 'anim--once');
943
+ if (anim.durationMs)
944
+ style['animation-duration'] = `${anim.durationMs}ms`;
945
+ if (anim.delayMs)
946
+ style['animation-delay'] = `${anim.delayMs}ms`;
947
+ }
948
+ return { classList, style };
949
+ }
950
+
951
+ /**
952
+ * Generated bundle index. Do not edit.
953
+ */
954
+
955
+ export { AnimacaoEditorComponent, DEFAULT_EFFECT_PRESETS, EffectRegistryService, EstiloEditorComponent, FundoEditorComponent, IconeBadgeEditorComponent, LayoutEditorComponent, RuleEffectsPanelComponent, TooltipEditorComponent, toCellClassAndStyle };
956
+ //# sourceMappingURL=praxisui-table-rule-builder.mjs.map