@mosaicoo/kanban 0.2.0 → 0.3.0

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.
@@ -1,26 +1,380 @@
1
1
  import * as i0 from '@angular/core';
2
- import { signal, computed, Injectable, inject, ChangeDetectionStrategy, Component, input, output, effect, untracked } from '@angular/core';
3
- import * as i7 from '@angular/material/button';
4
- import { MatButtonModule } from '@angular/material/button';
5
- import * as i1$1 from '@angular/material/tabs';
2
+ import { input, ChangeDetectionStrategy, Component, output, signal, viewChild, computed, Injectable, inject, effect, untracked } from '@angular/core';
3
+ import * as i1 from '@angular/material/menu';
4
+ import { MatMenuModule } from '@angular/material/menu';
5
+ import * as i1$2 from '@angular/material/tabs';
6
6
  import { MatTabsModule } from '@angular/material/tabs';
7
7
  import { MosKanbanBoard } from '@mosaicoo/kanban/ui';
8
+ import { CdkDropList, CdkDrag, CdkDragHandle } from '@angular/cdk/drag-drop';
8
9
  import { NgTemplateOutlet } from '@angular/common';
9
- import * as i1 from '@angular/forms';
10
+ import * as i1$1 from '@angular/forms';
10
11
  import { FormsModule } from '@angular/forms';
11
- import * as i6 from '@angular/material/checkbox';
12
- import { MatCheckboxModule } from '@angular/material/checkbox';
13
- import * as i2 from '@angular/material/form-field';
14
- import { MatFormFieldModule } from '@angular/material/form-field';
15
- import * as i3 from '@angular/material/input';
16
- import { MatInputModule } from '@angular/material/input';
17
- import * as i4 from '@angular/material/select';
18
- import { MatSelectModule } from '@angular/material/select';
19
- import * as i5 from '@angular/material/slide-toggle';
20
- import { MatSlideToggleModule } from '@angular/material/slide-toggle';
21
12
  import { validateConfig, createBoard } from '@mosaicoo/kanban/core';
22
- import * as i7$1 from '@angular/material/expansion';
23
- import { MatExpansionModule } from '@angular/material/expansion';
13
+
14
+ class MkbIcon {
15
+ name = input.required(...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
16
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbIcon, deps: [], target: i0.ɵɵFactoryTarget.Component });
17
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MkbIcon, isStandalone: true, selector: "mkb-icon", inputs: { name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: true, transformFunction: null } }, ngImport: i0, template: `
18
+ <svg
19
+ viewBox="0 0 24 24"
20
+ fill="none"
21
+ stroke="currentColor"
22
+ stroke-width="1.8"
23
+ stroke-linecap="round"
24
+ stroke-linejoin="round"
25
+ aria-hidden="true"
26
+ focusable="false"
27
+ >
28
+ @switch (name()) {
29
+ @case ('drag') {
30
+ <circle cx="9" cy="5" r="1.6" fill="currentColor" stroke="none" />
31
+ <circle cx="15" cy="5" r="1.6" fill="currentColor" stroke="none" />
32
+ <circle cx="9" cy="12" r="1.6" fill="currentColor" stroke="none" />
33
+ <circle cx="15" cy="12" r="1.6" fill="currentColor" stroke="none" />
34
+ <circle cx="9" cy="19" r="1.6" fill="currentColor" stroke="none" />
35
+ <circle cx="15" cy="19" r="1.6" fill="currentColor" stroke="none" />
36
+ }
37
+ @case ('up') {
38
+ <path d="M6 14.5 12 8.5l6 6" />
39
+ }
40
+ @case ('down') {
41
+ <path d="M6 9.5 12 15.5l6-6" />
42
+ }
43
+ @case ('close') {
44
+ <path d="M6.5 6.5 17.5 17.5M17.5 6.5 6.5 17.5" />
45
+ }
46
+ @case ('add') {
47
+ <path d="M12 5v14M5 12h14" />
48
+ }
49
+ @case ('upload') {
50
+ <path d="M12 15.5V4M8 7.5 12 3.5l4 4" />
51
+ <path d="M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" />
52
+ }
53
+ @case ('download') {
54
+ <path d="M12 3.5V15M8 11l4 4 4-4" />
55
+ <path d="M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" />
56
+ }
57
+ @case ('expand') {
58
+ <path d="M7 10l5 5 5-5" />
59
+ }
60
+ @case ('trash') {
61
+ <path d="M4 7h16M10 7V4.5h4V7M6.5 7l1 13h9l1-13" />
62
+ }
63
+ @case ('check-circle') {
64
+ <circle cx="12" cy="12" r="8.5" />
65
+ <path d="M8.5 12.2l2.6 2.6 4.6-5.2" />
66
+ }
67
+ @case ('alert-circle') {
68
+ <circle cx="12" cy="12" r="8.5" />
69
+ <path d="M12 7.6v5" />
70
+ <circle cx="12" cy="16" r="1" fill="currentColor" stroke="none" />
71
+ }
72
+ @case ('eye') {
73
+ <path d="M2.5 12S6 6.2 12 6.2 21.5 12 21.5 12 18 17.8 12 17.8 2.5 12 2.5 12Z" />
74
+ <circle cx="12" cy="12" r="3" />
75
+ }
76
+ @case ('rows') {
77
+ <rect x="3.2" y="4.5" width="17.6" height="15" rx="2.4" />
78
+ <path d="M3.2 9.5h17.6M3.2 14.5h17.6" />
79
+ }
80
+ @case ('reset') {
81
+ <path d="M4 11a8 8 0 1 0 2.6-5.3" />
82
+ <path d="M3.6 4.2v4.6h4.6" />
83
+ }
84
+ }
85
+ </svg>
86
+ `, isInline: true, styles: [":host{display:inline-flex;width:1.25em;height:1.25em;flex:none}svg{width:100%;height:100%;display:block}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
87
+ }
88
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbIcon, decorators: [{
89
+ type: Component,
90
+ args: [{ selector: 'mkb-icon', changeDetection: ChangeDetectionStrategy.OnPush, template: `
91
+ <svg
92
+ viewBox="0 0 24 24"
93
+ fill="none"
94
+ stroke="currentColor"
95
+ stroke-width="1.8"
96
+ stroke-linecap="round"
97
+ stroke-linejoin="round"
98
+ aria-hidden="true"
99
+ focusable="false"
100
+ >
101
+ @switch (name()) {
102
+ @case ('drag') {
103
+ <circle cx="9" cy="5" r="1.6" fill="currentColor" stroke="none" />
104
+ <circle cx="15" cy="5" r="1.6" fill="currentColor" stroke="none" />
105
+ <circle cx="9" cy="12" r="1.6" fill="currentColor" stroke="none" />
106
+ <circle cx="15" cy="12" r="1.6" fill="currentColor" stroke="none" />
107
+ <circle cx="9" cy="19" r="1.6" fill="currentColor" stroke="none" />
108
+ <circle cx="15" cy="19" r="1.6" fill="currentColor" stroke="none" />
109
+ }
110
+ @case ('up') {
111
+ <path d="M6 14.5 12 8.5l6 6" />
112
+ }
113
+ @case ('down') {
114
+ <path d="M6 9.5 12 15.5l6-6" />
115
+ }
116
+ @case ('close') {
117
+ <path d="M6.5 6.5 17.5 17.5M17.5 6.5 6.5 17.5" />
118
+ }
119
+ @case ('add') {
120
+ <path d="M12 5v14M5 12h14" />
121
+ }
122
+ @case ('upload') {
123
+ <path d="M12 15.5V4M8 7.5 12 3.5l4 4" />
124
+ <path d="M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" />
125
+ }
126
+ @case ('download') {
127
+ <path d="M12 3.5V15M8 11l4 4 4-4" />
128
+ <path d="M4 16v3a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-3" />
129
+ }
130
+ @case ('expand') {
131
+ <path d="M7 10l5 5 5-5" />
132
+ }
133
+ @case ('trash') {
134
+ <path d="M4 7h16M10 7V4.5h4V7M6.5 7l1 13h9l1-13" />
135
+ }
136
+ @case ('check-circle') {
137
+ <circle cx="12" cy="12" r="8.5" />
138
+ <path d="M8.5 12.2l2.6 2.6 4.6-5.2" />
139
+ }
140
+ @case ('alert-circle') {
141
+ <circle cx="12" cy="12" r="8.5" />
142
+ <path d="M12 7.6v5" />
143
+ <circle cx="12" cy="16" r="1" fill="currentColor" stroke="none" />
144
+ }
145
+ @case ('eye') {
146
+ <path d="M2.5 12S6 6.2 12 6.2 21.5 12 21.5 12 18 17.8 12 17.8 2.5 12 2.5 12Z" />
147
+ <circle cx="12" cy="12" r="3" />
148
+ }
149
+ @case ('rows') {
150
+ <rect x="3.2" y="4.5" width="17.6" height="15" rx="2.4" />
151
+ <path d="M3.2 9.5h17.6M3.2 14.5h17.6" />
152
+ }
153
+ @case ('reset') {
154
+ <path d="M4 11a8 8 0 1 0 2.6-5.3" />
155
+ <path d="M3.6 4.2v4.6h4.6" />
156
+ }
157
+ }
158
+ </svg>
159
+ `, styles: [":host{display:inline-flex;width:1.25em;height:1.25em;flex:none}svg{width:100%;height:100%;display:block}\n"] }]
160
+ }], propDecorators: { name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: true }] }] } });
161
+
162
+ /** Comparação tolerante: sem caixa e sem acento (ex.: "icone" acha "Ícone"). */
163
+ function normalize(text) {
164
+ return text
165
+ .toLocaleLowerCase('pt-BR')
166
+ .normalize('NFD')
167
+ .replace(/[\u0300-\u036f]/g, '')
168
+ .trim();
169
+ }
170
+ /**
171
+ * Combobox do Designer — gatilho no padrão de campo do DS + painel de menu
172
+ * (§11 dos Componentes: superfície card, itens navitem, selecionado em
173
+ * primary-container).
174
+ *
175
+ * Existe porque `<select>` nativo abre uma lista renderizada pelo SISTEMA,
176
+ * que não aceita estilo: dentro do DS ela destoa por completo. Serve tanto
177
+ * seleção única quanto múltipla; no múltiplo o painel não fecha a cada
178
+ * escolha e o estado é booleano por item (nada de array em [ngModel], que
179
+ * realimentava a detecção de mudanças).
180
+ */
181
+ class MkbCombo {
182
+ label = input.required(...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
183
+ options = input.required(...(ngDevMode ? [{ debugName: "options" }] : /* istanbul ignore next */ []));
184
+ /** Valor único (string) ou lista de valores quando `multiple`. */
185
+ value = input(null, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
186
+ multiple = input(false, ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
187
+ /** Texto exibido quando nada está selecionado. */
188
+ placeholder = input('', ...(ngDevMode ? [{ debugName: "placeholder" }] : /* istanbul ignore next */ []));
189
+ valueChange = output();
190
+ valuesChange = output();
191
+ /** Acima deste número a varredura visual perde para a digitação: o painel
192
+ * ganha campo de filtro (convenção de ~10 itens). */
193
+ static SEARCH_THRESHOLD = 10;
194
+ open = signal(false, ...(ngDevMode ? [{ debugName: "open" }] : /* istanbul ignore next */ []));
195
+ filter = signal('', ...(ngDevMode ? [{ debugName: "filter" }] : /* istanbul ignore next */ []));
196
+ search = viewChild('search', ...(ngDevMode ? [{ debugName: "search" }] : /* istanbul ignore next */ []));
197
+ searchable = computed(() => this.options().length > MkbCombo.SEARCH_THRESHOLD, ...(ngDevMode ? [{ debugName: "searchable" }] : /* istanbul ignore next */ []));
198
+ /** Opções após o filtro — sem acento e sem caixa, como se espera em pt-BR. */
199
+ visible = computed(() => {
200
+ const query = normalize(this.filter());
201
+ if (!query)
202
+ return this.options();
203
+ return this.options().filter((o) => normalize(o.label).includes(query));
204
+ }, ...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
205
+ onOpen() {
206
+ this.open.set(true);
207
+ // o menu foca o primeiro item; com filtro, o cursor deve ir para a busca
208
+ if (this.searchable()) {
209
+ setTimeout(() => this.search()?.nativeElement.focus());
210
+ }
211
+ }
212
+ onClose() {
213
+ this.open.set(false);
214
+ this.filter.set('');
215
+ }
216
+ /** Deixa passar o que o MENU precisa tratar (fechar, navegar, escolher) e
217
+ * segura o resto, senão o typeahead do Material rouba a digitação. */
218
+ onSearchKeydown(event) {
219
+ const passthrough = event.key === 'Escape' ||
220
+ event.key === 'Enter' ||
221
+ event.key === 'Tab' ||
222
+ event.key.startsWith('Arrow');
223
+ if (!passthrough)
224
+ event.stopPropagation();
225
+ }
226
+ selected = computed(() => {
227
+ const v = this.value();
228
+ if (v == null || v === '')
229
+ return [];
230
+ return typeof v === 'string' ? [v] : [...v];
231
+ }, ...(ngDevMode ? [{ debugName: "selected" }] : /* istanbul ignore next */ []));
232
+ isSelected(value) {
233
+ return this.selected().includes(value);
234
+ }
235
+ /** Resumo no gatilho: rótulo da opção, lista curta ou contagem. */
236
+ summary() {
237
+ const selected = this.selected();
238
+ if (!selected.length)
239
+ return '';
240
+ const labels = selected.map((v) => this.options().find((o) => o.value === v)?.label ?? v);
241
+ if (!this.multiple())
242
+ return labels[0] ?? '';
243
+ return labels.length <= 2 ? labels.join(', ') : `${labels.length} selecionados`;
244
+ }
245
+ pick(value, event) {
246
+ if (!this.multiple()) {
247
+ this.valueChange.emit(value);
248
+ return;
249
+ }
250
+ // múltiplo: mantém o painel aberto para várias escolhas seguidas
251
+ event.stopPropagation();
252
+ const current = this.selected();
253
+ this.valuesChange.emit(current.includes(value) ? current.filter((v) => v !== value) : [...current, value]);
254
+ }
255
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbCombo, deps: [], target: i0.ɵɵFactoryTarget.Component });
256
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MkbCombo, isStandalone: true, selector: "mkb-combo", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: true, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", isSignal: true, isRequired: true, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { valueChange: "valueChange", valuesChange: "valuesChange" }, viewQueries: [{ propertyName: "search", first: true, predicate: ["search"], descendants: true, isSignal: true }], ngImport: i0, template: `
257
+ <div class="mkbd-field mkbd-field-combo" [class.mkbd-combo-open]="open()">
258
+ <span class="mkbd-label">{{ label() }}</span>
259
+ <button
260
+ type="button"
261
+ class="mkbd-combo-btn"
262
+ [matMenuTriggerFor]="menu"
263
+ (menuOpened)="onOpen()"
264
+ (menuClosed)="onClose()"
265
+ [attr.aria-label]="label()"
266
+ >
267
+ <span class="mkbd-combo-value" [class.mkbd-combo-empty]="!summary()">
268
+ {{ summary() || placeholder() }}
269
+ </span>
270
+ <mkb-icon name="expand" class="mkbd-combo-caret" />
271
+ </button>
272
+ </div>
273
+
274
+ <mat-menu #menu="matMenu" class="mkbd-menu">
275
+ @if (searchable()) {
276
+ <div class="mkbd-menu-search" (click)="$event.stopPropagation()">
277
+ <input
278
+ #search
279
+ type="text"
280
+ [value]="filter()"
281
+ (input)="filter.set($any($event.target).value)"
282
+ (keydown)="onSearchKeydown($event)"
283
+ [attr.aria-label]="'Filtrar ' + label()"
284
+ [placeholder]="'Filtrar ' + options().length + ' opções…'"
285
+ />
286
+ @if (filter()) {
287
+ <span class="mkbd-menu-count">{{ visible().length }}/{{ options().length }}</span>
288
+ }
289
+ </div>
290
+ }
291
+
292
+ @for (opt of visible(); track opt.value) {
293
+ <button
294
+ mat-menu-item
295
+ type="button"
296
+ [role]="multiple() ? 'menuitemcheckbox' : 'menuitemradio'"
297
+ [attr.aria-checked]="isSelected(opt.value)"
298
+ [class.mkbd-menu-item-active]="isSelected(opt.value)"
299
+ (click)="pick(opt.value, $event)"
300
+ >
301
+ @if (multiple()) {
302
+ <span
303
+ class="mkbd-menu-check"
304
+ [class.mkbd-menu-check-on]="isSelected(opt.value)"
305
+ aria-hidden="true"
306
+ ></span>
307
+ }
308
+ {{ opt.label }}
309
+ </button>
310
+ } @empty {
311
+ <p class="mkbd-menu-empty">Nenhuma opção corresponde a “{{ filter() }}”.</p>
312
+ }
313
+ </mat-menu>
314
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block;min-width:0}:host .mkbd-field{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1.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: i1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
315
+ }
316
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbCombo, decorators: [{
317
+ type: Component,
318
+ args: [{ selector: 'mkb-combo', changeDetection: ChangeDetectionStrategy.OnPush, imports: [MatMenuModule, MkbIcon], template: `
319
+ <div class="mkbd-field mkbd-field-combo" [class.mkbd-combo-open]="open()">
320
+ <span class="mkbd-label">{{ label() }}</span>
321
+ <button
322
+ type="button"
323
+ class="mkbd-combo-btn"
324
+ [matMenuTriggerFor]="menu"
325
+ (menuOpened)="onOpen()"
326
+ (menuClosed)="onClose()"
327
+ [attr.aria-label]="label()"
328
+ >
329
+ <span class="mkbd-combo-value" [class.mkbd-combo-empty]="!summary()">
330
+ {{ summary() || placeholder() }}
331
+ </span>
332
+ <mkb-icon name="expand" class="mkbd-combo-caret" />
333
+ </button>
334
+ </div>
335
+
336
+ <mat-menu #menu="matMenu" class="mkbd-menu">
337
+ @if (searchable()) {
338
+ <div class="mkbd-menu-search" (click)="$event.stopPropagation()">
339
+ <input
340
+ #search
341
+ type="text"
342
+ [value]="filter()"
343
+ (input)="filter.set($any($event.target).value)"
344
+ (keydown)="onSearchKeydown($event)"
345
+ [attr.aria-label]="'Filtrar ' + label()"
346
+ [placeholder]="'Filtrar ' + options().length + ' opções…'"
347
+ />
348
+ @if (filter()) {
349
+ <span class="mkbd-menu-count">{{ visible().length }}/{{ options().length }}</span>
350
+ }
351
+ </div>
352
+ }
353
+
354
+ @for (opt of visible(); track opt.value) {
355
+ <button
356
+ mat-menu-item
357
+ type="button"
358
+ [role]="multiple() ? 'menuitemcheckbox' : 'menuitemradio'"
359
+ [attr.aria-checked]="isSelected(opt.value)"
360
+ [class.mkbd-menu-item-active]="isSelected(opt.value)"
361
+ (click)="pick(opt.value, $event)"
362
+ >
363
+ @if (multiple()) {
364
+ <span
365
+ class="mkbd-menu-check"
366
+ [class.mkbd-menu-check-on]="isSelected(opt.value)"
367
+ aria-hidden="true"
368
+ ></span>
369
+ }
370
+ {{ opt.label }}
371
+ </button>
372
+ } @empty {
373
+ <p class="mkbd-menu-empty">Nenhuma opção corresponde a “{{ filter() }}”.</p>
374
+ }
375
+ </mat-menu>
376
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block;min-width:0}:host .mkbd-field{width:100%}\n"] }]
377
+ }], propDecorators: { label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: true }] }], options: [{ type: i0.Input, args: [{ isSignal: true, alias: "options", required: true }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], valueChange: [{ type: i0.Output, args: ["valueChange"] }], valuesChange: [{ type: i0.Output, args: ["valuesChange"] }], search: [{ type: i0.ViewChild, args: ['search', { isSignal: true }] }] } });
24
378
 
25
379
  /** Espelho de styles/kanban-tokens.css (defaults de fábrica). */
26
380
  const TOKEN_GROUPS = [
@@ -411,10 +765,24 @@ function blankBlock(type) {
411
765
  class MkbCardEditor {
412
766
  store = inject(DesignerStore);
413
767
  config = this.store.config;
414
- blockTypes = BLOCK_TYPE_LABELS;
415
- tones = ['', 'neutral', 'info', 'success', 'warning', 'danger'];
768
+ blockTypeOptions = BLOCK_TYPE_LABELS.map((t) => ({
769
+ value: t.type,
770
+ label: t.label,
771
+ }));
772
+ toneOptions = ['', 'neutral', 'info', 'success', 'warning', 'danger'].map((tone) => ({ value: tone, label: tone || '—' }));
416
773
  allCapabilities = ['check', 'reorder', 'move-across', 'action'];
417
- newType = 'text';
774
+ /** Opções por descritor de campo — memoizadas: os defs são constantes do
775
+ * módulo, então a referência da lista precisa ser estável entre ciclos. */
776
+ selectOptionsCache = new WeakMap();
777
+ selectOptions(def) {
778
+ let options = this.selectOptionsCache.get(def);
779
+ if (!options) {
780
+ options = (def.options ?? []).map((opt) => ({ value: opt, label: opt || '—' }));
781
+ this.selectOptionsCache.set(def, options);
782
+ }
783
+ return options;
784
+ }
785
+ newType = signal('text', ...(ngDevMode ? [{ debugName: "newType" }] : /* istanbul ignore next */ []));
418
786
  selectedPath = signal(null, ...(ngDevMode ? [{ debugName: "selectedPath" }] : /* istanbul ignore next */ []));
419
787
  jsonError = signal(null, ...(ngDevMode ? [{ debugName: "jsonError" }] : /* istanbul ignore next */ []));
420
788
  selectedBlock = computed(() => {
@@ -468,7 +836,7 @@ class MkbCardEditor {
468
836
  return parent?.type === 'row' ? parent.blocks : null;
469
837
  }
470
838
  add(intoSelectedRow) {
471
- const block = blankBlock(this.newType);
839
+ const block = blankBlock(this.newType());
472
840
  const rowPath = intoSelectedRow ? this.selectedPath() : null;
473
841
  this.store.update((d) => {
474
842
  d.card ??= { blocks: [] };
@@ -495,6 +863,13 @@ class MkbCardEditor {
495
863
  });
496
864
  this.selectedPath.set(null);
497
865
  }
866
+ /** Arraste (CDK): `parentPath` vazio = lista raiz; [i] = filhos da row i. */
867
+ dropBlock(parentPath, event) {
868
+ const { previousIndex, currentIndex } = event;
869
+ if (previousIndex === currentIndex)
870
+ return;
871
+ this.move([...parentPath, previousIndex], currentIndex - previousIndex);
872
+ }
498
873
  move(path, delta) {
499
874
  const index = path[path.length - 1];
500
875
  const target = index + delta;
@@ -664,153 +1039,217 @@ class MkbCardEditor {
664
1039
  }
665
1040
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbCardEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
666
1041
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MkbCardEditor, isStandalone: true, selector: "mkb-card-editor", ngImport: i0, template: `
667
- <div class="mkbd-row">
668
- <mat-slide-toggle
669
- [ngModel]="config().card?.dragHandle ?? false"
670
- (ngModelChange)="setDragHandle($event)"
671
- >
672
- Arrastar só pela alça ⠿
673
- </mat-slide-toggle>
1042
+ <div class="mkbd-options">
1043
+ <label class="mkbd-switch mkbd-switch-boxed">
1044
+ <input
1045
+ type="checkbox"
1046
+ [ngModel]="config().card?.dragHandle ?? false"
1047
+ (ngModelChange)="setDragHandle($event)"
1048
+ />
1049
+ Arrastar só pela alça
1050
+ </label>
674
1051
  </div>
675
1052
 
676
- <h3 class="mkbd-h">Blocos do cartão</h3>
677
- <div class="mkbd-tree" role="tree" aria-label="Blocos do cartão">
1053
+ <div class="mkbd-section">
1054
+ <span class="mkbd-overline">Blocos do cartão</span>
1055
+ <span class="mkbd-count">{{ blocks().length }}</span>
1056
+ </div>
1057
+
1058
+ <!-- Listas AUTÔNOMAS (sem cdkDropListGroup): a raiz e os filhos de cada
1059
+ linha reordenam dentro de si. Conectar ancestral com descendente foi
1060
+ o que quebrou o DnD do board no spike D0. -->
1061
+ <div
1062
+ class="mkbd-rows"
1063
+ role="tree"
1064
+ aria-label="Blocos do cartão"
1065
+ cdkDropList
1066
+ (cdkDropListDropped)="dropBlock([], $event)"
1067
+ >
678
1068
  @for (block of blocks(); track $index; let i = $index) {
679
- <ng-container
680
- *ngTemplateOutlet="blockRow; context: { block, path: [i], siblings: blocks().length }"
681
- />
1069
+ <!-- cdkDrag e a alça ficam AQUI, no mesmo template do cdkDropList:
1070
+ as queries do CDK seguem a posição de DECLARAÇÃO, então um
1071
+ ng-template com outlet não é registrado pela lista. Só o CORPO
1072
+ da linha continua fatorado no template. -->
1073
+ <div
1074
+ class="mkbd-row mkbd-block"
1075
+ role="treeitem"
1076
+ tabindex="0"
1077
+ cdkDrag
1078
+ cdkDragLockAxis="y"
1079
+ [class.mkbd-row-selected]="isSelected([i])"
1080
+ [attr.aria-selected]="isSelected([i])"
1081
+ (click)="select([i])"
1082
+ (keydown.enter)="select([i])"
1083
+ >
1084
+ <span class="mkbd-handle" cdkDragHandle [attr.aria-label]="'Arrastar bloco ' + typeLabel(block.type)">
1085
+ <mkb-icon name="drag" />
1086
+ </span>
1087
+ <ng-container
1088
+ *ngTemplateOutlet="blockBody; context: { block, path: [i], siblings: blocks().length }"
1089
+ />
1090
+ </div>
1091
+
682
1092
  @if (block.type === 'row') {
683
- @for (child of rowChildren(block); track $index; let j = $index) {
684
- <ng-container
685
- *ngTemplateOutlet="
686
- blockRow;
687
- context: { block: child, path: [i, j], siblings: rowChildren(block).length }
688
- "
689
- />
690
- }
1093
+ <div
1094
+ class="mkbd-rows mkbd-nested"
1095
+ cdkDropList
1096
+ (cdkDropListDropped)="dropBlock([i], $event)"
1097
+ >
1098
+ @for (child of rowChildren(block); track $index; let j = $index) {
1099
+ <div
1100
+ class="mkbd-row mkbd-block mkbd-block-child"
1101
+ role="treeitem"
1102
+ tabindex="0"
1103
+ cdkDrag
1104
+ cdkDragLockAxis="y"
1105
+ [class.mkbd-row-selected]="isSelected([i, j])"
1106
+ [attr.aria-selected]="isSelected([i, j])"
1107
+ (click)="select([i, j])"
1108
+ (keydown.enter)="select([i, j])"
1109
+ >
1110
+ <span class="mkbd-handle" cdkDragHandle [attr.aria-label]="'Arrastar bloco ' + typeLabel(child.type)">
1111
+ <mkb-icon name="drag" />
1112
+ </span>
1113
+ <ng-container
1114
+ *ngTemplateOutlet="
1115
+ blockBody;
1116
+ context: { block: child, path: [i, j], siblings: rowChildren(block).length }
1117
+ "
1118
+ />
1119
+ </div>
1120
+ }
1121
+ </div>
691
1122
  }
692
1123
  } @empty {
693
1124
  <p class="mkbd-hint">Nenhum bloco — o cartão renderiza vazio. Adicione abaixo.</p>
694
1125
  }
695
1126
  </div>
696
1127
 
697
- <ng-template #blockRow let-block="block" let-path="path" let-siblings="siblings">
698
- <div
699
- class="mkbd-node"
700
- role="treeitem"
701
- tabindex="0"
702
- [class.mkbd-node-child]="path.length > 1"
703
- [class.mkbd-node-selected]="isSelected(path)"
704
- [attr.aria-selected]="isSelected(path)"
705
- (click)="select(path)"
706
- (keydown.enter)="select(path)"
707
- >
708
- <span class="mkbd-node-type">{{ typeLabel(block.type) }}</span>
709
- <span class="mkbd-node-summary">{{ summary(block) }}</span>
710
- <span class="mkbd-spacer"></span>
711
- <button matIconButton type="button" (click)="move(path, -1); $event.stopPropagation()" [disabled]="path[path.length - 1] === 0" aria-label="Subir bloco">↑</button>
712
- <button matIconButton type="button" (click)="move(path, 1); $event.stopPropagation()" [disabled]="path[path.length - 1] === siblings - 1" aria-label="Descer bloco">↓</button>
713
- <button matIconButton type="button" (click)="remove(path); $event.stopPropagation()" aria-label="Remover bloco">✕</button>
1128
+ <!-- Corpo da linha (sem a alça): compartilhado pela raiz e pelos filhos. -->
1129
+ <ng-template #blockBody let-block="block" let-path="path" let-siblings="siblings">
1130
+ <span class="mkbd-block-type">{{ typeLabel(block.type) }}</span>
1131
+ <span class="mkbd-block-summary">{{ summary(block) }}</span>
1132
+ <div class="mkbd-row-ctrls">
1133
+ <button
1134
+ class="mkbd-icon-btn"
1135
+ type="button"
1136
+ (click)="move(path, -1); $event.stopPropagation()"
1137
+ [disabled]="path[path.length - 1] === 0"
1138
+ aria-label="Mover para cima"
1139
+ >
1140
+ <mkb-icon name="up" />
1141
+ </button>
1142
+ <button
1143
+ class="mkbd-icon-btn"
1144
+ type="button"
1145
+ (click)="move(path, 1); $event.stopPropagation()"
1146
+ [disabled]="path[path.length - 1] === siblings - 1"
1147
+ aria-label="Mover para baixo"
1148
+ >
1149
+ <mkb-icon name="down" />
1150
+ </button>
1151
+ <button
1152
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1153
+ type="button"
1154
+ (click)="remove(path); $event.stopPropagation()"
1155
+ aria-label="Remover bloco"
1156
+ >
1157
+ <mkb-icon name="close" />
1158
+ </button>
714
1159
  </div>
715
1160
  </ng-template>
716
1161
 
717
- <div class="mkbd-row mkbd-mt">
718
- <mat-form-field appearance="outline" class="mkbd-slim">
719
- <mat-label>Tipo do novo bloco</mat-label>
720
- <mat-select [(ngModel)]="newType">
721
- @for (t of blockTypes; track t.type) {
722
- <mat-option [value]="t.type">{{ t.label }}</mat-option>
723
- }
724
- </mat-select>
725
- </mat-form-field>
726
- <button matButton type="button" (click)="add(false)">+ Adicionar</button>
1162
+ <div class="mkbd-new-block">
1163
+ <mkb-combo
1164
+ label="Tipo do novo bloco"
1165
+ [options]="blockTypeOptions"
1166
+ [value]="newType()"
1167
+ (valueChange)="newType.set($any($event))"
1168
+ />
1169
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="add(false)">
1170
+ <mkb-icon name="add" />
1171
+ Adicionar
1172
+ </button>
727
1173
  @if (selectedIsRow()) {
728
- <button matButton type="button" (click)="add(true)">+ Adicionar DENTRO da linha</button>
1174
+ <button class="mkbd-btn mkbd-btn-tonal" type="button" (click)="add(true)">
1175
+ <mkb-icon name="add" />
1176
+ Dentro da linha
1177
+ </button>
729
1178
  }
730
1179
  </div>
731
1180
 
732
1181
  @if (selectedBlock(); as block) {
733
- <h3 class="mkbd-h">Propriedades — {{ typeLabel(block.type) }}</h3>
734
- <div class="mkbd-props">
1182
+ <div class="mkbd-section">
1183
+ <span class="mkbd-overline">Propriedades · {{ typeLabel(block.type) }}</span>
1184
+ </div>
1185
+ <div class="mkbd-stack">
735
1186
  @for (def of fieldsFor(block.type); track def.key) {
736
1187
  @switch (def.kind) {
737
1188
  @case ('text') {
738
- <mat-form-field appearance="outline" class="mkbd-slim">
739
- <mat-label>{{ def.label }}</mat-label>
1189
+ <label class="mkbd-field">
1190
+ <span class="mkbd-label">{{ def.label }}</span>
740
1191
  <input
741
- matInput
742
1192
  [ngModel]="str(block, def.key)"
743
1193
  (ngModelChange)="setProp(def.key, $event || undefined)"
1194
+ [placeholder]="def.hint ?? ''"
744
1195
  />
745
- @if (def.hint) { <mat-hint>{{ def.hint }}</mat-hint> }
746
- </mat-form-field>
1196
+ </label>
747
1197
  }
748
1198
  @case ('number') {
749
- <mat-form-field appearance="outline" class="mkbd-tiny">
750
- <mat-label>{{ def.label }}</mat-label>
1199
+ <label class="mkbd-field mkbd-field-sm">
1200
+ <span class="mkbd-label">{{ def.label }}</span>
751
1201
  <input
752
- matInput
753
1202
  type="number"
754
1203
  [ngModel]="num(block, def.key)"
755
1204
  (ngModelChange)="setProp(def.key, $event === null || $event === '' ? undefined : +$event)"
756
1205
  />
757
- </mat-form-field>
1206
+ </label>
758
1207
  }
759
1208
  @case ('toggle') {
760
- <mat-slide-toggle
761
- [ngModel]="bool(block, def.key)"
762
- (ngModelChange)="setProp(def.key, $event || undefined)"
763
- >
1209
+ <label class="mkbd-switch mkbd-switch-boxed">
1210
+ <input
1211
+ type="checkbox"
1212
+ [ngModel]="bool(block, def.key)"
1213
+ (ngModelChange)="setProp(def.key, $event || undefined)"
1214
+ />
764
1215
  {{ def.label }}
765
- </mat-slide-toggle>
1216
+ </label>
766
1217
  }
767
1218
  @case ('select') {
768
- <mat-form-field appearance="outline" class="mkbd-slim">
769
- <mat-label>{{ def.label }}</mat-label>
770
- <mat-select
771
- [ngModel]="str(block, def.key)"
772
- (ngModelChange)="setProp(def.key, $event || undefined)"
773
- >
774
- @for (opt of def.options; track opt) {
775
- <mat-option [value]="opt">{{ opt || '—' }}</mat-option>
776
- }
777
- </mat-select>
778
- </mat-form-field>
1219
+ <mkb-combo
1220
+ [label]="def.label"
1221
+ [options]="selectOptions(def)"
1222
+ [value]="str(block, def.key)"
1223
+ (valueChange)="setProp(def.key, $event || undefined)"
1224
+ />
779
1225
  }
780
1226
  @case ('csv') {
781
- <mat-form-field appearance="outline" class="mkbd-grow">
782
- <mat-label>{{ def.label }}</mat-label>
783
- <input
784
- matInput
785
- [ngModel]="csv(block, def.key)"
786
- (ngModelChange)="setCsv(def.key, $event)"
787
- />
788
- </mat-form-field>
1227
+ <label class="mkbd-field mkbd-field-grow">
1228
+ <span class="mkbd-label">{{ def.label }}</span>
1229
+ <input [ngModel]="csv(block, def.key)" (ngModelChange)="setCsv(def.key, $event)" />
1230
+ </label>
789
1231
  }
790
1232
  @case ('json') {
791
- <mat-form-field appearance="outline" class="mkbd-full">
792
- <mat-label>{{ def.label }}</mat-label>
793
- <textarea
794
- matInput
795
- rows="4"
796
- [value]="json(block, def.key)"
797
- (change)="setJson(def.key, $event)"
798
- ></textarea>
799
- <mat-hint [class.mkbd-error]="jsonError()">
800
- {{ jsonError() || def.hint || 'Objeto JSON; vazio remove.' }}
801
- </mat-hint>
802
- </mat-form-field>
1233
+ <label class="mkbd-field mkbd-field-area mkbd-field-full">
1234
+ <span class="mkbd-label">{{ def.label }}</span>
1235
+ <textarea rows="4" [value]="json(block, def.key)" (change)="setJson(def.key, $event)"></textarea>
1236
+ </label>
1237
+ <p class="mkbd-hint mkbd-full" [class.mkbd-error-text]="jsonError()">
1238
+ {{ jsonError() || def.hint || 'Objeto JSON; vazio remove.' }}
1239
+ </p>
803
1240
  }
804
1241
  @case ('capabilities') {
805
1242
  <div class="mkbd-caps">
806
- <span class="mkbd-caps-label">{{ def.label }}:</span>
1243
+ <span class="mkbd-caps-label">{{ def.label }}</span>
807
1244
  @for (cap of allCapabilities; track cap) {
808
- <mat-checkbox
809
- [ngModel]="hasCapability(block, cap)"
810
- (ngModelChange)="toggleCapability(cap, $event)"
811
- >
1245
+ <label class="mkbd-check">
1246
+ <input
1247
+ type="checkbox"
1248
+ [ngModel]="hasCapability(block, cap)"
1249
+ (ngModelChange)="toggleCapability(cap, $event)"
1250
+ />
812
1251
  {{ cap }}
813
- </mat-checkbox>
1252
+ </label>
814
1253
  }
815
1254
  </div>
816
1255
  }
@@ -818,240 +1257,313 @@ class MkbCardEditor {
818
1257
  <div class="mkbd-sub">
819
1258
  <span class="mkbd-caps-label">{{ def.label }}</span>
820
1259
  @for (fact of facts(block); track $index; let fi = $index) {
821
- <div class="mkbd-subrow">
822
- <mat-form-field appearance="outline" class="mkbd-tiny2">
823
- <mat-label>Campo</mat-label>
824
- <input matInput [ngModel]="fact.field" (ngModelChange)="setFact(fi, 'field', $event)" />
825
- </mat-form-field>
826
- <mat-form-field appearance="outline" class="mkbd-tiny2">
827
- <mat-label>Ícone</mat-label>
828
- <input matInput [ngModel]="fact.icon ?? ''" (ngModelChange)="setFact(fi, 'icon', $event || undefined)" />
829
- </mat-form-field>
830
- <mat-form-field appearance="outline" class="mkbd-tiny2">
831
- <mat-label>Rótulo</mat-label>
832
- <input matInput [ngModel]="fact.label ?? ''" (ngModelChange)="setFact(fi, 'label', $event || undefined)" />
833
- </mat-form-field>
834
- <mat-form-field appearance="outline" class="mkbd-tiny2">
835
- <mat-label>Prefixo</mat-label>
836
- <input matInput [ngModel]="fact.prefix ?? ''" (ngModelChange)="setFact(fi, 'prefix', $event || undefined)" />
837
- </mat-form-field>
838
- <mat-form-field appearance="outline" class="mkbd-tiny2">
839
- <mat-label>Sufixo</mat-label>
840
- <input matInput [ngModel]="fact.suffix ?? ''" (ngModelChange)="setFact(fi, 'suffix', $event || undefined)" />
841
- </mat-form-field>
842
- <button matIconButton type="button" (click)="removeListItem(def.key, fi)" aria-label="Remover fato">✕</button>
1260
+ <div class="mkbd-stack mkbd-subrow">
1261
+ <label class="mkbd-field mkbd-field-sm">
1262
+ <span class="mkbd-label">Campo</span>
1263
+ <input [ngModel]="fact.field" (ngModelChange)="setFact(fi, 'field', $event)" />
1264
+ </label>
1265
+ <label class="mkbd-field mkbd-field-sm">
1266
+ <span class="mkbd-label">Ícone</span>
1267
+ <input [ngModel]="fact.icon ?? ''" (ngModelChange)="setFact(fi, 'icon', $event || undefined)" />
1268
+ </label>
1269
+ <label class="mkbd-field mkbd-field-sm">
1270
+ <span class="mkbd-label">Rótulo</span>
1271
+ <input [ngModel]="fact.label ?? ''" (ngModelChange)="setFact(fi, 'label', $event || undefined)" />
1272
+ </label>
1273
+ <label class="mkbd-field mkbd-field-sm">
1274
+ <span class="mkbd-label">Prefixo</span>
1275
+ <input [ngModel]="fact.prefix ?? ''" (ngModelChange)="setFact(fi, 'prefix', $event || undefined)" />
1276
+ </label>
1277
+ <label class="mkbd-field mkbd-field-sm">
1278
+ <span class="mkbd-label">Sufixo</span>
1279
+ <input [ngModel]="fact.suffix ?? ''" (ngModelChange)="setFact(fi, 'suffix', $event || undefined)" />
1280
+ </label>
1281
+ <button
1282
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1283
+ type="button"
1284
+ (click)="removeListItem(def.key, fi)"
1285
+ aria-label="Remover fato"
1286
+ >
1287
+ <mkb-icon name="close" />
1288
+ </button>
843
1289
  </div>
844
1290
  }
845
- <button matButton type="button" (click)="addFact(def.key)">+ Fato</button>
1291
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addFact(def.key)">
1292
+ <mkb-icon name="add" />
1293
+ Fato
1294
+ </button>
846
1295
  </div>
847
1296
  }
848
1297
  @case ('card-actions') {
849
1298
  <div class="mkbd-sub">
850
1299
  <span class="mkbd-caps-label">{{ def.label }}</span>
851
1300
  @for (action of actions(block, def.key); track $index; let ai = $index) {
852
- <div class="mkbd-subrow">
853
- <mat-form-field appearance="outline" class="mkbd-tiny2">
854
- <mat-label>Id</mat-label>
855
- <input matInput [ngModel]="action.id" (ngModelChange)="setAction(def.key, ai, 'id', $event)" />
856
- </mat-form-field>
857
- <mat-form-field appearance="outline" class="mkbd-tiny2">
858
- <mat-label>Rótulo</mat-label>
859
- <input matInput [ngModel]="action.label" (ngModelChange)="setAction(def.key, ai, 'label', $event)" />
860
- </mat-form-field>
861
- <mat-form-field appearance="outline" class="mkbd-tiny2">
862
- <mat-label>Ícone</mat-label>
863
- <input matInput [ngModel]="action.icon ?? ''" (ngModelChange)="setAction(def.key, ai, 'icon', $event || undefined)" />
864
- </mat-form-field>
865
- <mat-form-field appearance="outline" class="mkbd-tiny2">
866
- <mat-label>Tom</mat-label>
867
- <mat-select [ngModel]="action.tone ?? ''" (ngModelChange)="setAction(def.key, ai, 'tone', $event || undefined)">
868
- @for (tone of tones; track tone) {
869
- <mat-option [value]="tone">{{ tone || '' }}</mat-option>
870
- }
871
- </mat-select>
872
- </mat-form-field>
873
- <mat-form-field appearance="outline" class="mkbd-tiny2">
874
- <mat-label>Só nas colunas</mat-label>
1301
+ <div class="mkbd-stack mkbd-subrow">
1302
+ <label class="mkbd-field mkbd-field-sm mkbd-field-mono">
1303
+ <span class="mkbd-label">Id</span>
1304
+ <input [ngModel]="action.id" (ngModelChange)="setAction(def.key, ai, 'id', $event)" />
1305
+ </label>
1306
+ <label class="mkbd-field mkbd-field-sm">
1307
+ <span class="mkbd-label">Rótulo</span>
1308
+ <input [ngModel]="action.label" (ngModelChange)="setAction(def.key, ai, 'label', $event)" />
1309
+ </label>
1310
+ <label class="mkbd-field mkbd-field-sm">
1311
+ <span class="mkbd-label">Ícone</span>
1312
+ <input [ngModel]="action.icon ?? ''" (ngModelChange)="setAction(def.key, ai, 'icon', $event || undefined)" />
1313
+ </label>
1314
+ <mkb-combo
1315
+ class="mkbd-field-sm"
1316
+ label="Tom"
1317
+ [options]="toneOptions"
1318
+ [value]="action.tone ?? ''"
1319
+ (valueChange)="setAction(def.key, ai, 'tone', $event || undefined)"
1320
+ />
1321
+ <label class="mkbd-field mkbd-field-sm">
1322
+ <span class="mkbd-label">Só nas colunas</span>
875
1323
  <input
876
- matInput
877
1324
  placeholder="col-a, col-b"
878
1325
  [ngModel]="whenColumns(action)"
879
1326
  (ngModelChange)="setActionWhen(def.key, ai, $event)"
880
1327
  />
881
- </mat-form-field>
882
- <button matIconButton type="button" (click)="removeListItem(def.key, ai)" aria-label="Remover ação">✕</button>
1328
+ </label>
1329
+ <button
1330
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1331
+ type="button"
1332
+ (click)="removeListItem(def.key, ai)"
1333
+ aria-label="Remover ação"
1334
+ >
1335
+ <mkb-icon name="close" />
1336
+ </button>
883
1337
  </div>
884
1338
  }
885
- <button matButton type="button" (click)="addAction(def.key)">+ Ação</button>
1339
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addAction(def.key)">
1340
+ <mkb-icon name="add" />
1341
+ Ação
1342
+ </button>
886
1343
  </div>
887
1344
  }
888
1345
  }
889
1346
  }
890
1347
  </div>
891
1348
  } @else {
892
- <p class="mkbd-hint mkbd-mt">Selecione um bloco para editar as propriedades.</p>
1349
+ <p class="mkbd-hint">Selecione um bloco para editar as propriedades.</p>
893
1350
  }
894
- `, isInline: true, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.mkbd-mt{margin-top:12px}.mkbd-tree{display:flex;flex-direction:column;gap:3px}.mkbd-node{display:flex;align-items:center;gap:8px;padding:3px 10px;border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px;cursor:pointer;background:var(--mkb-card-bg, #fff)}.mkbd-node:focus-visible{outline:2px solid var(--mkb-accent, #5e35b1);outline-offset:1px}.mkbd-node-child{margin-left:26px}.mkbd-node-selected{border-color:var(--mkb-accent, #5e35b1);box-shadow:inset 2px 0 0 var(--mkb-accent, #5e35b1)}.mkbd-node-type{font-size:12px;font-weight:600}.mkbd-node-summary{font-size:11.5px;color:var(--mkb-muted, #6f6a7c);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-spacer{flex:1}.mkbd-props{display:flex;flex-wrap:wrap;gap:18px 10px;align-items:center}.mkbd-slim{width:200px}.mkbd-tiny{width:110px}.mkbd-tiny2{width:130px}.mkbd-grow{flex:1;min-width:220px}.mkbd-full{width:100%}.mkbd-caps,.mkbd-sub{display:flex;flex-wrap:wrap;gap:10px;align-items:center;width:100%}.mkbd-sub{flex-direction:column;align-items:stretch;gap:4px}.mkbd-subrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.mkbd-caps-label{font-size:12px;color:var(--mkb-muted, #6f6a7c)}.mkbd-error{color:var(--mkb-danger, #b3261e)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.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.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1351
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-block{grid-template-columns:22px auto minmax(0,1fr) auto;cursor:pointer;border-left-color:var(--mkbd-border-strong)}.mkbd-block:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-block-child{border-left-color:var(--mkbd-primary-outline)}.mkbd-nested{margin-left:26px;margin-top:3px;gap:3px}.mkbd-handle[cdkDragHandle]{cursor:grab;touch-action:none}.mkbd-block.cdk-drag-preview{box-shadow:var(--elevation-3, 0 8px 30px rgba(20, 22, 30, .14));opacity:.96}.mkbd-block.cdk-drag-placeholder{opacity:.35}.cdk-drop-list-dragging .mkbd-block:not(.cdk-drag-placeholder){transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-block-type{font-size:12.5px;font-weight:500}.mkbd-block-summary{font:500 11.5px var(--mkbd-font-mono);color:var(--mkbd-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-new-block{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px}.mkbd-new-block .mkbd-field{width:230px}.mkbd-new-block .mkbd-field>.mkbd-label{background:var(--mkbd-canvas)}.mkbd-caps,.mkbd-sub{display:flex;flex-wrap:wrap;gap:10px;align-items:center;width:100%}.mkbd-sub{flex-direction:column;align-items:stretch;gap:8px}.mkbd-subrow{flex-wrap:wrap}.mkbd-caps-label{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-full{flex:1 0 100%;margin:0}.mkbd-error-text{color:var(--mkbd-error)}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MkbCombo, selector: "mkb-combo", inputs: ["label", "options", "value", "multiple", "placeholder"], outputs: ["valueChange", "valuesChange"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
895
1352
  }
896
1353
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbCardEditor, decorators: [{
897
1354
  type: Component,
898
- args: [{ selector: 'mkb-card-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
899
- NgTemplateOutlet,
900
- FormsModule,
901
- MatFormFieldModule,
902
- MatInputModule,
903
- MatSelectModule,
904
- MatSlideToggleModule,
905
- MatCheckboxModule,
906
- MatButtonModule,
907
- ], template: `
908
- <div class="mkbd-row">
909
- <mat-slide-toggle
910
- [ngModel]="config().card?.dragHandle ?? false"
911
- (ngModelChange)="setDragHandle($event)"
912
- >
913
- Arrastar só pela alça ⠿
914
- </mat-slide-toggle>
1355
+ args: [{ selector: 'mkb-card-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, FormsModule, CdkDropList, CdkDrag, CdkDragHandle, MkbCombo, MkbIcon], template: `
1356
+ <div class="mkbd-options">
1357
+ <label class="mkbd-switch mkbd-switch-boxed">
1358
+ <input
1359
+ type="checkbox"
1360
+ [ngModel]="config().card?.dragHandle ?? false"
1361
+ (ngModelChange)="setDragHandle($event)"
1362
+ />
1363
+ Arrastar só pela alça
1364
+ </label>
915
1365
  </div>
916
1366
 
917
- <h3 class="mkbd-h">Blocos do cartão</h3>
918
- <div class="mkbd-tree" role="tree" aria-label="Blocos do cartão">
1367
+ <div class="mkbd-section">
1368
+ <span class="mkbd-overline">Blocos do cartão</span>
1369
+ <span class="mkbd-count">{{ blocks().length }}</span>
1370
+ </div>
1371
+
1372
+ <!-- Listas AUTÔNOMAS (sem cdkDropListGroup): a raiz e os filhos de cada
1373
+ linha reordenam dentro de si. Conectar ancestral com descendente foi
1374
+ o que quebrou o DnD do board no spike D0. -->
1375
+ <div
1376
+ class="mkbd-rows"
1377
+ role="tree"
1378
+ aria-label="Blocos do cartão"
1379
+ cdkDropList
1380
+ (cdkDropListDropped)="dropBlock([], $event)"
1381
+ >
919
1382
  @for (block of blocks(); track $index; let i = $index) {
920
- <ng-container
921
- *ngTemplateOutlet="blockRow; context: { block, path: [i], siblings: blocks().length }"
922
- />
1383
+ <!-- cdkDrag e a alça ficam AQUI, no mesmo template do cdkDropList:
1384
+ as queries do CDK seguem a posição de DECLARAÇÃO, então um
1385
+ ng-template com outlet não é registrado pela lista. Só o CORPO
1386
+ da linha continua fatorado no template. -->
1387
+ <div
1388
+ class="mkbd-row mkbd-block"
1389
+ role="treeitem"
1390
+ tabindex="0"
1391
+ cdkDrag
1392
+ cdkDragLockAxis="y"
1393
+ [class.mkbd-row-selected]="isSelected([i])"
1394
+ [attr.aria-selected]="isSelected([i])"
1395
+ (click)="select([i])"
1396
+ (keydown.enter)="select([i])"
1397
+ >
1398
+ <span class="mkbd-handle" cdkDragHandle [attr.aria-label]="'Arrastar bloco ' + typeLabel(block.type)">
1399
+ <mkb-icon name="drag" />
1400
+ </span>
1401
+ <ng-container
1402
+ *ngTemplateOutlet="blockBody; context: { block, path: [i], siblings: blocks().length }"
1403
+ />
1404
+ </div>
1405
+
923
1406
  @if (block.type === 'row') {
924
- @for (child of rowChildren(block); track $index; let j = $index) {
925
- <ng-container
926
- *ngTemplateOutlet="
927
- blockRow;
928
- context: { block: child, path: [i, j], siblings: rowChildren(block).length }
929
- "
930
- />
931
- }
1407
+ <div
1408
+ class="mkbd-rows mkbd-nested"
1409
+ cdkDropList
1410
+ (cdkDropListDropped)="dropBlock([i], $event)"
1411
+ >
1412
+ @for (child of rowChildren(block); track $index; let j = $index) {
1413
+ <div
1414
+ class="mkbd-row mkbd-block mkbd-block-child"
1415
+ role="treeitem"
1416
+ tabindex="0"
1417
+ cdkDrag
1418
+ cdkDragLockAxis="y"
1419
+ [class.mkbd-row-selected]="isSelected([i, j])"
1420
+ [attr.aria-selected]="isSelected([i, j])"
1421
+ (click)="select([i, j])"
1422
+ (keydown.enter)="select([i, j])"
1423
+ >
1424
+ <span class="mkbd-handle" cdkDragHandle [attr.aria-label]="'Arrastar bloco ' + typeLabel(child.type)">
1425
+ <mkb-icon name="drag" />
1426
+ </span>
1427
+ <ng-container
1428
+ *ngTemplateOutlet="
1429
+ blockBody;
1430
+ context: { block: child, path: [i, j], siblings: rowChildren(block).length }
1431
+ "
1432
+ />
1433
+ </div>
1434
+ }
1435
+ </div>
932
1436
  }
933
1437
  } @empty {
934
1438
  <p class="mkbd-hint">Nenhum bloco — o cartão renderiza vazio. Adicione abaixo.</p>
935
1439
  }
936
1440
  </div>
937
1441
 
938
- <ng-template #blockRow let-block="block" let-path="path" let-siblings="siblings">
939
- <div
940
- class="mkbd-node"
941
- role="treeitem"
942
- tabindex="0"
943
- [class.mkbd-node-child]="path.length > 1"
944
- [class.mkbd-node-selected]="isSelected(path)"
945
- [attr.aria-selected]="isSelected(path)"
946
- (click)="select(path)"
947
- (keydown.enter)="select(path)"
948
- >
949
- <span class="mkbd-node-type">{{ typeLabel(block.type) }}</span>
950
- <span class="mkbd-node-summary">{{ summary(block) }}</span>
951
- <span class="mkbd-spacer"></span>
952
- <button matIconButton type="button" (click)="move(path, -1); $event.stopPropagation()" [disabled]="path[path.length - 1] === 0" aria-label="Subir bloco">↑</button>
953
- <button matIconButton type="button" (click)="move(path, 1); $event.stopPropagation()" [disabled]="path[path.length - 1] === siblings - 1" aria-label="Descer bloco">↓</button>
954
- <button matIconButton type="button" (click)="remove(path); $event.stopPropagation()" aria-label="Remover bloco">✕</button>
1442
+ <!-- Corpo da linha (sem a alça): compartilhado pela raiz e pelos filhos. -->
1443
+ <ng-template #blockBody let-block="block" let-path="path" let-siblings="siblings">
1444
+ <span class="mkbd-block-type">{{ typeLabel(block.type) }}</span>
1445
+ <span class="mkbd-block-summary">{{ summary(block) }}</span>
1446
+ <div class="mkbd-row-ctrls">
1447
+ <button
1448
+ class="mkbd-icon-btn"
1449
+ type="button"
1450
+ (click)="move(path, -1); $event.stopPropagation()"
1451
+ [disabled]="path[path.length - 1] === 0"
1452
+ aria-label="Mover para cima"
1453
+ >
1454
+ <mkb-icon name="up" />
1455
+ </button>
1456
+ <button
1457
+ class="mkbd-icon-btn"
1458
+ type="button"
1459
+ (click)="move(path, 1); $event.stopPropagation()"
1460
+ [disabled]="path[path.length - 1] === siblings - 1"
1461
+ aria-label="Mover para baixo"
1462
+ >
1463
+ <mkb-icon name="down" />
1464
+ </button>
1465
+ <button
1466
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1467
+ type="button"
1468
+ (click)="remove(path); $event.stopPropagation()"
1469
+ aria-label="Remover bloco"
1470
+ >
1471
+ <mkb-icon name="close" />
1472
+ </button>
955
1473
  </div>
956
1474
  </ng-template>
957
1475
 
958
- <div class="mkbd-row mkbd-mt">
959
- <mat-form-field appearance="outline" class="mkbd-slim">
960
- <mat-label>Tipo do novo bloco</mat-label>
961
- <mat-select [(ngModel)]="newType">
962
- @for (t of blockTypes; track t.type) {
963
- <mat-option [value]="t.type">{{ t.label }}</mat-option>
964
- }
965
- </mat-select>
966
- </mat-form-field>
967
- <button matButton type="button" (click)="add(false)">+ Adicionar</button>
1476
+ <div class="mkbd-new-block">
1477
+ <mkb-combo
1478
+ label="Tipo do novo bloco"
1479
+ [options]="blockTypeOptions"
1480
+ [value]="newType()"
1481
+ (valueChange)="newType.set($any($event))"
1482
+ />
1483
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="add(false)">
1484
+ <mkb-icon name="add" />
1485
+ Adicionar
1486
+ </button>
968
1487
  @if (selectedIsRow()) {
969
- <button matButton type="button" (click)="add(true)">+ Adicionar DENTRO da linha</button>
1488
+ <button class="mkbd-btn mkbd-btn-tonal" type="button" (click)="add(true)">
1489
+ <mkb-icon name="add" />
1490
+ Dentro da linha
1491
+ </button>
970
1492
  }
971
1493
  </div>
972
1494
 
973
1495
  @if (selectedBlock(); as block) {
974
- <h3 class="mkbd-h">Propriedades — {{ typeLabel(block.type) }}</h3>
975
- <div class="mkbd-props">
1496
+ <div class="mkbd-section">
1497
+ <span class="mkbd-overline">Propriedades · {{ typeLabel(block.type) }}</span>
1498
+ </div>
1499
+ <div class="mkbd-stack">
976
1500
  @for (def of fieldsFor(block.type); track def.key) {
977
1501
  @switch (def.kind) {
978
1502
  @case ('text') {
979
- <mat-form-field appearance="outline" class="mkbd-slim">
980
- <mat-label>{{ def.label }}</mat-label>
1503
+ <label class="mkbd-field">
1504
+ <span class="mkbd-label">{{ def.label }}</span>
981
1505
  <input
982
- matInput
983
1506
  [ngModel]="str(block, def.key)"
984
1507
  (ngModelChange)="setProp(def.key, $event || undefined)"
1508
+ [placeholder]="def.hint ?? ''"
985
1509
  />
986
- @if (def.hint) { <mat-hint>{{ def.hint }}</mat-hint> }
987
- </mat-form-field>
1510
+ </label>
988
1511
  }
989
1512
  @case ('number') {
990
- <mat-form-field appearance="outline" class="mkbd-tiny">
991
- <mat-label>{{ def.label }}</mat-label>
1513
+ <label class="mkbd-field mkbd-field-sm">
1514
+ <span class="mkbd-label">{{ def.label }}</span>
992
1515
  <input
993
- matInput
994
1516
  type="number"
995
1517
  [ngModel]="num(block, def.key)"
996
1518
  (ngModelChange)="setProp(def.key, $event === null || $event === '' ? undefined : +$event)"
997
1519
  />
998
- </mat-form-field>
1520
+ </label>
999
1521
  }
1000
1522
  @case ('toggle') {
1001
- <mat-slide-toggle
1002
- [ngModel]="bool(block, def.key)"
1003
- (ngModelChange)="setProp(def.key, $event || undefined)"
1004
- >
1523
+ <label class="mkbd-switch mkbd-switch-boxed">
1524
+ <input
1525
+ type="checkbox"
1526
+ [ngModel]="bool(block, def.key)"
1527
+ (ngModelChange)="setProp(def.key, $event || undefined)"
1528
+ />
1005
1529
  {{ def.label }}
1006
- </mat-slide-toggle>
1530
+ </label>
1007
1531
  }
1008
1532
  @case ('select') {
1009
- <mat-form-field appearance="outline" class="mkbd-slim">
1010
- <mat-label>{{ def.label }}</mat-label>
1011
- <mat-select
1012
- [ngModel]="str(block, def.key)"
1013
- (ngModelChange)="setProp(def.key, $event || undefined)"
1014
- >
1015
- @for (opt of def.options; track opt) {
1016
- <mat-option [value]="opt">{{ opt || '—' }}</mat-option>
1017
- }
1018
- </mat-select>
1019
- </mat-form-field>
1533
+ <mkb-combo
1534
+ [label]="def.label"
1535
+ [options]="selectOptions(def)"
1536
+ [value]="str(block, def.key)"
1537
+ (valueChange)="setProp(def.key, $event || undefined)"
1538
+ />
1020
1539
  }
1021
1540
  @case ('csv') {
1022
- <mat-form-field appearance="outline" class="mkbd-grow">
1023
- <mat-label>{{ def.label }}</mat-label>
1024
- <input
1025
- matInput
1026
- [ngModel]="csv(block, def.key)"
1027
- (ngModelChange)="setCsv(def.key, $event)"
1028
- />
1029
- </mat-form-field>
1541
+ <label class="mkbd-field mkbd-field-grow">
1542
+ <span class="mkbd-label">{{ def.label }}</span>
1543
+ <input [ngModel]="csv(block, def.key)" (ngModelChange)="setCsv(def.key, $event)" />
1544
+ </label>
1030
1545
  }
1031
1546
  @case ('json') {
1032
- <mat-form-field appearance="outline" class="mkbd-full">
1033
- <mat-label>{{ def.label }}</mat-label>
1034
- <textarea
1035
- matInput
1036
- rows="4"
1037
- [value]="json(block, def.key)"
1038
- (change)="setJson(def.key, $event)"
1039
- ></textarea>
1040
- <mat-hint [class.mkbd-error]="jsonError()">
1041
- {{ jsonError() || def.hint || 'Objeto JSON; vazio remove.' }}
1042
- </mat-hint>
1043
- </mat-form-field>
1547
+ <label class="mkbd-field mkbd-field-area mkbd-field-full">
1548
+ <span class="mkbd-label">{{ def.label }}</span>
1549
+ <textarea rows="4" [value]="json(block, def.key)" (change)="setJson(def.key, $event)"></textarea>
1550
+ </label>
1551
+ <p class="mkbd-hint mkbd-full" [class.mkbd-error-text]="jsonError()">
1552
+ {{ jsonError() || def.hint || 'Objeto JSON; vazio remove.' }}
1553
+ </p>
1044
1554
  }
1045
1555
  @case ('capabilities') {
1046
1556
  <div class="mkbd-caps">
1047
- <span class="mkbd-caps-label">{{ def.label }}:</span>
1557
+ <span class="mkbd-caps-label">{{ def.label }}</span>
1048
1558
  @for (cap of allCapabilities; track cap) {
1049
- <mat-checkbox
1050
- [ngModel]="hasCapability(block, cap)"
1051
- (ngModelChange)="toggleCapability(cap, $event)"
1052
- >
1559
+ <label class="mkbd-check">
1560
+ <input
1561
+ type="checkbox"
1562
+ [ngModel]="hasCapability(block, cap)"
1563
+ (ngModelChange)="toggleCapability(cap, $event)"
1564
+ />
1053
1565
  {{ cap }}
1054
- </mat-checkbox>
1566
+ </label>
1055
1567
  }
1056
1568
  </div>
1057
1569
  }
@@ -1059,80 +1571,98 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
1059
1571
  <div class="mkbd-sub">
1060
1572
  <span class="mkbd-caps-label">{{ def.label }}</span>
1061
1573
  @for (fact of facts(block); track $index; let fi = $index) {
1062
- <div class="mkbd-subrow">
1063
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1064
- <mat-label>Campo</mat-label>
1065
- <input matInput [ngModel]="fact.field" (ngModelChange)="setFact(fi, 'field', $event)" />
1066
- </mat-form-field>
1067
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1068
- <mat-label>Ícone</mat-label>
1069
- <input matInput [ngModel]="fact.icon ?? ''" (ngModelChange)="setFact(fi, 'icon', $event || undefined)" />
1070
- </mat-form-field>
1071
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1072
- <mat-label>Rótulo</mat-label>
1073
- <input matInput [ngModel]="fact.label ?? ''" (ngModelChange)="setFact(fi, 'label', $event || undefined)" />
1074
- </mat-form-field>
1075
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1076
- <mat-label>Prefixo</mat-label>
1077
- <input matInput [ngModel]="fact.prefix ?? ''" (ngModelChange)="setFact(fi, 'prefix', $event || undefined)" />
1078
- </mat-form-field>
1079
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1080
- <mat-label>Sufixo</mat-label>
1081
- <input matInput [ngModel]="fact.suffix ?? ''" (ngModelChange)="setFact(fi, 'suffix', $event || undefined)" />
1082
- </mat-form-field>
1083
- <button matIconButton type="button" (click)="removeListItem(def.key, fi)" aria-label="Remover fato">✕</button>
1574
+ <div class="mkbd-stack mkbd-subrow">
1575
+ <label class="mkbd-field mkbd-field-sm">
1576
+ <span class="mkbd-label">Campo</span>
1577
+ <input [ngModel]="fact.field" (ngModelChange)="setFact(fi, 'field', $event)" />
1578
+ </label>
1579
+ <label class="mkbd-field mkbd-field-sm">
1580
+ <span class="mkbd-label">Ícone</span>
1581
+ <input [ngModel]="fact.icon ?? ''" (ngModelChange)="setFact(fi, 'icon', $event || undefined)" />
1582
+ </label>
1583
+ <label class="mkbd-field mkbd-field-sm">
1584
+ <span class="mkbd-label">Rótulo</span>
1585
+ <input [ngModel]="fact.label ?? ''" (ngModelChange)="setFact(fi, 'label', $event || undefined)" />
1586
+ </label>
1587
+ <label class="mkbd-field mkbd-field-sm">
1588
+ <span class="mkbd-label">Prefixo</span>
1589
+ <input [ngModel]="fact.prefix ?? ''" (ngModelChange)="setFact(fi, 'prefix', $event || undefined)" />
1590
+ </label>
1591
+ <label class="mkbd-field mkbd-field-sm">
1592
+ <span class="mkbd-label">Sufixo</span>
1593
+ <input [ngModel]="fact.suffix ?? ''" (ngModelChange)="setFact(fi, 'suffix', $event || undefined)" />
1594
+ </label>
1595
+ <button
1596
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1597
+ type="button"
1598
+ (click)="removeListItem(def.key, fi)"
1599
+ aria-label="Remover fato"
1600
+ >
1601
+ <mkb-icon name="close" />
1602
+ </button>
1084
1603
  </div>
1085
1604
  }
1086
- <button matButton type="button" (click)="addFact(def.key)">+ Fato</button>
1605
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addFact(def.key)">
1606
+ <mkb-icon name="add" />
1607
+ Fato
1608
+ </button>
1087
1609
  </div>
1088
1610
  }
1089
1611
  @case ('card-actions') {
1090
1612
  <div class="mkbd-sub">
1091
1613
  <span class="mkbd-caps-label">{{ def.label }}</span>
1092
1614
  @for (action of actions(block, def.key); track $index; let ai = $index) {
1093
- <div class="mkbd-subrow">
1094
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1095
- <mat-label>Id</mat-label>
1096
- <input matInput [ngModel]="action.id" (ngModelChange)="setAction(def.key, ai, 'id', $event)" />
1097
- </mat-form-field>
1098
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1099
- <mat-label>Rótulo</mat-label>
1100
- <input matInput [ngModel]="action.label" (ngModelChange)="setAction(def.key, ai, 'label', $event)" />
1101
- </mat-form-field>
1102
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1103
- <mat-label>Ícone</mat-label>
1104
- <input matInput [ngModel]="action.icon ?? ''" (ngModelChange)="setAction(def.key, ai, 'icon', $event || undefined)" />
1105
- </mat-form-field>
1106
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1107
- <mat-label>Tom</mat-label>
1108
- <mat-select [ngModel]="action.tone ?? ''" (ngModelChange)="setAction(def.key, ai, 'tone', $event || undefined)">
1109
- @for (tone of tones; track tone) {
1110
- <mat-option [value]="tone">{{ tone || '' }}</mat-option>
1111
- }
1112
- </mat-select>
1113
- </mat-form-field>
1114
- <mat-form-field appearance="outline" class="mkbd-tiny2">
1115
- <mat-label>Só nas colunas</mat-label>
1615
+ <div class="mkbd-stack mkbd-subrow">
1616
+ <label class="mkbd-field mkbd-field-sm mkbd-field-mono">
1617
+ <span class="mkbd-label">Id</span>
1618
+ <input [ngModel]="action.id" (ngModelChange)="setAction(def.key, ai, 'id', $event)" />
1619
+ </label>
1620
+ <label class="mkbd-field mkbd-field-sm">
1621
+ <span class="mkbd-label">Rótulo</span>
1622
+ <input [ngModel]="action.label" (ngModelChange)="setAction(def.key, ai, 'label', $event)" />
1623
+ </label>
1624
+ <label class="mkbd-field mkbd-field-sm">
1625
+ <span class="mkbd-label">Ícone</span>
1626
+ <input [ngModel]="action.icon ?? ''" (ngModelChange)="setAction(def.key, ai, 'icon', $event || undefined)" />
1627
+ </label>
1628
+ <mkb-combo
1629
+ class="mkbd-field-sm"
1630
+ label="Tom"
1631
+ [options]="toneOptions"
1632
+ [value]="action.tone ?? ''"
1633
+ (valueChange)="setAction(def.key, ai, 'tone', $event || undefined)"
1634
+ />
1635
+ <label class="mkbd-field mkbd-field-sm">
1636
+ <span class="mkbd-label">Só nas colunas</span>
1116
1637
  <input
1117
- matInput
1118
1638
  placeholder="col-a, col-b"
1119
1639
  [ngModel]="whenColumns(action)"
1120
1640
  (ngModelChange)="setActionWhen(def.key, ai, $event)"
1121
1641
  />
1122
- </mat-form-field>
1123
- <button matIconButton type="button" (click)="removeListItem(def.key, ai)" aria-label="Remover ação">✕</button>
1642
+ </label>
1643
+ <button
1644
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1645
+ type="button"
1646
+ (click)="removeListItem(def.key, ai)"
1647
+ aria-label="Remover ação"
1648
+ >
1649
+ <mkb-icon name="close" />
1650
+ </button>
1124
1651
  </div>
1125
1652
  }
1126
- <button matButton type="button" (click)="addAction(def.key)">+ Ação</button>
1653
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addAction(def.key)">
1654
+ <mkb-icon name="add" />
1655
+ Ação
1656
+ </button>
1127
1657
  </div>
1128
1658
  }
1129
1659
  }
1130
1660
  }
1131
1661
  </div>
1132
1662
  } @else {
1133
- <p class="mkbd-hint mkbd-mt">Selecione um bloco para editar as propriedades.</p>
1663
+ <p class="mkbd-hint">Selecione um bloco para editar as propriedades.</p>
1134
1664
  }
1135
- `, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.mkbd-mt{margin-top:12px}.mkbd-tree{display:flex;flex-direction:column;gap:3px}.mkbd-node{display:flex;align-items:center;gap:8px;padding:3px 10px;border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px;cursor:pointer;background:var(--mkb-card-bg, #fff)}.mkbd-node:focus-visible{outline:2px solid var(--mkb-accent, #5e35b1);outline-offset:1px}.mkbd-node-child{margin-left:26px}.mkbd-node-selected{border-color:var(--mkb-accent, #5e35b1);box-shadow:inset 2px 0 0 var(--mkb-accent, #5e35b1)}.mkbd-node-type{font-size:12px;font-weight:600}.mkbd-node-summary{font-size:11.5px;color:var(--mkb-muted, #6f6a7c);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-spacer{flex:1}.mkbd-props{display:flex;flex-wrap:wrap;gap:18px 10px;align-items:center}.mkbd-slim{width:200px}.mkbd-tiny{width:110px}.mkbd-tiny2{width:130px}.mkbd-grow{flex:1;min-width:220px}.mkbd-full{width:100%}.mkbd-caps,.mkbd-sub{display:flex;flex-wrap:wrap;gap:10px;align-items:center;width:100%}.mkbd-sub{flex-direction:column;align-items:stretch;gap:4px}.mkbd-subrow{display:flex;flex-wrap:wrap;gap:8px;align-items:center}.mkbd-caps-label{font-size:12px;color:var(--mkb-muted, #6f6a7c)}.mkbd-error{color:var(--mkb-danger, #b3261e)}\n"] }]
1665
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-block{grid-template-columns:22px auto minmax(0,1fr) auto;cursor:pointer;border-left-color:var(--mkbd-border-strong)}.mkbd-block:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-block-child{border-left-color:var(--mkbd-primary-outline)}.mkbd-nested{margin-left:26px;margin-top:3px;gap:3px}.mkbd-handle[cdkDragHandle]{cursor:grab;touch-action:none}.mkbd-block.cdk-drag-preview{box-shadow:var(--elevation-3, 0 8px 30px rgba(20, 22, 30, .14));opacity:.96}.mkbd-block.cdk-drag-placeholder{opacity:.35}.cdk-drop-list-dragging .mkbd-block:not(.cdk-drag-placeholder){transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-block-type{font-size:12.5px;font-weight:500}.mkbd-block-summary{font:500 11.5px var(--mkbd-font-mono);color:var(--mkbd-muted);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-new-block{display:flex;align-items:center;gap:10px;flex-wrap:wrap;margin-top:12px}.mkbd-new-block .mkbd-field{width:230px}.mkbd-new-block .mkbd-field>.mkbd-label{background:var(--mkbd-canvas)}.mkbd-caps,.mkbd-sub{display:flex;flex-wrap:wrap;gap:10px;align-items:center;width:100%}.mkbd-sub{flex-direction:column;align-items:stretch;gap:8px}.mkbd-subrow{flex-wrap:wrap}.mkbd-caps-label{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-full{flex:1 0 100%;margin:0}.mkbd-error-text{color:var(--mkbd-error)}\n"] }]
1136
1666
  }] });
1137
1667
 
1138
1668
  /** Converte texto digitado no tipo mais provável (números e booleanos). */
@@ -1155,6 +1685,11 @@ class MkbDataEditor {
1155
1685
  store = inject(DesignerStore);
1156
1686
  config = this.store.config;
1157
1687
  filtersError = signal(null, ...(ngDevMode ? [{ debugName: "filtersError" }] : /* istanbul ignore next */ []));
1688
+ /** Índice do item aberto (acordeão de um por vez). */
1689
+ expanded = signal(null, ...(ngDevMode ? [{ debugName: "expanded" }] : /* istanbul ignore next */ []));
1690
+ toggle(index) {
1691
+ this.expanded.update((current) => (current === index ? null : index));
1692
+ }
1158
1693
  items() {
1159
1694
  return this.config().items ?? [];
1160
1695
  }
@@ -1167,6 +1702,15 @@ class MkbDataEditor {
1167
1702
  hasLanes() {
1168
1703
  return !!this.store.lanesAxis();
1169
1704
  }
1705
+ /** Opções derivadas da config — computed, para a referência ser estável. */
1706
+ columnOptions = computed(() => (this.store.columnsAxis().groups ?? []).map((g) => ({
1707
+ value: g.id,
1708
+ label: g.title ? `${g.id} · ${g.title}` : g.id,
1709
+ })), ...(ngDevMode ? [{ debugName: "columnOptions" }] : /* istanbul ignore next */ []));
1710
+ laneOptions = computed(() => (this.store.lanesAxis()?.groups ?? []).map((g) => ({
1711
+ value: g.id,
1712
+ label: g.title ? `${g.id} · ${g.title}` : g.id,
1713
+ })), ...(ngDevMode ? [{ debugName: "laneOptions" }] : /* istanbul ignore next */ []));
1170
1714
  columnIds() {
1171
1715
  return (this.store.columnsAxis().groups ?? []).map((g) => g.id);
1172
1716
  }
@@ -1242,6 +1786,7 @@ class MkbDataEditor {
1242
1786
  item[this.laneField()] = lane;
1243
1787
  d.items.push(item);
1244
1788
  });
1789
+ this.expanded.set(this.items().length - 1);
1245
1790
  }
1246
1791
  duplicateItem(index) {
1247
1792
  this.store.update((d) => {
@@ -1255,6 +1800,7 @@ class MkbDataEditor {
1255
1800
  }
1256
1801
  removeItem(index) {
1257
1802
  this.store.update((d) => d.items?.splice(index, 1));
1803
+ this.expanded.set(null);
1258
1804
  }
1259
1805
  setItemProp(index, key, value) {
1260
1806
  this.store.update((d) => {
@@ -1351,250 +1897,384 @@ class MkbDataEditor {
1351
1897
  }
1352
1898
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbDataEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
1353
1899
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MkbDataEditor, isStandalone: true, selector: "mkb-data-editor", ngImport: i0, template: `
1354
- <h3 class="mkbd-h">Itens ({{ items().length }})</h3>
1355
- <mat-accordion displayMode="flat" [multi]="false">
1356
- @for (item of items(); track item.id; let i = $index) {
1357
- <mat-expansion-panel class="mat-elevation-z0 mkbd-panel">
1358
- <mat-expansion-panel-header>
1359
- <mat-panel-title>{{ label(item) }}</mat-panel-title>
1360
- <mat-panel-description>{{ position(item) }}</mat-panel-description>
1361
- </mat-expansion-panel-header>
1362
-
1363
- <div class="mkbd-row">
1364
- <mat-form-field appearance="outline" class="mkbd-slim">
1365
- <mat-label>Id</mat-label>
1366
- <input matInput [ngModel]="item.id" (ngModelChange)="setItemProp(i, 'id', $event)" />
1367
- </mat-form-field>
1368
- @if (columnIds().length) {
1369
- <mat-form-field appearance="outline" class="mkbd-slim">
1370
- <mat-label>Coluna ({{ columnField() }})</mat-label>
1371
- <mat-select
1372
- [ngModel]="str(item, columnField())"
1373
- (ngModelChange)="setItemProp(i, columnField(), $event)"
1374
- >
1375
- @for (id of columnIds(); track id) {
1376
- <mat-option [value]="id">{{ id }}</mat-option>
1377
- }
1378
- </mat-select>
1379
- </mat-form-field>
1380
- } @else {
1381
- <mat-form-field appearance="outline" class="mkbd-slim">
1382
- <mat-label>Coluna ({{ columnField() }})</mat-label>
1383
- <input matInput [ngModel]="str(item, columnField())" (ngModelChange)="setItemProp(i, columnField(), $event)" />
1384
- </mat-form-field>
1385
- }
1386
- @if (hasLanes()) {
1387
- @if (laneIds().length) {
1388
- <mat-form-field appearance="outline" class="mkbd-slim">
1389
- <mat-label>Lane ({{ laneField() }})</mat-label>
1390
- <mat-select [ngModel]="str(item, laneField())" (ngModelChange)="setItemProp(i, laneField(), $event)">
1391
- @for (id of laneIds(); track id) {
1392
- <mat-option [value]="id">{{ id }}</mat-option>
1393
- }
1394
- </mat-select>
1395
- </mat-form-field>
1396
- } @else {
1397
- <mat-form-field appearance="outline" class="mkbd-slim">
1398
- <mat-label>Lane ({{ laneField() }})</mat-label>
1399
- <input matInput [ngModel]="str(item, laneField())" (ngModelChange)="setItemProp(i, laneField(), $event)" />
1400
- </mat-form-field>
1401
- }
1402
- }
1900
+ <div class="mkbd-section">
1901
+ <span class="mkbd-overline">Itens</span>
1902
+ <span class="mkbd-count">{{ items().length }}</span>
1903
+ </div>
1904
+
1905
+ <div class="mkbd-rows">
1906
+ @for (item of items(); track $index; let i = $index) {
1907
+ <div class="mkbd-row mkbd-item" [class.mkbd-row-selected]="expanded() === i">
1908
+ <div class="mkbd-item-head">
1909
+ <button
1910
+ class="mkbd-item-toggle"
1911
+ type="button"
1912
+ [attr.aria-expanded]="expanded() === i"
1913
+ (click)="toggle(i)"
1914
+ >
1915
+ <mkb-icon [name]="expanded() === i ? 'down' : 'expand'" />
1916
+ <span class="mkbd-item-title">{{ label(item) }}</span>
1917
+ <span class="mkbd-item-where">{{ position(item) }}</span>
1918
+ </button>
1919
+ <button class="mkbd-icon-btn" type="button" (click)="duplicateItem(i)" aria-label="Duplicar item">
1920
+ <mkb-icon name="add" />
1921
+ </button>
1922
+ <button
1923
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1924
+ type="button"
1925
+ (click)="removeItem(i)"
1926
+ aria-label="Remover item"
1927
+ >
1928
+ <mkb-icon name="close" />
1929
+ </button>
1403
1930
  </div>
1404
1931
 
1405
- <h4 class="mkbd-h4">Campos</h4>
1406
- @for (key of freeFields(item); track key) {
1407
- <div class="mkbd-row">
1408
- <mat-form-field appearance="outline" class="mkbd-slim">
1409
- <mat-label>Campo</mat-label>
1410
- <input matInput [ngModel]="key" (change)="renameField(i, key, $event)" />
1411
- </mat-form-field>
1412
- <mat-form-field appearance="outline" class="mkbd-grow">
1413
- <mat-label>Valor</mat-label>
1414
- <input matInput [ngModel]="display(item, key)" (ngModelChange)="setItemProp(i, key, coerceValue($event))" />
1415
- </mat-form-field>
1416
- <button matIconButton type="button" (click)="removeField(i, key)" aria-label="Remover campo">✕</button>
1417
- </div>
1418
- }
1419
- <button matButton type="button" (click)="addField(i)">+ Campo</button>
1420
-
1421
- @for (def of entryDefs(); track def.field) {
1422
- <h4 class="mkbd-h4">Itens internos — {{ def.field }}</h4>
1423
- @for (entry of entriesOf(item, def.field); track entry.id; let ei = $index) {
1424
- <div class="mkbd-row">
1425
- @if (def.checkField; as checkField) {
1426
- <mat-checkbox
1427
- [ngModel]="entry[checkField] === true"
1428
- (ngModelChange)="setEntryProp(i, def.field, ei, checkField, $event)"
1429
- aria-label="Concluído"
1932
+ @if (expanded() === i) {
1933
+ <div class="mkbd-item-body">
1934
+ <div class="mkbd-stack">
1935
+ <label class="mkbd-field mkbd-field-mono">
1936
+ <span class="mkbd-label">Id</span>
1937
+ <input [ngModel]="item.id" (ngModelChange)="setItemProp(i, 'id', $event)" />
1938
+ </label>
1939
+
1940
+ @if (columnOptions().length) {
1941
+ <mkb-combo
1942
+ [label]="'Coluna (' + columnField() + ')'"
1943
+ [options]="columnOptions()"
1944
+ [value]="str(item, columnField())"
1945
+ (valueChange)="setItemProp(i, columnField(), $event)"
1430
1946
  />
1947
+ } @else {
1948
+ <label class="mkbd-field">
1949
+ <span class="mkbd-label">Coluna ({{ columnField() }})</span>
1950
+ <input
1951
+ [ngModel]="str(item, columnField())"
1952
+ (ngModelChange)="setItemProp(i, columnField(), $event)"
1953
+ />
1954
+ </label>
1955
+ }
1956
+
1957
+ @if (hasLanes()) {
1958
+ @if (laneOptions().length) {
1959
+ <mkb-combo
1960
+ [label]="'Lane (' + laneField() + ')'"
1961
+ [options]="laneOptions()"
1962
+ [value]="str(item, laneField())"
1963
+ (valueChange)="setItemProp(i, laneField(), $event)"
1964
+ />
1965
+ } @else {
1966
+ <label class="mkbd-field">
1967
+ <span class="mkbd-label">Lane ({{ laneField() }})</span>
1968
+ <input
1969
+ [ngModel]="str(item, laneField())"
1970
+ (ngModelChange)="setItemProp(i, laneField(), $event)"
1971
+ />
1972
+ </label>
1973
+ }
1431
1974
  }
1432
- <mat-form-field appearance="outline" class="mkbd-grow">
1433
- <mat-label>{{ def.labelField }}</mat-label>
1434
- <input
1435
- matInput
1436
- [ngModel]="str(entry, def.labelField)"
1437
- (ngModelChange)="setEntryProp(i, def.field, ei, def.labelField, $event)"
1438
- />
1439
- </mat-form-field>
1440
- <button matIconButton type="button" (click)="removeEntry(i, def.field, ei)" aria-label="Remover item interno">✕</button>
1441
1975
  </div>
1442
- }
1443
- <button matButton type="button" (click)="addEntry(i, def)">+ Item interno</button>
1444
- }
1445
1976
 
1446
- <div class="mkbd-row mkbd-mt">
1447
- <button matButton type="button" (click)="duplicateItem(i)">Duplicar</button>
1448
- <button matButton type="button" (click)="removeItem(i)">Remover item</button>
1449
- </div>
1450
- </mat-expansion-panel>
1977
+ <div class="mkbd-subsection">
1978
+ <span class="mkbd-overline">Campos</span>
1979
+ </div>
1980
+ @for (key of freeFields(item); track key) {
1981
+ <div class="mkbd-stack mkbd-field-row">
1982
+ <label class="mkbd-field mkbd-field-mono mkbd-field-sm">
1983
+ <span class="mkbd-label">Campo</span>
1984
+ <input [ngModel]="key" (change)="renameField(i, key, $event)" />
1985
+ </label>
1986
+ <label class="mkbd-field mkbd-field-grow">
1987
+ <span class="mkbd-label">Valor</span>
1988
+ <input
1989
+ [ngModel]="display(item, key)"
1990
+ (ngModelChange)="setItemProp(i, key, coerceValue($event))"
1991
+ />
1992
+ </label>
1993
+ <button
1994
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
1995
+ type="button"
1996
+ (click)="removeField(i, key)"
1997
+ aria-label="Remover campo"
1998
+ >
1999
+ <mkb-icon name="close" />
2000
+ </button>
2001
+ </div>
2002
+ }
2003
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addField(i)">
2004
+ <mkb-icon name="add" />
2005
+ Campo
2006
+ </button>
2007
+
2008
+ @for (def of entryDefs(); track def.field) {
2009
+ <div class="mkbd-subsection">
2010
+ <span class="mkbd-overline">Itens internos · {{ def.field }}</span>
2011
+ </div>
2012
+ @for (entry of entriesOf(item, def.field); track $index; let ei = $index) {
2013
+ <div class="mkbd-stack mkbd-field-row">
2014
+ @if (def.checkField; as checkField) {
2015
+ <label class="mkbd-check">
2016
+ <input
2017
+ type="checkbox"
2018
+ [ngModel]="entry[checkField] === true"
2019
+ (ngModelChange)="setEntryProp(i, def.field, ei, checkField, $event)"
2020
+ />
2021
+ Feito
2022
+ </label>
2023
+ }
2024
+ <label class="mkbd-field mkbd-field-grow">
2025
+ <span class="mkbd-label">{{ def.labelField }}</span>
2026
+ <input
2027
+ [ngModel]="str(entry, def.labelField)"
2028
+ (ngModelChange)="setEntryProp(i, def.field, ei, def.labelField, $event)"
2029
+ />
2030
+ </label>
2031
+ <button
2032
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2033
+ type="button"
2034
+ (click)="removeEntry(i, def.field, ei)"
2035
+ aria-label="Remover item interno"
2036
+ >
2037
+ <mkb-icon name="close" />
2038
+ </button>
2039
+ </div>
2040
+ }
2041
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addEntry(i, def)">
2042
+ <mkb-icon name="add" />
2043
+ Item interno
2044
+ </button>
2045
+ }
2046
+ </div>
2047
+ }
2048
+ </div>
1451
2049
  }
1452
- </mat-accordion>
1453
- <button matButton class="mkbd-mt" type="button" (click)="addItem()">+ Adicionar item</button>
2050
+ </div>
1454
2051
 
1455
- <h3 class="mkbd-h">Filtros iniciais (JSON)</h3>
2052
+ <button class="mkbd-add" type="button" (click)="addItem()">
2053
+ <mkb-icon name="add" />
2054
+ Adicionar item
2055
+ </button>
2056
+
2057
+ <div class="mkbd-section">
2058
+ <span class="mkbd-overline">Filtros iniciais</span>
2059
+ </div>
1456
2060
  <p class="mkbd-hint">Array de KanbanFilter aplicado na criação do board; vazio remove.</p>
1457
- <mat-form-field appearance="outline" class="mkbd-full">
1458
- <mat-label>filters</mat-label>
1459
- <textarea matInput rows="4" [value]="filtersJson()" (change)="setFilters($event)"></textarea>
1460
- @if (filtersError(); as err) {
1461
- <mat-hint class="mkbd-error">{{ err }}</mat-hint>
1462
- }
1463
- </mat-form-field>
1464
- `, isInline: true, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-h:first-child{margin-top:0}.mkbd-h4{margin:12px 0 6px;font-size:12px;font-weight:600;color:var(--mkb-muted, #6f6a7c)}.mkbd-hint{margin:0 0 8px;font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:2px}.mkbd-mt{margin-top:10px}.mkbd-slim{width:180px}.mkbd-grow{flex:1;min-width:180px}.mkbd-full{width:100%}.mkbd-panel{border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px!important;margin-bottom:6px}.mkbd-error{color:var(--mkb-danger, #b3261e)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }, { kind: "directive", type: i7$1.MatAccordion, selector: "mat-accordion", inputs: ["hideToggle", "displayMode", "togglePosition"], exportAs: ["matAccordion"] }, { kind: "component", type: i7$1.MatExpansionPanel, selector: "mat-expansion-panel", inputs: ["hideToggle", "togglePosition"], outputs: ["afterExpand", "afterCollapse"], exportAs: ["matExpansionPanel"] }, { kind: "component", type: i7$1.MatExpansionPanelHeader, selector: "mat-expansion-panel-header", inputs: ["expandedHeight", "collapsedHeight", "tabIndex"] }, { kind: "directive", type: i7$1.MatExpansionPanelTitle, selector: "mat-panel-title" }, { kind: "directive", type: i7$1.MatExpansionPanelDescription, selector: "mat-panel-description" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2061
+ <label class="mkbd-field mkbd-field-area mkbd-field-full">
2062
+ <span class="mkbd-label">filters (JSON)</span>
2063
+ <textarea rows="4" [value]="filtersJson()" (change)="setFilters($event)"></textarea>
2064
+ </label>
2065
+ @if (filtersError(); as err) {
2066
+ <p class="mkbd-error-text">{{ err }}</p>
2067
+ }
2068
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-item{display:block;padding:0;border-left-color:var(--mkbd-border-strong)}.mkbd-item-head{display:flex;align-items:center;gap:4px;padding:6px 8px 6px 4px}.mkbd-item-toggle{flex:1;display:flex;align-items:center;gap:8px;min-width:0;padding:6px 8px;border:none;border-radius:var(--mkbd-radius-sm);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.mkbd-item-toggle:hover{background:var(--mkbd-panel-3)}.mkbd-item-toggle:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-item-toggle>mkb-icon{font-size:18px;color:var(--mkbd-muted)}.mkbd-item-title{font-weight:500;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-item-where{margin-left:auto;font:500 10px var(--mkbd-font-mono);color:var(--mkbd-muted);background:var(--mkbd-panel-3);padding:2px 8px;border-radius:var(--mkbd-radius-pill);white-space:nowrap}.mkbd-item-body{padding:4px 12px 14px;border-top:1px solid var(--mkbd-border-soft)}.mkbd-item-body .mkbd-field>.mkbd-label{background:var(--mkbd-panel)}.mkbd-subsection{margin:16px 0 10px}.mkbd-field-row{margin-bottom:10px;flex-wrap:nowrap}.mkbd-add-sm{height:34px;margin-top:0;font-size:12px}.mkbd-error-text{margin:6px 0 0;font-size:11.5px;color:var(--mkbd-error)}.mkbd-field-full{width:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MkbCombo, selector: "mkb-combo", inputs: ["label", "options", "value", "multiple", "placeholder"], outputs: ["valueChange", "valuesChange"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1465
2069
  }
1466
2070
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbDataEditor, decorators: [{
1467
2071
  type: Component,
1468
- args: [{ selector: 'mkb-data-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1469
- FormsModule,
1470
- MatFormFieldModule,
1471
- MatInputModule,
1472
- MatSelectModule,
1473
- MatCheckboxModule,
1474
- MatButtonModule,
1475
- MatExpansionModule,
1476
- ], template: `
1477
- <h3 class="mkbd-h">Itens ({{ items().length }})</h3>
1478
- <mat-accordion displayMode="flat" [multi]="false">
1479
- @for (item of items(); track item.id; let i = $index) {
1480
- <mat-expansion-panel class="mat-elevation-z0 mkbd-panel">
1481
- <mat-expansion-panel-header>
1482
- <mat-panel-title>{{ label(item) }}</mat-panel-title>
1483
- <mat-panel-description>{{ position(item) }}</mat-panel-description>
1484
- </mat-expansion-panel-header>
1485
-
1486
- <div class="mkbd-row">
1487
- <mat-form-field appearance="outline" class="mkbd-slim">
1488
- <mat-label>Id</mat-label>
1489
- <input matInput [ngModel]="item.id" (ngModelChange)="setItemProp(i, 'id', $event)" />
1490
- </mat-form-field>
1491
- @if (columnIds().length) {
1492
- <mat-form-field appearance="outline" class="mkbd-slim">
1493
- <mat-label>Coluna ({{ columnField() }})</mat-label>
1494
- <mat-select
1495
- [ngModel]="str(item, columnField())"
1496
- (ngModelChange)="setItemProp(i, columnField(), $event)"
1497
- >
1498
- @for (id of columnIds(); track id) {
1499
- <mat-option [value]="id">{{ id }}</mat-option>
1500
- }
1501
- </mat-select>
1502
- </mat-form-field>
1503
- } @else {
1504
- <mat-form-field appearance="outline" class="mkbd-slim">
1505
- <mat-label>Coluna ({{ columnField() }})</mat-label>
1506
- <input matInput [ngModel]="str(item, columnField())" (ngModelChange)="setItemProp(i, columnField(), $event)" />
1507
- </mat-form-field>
1508
- }
1509
- @if (hasLanes()) {
1510
- @if (laneIds().length) {
1511
- <mat-form-field appearance="outline" class="mkbd-slim">
1512
- <mat-label>Lane ({{ laneField() }})</mat-label>
1513
- <mat-select [ngModel]="str(item, laneField())" (ngModelChange)="setItemProp(i, laneField(), $event)">
1514
- @for (id of laneIds(); track id) {
1515
- <mat-option [value]="id">{{ id }}</mat-option>
1516
- }
1517
- </mat-select>
1518
- </mat-form-field>
1519
- } @else {
1520
- <mat-form-field appearance="outline" class="mkbd-slim">
1521
- <mat-label>Lane ({{ laneField() }})</mat-label>
1522
- <input matInput [ngModel]="str(item, laneField())" (ngModelChange)="setItemProp(i, laneField(), $event)" />
1523
- </mat-form-field>
1524
- }
1525
- }
2072
+ args: [{ selector: 'mkb-data-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, MkbCombo, MkbIcon], template: `
2073
+ <div class="mkbd-section">
2074
+ <span class="mkbd-overline">Itens</span>
2075
+ <span class="mkbd-count">{{ items().length }}</span>
2076
+ </div>
2077
+
2078
+ <div class="mkbd-rows">
2079
+ @for (item of items(); track $index; let i = $index) {
2080
+ <div class="mkbd-row mkbd-item" [class.mkbd-row-selected]="expanded() === i">
2081
+ <div class="mkbd-item-head">
2082
+ <button
2083
+ class="mkbd-item-toggle"
2084
+ type="button"
2085
+ [attr.aria-expanded]="expanded() === i"
2086
+ (click)="toggle(i)"
2087
+ >
2088
+ <mkb-icon [name]="expanded() === i ? 'down' : 'expand'" />
2089
+ <span class="mkbd-item-title">{{ label(item) }}</span>
2090
+ <span class="mkbd-item-where">{{ position(item) }}</span>
2091
+ </button>
2092
+ <button class="mkbd-icon-btn" type="button" (click)="duplicateItem(i)" aria-label="Duplicar item">
2093
+ <mkb-icon name="add" />
2094
+ </button>
2095
+ <button
2096
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2097
+ type="button"
2098
+ (click)="removeItem(i)"
2099
+ aria-label="Remover item"
2100
+ >
2101
+ <mkb-icon name="close" />
2102
+ </button>
1526
2103
  </div>
1527
2104
 
1528
- <h4 class="mkbd-h4">Campos</h4>
1529
- @for (key of freeFields(item); track key) {
1530
- <div class="mkbd-row">
1531
- <mat-form-field appearance="outline" class="mkbd-slim">
1532
- <mat-label>Campo</mat-label>
1533
- <input matInput [ngModel]="key" (change)="renameField(i, key, $event)" />
1534
- </mat-form-field>
1535
- <mat-form-field appearance="outline" class="mkbd-grow">
1536
- <mat-label>Valor</mat-label>
1537
- <input matInput [ngModel]="display(item, key)" (ngModelChange)="setItemProp(i, key, coerceValue($event))" />
1538
- </mat-form-field>
1539
- <button matIconButton type="button" (click)="removeField(i, key)" aria-label="Remover campo">✕</button>
1540
- </div>
1541
- }
1542
- <button matButton type="button" (click)="addField(i)">+ Campo</button>
1543
-
1544
- @for (def of entryDefs(); track def.field) {
1545
- <h4 class="mkbd-h4">Itens internos — {{ def.field }}</h4>
1546
- @for (entry of entriesOf(item, def.field); track entry.id; let ei = $index) {
1547
- <div class="mkbd-row">
1548
- @if (def.checkField; as checkField) {
1549
- <mat-checkbox
1550
- [ngModel]="entry[checkField] === true"
1551
- (ngModelChange)="setEntryProp(i, def.field, ei, checkField, $event)"
1552
- aria-label="Concluído"
2105
+ @if (expanded() === i) {
2106
+ <div class="mkbd-item-body">
2107
+ <div class="mkbd-stack">
2108
+ <label class="mkbd-field mkbd-field-mono">
2109
+ <span class="mkbd-label">Id</span>
2110
+ <input [ngModel]="item.id" (ngModelChange)="setItemProp(i, 'id', $event)" />
2111
+ </label>
2112
+
2113
+ @if (columnOptions().length) {
2114
+ <mkb-combo
2115
+ [label]="'Coluna (' + columnField() + ')'"
2116
+ [options]="columnOptions()"
2117
+ [value]="str(item, columnField())"
2118
+ (valueChange)="setItemProp(i, columnField(), $event)"
1553
2119
  />
2120
+ } @else {
2121
+ <label class="mkbd-field">
2122
+ <span class="mkbd-label">Coluna ({{ columnField() }})</span>
2123
+ <input
2124
+ [ngModel]="str(item, columnField())"
2125
+ (ngModelChange)="setItemProp(i, columnField(), $event)"
2126
+ />
2127
+ </label>
2128
+ }
2129
+
2130
+ @if (hasLanes()) {
2131
+ @if (laneOptions().length) {
2132
+ <mkb-combo
2133
+ [label]="'Lane (' + laneField() + ')'"
2134
+ [options]="laneOptions()"
2135
+ [value]="str(item, laneField())"
2136
+ (valueChange)="setItemProp(i, laneField(), $event)"
2137
+ />
2138
+ } @else {
2139
+ <label class="mkbd-field">
2140
+ <span class="mkbd-label">Lane ({{ laneField() }})</span>
2141
+ <input
2142
+ [ngModel]="str(item, laneField())"
2143
+ (ngModelChange)="setItemProp(i, laneField(), $event)"
2144
+ />
2145
+ </label>
2146
+ }
1554
2147
  }
1555
- <mat-form-field appearance="outline" class="mkbd-grow">
1556
- <mat-label>{{ def.labelField }}</mat-label>
1557
- <input
1558
- matInput
1559
- [ngModel]="str(entry, def.labelField)"
1560
- (ngModelChange)="setEntryProp(i, def.field, ei, def.labelField, $event)"
1561
- />
1562
- </mat-form-field>
1563
- <button matIconButton type="button" (click)="removeEntry(i, def.field, ei)" aria-label="Remover item interno">✕</button>
1564
2148
  </div>
1565
- }
1566
- <button matButton type="button" (click)="addEntry(i, def)">+ Item interno</button>
1567
- }
1568
2149
 
1569
- <div class="mkbd-row mkbd-mt">
1570
- <button matButton type="button" (click)="duplicateItem(i)">Duplicar</button>
1571
- <button matButton type="button" (click)="removeItem(i)">Remover item</button>
1572
- </div>
1573
- </mat-expansion-panel>
2150
+ <div class="mkbd-subsection">
2151
+ <span class="mkbd-overline">Campos</span>
2152
+ </div>
2153
+ @for (key of freeFields(item); track key) {
2154
+ <div class="mkbd-stack mkbd-field-row">
2155
+ <label class="mkbd-field mkbd-field-mono mkbd-field-sm">
2156
+ <span class="mkbd-label">Campo</span>
2157
+ <input [ngModel]="key" (change)="renameField(i, key, $event)" />
2158
+ </label>
2159
+ <label class="mkbd-field mkbd-field-grow">
2160
+ <span class="mkbd-label">Valor</span>
2161
+ <input
2162
+ [ngModel]="display(item, key)"
2163
+ (ngModelChange)="setItemProp(i, key, coerceValue($event))"
2164
+ />
2165
+ </label>
2166
+ <button
2167
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2168
+ type="button"
2169
+ (click)="removeField(i, key)"
2170
+ aria-label="Remover campo"
2171
+ >
2172
+ <mkb-icon name="close" />
2173
+ </button>
2174
+ </div>
2175
+ }
2176
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addField(i)">
2177
+ <mkb-icon name="add" />
2178
+ Campo
2179
+ </button>
2180
+
2181
+ @for (def of entryDefs(); track def.field) {
2182
+ <div class="mkbd-subsection">
2183
+ <span class="mkbd-overline">Itens internos · {{ def.field }}</span>
2184
+ </div>
2185
+ @for (entry of entriesOf(item, def.field); track $index; let ei = $index) {
2186
+ <div class="mkbd-stack mkbd-field-row">
2187
+ @if (def.checkField; as checkField) {
2188
+ <label class="mkbd-check">
2189
+ <input
2190
+ type="checkbox"
2191
+ [ngModel]="entry[checkField] === true"
2192
+ (ngModelChange)="setEntryProp(i, def.field, ei, checkField, $event)"
2193
+ />
2194
+ Feito
2195
+ </label>
2196
+ }
2197
+ <label class="mkbd-field mkbd-field-grow">
2198
+ <span class="mkbd-label">{{ def.labelField }}</span>
2199
+ <input
2200
+ [ngModel]="str(entry, def.labelField)"
2201
+ (ngModelChange)="setEntryProp(i, def.field, ei, def.labelField, $event)"
2202
+ />
2203
+ </label>
2204
+ <button
2205
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2206
+ type="button"
2207
+ (click)="removeEntry(i, def.field, ei)"
2208
+ aria-label="Remover item interno"
2209
+ >
2210
+ <mkb-icon name="close" />
2211
+ </button>
2212
+ </div>
2213
+ }
2214
+ <button class="mkbd-add mkbd-add-sm" type="button" (click)="addEntry(i, def)">
2215
+ <mkb-icon name="add" />
2216
+ Item interno
2217
+ </button>
2218
+ }
2219
+ </div>
2220
+ }
2221
+ </div>
1574
2222
  }
1575
- </mat-accordion>
1576
- <button matButton class="mkbd-mt" type="button" (click)="addItem()">+ Adicionar item</button>
2223
+ </div>
2224
+
2225
+ <button class="mkbd-add" type="button" (click)="addItem()">
2226
+ <mkb-icon name="add" />
2227
+ Adicionar item
2228
+ </button>
1577
2229
 
1578
- <h3 class="mkbd-h">Filtros iniciais (JSON)</h3>
2230
+ <div class="mkbd-section">
2231
+ <span class="mkbd-overline">Filtros iniciais</span>
2232
+ </div>
1579
2233
  <p class="mkbd-hint">Array de KanbanFilter aplicado na criação do board; vazio remove.</p>
1580
- <mat-form-field appearance="outline" class="mkbd-full">
1581
- <mat-label>filters</mat-label>
1582
- <textarea matInput rows="4" [value]="filtersJson()" (change)="setFilters($event)"></textarea>
1583
- @if (filtersError(); as err) {
1584
- <mat-hint class="mkbd-error">{{ err }}</mat-hint>
1585
- }
1586
- </mat-form-field>
1587
- `, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-h:first-child{margin-top:0}.mkbd-h4{margin:12px 0 6px;font-size:12px;font-weight:600;color:var(--mkb-muted, #6f6a7c)}.mkbd-hint{margin:0 0 8px;font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:8px;align-items:center;margin-bottom:2px}.mkbd-mt{margin-top:10px}.mkbd-slim{width:180px}.mkbd-grow{flex:1;min-width:180px}.mkbd-full{width:100%}.mkbd-panel{border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px!important;margin-bottom:6px}.mkbd-error{color:var(--mkb-danger, #b3261e)}\n"] }]
2234
+ <label class="mkbd-field mkbd-field-area mkbd-field-full">
2235
+ <span class="mkbd-label">filters (JSON)</span>
2236
+ <textarea rows="4" [value]="filtersJson()" (change)="setFilters($event)"></textarea>
2237
+ </label>
2238
+ @if (filtersError(); as err) {
2239
+ <p class="mkbd-error-text">{{ err }}</p>
2240
+ }
2241
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-item{display:block;padding:0;border-left-color:var(--mkbd-border-strong)}.mkbd-item-head{display:flex;align-items:center;gap:4px;padding:6px 8px 6px 4px}.mkbd-item-toggle{flex:1;display:flex;align-items:center;gap:8px;min-width:0;padding:6px 8px;border:none;border-radius:var(--mkbd-radius-sm);background:transparent;color:inherit;font:inherit;text-align:left;cursor:pointer}.mkbd-item-toggle:hover{background:var(--mkbd-panel-3)}.mkbd-item-toggle:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-item-toggle>mkb-icon{font-size:18px;color:var(--mkbd-muted)}.mkbd-item-title{font-weight:500;font-size:12.5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-item-where{margin-left:auto;font:500 10px var(--mkbd-font-mono);color:var(--mkbd-muted);background:var(--mkbd-panel-3);padding:2px 8px;border-radius:var(--mkbd-radius-pill);white-space:nowrap}.mkbd-item-body{padding:4px 12px 14px;border-top:1px solid var(--mkbd-border-soft)}.mkbd-item-body .mkbd-field>.mkbd-label{background:var(--mkbd-panel)}.mkbd-subsection{margin:16px 0 10px}.mkbd-field-row{margin-bottom:10px;flex-wrap:nowrap}.mkbd-add-sm{height:34px;margin-top:0;font-size:12px}.mkbd-error-text{margin:6px 0 0;font-size:11.5px;color:var(--mkbd-error)}.mkbd-field-full{width:100%}\n"] }]
1588
2242
  }] });
1589
2243
 
1590
2244
  /**
1591
2245
  * Editor do PIPELINE: eixos (colunas/lanes — estáticos ou derivados),
1592
- * regras de transição/nomeadas e ordenação. Todos os recursos flexíveis
1593
- * do BoardConfig fora do cartão.
2246
+ * regras de transição/nomeadas e ordenação.
2247
+ *
2248
+ * Visual: "linha de lista editável" do DS (§16 dos Componentes) — cada grupo
2249
+ * é um card em grid com acento de cor, alça, campos outline e controles de
2250
+ * ordem, como na tela 13a.
1594
2251
  */
1595
2252
  class MkbPipelineEditor {
1596
2253
  store = inject(DesignerStore);
1597
2254
  config = this.store.config;
2255
+ /** Cor default por posição — a paleta de dados do DS (--viz-*). */
2256
+ static PALETTE = ['#6f6a7c', '#2264c4', '#9a6b00', '#2e7d32', '#c62828', '#00897b'];
2257
+ // Opções fixas: constantes de instância (referência estável entre ciclos).
2258
+ modeOptions = [
2259
+ { value: 'static', label: 'Estático (grupos)' },
2260
+ { value: 'derived', label: 'Derivado (dinâmico)' },
2261
+ ];
2262
+ sortGroupOptions = [
2263
+ { value: '', label: 'Ordem declarada' },
2264
+ { value: 'asc', label: 'Crescente' },
2265
+ { value: 'desc', label: 'Decrescente' },
2266
+ ];
2267
+ directionOptions = [
2268
+ { value: 'asc', label: 'Crescente' },
2269
+ { value: 'desc', label: 'Decrescente' },
2270
+ ];
2271
+ /** Opções derivadas da config — computed, para não realocar a cada ciclo.
2272
+ * Nas regras o rótulo é o ID puro: é ele que a transição referencia. */
2273
+ columnOptions = computed(() => (this.store.columnsAxis().groups ?? []).map((g) => ({ value: g.id, label: g.id })), ...(ngDevMode ? [{ debugName: "columnOptions" }] : /* istanbul ignore next */ []));
2274
+ fromOptions = computed(() => [
2275
+ { value: '*', label: 'Qualquer' },
2276
+ ...this.columnOptions(),
2277
+ ], ...(ngDevMode ? [{ debugName: "fromOptions" }] : /* istanbul ignore next */ []));
1598
2278
  columnIds() {
1599
2279
  return (this.store.columnsAxis().groups ?? []).map((g) => g.id);
1600
2280
  }
@@ -1642,9 +2322,14 @@ class MkbPipelineEditor {
1642
2322
  group[prop] = value;
1643
2323
  });
1644
2324
  }
1645
- groupColor(group) {
1646
- const c = group.meta?.['color'];
1647
- return typeof c === 'string' ? c : '#efedf3';
2325
+ /** Cor do grupo: `meta.color` do host ou a cor default da POSIÇÃO na lista
2326
+ * (só exibição — nada é gravado na config até o usuário escolher uma cor). */
2327
+ groupColor(group, index = 0) {
2328
+ const color = group.meta?.['color'];
2329
+ if (typeof color === 'string')
2330
+ return color;
2331
+ const palette = MkbPipelineEditor.PALETTE;
2332
+ return palette[index % palette.length];
1648
2333
  }
1649
2334
  setGroupColor(key, index, color) {
1650
2335
  this.store.update((d) => {
@@ -1657,12 +2342,19 @@ class MkbPipelineEditor {
1657
2342
  addGroup(key) {
1658
2343
  this.store.update((d) => {
1659
2344
  const groups = this.draftAxis(d, key).groups;
1660
- groups?.push({ id: `grupo-${(groups.length + 1)}` });
2345
+ groups?.push({ id: `grupo-${groups.length + 1}` });
1661
2346
  });
1662
2347
  }
1663
2348
  removeGroup(key, index) {
1664
2349
  this.store.update((d) => this.draftAxis(d, key).groups?.splice(index, 1));
1665
2350
  }
2351
+ /** Arraste (CDK) — mesma reordenação das setas ↑↓, por posição absoluta. */
2352
+ dropGroup(key, event) {
2353
+ const { previousIndex, currentIndex } = event;
2354
+ if (previousIndex === currentIndex)
2355
+ return;
2356
+ this.moveGroup(key, previousIndex, currentIndex - previousIndex);
2357
+ }
1666
2358
  moveGroup(key, index, delta) {
1667
2359
  this.store.update((d) => {
1668
2360
  const groups = this.draftAxis(d, key).groups;
@@ -1693,9 +2385,6 @@ class MkbPipelineEditor {
1693
2385
  fromOf(t) {
1694
2386
  return typeof t.from === 'string' ? t.from : Array.isArray(t.from) ? (t.from[0] ?? '*') : '*';
1695
2387
  }
1696
- toOf(t) {
1697
- return typeof t.to === 'string' ? [t.to] : (t.to ?? []);
1698
- }
1699
2388
  addTransition() {
1700
2389
  this.store.update((d) => {
1701
2390
  d.rules ??= {};
@@ -1773,383 +2462,533 @@ class MkbPipelineEditor {
1773
2462
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbPipelineEditor, deps: [], target: i0.ɵɵFactoryTarget.Component });
1774
2463
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MkbPipelineEditor, isStandalone: true, selector: "mkb-pipeline-editor", ngImport: i0, template: `
1775
2464
  <!-- ======================= COLUNAS ======================= -->
1776
- <h3 class="mkbd-h">Colunas</h3>
1777
2465
  <ng-container
1778
2466
  *ngTemplateOutlet="axisEditor; context: { axis: store.columnsAxis(), key: 'columns' }"
1779
2467
  />
1780
2468
 
1781
- <!-- ======================= LANES ========================= -->
1782
- <h3 class="mkbd-h">
1783
- Lanes (swimlanes)
1784
- <mat-slide-toggle
1785
- [ngModel]="!!store.lanesAxis()"
1786
- (ngModelChange)="toggleLanes($event)"
1787
- aria-label="Usar lanes"
1788
- />
1789
- </h3>
2469
+ <!-- ======================== LANES ======================== -->
2470
+ <div class="mkbd-feature">
2471
+ <mkb-icon name="rows" />
2472
+ <div>
2473
+ <div class="mkbd-feature-title">Lanes (swimlanes)</div>
2474
+ <div class="mkbd-feature-desc">Agrupa cartões em faixas horizontais por um eixo</div>
2475
+ </div>
2476
+ <label class="mkbd-switch">
2477
+ <input
2478
+ type="checkbox"
2479
+ [ngModel]="!!store.lanesAxis()"
2480
+ (ngModelChange)="toggleLanes($event)"
2481
+ aria-label="Usar lanes"
2482
+ />
2483
+ </label>
2484
+ </div>
1790
2485
  @if (store.lanesAxis(); as lanes) {
1791
2486
  <ng-container *ngTemplateOutlet="axisEditor; context: { axis: lanes, key: 'lanes' }" />
1792
2487
  }
1793
2488
 
1794
2489
  <!-- ================= EDITOR DE EIXO (template) ============ -->
1795
2490
  <ng-template #axisEditor let-axis="axis" let-key="key">
1796
- <div class="mkbd-row">
1797
- <mat-form-field appearance="outline" class="mkbd-slim">
1798
- <mat-label>Modo</mat-label>
1799
- <mat-select
1800
- [ngModel]="axis.groups ? 'static' : 'derived'"
1801
- (ngModelChange)="setAxisMode(key, $event)"
1802
- >
1803
- <mat-option value="static">Estático (grupos declarados)</mat-option>
1804
- <mat-option value="derived">Derivado (agrupamento dinâmico)</mat-option>
1805
- </mat-select>
1806
- </mat-form-field>
1807
- <mat-form-field appearance="outline" class="mkbd-slim">
1808
- <mat-label>Campo do item</mat-label>
2491
+ <div class="mkbd-options">
2492
+ <mkb-combo
2493
+ label="Modo"
2494
+ [options]="modeOptions"
2495
+ [value]="axis.groups ? 'static' : 'derived'"
2496
+ (valueChange)="setAxisMode(key, $any($event))"
2497
+ />
2498
+ <label class="mkbd-field">
2499
+ <span class="mkbd-label">Campo do item</span>
1809
2500
  <input
1810
- matInput
1811
2501
  [ngModel]="axis.field ?? ''"
1812
2502
  (ngModelChange)="setAxisProp(key, 'field', $event || undefined)"
1813
2503
  [placeholder]="key === 'columns' ? 'column' : 'lane'"
1814
2504
  />
1815
- </mat-form-field>
1816
- <mat-form-field appearance="outline" class="mkbd-slim">
1817
- <mat-label>Ordenar grupos</mat-label>
1818
- <mat-select
1819
- [ngModel]="axis.sortGroups ?? ''"
1820
- (ngModelChange)="setAxisProp(key, 'sortGroups', $event || undefined)"
1821
- >
1822
- <mat-option value="">Ordem declarada / de aparição</mat-option>
1823
- <mat-option value="asc">Crescente</mat-option>
1824
- <mat-option value="desc">Decrescente</mat-option>
1825
- </mat-select>
1826
- </mat-form-field>
2505
+ </label>
2506
+ <mkb-combo
2507
+ label="Ordenar grupos"
2508
+ [options]="sortGroupOptions"
2509
+ [value]="axis.sortGroups ?? ''"
2510
+ (valueChange)="setAxisProp(key, 'sortGroups', $event || undefined)"
2511
+ />
1827
2512
  @if (axis.groups) {
1828
- <mat-slide-toggle
1829
- [ngModel]="axis.reorderable ?? false"
1830
- (ngModelChange)="setAxisProp(key, 'reorderable', $event || undefined)"
1831
- >
1832
- Reordenável (arrastar)
1833
- </mat-slide-toggle>
2513
+ <label class="mkbd-switch mkbd-switch-boxed">
2514
+ <input
2515
+ type="checkbox"
2516
+ [ngModel]="axis.reorderable ?? false"
2517
+ (ngModelChange)="setAxisProp(key, 'reorderable', $event || undefined)"
2518
+ />
2519
+ Reordenável
2520
+ </label>
1834
2521
  }
1835
2522
  </div>
1836
2523
 
1837
2524
  @if (axis.groups; as groups) {
1838
- <div class="mkbd-groups">
2525
+ <div class="mkbd-section">
2526
+ <span class="mkbd-overline">{{ key === 'columns' ? 'Colunas' : 'Lanes' }}</span>
2527
+ <span class="mkbd-count">{{ groups.length }}</span>
2528
+ </div>
2529
+
2530
+ <div class="mkbd-rows" cdkDropList (cdkDropListDropped)="dropGroup(key, $event)">
1839
2531
  @for (group of groups; track $index; let i = $index) {
1840
- <div class="mkbd-group">
1841
- <mat-form-field appearance="outline" class="mkbd-slim">
1842
- <mat-label>Id</mat-label>
1843
- <input matInput [ngModel]="group.id" (ngModelChange)="setGroup(key, i, 'id', $event)" />
1844
- </mat-form-field>
1845
- <mat-form-field appearance="outline" class="mkbd-slim">
1846
- <mat-label>Título</mat-label>
1847
- <input matInput [ngModel]="group.title ?? ''" (ngModelChange)="setGroup(key, i, 'title', $event || undefined)" />
1848
- </mat-form-field>
1849
- <label class="mkbd-color">
1850
- Cor
2532
+ <div
2533
+ class="mkbd-row mkbd-row-group"
2534
+ cdkDrag
2535
+ cdkDragLockAxis="y"
2536
+ [cdkDragPreviewClass]="'mkbd-drag-preview'"
2537
+ [style.--mkbd-accent]="groupColor(group, i)"
2538
+ >
2539
+ <span
2540
+ class="mkbd-handle"
2541
+ cdkDragHandle
2542
+ [attr.aria-label]="'Arrastar ' + (group.title ?? group.id)"
2543
+ >
2544
+ <mkb-icon name="drag" />
2545
+ </span>
2546
+
2547
+ <label class="mkbd-field mkbd-field-mono">
2548
+ <span class="mkbd-label">Id</span>
2549
+ <input [ngModel]="group.id" (ngModelChange)="setGroup(key, i, 'id', $event)" />
2550
+ </label>
2551
+
2552
+ <label class="mkbd-field">
2553
+ <span class="mkbd-label">Título</span>
2554
+ <input
2555
+ [ngModel]="group.title ?? ''"
2556
+ (ngModelChange)="setGroup(key, i, 'title', $event || undefined)"
2557
+ />
2558
+ </label>
2559
+
2560
+ <label class="mkbd-swatch" [title]="'Cor de ' + (group.title ?? group.id)">
1851
2561
  <input
1852
2562
  type="color"
1853
- [ngModel]="groupColor(group)"
2563
+ [ngModel]="groupColor(group, i)"
1854
2564
  (ngModelChange)="setGroupColor(key, i, $event)"
2565
+ [attr.aria-label]="'Cor de ' + (group.title ?? group.id)"
1855
2566
  />
2567
+ <span [style.background]="groupColor(group, i)"></span>
1856
2568
  </label>
1857
- <mat-form-field appearance="outline" class="mkbd-tiny">
1858
- <mat-label>WIP</mat-label>
2569
+
2570
+ <label class="mkbd-field mkbd-field-optional">
2571
+ <span class="mkbd-label">WIP</span>
1859
2572
  <input
1860
- matInput
1861
2573
  type="number"
1862
2574
  min="0"
2575
+ placeholder="∞"
1863
2576
  [ngModel]="group.limit ?? null"
1864
2577
  (ngModelChange)="setGroup(key, i, 'limit', $event === null || $event === '' ? undefined : +$event)"
1865
2578
  />
1866
- </mat-form-field>
1867
- <mat-checkbox
1868
- [ngModel]="group.locked ?? false"
1869
- (ngModelChange)="setGroup(key, i, 'locked', $event || undefined)"
1870
- >
1871
- Travado
1872
- </mat-checkbox>
1873
- <span class="mkbd-spacer"></span>
1874
- <button matIconButton type="button" (click)="moveGroup(key, i, -1)" [disabled]="i === 0" aria-label="Subir">↑</button>
1875
- <button matIconButton type="button" (click)="moveGroup(key, i, 1)" [disabled]="i === groups.length - 1" aria-label="Descer">↓</button>
1876
- <button matIconButton type="button" (click)="removeGroup(key, i)" aria-label="Remover grupo">✕</button>
2579
+ </label>
2580
+
2581
+ <div class="mkbd-row-ctrls">
2582
+ <label class="mkbd-check">
2583
+ <input
2584
+ type="checkbox"
2585
+ [ngModel]="group.locked ?? false"
2586
+ (ngModelChange)="setGroup(key, i, 'locked', $event || undefined)"
2587
+ />
2588
+ Travado
2589
+ </label>
2590
+ <button
2591
+ class="mkbd-icon-btn"
2592
+ type="button"
2593
+ (click)="moveGroup(key, i, -1)"
2594
+ [disabled]="i === 0"
2595
+ aria-label="Mover para cima"
2596
+ >
2597
+ <mkb-icon name="up" />
2598
+ </button>
2599
+ <button
2600
+ class="mkbd-icon-btn"
2601
+ type="button"
2602
+ (click)="moveGroup(key, i, 1)"
2603
+ [disabled]="i === groups.length - 1"
2604
+ aria-label="Mover para baixo"
2605
+ >
2606
+ <mkb-icon name="down" />
2607
+ </button>
2608
+ <button
2609
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2610
+ type="button"
2611
+ (click)="removeGroup(key, i)"
2612
+ aria-label="Remover grupo"
2613
+ >
2614
+ <mkb-icon name="close" />
2615
+ </button>
2616
+ </div>
1877
2617
  </div>
1878
2618
  }
1879
- <button matButton type="button" (click)="addGroup(key)">+ Adicionar {{ key === 'columns' ? 'coluna' : 'lane' }}</button>
1880
2619
  </div>
2620
+
2621
+ <button class="mkbd-add" type="button" (click)="addGroup(key)">
2622
+ <mkb-icon name="add" />
2623
+ Adicionar {{ key === 'columns' ? 'coluna' : 'lane' }}
2624
+ </button>
1881
2625
  }
1882
2626
  </ng-template>
1883
2627
 
1884
2628
  <!-- ======================= REGRAS ========================= -->
1885
- <h3 class="mkbd-h">Regras de transição (colunas)</h3>
2629
+ <div class="mkbd-section">
2630
+ <span class="mkbd-overline">Regras de transição</span>
2631
+ @if (transitions().length) {
2632
+ <span class="mkbd-count">{{ transitions().length }}</span>
2633
+ }
2634
+ </div>
1886
2635
  <p class="mkbd-hint">
1887
- Sem linhas = qualquer transição é permitida. Com linhas, as listadas passam.
2636
+ Sem regras = qualquer transição é permitida. Com regras, as listadas passam.
1888
2637
  </p>
1889
- @for (t of transitions(); track $index; let i = $index) {
1890
- <div class="mkbd-row">
1891
- <mat-form-field appearance="outline" class="mkbd-slim">
1892
- <mat-label>De</mat-label>
1893
- <mat-select [ngModel]="fromOf(t)" (ngModelChange)="setTransition(i, 'from', $event)">
1894
- <mat-option value="*">Qualquer</mat-option>
1895
- @for (id of columnIds(); track id) {
1896
- <mat-option [value]="id">{{ id }}</mat-option>
1897
- }
1898
- </mat-select>
1899
- </mat-form-field>
1900
- <mat-form-field appearance="outline" class="mkbd-grow">
1901
- <mat-label>Para</mat-label>
1902
- <mat-select multiple [ngModel]="toOf(t)" (ngModelChange)="setTransition(i, 'to', $event)">
1903
- @for (id of columnIds(); track id) {
1904
- <mat-option [value]="id">{{ id }}</mat-option>
1905
- }
1906
- </mat-select>
1907
- </mat-form-field>
1908
- <button matIconButton type="button" (click)="removeTransition(i)" aria-label="Remover transição">✕</button>
2638
+
2639
+ @if (transitions().length) {
2640
+ <div class="mkbd-rows">
2641
+ @for (t of transitions(); track $index; let i = $index) {
2642
+ <div class="mkbd-row mkbd-row-rule">
2643
+ <mkb-combo
2644
+ label="De"
2645
+ [options]="fromOptions()"
2646
+ [value]="fromOf(t)"
2647
+ (valueChange)="setTransition(i, 'from', $event)"
2648
+ />
2649
+ <!-- Destino é multi-seleção: o valor vem da própria config (sem
2650
+ alocar array a cada ciclo, que foi o que travou a tela). -->
2651
+ <mkb-combo
2652
+ label="Para"
2653
+ [multiple]="true"
2654
+ placeholder="Qualquer"
2655
+ [options]="columnOptions()"
2656
+ [value]="t.to ?? null"
2657
+ (valuesChange)="setTransition(i, 'to', $event)"
2658
+ />
2659
+ <button
2660
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2661
+ type="button"
2662
+ (click)="removeTransition(i)"
2663
+ aria-label="Remover transição"
2664
+ >
2665
+ <mkb-icon name="close" />
2666
+ </button>
2667
+ </div>
2668
+ }
1909
2669
  </div>
1910
2670
  }
1911
- <button matButton type="button" (click)="addTransition()">+ Adicionar transição</button>
2671
+ <button class="mkbd-btn mkbd-btn-outline mkbd-btn-block" type="button" (click)="addTransition()">
2672
+ <mkb-icon name="add" />
2673
+ Adicionar transição
2674
+ </button>
1912
2675
 
1913
- <div class="mkbd-row mkbd-mt">
1914
- <mat-form-field appearance="outline" class="mkbd-grow">
1915
- <mat-label>Regras nomeadas de cartão (rule:*)</mat-label>
2676
+ <div class="mkbd-section">
2677
+ <span class="mkbd-overline">Regras nomeadas</span>
2678
+ </div>
2679
+ <p class="mkbd-hint">Os nomes referenciam código registrado pelo host no KanbanRegistry.</p>
2680
+ <div class="mkbd-stack">
2681
+ <label class="mkbd-field mkbd-field-grow">
2682
+ <span class="mkbd-label">Regras de cartão (rule:*)</span>
1916
2683
  <input
1917
- matInput
1918
2684
  [ngModel]="namesOf('rules')"
1919
2685
  (ngModelChange)="setNames('rules', $event)"
1920
2686
  placeholder="rule:berco-livre, rule:sla"
1921
2687
  />
1922
- </mat-form-field>
1923
- <mat-form-field appearance="outline" class="mkbd-grow">
1924
- <mat-label>Regras nomeadas de itens (entryRules)</mat-label>
1925
- <input matInput [ngModel]="namesOf('entryRules')" (ngModelChange)="setNames('entryRules', $event)" />
1926
- </mat-form-field>
2688
+ </label>
2689
+ <label class="mkbd-field mkbd-field-grow">
2690
+ <span class="mkbd-label">Regras de itens (entryRules)</span>
2691
+ <input [ngModel]="namesOf('entryRules')" (ngModelChange)="setNames('entryRules', $event)" />
2692
+ </label>
1927
2693
  </div>
1928
- <p class="mkbd-hint">Os nomes referenciam código registrado pelo host no KanbanRegistry.</p>
1929
2694
 
1930
2695
  <!-- ================== ORDENAÇÃO / GERAL ==================== -->
1931
- <h3 class="mkbd-h">Ordenação e geral</h3>
1932
- <div class="mkbd-row">
1933
- <mat-slide-toggle [ngModel]="!!config().sort" (ngModelChange)="toggleSort($event)">
2696
+ <div class="mkbd-section">
2697
+ <span class="mkbd-overline">Ordenação e geral</span>
2698
+ </div>
2699
+ <div class="mkbd-stack">
2700
+ <label class="mkbd-switch mkbd-switch-boxed">
2701
+ <input type="checkbox" [ngModel]="!!config().sort" (ngModelChange)="toggleSort($event)" />
1934
2702
  Ordenar itens por campo
1935
- </mat-slide-toggle>
2703
+ </label>
1936
2704
  @if (config().sort; as sort) {
1937
- <mat-form-field appearance="outline" class="mkbd-slim">
1938
- <mat-label>Campo</mat-label>
1939
- <input matInput [ngModel]="sort.field" (ngModelChange)="setSort('field', $event)" />
1940
- </mat-form-field>
1941
- <mat-form-field appearance="outline" class="mkbd-slim">
1942
- <mat-label>Direção</mat-label>
1943
- <mat-select [ngModel]="sort.direction ?? 'asc'" (ngModelChange)="setSort('direction', $event)">
1944
- <mat-option value="asc">Crescente</mat-option>
1945
- <mat-option value="desc">Decrescente</mat-option>
1946
- </mat-select>
1947
- </mat-form-field>
2705
+ <label class="mkbd-field">
2706
+ <span class="mkbd-label">Campo</span>
2707
+ <input [ngModel]="sort.field" (ngModelChange)="setSort('field', $event)" />
2708
+ </label>
2709
+ <mkb-combo
2710
+ label="Direção"
2711
+ [options]="directionOptions"
2712
+ [value]="sort.direction ?? 'asc'"
2713
+ (valueChange)="setSort('direction', $event)"
2714
+ />
1948
2715
  }
1949
- <mat-slide-toggle
1950
- [ngModel]="config().readOnly ?? false"
1951
- (ngModelChange)="setReadOnly($event)"
1952
- >
2716
+ <label class="mkbd-switch mkbd-switch-boxed">
2717
+ <input
2718
+ type="checkbox"
2719
+ [ngModel]="config().readOnly ?? false"
2720
+ (ngModelChange)="setReadOnly($event)"
2721
+ />
1953
2722
  Somente leitura
1954
- </mat-slide-toggle>
2723
+ </label>
1955
2724
  </div>
1956
- `, isInline: true, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600;display:flex;align-items:center;gap:12px}.mkbd-h:first-child{margin-top:0}.mkbd-hint{margin:0 0 8px;font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.mkbd-mt{margin-top:10px}.mkbd-groups{display:flex;flex-direction:column;gap:4px}.mkbd-group{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:4px 8px;border:1px dashed var(--mkb-border, #e3e0ea);border-radius:8px}.mkbd-slim{width:170px}.mkbd-tiny{width:90px}.mkbd-grow{flex:1;min-width:200px}.mkbd-spacer{flex:1}.mkbd-color{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--mkb-muted, #6f6a7c)}.mkbd-color input{width:34px;height:28px;border:none;background:none;padding:0;cursor:pointer}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.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.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: MatSelectModule }, { kind: "component", type: i4.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth", "canSelectNullableOptions"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i4.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "ngmodule", type: MatSlideToggleModule }, { kind: "component", type: i5.MatSlideToggle, selector: "mat-slide-toggle", inputs: ["name", "id", "labelPosition", "aria-label", "aria-labelledby", "aria-describedby", "required", "color", "disabled", "disableRipple", "tabIndex", "checked", "hideIcon", "disabledInteractive"], outputs: ["change", "toggleChange"], exportAs: ["matSlideToggle"] }, { kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i6.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "aria-expanded", "aria-controls", "aria-owns", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }, { kind: "ngmodule", type: MatExpansionModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2725
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-row-group{grid-template-columns:22px minmax(0,1.1fr) minmax(0,1.3fr) 42px 76px auto}.mkbd-row-rule{grid-template-columns:minmax(0,1fr) minmax(0,1.6fr) auto;border-left-color:var(--mkbd-border-strong)}.mkbd-btn-block{margin-top:4px}.mkbd-combo-btn{flex:1;min-width:0;height:100%;padding:0 16px 0 0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-field-combo:has(.mkbd-combo-btn:focus-visible){border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-combo-empty{color:var(--mkbd-muted)}.mkbd-handle[cdkDragHandle]{cursor:grab;touch-action:none}.mkbd-row.cdk-drag-preview{box-shadow:var(--elevation-3, 0 8px 30px rgba(20, 22, 30, .14));opacity:.96}.mkbd-row.cdk-drag-placeholder{opacity:.35}.mkbd-rows.cdk-drop-list-dragging .mkbd-row:not(.cdk-drag-placeholder){transition:transform var(--mkbd-dur) var(--mkbd-ease)}@media(max-width:720px){.mkbd-row-group{grid-template-columns:22px minmax(0,1fr) 42px 76px}.mkbd-row-group .mkbd-row-ctrls{grid-column:1 / -1;justify-content:flex-end}}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1$1.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i1$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: CdkDropList, selector: "[cdkDropList], cdk-drop-list", inputs: ["cdkDropListConnectedTo", "cdkDropListData", "cdkDropListOrientation", "id", "cdkDropListLockAxis", "cdkDropListDisabled", "cdkDropListSortingDisabled", "cdkDropListEnterPredicate", "cdkDropListSortPredicate", "cdkDropListAutoScrollDisabled", "cdkDropListAutoScrollStep", "cdkDropListElementContainer", "cdkDropListHasAnchor"], outputs: ["cdkDropListDropped", "cdkDropListEntered", "cdkDropListExited", "cdkDropListSorted"], exportAs: ["cdkDropList"] }, { kind: "directive", type: CdkDrag, selector: "[cdkDrag]", inputs: ["cdkDragData", "cdkDragLockAxis", "cdkDragRootElement", "cdkDragBoundary", "cdkDragStartDelay", "cdkDragFreeDragPosition", "cdkDragDisabled", "cdkDragConstrainPosition", "cdkDragPreviewClass", "cdkDragPreviewContainer", "cdkDragScale"], outputs: ["cdkDragStarted", "cdkDragReleased", "cdkDragEnded", "cdkDragEntered", "cdkDragExited", "cdkDragDropped", "cdkDragMoved"], exportAs: ["cdkDrag"] }, { kind: "directive", type: CdkDragHandle, selector: "[cdkDragHandle]", inputs: ["cdkDragHandleDisabled"] }, { kind: "component", type: MkbCombo, selector: "mkb-combo", inputs: ["label", "options", "value", "multiple", "placeholder"], outputs: ["valueChange", "valuesChange"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1957
2726
  }
1958
2727
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbPipelineEditor, decorators: [{
1959
2728
  type: Component,
1960
- args: [{ selector: 'mkb-pipeline-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [
1961
- NgTemplateOutlet,
1962
- FormsModule,
1963
- MatFormFieldModule,
1964
- MatInputModule,
1965
- MatSelectModule,
1966
- MatSlideToggleModule,
1967
- MatCheckboxModule,
1968
- MatButtonModule,
1969
- MatExpansionModule,
1970
- ], template: `
2729
+ args: [{ selector: 'mkb-pipeline-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgTemplateOutlet, FormsModule, CdkDropList, CdkDrag, CdkDragHandle, MkbCombo, MkbIcon], template: `
1971
2730
  <!-- ======================= COLUNAS ======================= -->
1972
- <h3 class="mkbd-h">Colunas</h3>
1973
2731
  <ng-container
1974
2732
  *ngTemplateOutlet="axisEditor; context: { axis: store.columnsAxis(), key: 'columns' }"
1975
2733
  />
1976
2734
 
1977
- <!-- ======================= LANES ========================= -->
1978
- <h3 class="mkbd-h">
1979
- Lanes (swimlanes)
1980
- <mat-slide-toggle
1981
- [ngModel]="!!store.lanesAxis()"
1982
- (ngModelChange)="toggleLanes($event)"
1983
- aria-label="Usar lanes"
1984
- />
1985
- </h3>
2735
+ <!-- ======================== LANES ======================== -->
2736
+ <div class="mkbd-feature">
2737
+ <mkb-icon name="rows" />
2738
+ <div>
2739
+ <div class="mkbd-feature-title">Lanes (swimlanes)</div>
2740
+ <div class="mkbd-feature-desc">Agrupa cartões em faixas horizontais por um eixo</div>
2741
+ </div>
2742
+ <label class="mkbd-switch">
2743
+ <input
2744
+ type="checkbox"
2745
+ [ngModel]="!!store.lanesAxis()"
2746
+ (ngModelChange)="toggleLanes($event)"
2747
+ aria-label="Usar lanes"
2748
+ />
2749
+ </label>
2750
+ </div>
1986
2751
  @if (store.lanesAxis(); as lanes) {
1987
2752
  <ng-container *ngTemplateOutlet="axisEditor; context: { axis: lanes, key: 'lanes' }" />
1988
2753
  }
1989
2754
 
1990
2755
  <!-- ================= EDITOR DE EIXO (template) ============ -->
1991
2756
  <ng-template #axisEditor let-axis="axis" let-key="key">
1992
- <div class="mkbd-row">
1993
- <mat-form-field appearance="outline" class="mkbd-slim">
1994
- <mat-label>Modo</mat-label>
1995
- <mat-select
1996
- [ngModel]="axis.groups ? 'static' : 'derived'"
1997
- (ngModelChange)="setAxisMode(key, $event)"
1998
- >
1999
- <mat-option value="static">Estático (grupos declarados)</mat-option>
2000
- <mat-option value="derived">Derivado (agrupamento dinâmico)</mat-option>
2001
- </mat-select>
2002
- </mat-form-field>
2003
- <mat-form-field appearance="outline" class="mkbd-slim">
2004
- <mat-label>Campo do item</mat-label>
2757
+ <div class="mkbd-options">
2758
+ <mkb-combo
2759
+ label="Modo"
2760
+ [options]="modeOptions"
2761
+ [value]="axis.groups ? 'static' : 'derived'"
2762
+ (valueChange)="setAxisMode(key, $any($event))"
2763
+ />
2764
+ <label class="mkbd-field">
2765
+ <span class="mkbd-label">Campo do item</span>
2005
2766
  <input
2006
- matInput
2007
2767
  [ngModel]="axis.field ?? ''"
2008
2768
  (ngModelChange)="setAxisProp(key, 'field', $event || undefined)"
2009
2769
  [placeholder]="key === 'columns' ? 'column' : 'lane'"
2010
2770
  />
2011
- </mat-form-field>
2012
- <mat-form-field appearance="outline" class="mkbd-slim">
2013
- <mat-label>Ordenar grupos</mat-label>
2014
- <mat-select
2015
- [ngModel]="axis.sortGroups ?? ''"
2016
- (ngModelChange)="setAxisProp(key, 'sortGroups', $event || undefined)"
2017
- >
2018
- <mat-option value="">Ordem declarada / de aparição</mat-option>
2019
- <mat-option value="asc">Crescente</mat-option>
2020
- <mat-option value="desc">Decrescente</mat-option>
2021
- </mat-select>
2022
- </mat-form-field>
2771
+ </label>
2772
+ <mkb-combo
2773
+ label="Ordenar grupos"
2774
+ [options]="sortGroupOptions"
2775
+ [value]="axis.sortGroups ?? ''"
2776
+ (valueChange)="setAxisProp(key, 'sortGroups', $event || undefined)"
2777
+ />
2023
2778
  @if (axis.groups) {
2024
- <mat-slide-toggle
2025
- [ngModel]="axis.reorderable ?? false"
2026
- (ngModelChange)="setAxisProp(key, 'reorderable', $event || undefined)"
2027
- >
2028
- Reordenável (arrastar)
2029
- </mat-slide-toggle>
2779
+ <label class="mkbd-switch mkbd-switch-boxed">
2780
+ <input
2781
+ type="checkbox"
2782
+ [ngModel]="axis.reorderable ?? false"
2783
+ (ngModelChange)="setAxisProp(key, 'reorderable', $event || undefined)"
2784
+ />
2785
+ Reordenável
2786
+ </label>
2030
2787
  }
2031
2788
  </div>
2032
2789
 
2033
2790
  @if (axis.groups; as groups) {
2034
- <div class="mkbd-groups">
2791
+ <div class="mkbd-section">
2792
+ <span class="mkbd-overline">{{ key === 'columns' ? 'Colunas' : 'Lanes' }}</span>
2793
+ <span class="mkbd-count">{{ groups.length }}</span>
2794
+ </div>
2795
+
2796
+ <div class="mkbd-rows" cdkDropList (cdkDropListDropped)="dropGroup(key, $event)">
2035
2797
  @for (group of groups; track $index; let i = $index) {
2036
- <div class="mkbd-group">
2037
- <mat-form-field appearance="outline" class="mkbd-slim">
2038
- <mat-label>Id</mat-label>
2039
- <input matInput [ngModel]="group.id" (ngModelChange)="setGroup(key, i, 'id', $event)" />
2040
- </mat-form-field>
2041
- <mat-form-field appearance="outline" class="mkbd-slim">
2042
- <mat-label>Título</mat-label>
2043
- <input matInput [ngModel]="group.title ?? ''" (ngModelChange)="setGroup(key, i, 'title', $event || undefined)" />
2044
- </mat-form-field>
2045
- <label class="mkbd-color">
2046
- Cor
2798
+ <div
2799
+ class="mkbd-row mkbd-row-group"
2800
+ cdkDrag
2801
+ cdkDragLockAxis="y"
2802
+ [cdkDragPreviewClass]="'mkbd-drag-preview'"
2803
+ [style.--mkbd-accent]="groupColor(group, i)"
2804
+ >
2805
+ <span
2806
+ class="mkbd-handle"
2807
+ cdkDragHandle
2808
+ [attr.aria-label]="'Arrastar ' + (group.title ?? group.id)"
2809
+ >
2810
+ <mkb-icon name="drag" />
2811
+ </span>
2812
+
2813
+ <label class="mkbd-field mkbd-field-mono">
2814
+ <span class="mkbd-label">Id</span>
2815
+ <input [ngModel]="group.id" (ngModelChange)="setGroup(key, i, 'id', $event)" />
2816
+ </label>
2817
+
2818
+ <label class="mkbd-field">
2819
+ <span class="mkbd-label">Título</span>
2820
+ <input
2821
+ [ngModel]="group.title ?? ''"
2822
+ (ngModelChange)="setGroup(key, i, 'title', $event || undefined)"
2823
+ />
2824
+ </label>
2825
+
2826
+ <label class="mkbd-swatch" [title]="'Cor de ' + (group.title ?? group.id)">
2047
2827
  <input
2048
2828
  type="color"
2049
- [ngModel]="groupColor(group)"
2829
+ [ngModel]="groupColor(group, i)"
2050
2830
  (ngModelChange)="setGroupColor(key, i, $event)"
2831
+ [attr.aria-label]="'Cor de ' + (group.title ?? group.id)"
2051
2832
  />
2833
+ <span [style.background]="groupColor(group, i)"></span>
2052
2834
  </label>
2053
- <mat-form-field appearance="outline" class="mkbd-tiny">
2054
- <mat-label>WIP</mat-label>
2835
+
2836
+ <label class="mkbd-field mkbd-field-optional">
2837
+ <span class="mkbd-label">WIP</span>
2055
2838
  <input
2056
- matInput
2057
2839
  type="number"
2058
2840
  min="0"
2841
+ placeholder="∞"
2059
2842
  [ngModel]="group.limit ?? null"
2060
2843
  (ngModelChange)="setGroup(key, i, 'limit', $event === null || $event === '' ? undefined : +$event)"
2061
2844
  />
2062
- </mat-form-field>
2063
- <mat-checkbox
2064
- [ngModel]="group.locked ?? false"
2065
- (ngModelChange)="setGroup(key, i, 'locked', $event || undefined)"
2066
- >
2067
- Travado
2068
- </mat-checkbox>
2069
- <span class="mkbd-spacer"></span>
2070
- <button matIconButton type="button" (click)="moveGroup(key, i, -1)" [disabled]="i === 0" aria-label="Subir">↑</button>
2071
- <button matIconButton type="button" (click)="moveGroup(key, i, 1)" [disabled]="i === groups.length - 1" aria-label="Descer">↓</button>
2072
- <button matIconButton type="button" (click)="removeGroup(key, i)" aria-label="Remover grupo">✕</button>
2845
+ </label>
2846
+
2847
+ <div class="mkbd-row-ctrls">
2848
+ <label class="mkbd-check">
2849
+ <input
2850
+ type="checkbox"
2851
+ [ngModel]="group.locked ?? false"
2852
+ (ngModelChange)="setGroup(key, i, 'locked', $event || undefined)"
2853
+ />
2854
+ Travado
2855
+ </label>
2856
+ <button
2857
+ class="mkbd-icon-btn"
2858
+ type="button"
2859
+ (click)="moveGroup(key, i, -1)"
2860
+ [disabled]="i === 0"
2861
+ aria-label="Mover para cima"
2862
+ >
2863
+ <mkb-icon name="up" />
2864
+ </button>
2865
+ <button
2866
+ class="mkbd-icon-btn"
2867
+ type="button"
2868
+ (click)="moveGroup(key, i, 1)"
2869
+ [disabled]="i === groups.length - 1"
2870
+ aria-label="Mover para baixo"
2871
+ >
2872
+ <mkb-icon name="down" />
2873
+ </button>
2874
+ <button
2875
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2876
+ type="button"
2877
+ (click)="removeGroup(key, i)"
2878
+ aria-label="Remover grupo"
2879
+ >
2880
+ <mkb-icon name="close" />
2881
+ </button>
2882
+ </div>
2073
2883
  </div>
2074
2884
  }
2075
- <button matButton type="button" (click)="addGroup(key)">+ Adicionar {{ key === 'columns' ? 'coluna' : 'lane' }}</button>
2076
2885
  </div>
2886
+
2887
+ <button class="mkbd-add" type="button" (click)="addGroup(key)">
2888
+ <mkb-icon name="add" />
2889
+ Adicionar {{ key === 'columns' ? 'coluna' : 'lane' }}
2890
+ </button>
2077
2891
  }
2078
2892
  </ng-template>
2079
2893
 
2080
2894
  <!-- ======================= REGRAS ========================= -->
2081
- <h3 class="mkbd-h">Regras de transição (colunas)</h3>
2895
+ <div class="mkbd-section">
2896
+ <span class="mkbd-overline">Regras de transição</span>
2897
+ @if (transitions().length) {
2898
+ <span class="mkbd-count">{{ transitions().length }}</span>
2899
+ }
2900
+ </div>
2082
2901
  <p class="mkbd-hint">
2083
- Sem linhas = qualquer transição é permitida. Com linhas, as listadas passam.
2902
+ Sem regras = qualquer transição é permitida. Com regras, as listadas passam.
2084
2903
  </p>
2085
- @for (t of transitions(); track $index; let i = $index) {
2086
- <div class="mkbd-row">
2087
- <mat-form-field appearance="outline" class="mkbd-slim">
2088
- <mat-label>De</mat-label>
2089
- <mat-select [ngModel]="fromOf(t)" (ngModelChange)="setTransition(i, 'from', $event)">
2090
- <mat-option value="*">Qualquer</mat-option>
2091
- @for (id of columnIds(); track id) {
2092
- <mat-option [value]="id">{{ id }}</mat-option>
2093
- }
2094
- </mat-select>
2095
- </mat-form-field>
2096
- <mat-form-field appearance="outline" class="mkbd-grow">
2097
- <mat-label>Para</mat-label>
2098
- <mat-select multiple [ngModel]="toOf(t)" (ngModelChange)="setTransition(i, 'to', $event)">
2099
- @for (id of columnIds(); track id) {
2100
- <mat-option [value]="id">{{ id }}</mat-option>
2101
- }
2102
- </mat-select>
2103
- </mat-form-field>
2104
- <button matIconButton type="button" (click)="removeTransition(i)" aria-label="Remover transição">✕</button>
2904
+
2905
+ @if (transitions().length) {
2906
+ <div class="mkbd-rows">
2907
+ @for (t of transitions(); track $index; let i = $index) {
2908
+ <div class="mkbd-row mkbd-row-rule">
2909
+ <mkb-combo
2910
+ label="De"
2911
+ [options]="fromOptions()"
2912
+ [value]="fromOf(t)"
2913
+ (valueChange)="setTransition(i, 'from', $event)"
2914
+ />
2915
+ <!-- Destino é multi-seleção: o valor vem da própria config (sem
2916
+ alocar array a cada ciclo, que foi o que travou a tela). -->
2917
+ <mkb-combo
2918
+ label="Para"
2919
+ [multiple]="true"
2920
+ placeholder="Qualquer"
2921
+ [options]="columnOptions()"
2922
+ [value]="t.to ?? null"
2923
+ (valuesChange)="setTransition(i, 'to', $event)"
2924
+ />
2925
+ <button
2926
+ class="mkbd-icon-btn mkbd-icon-btn-danger"
2927
+ type="button"
2928
+ (click)="removeTransition(i)"
2929
+ aria-label="Remover transição"
2930
+ >
2931
+ <mkb-icon name="close" />
2932
+ </button>
2933
+ </div>
2934
+ }
2105
2935
  </div>
2106
2936
  }
2107
- <button matButton type="button" (click)="addTransition()">+ Adicionar transição</button>
2937
+ <button class="mkbd-btn mkbd-btn-outline mkbd-btn-block" type="button" (click)="addTransition()">
2938
+ <mkb-icon name="add" />
2939
+ Adicionar transição
2940
+ </button>
2108
2941
 
2109
- <div class="mkbd-row mkbd-mt">
2110
- <mat-form-field appearance="outline" class="mkbd-grow">
2111
- <mat-label>Regras nomeadas de cartão (rule:*)</mat-label>
2942
+ <div class="mkbd-section">
2943
+ <span class="mkbd-overline">Regras nomeadas</span>
2944
+ </div>
2945
+ <p class="mkbd-hint">Os nomes referenciam código registrado pelo host no KanbanRegistry.</p>
2946
+ <div class="mkbd-stack">
2947
+ <label class="mkbd-field mkbd-field-grow">
2948
+ <span class="mkbd-label">Regras de cartão (rule:*)</span>
2112
2949
  <input
2113
- matInput
2114
2950
  [ngModel]="namesOf('rules')"
2115
2951
  (ngModelChange)="setNames('rules', $event)"
2116
2952
  placeholder="rule:berco-livre, rule:sla"
2117
2953
  />
2118
- </mat-form-field>
2119
- <mat-form-field appearance="outline" class="mkbd-grow">
2120
- <mat-label>Regras nomeadas de itens (entryRules)</mat-label>
2121
- <input matInput [ngModel]="namesOf('entryRules')" (ngModelChange)="setNames('entryRules', $event)" />
2122
- </mat-form-field>
2954
+ </label>
2955
+ <label class="mkbd-field mkbd-field-grow">
2956
+ <span class="mkbd-label">Regras de itens (entryRules)</span>
2957
+ <input [ngModel]="namesOf('entryRules')" (ngModelChange)="setNames('entryRules', $event)" />
2958
+ </label>
2123
2959
  </div>
2124
- <p class="mkbd-hint">Os nomes referenciam código registrado pelo host no KanbanRegistry.</p>
2125
2960
 
2126
2961
  <!-- ================== ORDENAÇÃO / GERAL ==================== -->
2127
- <h3 class="mkbd-h">Ordenação e geral</h3>
2128
- <div class="mkbd-row">
2129
- <mat-slide-toggle [ngModel]="!!config().sort" (ngModelChange)="toggleSort($event)">
2962
+ <div class="mkbd-section">
2963
+ <span class="mkbd-overline">Ordenação e geral</span>
2964
+ </div>
2965
+ <div class="mkbd-stack">
2966
+ <label class="mkbd-switch mkbd-switch-boxed">
2967
+ <input type="checkbox" [ngModel]="!!config().sort" (ngModelChange)="toggleSort($event)" />
2130
2968
  Ordenar itens por campo
2131
- </mat-slide-toggle>
2969
+ </label>
2132
2970
  @if (config().sort; as sort) {
2133
- <mat-form-field appearance="outline" class="mkbd-slim">
2134
- <mat-label>Campo</mat-label>
2135
- <input matInput [ngModel]="sort.field" (ngModelChange)="setSort('field', $event)" />
2136
- </mat-form-field>
2137
- <mat-form-field appearance="outline" class="mkbd-slim">
2138
- <mat-label>Direção</mat-label>
2139
- <mat-select [ngModel]="sort.direction ?? 'asc'" (ngModelChange)="setSort('direction', $event)">
2140
- <mat-option value="asc">Crescente</mat-option>
2141
- <mat-option value="desc">Decrescente</mat-option>
2142
- </mat-select>
2143
- </mat-form-field>
2971
+ <label class="mkbd-field">
2972
+ <span class="mkbd-label">Campo</span>
2973
+ <input [ngModel]="sort.field" (ngModelChange)="setSort('field', $event)" />
2974
+ </label>
2975
+ <mkb-combo
2976
+ label="Direção"
2977
+ [options]="directionOptions"
2978
+ [value]="sort.direction ?? 'asc'"
2979
+ (valueChange)="setSort('direction', $event)"
2980
+ />
2144
2981
  }
2145
- <mat-slide-toggle
2146
- [ngModel]="config().readOnly ?? false"
2147
- (ngModelChange)="setReadOnly($event)"
2148
- >
2982
+ <label class="mkbd-switch mkbd-switch-boxed">
2983
+ <input
2984
+ type="checkbox"
2985
+ [ngModel]="config().readOnly ?? false"
2986
+ (ngModelChange)="setReadOnly($event)"
2987
+ />
2149
2988
  Somente leitura
2150
- </mat-slide-toggle>
2989
+ </label>
2151
2990
  </div>
2152
- `, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600;display:flex;align-items:center;gap:12px}.mkbd-h:first-child{margin-top:0}.mkbd-hint{margin:0 0 8px;font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-row{display:flex;flex-wrap:wrap;gap:10px;align-items:center}.mkbd-mt{margin-top:10px}.mkbd-groups{display:flex;flex-direction:column;gap:4px}.mkbd-group{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:4px 8px;border:1px dashed var(--mkb-border, #e3e0ea);border-radius:8px}.mkbd-slim{width:170px}.mkbd-tiny{width:90px}.mkbd-grow{flex:1;min-width:200px}.mkbd-spacer{flex:1}.mkbd-color{display:inline-flex;align-items:center;gap:6px;font-size:12px;color:var(--mkb-muted, #6f6a7c)}.mkbd-color input{width:34px;height:28px;border:none;background:none;padding:0;cursor:pointer}\n"] }]
2991
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-row-group{grid-template-columns:22px minmax(0,1.1fr) minmax(0,1.3fr) 42px 76px auto}.mkbd-row-rule{grid-template-columns:minmax(0,1fr) minmax(0,1.6fr) auto;border-left-color:var(--mkbd-border-strong)}.mkbd-btn-block{margin-top:4px}.mkbd-combo-btn{flex:1;min-width:0;height:100%;padding:0 16px 0 0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-field-combo:has(.mkbd-combo-btn:focus-visible){border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-combo-empty{color:var(--mkbd-muted)}.mkbd-handle[cdkDragHandle]{cursor:grab;touch-action:none}.mkbd-row.cdk-drag-preview{box-shadow:var(--elevation-3, 0 8px 30px rgba(20, 22, 30, .14));opacity:.96}.mkbd-row.cdk-drag-placeholder{opacity:.35}.mkbd-rows.cdk-drop-list-dragging .mkbd-row:not(.cdk-drag-placeholder){transition:transform var(--mkbd-dur) var(--mkbd-ease)}@media(max-width:720px){.mkbd-row-group{grid-template-columns:22px minmax(0,1fr) 42px 76px}.mkbd-row-group .mkbd-row-ctrls{grid-column:1 / -1;justify-content:flex-end}}\n"] }]
2153
2992
  }] });
2154
2993
 
2155
2994
  /**
@@ -2166,6 +3005,11 @@ class MkbThemeEditor {
2166
3005
  isChanged(def) {
2167
3006
  return def.token in this.store.theme();
2168
3007
  }
3008
+ /** Quantos tokens do grupo estão alterados (0 = não mostra contador). */
3009
+ changedIn(label) {
3010
+ const group = this.groups.find((g) => g.label === label);
3011
+ return group?.tokens.filter((t) => this.isChanged(t)).length ?? 0;
3012
+ }
2169
3013
  changedCount() {
2170
3014
  return Object.keys(this.store.theme()).length;
2171
3015
  }
@@ -2175,110 +3019,144 @@ class MkbThemeEditor {
2175
3019
  Só o que você ALTERAR entra na exportação; o resto herda o default do
2176
3020
  pacote e os tokens do Design System do host.
2177
3021
  </p>
3022
+
2178
3023
  @for (group of groups; track group.label) {
2179
- <h3 class="mkbd-h">{{ group.label }}</h3>
2180
- <div class="mkbd-grid">
3024
+ <div class="mkbd-section">
3025
+ <span class="mkbd-overline">{{ group.label }}</span>
3026
+ @if (changedIn(group.label); as n) {
3027
+ <span class="mkbd-count">{{ n }}</span>
3028
+ }
3029
+ </div>
3030
+
3031
+ <div class="mkbd-tokens">
2181
3032
  @for (def of group.tokens; track def.token) {
2182
3033
  <div class="mkbd-token" [class.mkbd-token-changed]="isChanged(def)">
2183
3034
  @if (def.kind === 'color') {
2184
- <label class="mkbd-color">
3035
+ <label class="mkbd-swatch">
2185
3036
  <input
2186
3037
  type="color"
2187
3038
  [ngModel]="valueOf(def)"
2188
3039
  (ngModelChange)="store.setToken(def.token, $event)"
2189
3040
  [attr.aria-label]="def.label"
2190
3041
  />
2191
- <span>
2192
- <strong>{{ def.label }}</strong>
2193
- <code>{{ def.token }}</code>
2194
- </span>
3042
+ <span [style.background]="valueOf(def)"></span>
2195
3043
  </label>
3044
+ <span class="mkbd-token-text">
3045
+ <span class="mkbd-token-label">{{ def.label }}</span>
3046
+ <code>{{ def.token }}</code>
3047
+ </span>
2196
3048
  } @else {
2197
- <mat-form-field appearance="outline" class="mkbd-field">
2198
- <mat-label>{{ def.label }}</mat-label>
3049
+ <label class="mkbd-field mkbd-field-grow">
3050
+ <span class="mkbd-label">{{ def.label }}</span>
2199
3051
  <input
2200
- matInput
2201
3052
  [ngModel]="valueOf(def)"
2202
3053
  (ngModelChange)="store.setToken(def.token, $event)"
2203
3054
  [placeholder]="def.default"
2204
3055
  />
2205
- <mat-hint><code>{{ def.token }}</code></mat-hint>
2206
- </mat-form-field>
2207
- }
2208
- @if (isChanged(def)) {
2209
- <button matIconButton type="button" (click)="store.setToken(def.token, '')" [attr.aria-label]="'Restaurar ' + def.label">↺</button>
3056
+ </label>
3057
+ <code class="mkbd-token-code">{{ def.token }}</code>
2210
3058
  }
3059
+
3060
+ <button
3061
+ class="mkbd-icon-btn"
3062
+ type="button"
3063
+ (click)="store.setToken(def.token, '')"
3064
+ [disabled]="!isChanged(def)"
3065
+ [attr.aria-label]="'Restaurar ' + def.label"
3066
+ >
3067
+ <mkb-icon name="reset" />
3068
+ </button>
2211
3069
  </div>
2212
3070
  }
2213
3071
  </div>
2214
3072
  }
2215
- <div class="mkbd-actions">
2216
- <button matButton type="button" (click)="store.resetTheme()" [disabled]="!changedCount()">
3073
+
3074
+ <div class="mkbd-theme-actions">
3075
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="store.resetTheme()" [disabled]="!changedCount()">
3076
+ <mkb-icon name="reset" />
2217
3077
  Restaurar todos os defaults
2218
3078
  </button>
2219
- <span class="mkbd-hint">{{ changedCount() }} token(s) alterado(s)</span>
3079
+ <span class="mkbd-hint mkbd-theme-count">{{ changedCount() }} token(s) alterado(s)</span>
2220
3080
  </div>
2221
- `, isInline: true, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c);margin:0}.mkbd-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px 14px}.mkbd-token{display:flex;align-items:center;gap:6px;border-radius:8px;padding:2px 6px}.mkbd-token-changed{background:color-mix(in srgb,var(--mkb-accent, #5e35b1) 8%,transparent)}.mkbd-field{width:100%}.mkbd-color{display:flex;align-items:center;gap:10px;cursor:pointer;padding:4px 0}.mkbd-color input{width:34px;height:28px;border:none;background:none;padding:0;cursor:pointer}.mkbd-color span{display:flex;flex-direction:column;font-size:12px}.mkbd-color code,.mkbd-field code{font-size:10.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-actions{display:flex;align-items:center;gap:12px;margin-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { 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: "directive", type: i2.MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { 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: MatButtonModule }, { kind: "component", type: i7.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: "component", type: i7.MatIconButton, selector: "button[mat-icon-button], a[mat-icon-button], button[matIconButton], a[matIconButton]", exportAs: ["matButton", "matAnchor"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3081
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-tokens{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px 16px}.mkbd-token{display:flex;align-items:center;gap:10px;padding:6px 8px;border:1px solid transparent;border-radius:var(--mkbd-radius-md);min-width:0}.mkbd-token-changed{border-color:var(--mkbd-primary-outline);background:var(--mkbd-primary-soft)}.mkbd-token-text{display:flex;flex-direction:column;min-width:0;gap:2px}.mkbd-token-label{font-size:12.5px}.mkbd-token code,.mkbd-token-code{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mkbd-token-code{width:92px;flex:none}.mkbd-token>.mkbd-icon-btn{margin-left:auto}.mkbd-theme-actions{display:flex;align-items:center;gap:12px;margin-top:20px}.mkbd-theme-count{margin:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$1.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$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2222
3082
  }
2223
3083
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MkbThemeEditor, decorators: [{
2224
3084
  type: Component,
2225
- args: [{ selector: 'mkb-theme-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, MatFormFieldModule, MatInputModule, MatButtonModule], template: `
3085
+ args: [{ selector: 'mkb-theme-editor', changeDetection: ChangeDetectionStrategy.OnPush, imports: [FormsModule, MkbIcon], template: `
2226
3086
  <p class="mkbd-hint">
2227
3087
  Só o que você ALTERAR entra na exportação; o resto herda o default do
2228
3088
  pacote e os tokens do Design System do host.
2229
3089
  </p>
3090
+
2230
3091
  @for (group of groups; track group.label) {
2231
- <h3 class="mkbd-h">{{ group.label }}</h3>
2232
- <div class="mkbd-grid">
3092
+ <div class="mkbd-section">
3093
+ <span class="mkbd-overline">{{ group.label }}</span>
3094
+ @if (changedIn(group.label); as n) {
3095
+ <span class="mkbd-count">{{ n }}</span>
3096
+ }
3097
+ </div>
3098
+
3099
+ <div class="mkbd-tokens">
2233
3100
  @for (def of group.tokens; track def.token) {
2234
3101
  <div class="mkbd-token" [class.mkbd-token-changed]="isChanged(def)">
2235
3102
  @if (def.kind === 'color') {
2236
- <label class="mkbd-color">
3103
+ <label class="mkbd-swatch">
2237
3104
  <input
2238
3105
  type="color"
2239
3106
  [ngModel]="valueOf(def)"
2240
3107
  (ngModelChange)="store.setToken(def.token, $event)"
2241
3108
  [attr.aria-label]="def.label"
2242
3109
  />
2243
- <span>
2244
- <strong>{{ def.label }}</strong>
2245
- <code>{{ def.token }}</code>
2246
- </span>
3110
+ <span [style.background]="valueOf(def)"></span>
2247
3111
  </label>
3112
+ <span class="mkbd-token-text">
3113
+ <span class="mkbd-token-label">{{ def.label }}</span>
3114
+ <code>{{ def.token }}</code>
3115
+ </span>
2248
3116
  } @else {
2249
- <mat-form-field appearance="outline" class="mkbd-field">
2250
- <mat-label>{{ def.label }}</mat-label>
3117
+ <label class="mkbd-field mkbd-field-grow">
3118
+ <span class="mkbd-label">{{ def.label }}</span>
2251
3119
  <input
2252
- matInput
2253
3120
  [ngModel]="valueOf(def)"
2254
3121
  (ngModelChange)="store.setToken(def.token, $event)"
2255
3122
  [placeholder]="def.default"
2256
3123
  />
2257
- <mat-hint><code>{{ def.token }}</code></mat-hint>
2258
- </mat-form-field>
2259
- }
2260
- @if (isChanged(def)) {
2261
- <button matIconButton type="button" (click)="store.setToken(def.token, '')" [attr.aria-label]="'Restaurar ' + def.label">↺</button>
3124
+ </label>
3125
+ <code class="mkbd-token-code">{{ def.token }}</code>
2262
3126
  }
3127
+
3128
+ <button
3129
+ class="mkbd-icon-btn"
3130
+ type="button"
3131
+ (click)="store.setToken(def.token, '')"
3132
+ [disabled]="!isChanged(def)"
3133
+ [attr.aria-label]="'Restaurar ' + def.label"
3134
+ >
3135
+ <mkb-icon name="reset" />
3136
+ </button>
2263
3137
  </div>
2264
3138
  }
2265
3139
  </div>
2266
3140
  }
2267
- <div class="mkbd-actions">
2268
- <button matButton type="button" (click)="store.resetTheme()" [disabled]="!changedCount()">
3141
+
3142
+ <div class="mkbd-theme-actions">
3143
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="store.resetTheme()" [disabled]="!changedCount()">
3144
+ <mkb-icon name="reset" />
2269
3145
  Restaurar todos os defaults
2270
3146
  </button>
2271
- <span class="mkbd-hint">{{ changedCount() }} token(s) alterado(s)</span>
3147
+ <span class="mkbd-hint mkbd-theme-count">{{ changedCount() }} token(s) alterado(s)</span>
2272
3148
  </div>
2273
- `, styles: [":host{display:block}.mkbd-h{margin:18px 0 8px;font-size:13px;font-weight:600}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c);margin:0}.mkbd-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:8px 14px}.mkbd-token{display:flex;align-items:center;gap:6px;border-radius:8px;padding:2px 6px}.mkbd-token-changed{background:color-mix(in srgb,var(--mkb-accent, #5e35b1) 8%,transparent)}.mkbd-field{width:100%}.mkbd-color{display:flex;align-items:center;gap:10px;cursor:pointer;padding:4px 0}.mkbd-color input{width:34px;height:28px;border:none;background:none;padding:0;cursor:pointer}.mkbd-color span{display:flex;flex-direction:column;font-size:12px}.mkbd-color code,.mkbd-field code{font-size:10.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-actions{display:flex;align-items:center;gap:12px;margin-top:16px}\n"] }]
3149
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:block}.mkbd-tokens{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px 16px}.mkbd-token{display:flex;align-items:center;gap:10px;padding:6px 8px;border:1px solid transparent;border-radius:var(--mkbd-radius-md);min-width:0}.mkbd-token-changed{border-color:var(--mkbd-primary-outline);background:var(--mkbd-primary-soft)}.mkbd-token-text{display:flex;flex-direction:column;min-width:0;gap:2px}.mkbd-token-label{font-size:12.5px}.mkbd-token code,.mkbd-token-code{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-muted-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mkbd-token-code{width:92px;flex:none}.mkbd-token>.mkbd-icon-btn{margin-left:auto}.mkbd-theme-actions{display:flex;align-items:center;gap:12px;margin-top:20px}.mkbd-theme-count{margin:0}\n"] }]
2274
3150
  }] });
2275
3151
 
2276
3152
  /**
2277
3153
  * Designer do Board — tela OPT-IN (entry point isolado
2278
3154
  * `@mosaicoo/kanban/designer`): edita visualmente o BoardConfig (pipeline,
2279
3155
  * cartão, dados, tema) com preview ao vivo e importa/exporta no formato que
2280
- * o kanban consome em runtime. Exige @angular/material + @angular/forms
2281
- * (peers opcionais do pacote — quem não usa o designer não paga por eles).
3156
+ * o kanban consome em runtime.
3157
+ *
3158
+ * Visual: linguagem do Mosaicoo Design System (tela 13a dos Layouts). Os
3159
+ * tokens caem no DS do host quando embarcado — ver designer.css.
2282
3160
  */
2283
3161
  class MosKanbanDesigner {
2284
3162
  store = inject(DesignerStore);
@@ -2384,69 +3262,120 @@ class MosKanbanDesigner {
2384
3262
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MosKanbanDesigner, deps: [], target: i0.ɵɵFactoryTarget.Component });
2385
3263
  static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.18", type: MosKanbanDesigner, isStandalone: true, selector: "mos-kanban-designer", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, theme: { classPropertyName: "theme", publicName: "theme", isSignal: true, isRequired: false, transformFunction: null }, registry: { classPropertyName: "registry", publicName: "registry", isSignal: true, isRequired: false, transformFunction: null }, storageKey: { classPropertyName: "storageKey", publicName: "storageKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { configChange: "configChange", themeChange: "themeChange" }, providers: [DesignerStore], ngImport: i0, template: `
2386
3264
  <div class="mkbd-toolbar">
2387
- <span class="mkbd-title">Designer do Board</span>
3265
+ <h2 class="mkbd-title">Designer do Board</h2>
2388
3266
  @if (store.errors().length; as count) {
2389
- <span class="mkbd-chip mkbd-chip-error" role="status">{{ count }} erro(s)</span>
3267
+ <span class="mkbd-chip mkbd-chip-error" role="status">
3268
+ <mkb-icon name="alert-circle" />
3269
+ {{ count }} erro(s)
3270
+ </span>
2390
3271
  } @else {
2391
- <span class="mkbd-chip mkbd-chip-ok" role="status">Config válida</span>
2392
- }
2393
- <span class="mkbd-spacer"></span>
2394
- <button matButton type="button" (click)="fileInput.click()">Importar</button>
2395
- <input
2396
- #fileInput
2397
- type="file"
2398
- accept=".json,application/json"
2399
- hidden
2400
- (change)="onImportFile($event)"
2401
- />
2402
- <button matButton type="button" (click)="exportConfig()">Exportar config</button>
2403
- <button matButton type="button" (click)="exportDesign()">Exportar design</button>
2404
- <button matButton type="button" (click)="exportCss()" [disabled]="!hasTheme()">Exportar CSS</button>
2405
- @if (storageKey()) {
2406
- <button matButton type="button" (click)="clearDraft()">Limpar rascunho</button>
3272
+ <span class="mkbd-chip mkbd-chip-ok" role="status">
3273
+ <mkb-icon name="check-circle" />
3274
+ Config válida
3275
+ </span>
2407
3276
  }
3277
+
3278
+ <div class="mkbd-toolbar-actions">
3279
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="fileInput.click()">
3280
+ <mkb-icon name="upload" />
3281
+ Importar
3282
+ </button>
3283
+ <input
3284
+ #fileInput
3285
+ type="file"
3286
+ accept=".json,application/json"
3287
+ hidden
3288
+ (change)="onImportFile($event)"
3289
+ />
3290
+
3291
+ <button class="mkbd-btn mkbd-btn-tonal" type="button" [matMenuTriggerFor]="exportMenu">
3292
+ <mkb-icon name="download" />
3293
+ Exportar
3294
+ <mkb-icon name="expand" />
3295
+ </button>
3296
+ <mat-menu #exportMenu="matMenu">
3297
+ <button mat-menu-item type="button" (click)="exportConfig()">
3298
+ <span class="mkbd-menu-item">
3299
+ <strong>Exportar config</strong>
3300
+ <small>BoardConfig — o que o runtime consome</small>
3301
+ </span>
3302
+ </button>
3303
+ <button mat-menu-item type="button" (click)="exportDesign()">
3304
+ <span class="mkbd-menu-item">
3305
+ <strong>Exportar design</strong>
3306
+ <small>Config + tema, para reabrir aqui</small>
3307
+ </span>
3308
+ </button>
3309
+ <button mat-menu-item type="button" [disabled]="!hasTheme()" (click)="exportCss()">
3310
+ <span class="mkbd-menu-item">
3311
+ <strong>Exportar CSS</strong>
3312
+ <small>Só os tokens alterados</small>
3313
+ </span>
3314
+ </button>
3315
+ </mat-menu>
3316
+
3317
+ @if (storageKey()) {
3318
+ <span class="mkbd-toolbar-sep"></span>
3319
+ <button class="mkbd-btn mkbd-btn-danger" type="button" (click)="clearDraft()">
3320
+ <mkb-icon name="trash" />
3321
+ Limpar rascunho
3322
+ </button>
3323
+ }
3324
+ </div>
2408
3325
  </div>
2409
3326
 
2410
3327
  @if (importErrors().length) {
2411
- <div class="mkbd-import-errors" role="alert">
2412
- <strong>Importação rejeitada:</strong>
2413
- <ul>
2414
- @for (issue of importErrors(); track $index) {
2415
- <li><code>{{ issue.path }}</code> {{ issue.message }}</li>
2416
- }
2417
- </ul>
2418
- <button matButton type="button" (click)="importErrors.set([])">Fechar</button>
3328
+ <div class="mkbd-banner" role="alert">
3329
+ <mkb-icon name="alert-circle" />
3330
+ <div>
3331
+ <strong>Importação rejeitada</strong>
3332
+ <ul>
3333
+ @for (issue of importErrors(); track $index) {
3334
+ <li><code>{{ issue.path }}</code> {{ issue.message }}</li>
3335
+ }
3336
+ </ul>
3337
+ </div>
3338
+ <button class="mkbd-icon-btn" type="button" (click)="importErrors.set([])" aria-label="Fechar aviso">
3339
+ <mkb-icon name="close" />
3340
+ </button>
2419
3341
  </div>
2420
3342
  }
2421
3343
 
2422
3344
  <div class="mkbd-body">
2423
3345
  <div class="mkbd-editors">
2424
- <mat-tab-group stretchTabs="false" animationDuration="0ms">
2425
- <mat-tab label="Pipeline"><mkb-pipeline-editor /></mat-tab>
2426
- <mat-tab label="Cartão"><mkb-card-editor /></mat-tab>
2427
- <mat-tab label="Dados"><mkb-data-editor /></mat-tab>
2428
- <mat-tab label="Tema"><mkb-theme-editor /></mat-tab>
3346
+ <mat-tab-group class="mkbd-tabs" stretchTabs="false" animationDuration="0ms">
3347
+ <mat-tab label="Pipeline">
3348
+ <div class="mkbd-pane"><mkb-pipeline-editor /></div>
3349
+ </mat-tab>
3350
+ <mat-tab label="Cartão">
3351
+ <div class="mkbd-pane"><mkb-card-editor /></div>
3352
+ </mat-tab>
3353
+ <mat-tab label="Dados">
3354
+ <div class="mkbd-pane"><mkb-data-editor /></div>
3355
+ </mat-tab>
3356
+ <mat-tab label="Tema">
3357
+ <div class="mkbd-pane"><mkb-theme-editor /></div>
3358
+ </mat-tab>
2429
3359
  <mat-tab label="JSON">
2430
- <p class="mkbd-hint">
2431
- BoardConfig ao vivo. Edite e aplique — inválido não substitui o design atual.
2432
- </p>
2433
- <textarea
2434
- class="mkbd-json"
2435
- rows="24"
2436
- spellcheck="false"
2437
- [value]="store.exportConfigJson()"
2438
- #jsonArea
2439
- ></textarea>
2440
- <button matButton type="button" (click)="applyJson(jsonArea)">Aplicar JSON</button>
3360
+ <div class="mkbd-pane">
3361
+ <p class="mkbd-hint">
3362
+ BoardConfig ao vivo. Edite e aplique — inválido não substitui o design atual.
3363
+ </p>
3364
+ <textarea class="mkbd-json" rows="22" spellcheck="false" [value]="store.exportConfigJson()" #jsonArea></textarea>
3365
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="applyJson(jsonArea)">
3366
+ Aplicar JSON
3367
+ </button>
3368
+ </div>
2441
3369
  </mat-tab>
2442
3370
  </mat-tab-group>
2443
3371
  </div>
2444
3372
 
2445
3373
  <div class="mkbd-preview">
2446
3374
  <div class="mkbd-preview-head">
2447
- <span>Preview ao vivo</span>
3375
+ <mkb-icon name="eye" class="mkbd-preview-eye" />
3376
+ <span class="mkbd-overline">Preview ao vivo</span>
2448
3377
  @if (store.errors().length) {
2449
- <span class="mkbd-hint">mostrando a última config válida</span>
3378
+ <span class="mkbd-hint mkbd-preview-note">mostrando a última config válida</span>
2450
3379
  }
2451
3380
  </div>
2452
3381
  @if (store.errors().length) {
@@ -2461,13 +3390,14 @@ class MosKanbanDesigner {
2461
3390
  </div>
2462
3391
  </div>
2463
3392
  </div>
2464
- `, isInline: true, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;font-family:var(--mkb-font, inherit)}.mkbd-toolbar{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--mkb-border, #e3e0ea);flex-wrap:wrap}.mkbd-title{font-size:14px;font-weight:600}.mkbd-chip{font-size:11px;padding:2px 10px;border-radius:999px}.mkbd-chip-ok{background:color-mix(in srgb,var(--mkb-success, #1b6e3c) 12%,transparent);color:var(--mkb-success, #1b6e3c)}.mkbd-chip-error{background:color-mix(in srgb,var(--mkb-danger, #b3261e) 12%,transparent);color:var(--mkb-danger, #b3261e)}.mkbd-spacer{flex:1}.mkbd-import-errors{margin:8px 12px;padding:8px 12px;border:1px solid var(--mkb-danger, #b3261e);border-radius:8px;font-size:12px}.mkbd-import-errors ul{margin:4px 0;padding-left:18px}.mkbd-body{display:flex;flex:1;min-height:0}.mkbd-editors{flex:1 1 46%;min-width:340px;overflow:auto;padding:8px 12px 24px;border-right:1px solid var(--mkb-border, #e3e0ea)}.mkbd-preview{flex:1 1 54%;min-width:0;display:flex;flex-direction:column}.mkbd-preview-head{display:flex;align-items:baseline;gap:10px;padding:8px 12px 4px;font-size:12px;font-weight:600}.mkbd-preview-board{flex:1;min-height:0;overflow:auto}.mkbd-issues{margin:0 12px 6px;padding:6px 12px 6px 26px;font-size:12px;color:var(--mkb-danger, #b3261e);border:1px dashed var(--mkb-danger, #b3261e);border-radius:8px}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-json{width:100%;font-family:ui-monospace,monospace;font-size:12px;border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px;padding:8px;box-sizing:border-box}@media(max-width:900px){.mkbd-body{flex-direction:column}.mkbd-editors{border-right:none;border-bottom:1px solid var(--mkb-border, #e3e0ea)}}\n"], dependencies: [{ kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i1$1.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i1$1.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i7.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: "component", type: MosKanbanBoard, selector: "mos-kanban-board", inputs: ["board", "loading", "error", "showSearch", "itemActions"], outputs: ["itemClick", "itemMove", "moveRejected", "itemAction", "entryAction", "dragStarted", "dragEnded", "dragCanceled"] }, { kind: "component", type: MkbPipelineEditor, selector: "mkb-pipeline-editor" }, { kind: "component", type: MkbCardEditor, selector: "mkb-card-editor" }, { kind: "component", type: MkbDataEditor, selector: "mkb-data-editor" }, { kind: "component", type: MkbThemeEditor, selector: "mkb-theme-editor" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3393
+ `, isInline: true, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--mkbd-surface)}.mkbd-toolbar{flex:none;display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:14px 20px 12px;background:var(--mkbd-panel);border-bottom:1px solid var(--mkbd-border-soft)}.mkbd-title{margin:0;font:500 17px var(--mkbd-font);letter-spacing:-.2px}.mkbd-toolbar-actions{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.mkbd-toolbar-sep{width:1px;height:26px;background:var(--mkbd-border)}.mkbd-menu-item{display:flex;flex-direction:column;line-height:1.35}.mkbd-menu-item strong{font:500 13px var(--mkbd-font)}.mkbd-menu-item small{font-size:11px;color:var(--mkbd-muted)}.mkbd-banner{flex:none;display:flex;align-items:flex-start;gap:10px;margin:12px 20px 0;padding:12px 14px;border:1px solid var(--mkbd-error);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-error-container);color:var(--mkbd-error);font-size:12px}.mkbd-banner>mkb-icon{font-size:20px;margin-top:1px}.mkbd-banner ul{margin:4px 0 0;padding-left:18px}.mkbd-banner strong{font:500 13px var(--mkbd-font)}.mkbd-banner>.mkbd-icon-btn{margin-left:auto;color:inherit}.mkbd-body{display:flex;flex:1;min-height:0}.mkbd-editors{flex:1;display:flex;flex-direction:column;min-width:0;background:var(--mkbd-canvas);border-right:1px solid var(--mkbd-border)}.mkbd-pane{padding:18px 20px 28px}.mkbd-tabs{flex:1;min-height:0}.mkbd-tabs ::ng-deep .mat-mdc-tab-header{background:var(--mkbd-panel);padding:0 12px;flex:none;border-bottom:1px solid var(--mkbd-border-soft)}.mkbd-tabs ::ng-deep .mat-mdc-tab{min-width:0;padding:0 14px}.mkbd-tabs ::ng-deep .mdc-tab__text-label{font:500 13.5px var(--mkbd-font);letter-spacing:0;color:var(--mkbd-muted);transition:color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-tabs ::ng-deep .mdc-tab--active .mdc-tab__text-label{color:var(--mkbd-primary)}.mkbd-tabs ::ng-deep .mdc-tab-indicator__content--underline{border-top-width:3px;border-radius:3px 3px 0 0;border-color:var(--mkbd-primary)}.mkbd-tabs ::ng-deep .mat-mdc-tab-body-wrapper{flex:1;min-height:0}.mkbd-tabs ::ng-deep .mat-mdc-tab-body-content{overflow:auto}.mkbd-preview{flex:none;width:clamp(360px,42%,560px);display:flex;flex-direction:column;min-width:0;background:var(--mkbd-surface)}.mkbd-preview-head{flex:none;display:flex;align-items:center;gap:8px;padding:14px 18px 10px}.mkbd-preview-eye{font-size:16px;color:var(--mkbd-success)}.mkbd-preview-note{margin:0;text-transform:none}.mkbd-preview-board{flex:1;min-height:0;overflow:auto;padding:0 18px 16px}.mkbd-preview-board>mos-kanban-board{display:block;height:100%}.mkbd-issues{margin:0 18px 8px;padding:8px 12px 8px 26px;font-size:11.5px;color:var(--mkbd-error);background:var(--mkbd-error-container);border-radius:var(--mkbd-radius-md)}.mkbd-issues code,.mkbd-banner code{font-family:var(--mkbd-font-mono)}.mkbd-json{display:block;width:100%;margin-bottom:12px;padding:12px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel);color:var(--mkbd-fg);font:400 12px/1.5 var(--mkbd-font-mono);box-sizing:border-box;resize:vertical}.mkbd-json:focus-visible{outline:none;border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}::ng-deep .mat-mdc-menu-panel.mkbd-menu{min-width:176px;padding:6px;border:1px solid var(--color-border, #e6e8ee);border-radius:var(--radius-xl, 14px);background:var(--color-panel, #ffffff);box-shadow:var(--elevation-2, 0 1px 2px rgba(20, 22, 30, .1), 0 2px 6px rgba(20, 22, 30, .08))}::ng-deep .mkbd-menu .mat-mdc-menu-content{padding:0;max-height:285px;overflow-y:auto;overscroll-behavior:contain}::ng-deep .mkbd-menu .mkbd-menu-search{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;padding:2px 4px 8px;background:var(--color-panel, #ffffff)}::ng-deep .mkbd-menu .mkbd-menu-search input{flex:1;min-width:0;height:34px;padding:0 10px;border:1px solid var(--color-border-strong, #c9cdd6);border-radius:var(--radius-sm, 8px);background:var(--color-panel, #ffffff);color:var(--color-foreground, #1e1f24);font:400 12.5px var(--font-sans, \"Roboto\", system-ui, sans-serif);outline:none}::ng-deep .mkbd-menu .mkbd-menu-search input:focus{border-color:var(--color-primary, #5e35b1);box-shadow:var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4))}::ng-deep .mkbd-menu .mkbd-menu-count{font:500 10px var(--font-mono, ui-monospace, monospace);color:var(--color-muted, #8b909c);padding-right:4px}::ng-deep .mkbd-menu .mkbd-menu-empty{margin:0;padding:10px;font-size:12px;color:var(--color-muted, #8b909c)}::ng-deep .mkbd-menu .mat-mdc-menu-item{display:flex;align-items:center;gap:12px;min-height:38px;padding:0 10px;border-radius:var(--radius-md, 10px);color:var(--color-secondary, #4a4d57);font:400 12.5px var(--font-sans, \"Roboto\", system-ui, sans-serif);letter-spacing:0}::ng-deep .mkbd-menu .mat-mdc-menu-item .mat-mdc-menu-item-text{font:inherit;display:flex;align-items:center;gap:10px}::ng-deep .mkbd-menu .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--color-foreground, #1e1f24) 8%,transparent)}::ng-deep .mkbd-menu .mkbd-menu-item-active{background:var(--color-primary-container, #ede7f6);color:var(--color-on-primary-container, #2a1258);font-weight:500}::ng-deep .mkbd-menu .mat-mdc-menu-item[disabled]{color:var(--color-disabled-fg, #b3b7c1)}::ng-deep .mkbd-menu .mkbd-menu-item{display:flex;flex-direction:column;line-height:1.35}::ng-deep .mkbd-menu .mkbd-menu-item strong{font:500 13px var(--font-sans, sans-serif)}::ng-deep .mkbd-menu .mkbd-menu-item small{font-size:11px;color:var(--color-muted, #8b909c)}::ng-deep .mkbd-menu .mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;flex:none;border:1.5px solid var(--color-border-strong, #c9cdd6);border-radius:4px}::ng-deep .mkbd-menu .mkbd-menu-check-on{background:var(--color-primary, #5e35b1);border-color:var(--color-primary, #5e35b1)}::ng-deep .mkbd-menu .mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--color-on-primary, #ffffff);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}@media(max-width:900px){.mkbd-body{flex-direction:column}.mkbd-editors{border-right:none;border-bottom:1px solid var(--mkbd-border)}.mkbd-preview{width:auto;flex:1}}\n"], dependencies: [{ kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i1$2.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass", "id"], exportAs: ["matTab"] }, { kind: "component", type: i1$2.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "mat-align-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1.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: i1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "component", type: MkbIcon, selector: "mkb-icon", inputs: ["name"] }, { kind: "component", type: MosKanbanBoard, selector: "mos-kanban-board", inputs: ["board", "loading", "error", "showSearch", "itemActions"], outputs: ["itemClick", "itemMove", "moveRejected", "itemAction", "entryAction", "dragStarted", "dragEnded", "dragCanceled"] }, { kind: "component", type: MkbPipelineEditor, selector: "mkb-pipeline-editor" }, { kind: "component", type: MkbCardEditor, selector: "mkb-card-editor" }, { kind: "component", type: MkbDataEditor, selector: "mkb-data-editor" }, { kind: "component", type: MkbThemeEditor, selector: "mkb-theme-editor" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2465
3394
  }
2466
3395
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImport: i0, type: MosKanbanDesigner, decorators: [{
2467
3396
  type: Component,
2468
3397
  args: [{ selector: 'mos-kanban-designer', changeDetection: ChangeDetectionStrategy.OnPush, providers: [DesignerStore], imports: [
2469
3398
  MatTabsModule,
2470
- MatButtonModule,
3399
+ MatMenuModule,
3400
+ MkbIcon,
2471
3401
  MosKanbanBoard,
2472
3402
  MkbPipelineEditor,
2473
3403
  MkbCardEditor,
@@ -2475,69 +3405,120 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
2475
3405
  MkbThemeEditor,
2476
3406
  ], template: `
2477
3407
  <div class="mkbd-toolbar">
2478
- <span class="mkbd-title">Designer do Board</span>
3408
+ <h2 class="mkbd-title">Designer do Board</h2>
2479
3409
  @if (store.errors().length; as count) {
2480
- <span class="mkbd-chip mkbd-chip-error" role="status">{{ count }} erro(s)</span>
3410
+ <span class="mkbd-chip mkbd-chip-error" role="status">
3411
+ <mkb-icon name="alert-circle" />
3412
+ {{ count }} erro(s)
3413
+ </span>
2481
3414
  } @else {
2482
- <span class="mkbd-chip mkbd-chip-ok" role="status">Config válida</span>
2483
- }
2484
- <span class="mkbd-spacer"></span>
2485
- <button matButton type="button" (click)="fileInput.click()">Importar</button>
2486
- <input
2487
- #fileInput
2488
- type="file"
2489
- accept=".json,application/json"
2490
- hidden
2491
- (change)="onImportFile($event)"
2492
- />
2493
- <button matButton type="button" (click)="exportConfig()">Exportar config</button>
2494
- <button matButton type="button" (click)="exportDesign()">Exportar design</button>
2495
- <button matButton type="button" (click)="exportCss()" [disabled]="!hasTheme()">Exportar CSS</button>
2496
- @if (storageKey()) {
2497
- <button matButton type="button" (click)="clearDraft()">Limpar rascunho</button>
3415
+ <span class="mkbd-chip mkbd-chip-ok" role="status">
3416
+ <mkb-icon name="check-circle" />
3417
+ Config válida
3418
+ </span>
2498
3419
  }
3420
+
3421
+ <div class="mkbd-toolbar-actions">
3422
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="fileInput.click()">
3423
+ <mkb-icon name="upload" />
3424
+ Importar
3425
+ </button>
3426
+ <input
3427
+ #fileInput
3428
+ type="file"
3429
+ accept=".json,application/json"
3430
+ hidden
3431
+ (change)="onImportFile($event)"
3432
+ />
3433
+
3434
+ <button class="mkbd-btn mkbd-btn-tonal" type="button" [matMenuTriggerFor]="exportMenu">
3435
+ <mkb-icon name="download" />
3436
+ Exportar
3437
+ <mkb-icon name="expand" />
3438
+ </button>
3439
+ <mat-menu #exportMenu="matMenu">
3440
+ <button mat-menu-item type="button" (click)="exportConfig()">
3441
+ <span class="mkbd-menu-item">
3442
+ <strong>Exportar config</strong>
3443
+ <small>BoardConfig — o que o runtime consome</small>
3444
+ </span>
3445
+ </button>
3446
+ <button mat-menu-item type="button" (click)="exportDesign()">
3447
+ <span class="mkbd-menu-item">
3448
+ <strong>Exportar design</strong>
3449
+ <small>Config + tema, para reabrir aqui</small>
3450
+ </span>
3451
+ </button>
3452
+ <button mat-menu-item type="button" [disabled]="!hasTheme()" (click)="exportCss()">
3453
+ <span class="mkbd-menu-item">
3454
+ <strong>Exportar CSS</strong>
3455
+ <small>Só os tokens alterados</small>
3456
+ </span>
3457
+ </button>
3458
+ </mat-menu>
3459
+
3460
+ @if (storageKey()) {
3461
+ <span class="mkbd-toolbar-sep"></span>
3462
+ <button class="mkbd-btn mkbd-btn-danger" type="button" (click)="clearDraft()">
3463
+ <mkb-icon name="trash" />
3464
+ Limpar rascunho
3465
+ </button>
3466
+ }
3467
+ </div>
2499
3468
  </div>
2500
3469
 
2501
3470
  @if (importErrors().length) {
2502
- <div class="mkbd-import-errors" role="alert">
2503
- <strong>Importação rejeitada:</strong>
2504
- <ul>
2505
- @for (issue of importErrors(); track $index) {
2506
- <li><code>{{ issue.path }}</code> {{ issue.message }}</li>
2507
- }
2508
- </ul>
2509
- <button matButton type="button" (click)="importErrors.set([])">Fechar</button>
3471
+ <div class="mkbd-banner" role="alert">
3472
+ <mkb-icon name="alert-circle" />
3473
+ <div>
3474
+ <strong>Importação rejeitada</strong>
3475
+ <ul>
3476
+ @for (issue of importErrors(); track $index) {
3477
+ <li><code>{{ issue.path }}</code> {{ issue.message }}</li>
3478
+ }
3479
+ </ul>
3480
+ </div>
3481
+ <button class="mkbd-icon-btn" type="button" (click)="importErrors.set([])" aria-label="Fechar aviso">
3482
+ <mkb-icon name="close" />
3483
+ </button>
2510
3484
  </div>
2511
3485
  }
2512
3486
 
2513
3487
  <div class="mkbd-body">
2514
3488
  <div class="mkbd-editors">
2515
- <mat-tab-group stretchTabs="false" animationDuration="0ms">
2516
- <mat-tab label="Pipeline"><mkb-pipeline-editor /></mat-tab>
2517
- <mat-tab label="Cartão"><mkb-card-editor /></mat-tab>
2518
- <mat-tab label="Dados"><mkb-data-editor /></mat-tab>
2519
- <mat-tab label="Tema"><mkb-theme-editor /></mat-tab>
3489
+ <mat-tab-group class="mkbd-tabs" stretchTabs="false" animationDuration="0ms">
3490
+ <mat-tab label="Pipeline">
3491
+ <div class="mkbd-pane"><mkb-pipeline-editor /></div>
3492
+ </mat-tab>
3493
+ <mat-tab label="Cartão">
3494
+ <div class="mkbd-pane"><mkb-card-editor /></div>
3495
+ </mat-tab>
3496
+ <mat-tab label="Dados">
3497
+ <div class="mkbd-pane"><mkb-data-editor /></div>
3498
+ </mat-tab>
3499
+ <mat-tab label="Tema">
3500
+ <div class="mkbd-pane"><mkb-theme-editor /></div>
3501
+ </mat-tab>
2520
3502
  <mat-tab label="JSON">
2521
- <p class="mkbd-hint">
2522
- BoardConfig ao vivo. Edite e aplique — inválido não substitui o design atual.
2523
- </p>
2524
- <textarea
2525
- class="mkbd-json"
2526
- rows="24"
2527
- spellcheck="false"
2528
- [value]="store.exportConfigJson()"
2529
- #jsonArea
2530
- ></textarea>
2531
- <button matButton type="button" (click)="applyJson(jsonArea)">Aplicar JSON</button>
3503
+ <div class="mkbd-pane">
3504
+ <p class="mkbd-hint">
3505
+ BoardConfig ao vivo. Edite e aplique — inválido não substitui o design atual.
3506
+ </p>
3507
+ <textarea class="mkbd-json" rows="22" spellcheck="false" [value]="store.exportConfigJson()" #jsonArea></textarea>
3508
+ <button class="mkbd-btn mkbd-btn-outline" type="button" (click)="applyJson(jsonArea)">
3509
+ Aplicar JSON
3510
+ </button>
3511
+ </div>
2532
3512
  </mat-tab>
2533
3513
  </mat-tab-group>
2534
3514
  </div>
2535
3515
 
2536
3516
  <div class="mkbd-preview">
2537
3517
  <div class="mkbd-preview-head">
2538
- <span>Preview ao vivo</span>
3518
+ <mkb-icon name="eye" class="mkbd-preview-eye" />
3519
+ <span class="mkbd-overline">Preview ao vivo</span>
2539
3520
  @if (store.errors().length) {
2540
- <span class="mkbd-hint">mostrando a última config válida</span>
3521
+ <span class="mkbd-hint mkbd-preview-note">mostrando a última config válida</span>
2541
3522
  }
2542
3523
  </div>
2543
3524
  @if (store.errors().length) {
@@ -2552,7 +3533,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.18", ngImpo
2552
3533
  </div>
2553
3534
  </div>
2554
3535
  </div>
2555
- `, styles: [":host{display:flex;flex-direction:column;height:100%;min-height:0;font-family:var(--mkb-font, inherit)}.mkbd-toolbar{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--mkb-border, #e3e0ea);flex-wrap:wrap}.mkbd-title{font-size:14px;font-weight:600}.mkbd-chip{font-size:11px;padding:2px 10px;border-radius:999px}.mkbd-chip-ok{background:color-mix(in srgb,var(--mkb-success, #1b6e3c) 12%,transparent);color:var(--mkb-success, #1b6e3c)}.mkbd-chip-error{background:color-mix(in srgb,var(--mkb-danger, #b3261e) 12%,transparent);color:var(--mkb-danger, #b3261e)}.mkbd-spacer{flex:1}.mkbd-import-errors{margin:8px 12px;padding:8px 12px;border:1px solid var(--mkb-danger, #b3261e);border-radius:8px;font-size:12px}.mkbd-import-errors ul{margin:4px 0;padding-left:18px}.mkbd-body{display:flex;flex:1;min-height:0}.mkbd-editors{flex:1 1 46%;min-width:340px;overflow:auto;padding:8px 12px 24px;border-right:1px solid var(--mkb-border, #e3e0ea)}.mkbd-preview{flex:1 1 54%;min-width:0;display:flex;flex-direction:column}.mkbd-preview-head{display:flex;align-items:baseline;gap:10px;padding:8px 12px 4px;font-size:12px;font-weight:600}.mkbd-preview-board{flex:1;min-height:0;overflow:auto}.mkbd-issues{margin:0 12px 6px;padding:6px 12px 6px 26px;font-size:12px;color:var(--mkb-danger, #b3261e);border:1px dashed var(--mkb-danger, #b3261e);border-radius:8px}.mkbd-hint{font-size:11.5px;color:var(--mkb-muted, #6f6a7c)}.mkbd-json{width:100%;font-family:ui-monospace,monospace;font-size:12px;border:1px solid var(--mkb-border, #e3e0ea);border-radius:8px;padding:8px;box-sizing:border-box}@media(max-width:900px){.mkbd-body{flex-direction:column}.mkbd-editors{border-right:none;border-bottom:1px solid var(--mkb-border, #e3e0ea)}}\n"] }]
3536
+ `, styles: [":host{--mkbd-primary: var(--color-primary, #5e35b1);--mkbd-on-primary: var(--color-on-primary, #ffffff);--mkbd-primary-container: var(--color-primary-container, #ede7f6);--mkbd-primary-soft: color-mix(in srgb, var(--mkbd-primary) 8%, transparent);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 28%, #ffffff);--mkbd-surface: var(--color-surface, #f4f5f7);--mkbd-panel: var(--color-panel, #ffffff);--mkbd-panel-2: var(--color-panel-2, #f6f7f9);--mkbd-panel-3: var(--color-panel-3, #f1f2f5);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 70%, var(--mkbd-surface));--mkbd-border: var(--color-border, #e6e8ee);--mkbd-border-soft: var(--color-border-soft, #eef0f4);--mkbd-border-strong: var(--color-border-strong, #c9cdd6);--mkbd-fg: var(--color-foreground, #1e1f24);--mkbd-secondary: var(--color-secondary, #4a4d57);--mkbd-muted: var(--color-muted, #8b909c);--mkbd-muted-2: var(--color-muted-2, #a2a7b2);--mkbd-disabled: var(--color-disabled-fg, #b3b7c1);--mkbd-success: var(--color-success, #2e7d32);--mkbd-success-container: var(--color-success-container, #e8f5e9);--mkbd-error: var(--color-error-text, #c62828);--mkbd-error-container: var(--color-error-container, #fdecea);--mkbd-warning-text: var(--color-warning-text, #b76e00);--mkbd-warning-container: var(--color-warning-container, #fff4e0);--mkbd-radius-sm: var(--radius-sm, 8px);--mkbd-radius-md: var(--radius-md, 10px);--mkbd-radius-lg: var(--radius-lg, 12px);--mkbd-radius-pill: var(--radius-pill, 999px);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(20, 22, 30, .1));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4));--mkbd-dur: var(--dur-fast, .12s);--mkbd-ease: var(--ease-standard, cubic-bezier(.2, 0, 0, 1));--mkbd-font: var(--font-sans, \"Roboto\", system-ui, -apple-system, \"Segoe UI\", sans-serif);--mkbd-font-mono: var(--font-mono, \"Roboto Mono\", ui-monospace, \"SFMono-Regular\", Menlo, monospace);font-family:var(--mkbd-font);color:var(--mkbd-fg)}:host-context([data-theme=\"dark\"]){--mkbd-primary: var(--color-primary, #b39ddb);--mkbd-on-primary: var(--color-on-primary, #2a1258);--mkbd-primary-container: var(--color-primary-container, #4b3b80);--mkbd-primary-outline: color-mix(in srgb, var(--mkbd-primary) 40%, transparent);--mkbd-surface: var(--color-surface, #0e1116);--mkbd-panel: var(--color-panel, #14171d);--mkbd-panel-2: var(--color-panel-2, #1b1f27);--mkbd-panel-3: var(--color-panel-3, #222732);--mkbd-canvas: color-mix(in srgb, var(--mkbd-panel) 60%, var(--mkbd-surface));--mkbd-border: var(--color-border, #262b34);--mkbd-border-soft: var(--color-border-soft, #1e232b);--mkbd-border-strong: var(--color-border-strong, #3a4048);--mkbd-fg: var(--color-foreground, #e6e9ef);--mkbd-secondary: var(--color-secondary, #c2c7d0);--mkbd-muted: var(--color-muted, #9aa3b2);--mkbd-muted-2: var(--color-muted-2, #7c8494);--mkbd-disabled: var(--color-disabled-fg, #59606c);--mkbd-success: var(--color-success, #81c784);--mkbd-success-container: var(--color-success-container, #1e3a24);--mkbd-error: var(--color-error-text, #ef9a9a);--mkbd-error-container: var(--color-error-container, #3a1e1e);--mkbd-warning-text: var(--color-warning-text, #ffb74d);--mkbd-warning-container: var(--color-warning-container, #3a2c10);--mkbd-elevation-1: var(--elevation-1, 0 1px 3px rgba(0, 0, 0, .4));--mkbd-focus-ring: var(--focus-ring, 0 0 0 3px rgba(179, 157, 219, .55))}.mkbd-overline{font:500 11px var(--mkbd-font-mono);letter-spacing:.5px;text-transform:uppercase;color:var(--mkbd-muted)}.mkbd-hint{margin:0 0 10px;font-size:12px;line-height:1.45;color:var(--mkbd-muted)}.mkbd-section{display:flex;align-items:center;gap:8px;margin:22px 0 12px}.mkbd-section:first-child{margin-top:0}.mkbd-section:after{content:\"\";flex:1;height:1px;background:var(--mkbd-border-soft)}.mkbd-count{font:500 10px var(--mkbd-font-mono);color:var(--mkbd-primary);background:var(--mkbd-primary-container);padding:2px 8px;border-radius:var(--mkbd-radius-pill)}.mkbd-btn{display:inline-flex;align-items:center;gap:7px;height:38px;padding:0 14px;border-radius:var(--mkbd-radius-md);border:1px solid transparent;background:transparent;font:500 12.5px var(--mkbd-font);color:var(--mkbd-secondary);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-btn-outline{border-color:var(--mkbd-primary-outline);background:var(--mkbd-panel);color:var(--mkbd-primary)}.mkbd-btn-outline:hover:not(:disabled){background:var(--mkbd-primary-soft)}.mkbd-btn-tonal{background:var(--mkbd-primary-container);color:var(--mkbd-primary)}.mkbd-btn-tonal:hover:not(:disabled){background:color-mix(in srgb,var(--mkbd-primary) 16%,var(--mkbd-panel))}.mkbd-btn-tonal:disabled{background:var(--mkbd-panel-3)}.mkbd-btn-text:hover:not(:disabled){background:var(--mkbd-panel-3)}.mkbd-btn-danger{color:var(--mkbd-error)}.mkbd-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container)}.mkbd-icon-btn{display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--mkbd-muted);font-size:19px;cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-icon-btn:hover:not(:disabled){background:var(--mkbd-panel-3);color:var(--mkbd-secondary)}.mkbd-icon-btn:disabled{color:var(--mkbd-disabled);cursor:default}.mkbd-icon-btn:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-icon-btn-danger{color:color-mix(in srgb,var(--mkbd-error) 45%,var(--mkbd-muted))}.mkbd-icon-btn-danger:hover:not(:disabled){background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-add{display:flex;align-items:center;justify-content:center;gap:8px;width:100%;height:44px;margin-top:12px;border:1.5px dashed var(--mkbd-border-strong);border-radius:var(--mkbd-radius-lg);background:transparent;color:var(--mkbd-primary);font:500 13px var(--mkbd-font);cursor:pointer;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-add:hover{background:var(--mkbd-primary-soft);border-color:var(--mkbd-primary)}.mkbd-add:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-chip{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 11px;border-radius:var(--mkbd-radius-pill);font:500 11px var(--mkbd-font);white-space:nowrap}.mkbd-chip-ok{background:var(--mkbd-success-container);color:var(--mkbd-success)}.mkbd-chip-error{background:var(--mkbd-error-container);color:var(--mkbd-error)}.mkbd-field{position:relative;display:flex;align-items:center;min-width:0;height:40px;padding:0 10px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field>.mkbd-label{position:absolute;top:-6px;left:8px;padding:0 4px;background:var(--mkbd-label-bg, var(--mkbd-panel));font-size:9.5px;line-height:1;color:var(--mkbd-muted);pointer-events:none;white-space:nowrap}.mkbd-field input,.mkbd-field select,.mkbd-field textarea{width:100%;min-width:0;border:none;outline:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);padding:0}.mkbd-field input::placeholder{color:var(--mkbd-disabled)}.mkbd-field select{appearance:none;cursor:pointer;padding-right:18px}.mkbd-field-select:after{content:\"\";position:absolute;right:12px;width:8px;height:8px;border-right:1.6px solid var(--mkbd-muted);border-bottom:1.6px solid var(--mkbd-muted);transform:translateY(-2px) rotate(45deg);pointer-events:none}.mkbd-field:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-field-mono input{font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-grow{flex:1}.mkbd-field-optional{border-style:dashed;border-color:var(--mkbd-border);background:var(--mkbd-panel-2)}.mkbd-field-optional>.mkbd-label{background:var(--mkbd-panel-2);color:var(--mkbd-muted-2)}.mkbd-field-optional input{text-align:center;font-family:var(--mkbd-font-mono);font-weight:500}.mkbd-field-optional:focus-within{border-style:solid;background:var(--mkbd-panel)}.mkbd-field-optional:focus-within>.mkbd-label{background:var(--mkbd-panel)}.mkbd-field textarea{height:100%;padding:8px 0;resize:vertical;font-family:var(--mkbd-font-mono);font-size:12px;line-height:1.5}.mkbd-field-area{height:auto;align-items:stretch;padding:2px 10px}.mkbd-check{display:inline-flex;align-items:center;gap:7px;font-size:11.5px;color:var(--mkbd-muted);cursor:pointer;-webkit-user-select:none;user-select:none;white-space:nowrap}.mkbd-check input{appearance:none;width:16px;height:16px;margin:0;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;background:var(--mkbd-panel);cursor:pointer;position:relative;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease),border-color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-check input:checked{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-check input:checked:after{content:\"\";position:absolute;left:4.5px;top:1px;width:4px;height:8px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}.mkbd-check input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-check:has(input:checked){color:var(--mkbd-primary);font-weight:500}.mkbd-switch{display:inline-flex;align-items:center;gap:10px;font-size:12.5px;color:var(--mkbd-secondary);cursor:pointer;-webkit-user-select:none;user-select:none}.mkbd-switch input{appearance:none;position:relative;width:38px;height:22px;margin:0;border-radius:var(--mkbd-radius-pill);background:var(--mkbd-border-strong);cursor:pointer;flex:none;transition:background var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:after{content:\"\";position:absolute;top:3px;left:3px;width:16px;height:16px;border-radius:50%;background:var(--mkbd-panel);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-switch input:checked{background:var(--mkbd-primary)}.mkbd-switch input:checked:after{transform:translate(16px)}.mkbd-switch input:focus-visible{outline:none;box-shadow:var(--mkbd-focus-ring)}.mkbd-switch-boxed{height:40px;padding:0 14px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel)}.mkbd-swatch{position:relative;display:inline-flex;align-items:center;justify-content:center;width:42px;height:40px;padding:0;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-sm);background:var(--mkbd-panel);cursor:pointer;overflow:hidden}.mkbd-swatch input{position:absolute;inset:0;opacity:0;cursor:pointer}.mkbd-swatch span{width:20px;height:20px;border-radius:5px;box-shadow:inset 0 0 0 1px #0000001f}.mkbd-swatch:focus-within{border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}.mkbd-rows{display:flex;flex-direction:column;gap:10px}.mkbd-row{display:grid;align-items:center;gap:10px;padding:12px 12px 12px 8px;border:1px solid var(--mkbd-border);border-left:4px solid var(--mkbd-accent, var(--mkbd-border-strong));border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel);transition:border-color var(--mkbd-dur) var(--mkbd-ease),box-shadow var(--mkbd-dur) var(--mkbd-ease)}.mkbd-row-selected{border-color:var(--mkbd-primary);border-width:1.5px;padding:11.5px 11.5px 11.5px 7.5px;box-shadow:0 0 0 3px var(--mkbd-primary-soft)}.mkbd-handle{display:inline-flex;align-items:center;justify-content:center;color:var(--mkbd-disabled);font-size:19px;cursor:grab}.mkbd-row-ctrls{display:flex;align-items:center;gap:2px}.mkbd-feature{display:flex;align-items:center;gap:12px;margin-top:22px;padding:14px 16px;border:1px solid var(--mkbd-border);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-panel)}.mkbd-feature>mkb-icon{font-size:20px;color:var(--mkbd-primary)}.mkbd-feature-title{font-weight:500;font-size:13.5px}.mkbd-feature-desc{font-size:11.5px;color:var(--mkbd-muted)}.mkbd-feature>.mkbd-switch{margin-left:auto}.mkbd-options{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-bottom:20px}.mkbd-options,.mkbd-stack,.mkbd-new-block{--mkbd-label-bg: var(--mkbd-canvas)}.mkbd-options>.mkbd-field,.mkbd-options>mkb-combo{flex:1;min-width:150px}.mkbd-stack{display:flex;flex-wrap:wrap;gap:14px 12px;align-items:center}.mkbd-stack .mkbd-field,.mkbd-stack mkb-combo{width:190px}.mkbd-stack .mkbd-field-sm,.mkbd-stack mkb-combo.mkbd-field-sm{width:130px}.mkbd-stack .mkbd-field-grow,.mkbd-stack mkb-combo.mkbd-field-grow{flex:1;min-width:220px;width:auto}.mkbd-stack .mkbd-field-full{flex:1 0 100%;width:auto}.mkbd-combo-btn{display:flex;align-items:center;gap:6px;flex:1;min-width:0;height:100%;padding:0;border:none;background:transparent;color:inherit;font:400 12.5px var(--mkbd-font);text-align:left;cursor:pointer}.mkbd-combo-btn:focus-visible{outline:none}.mkbd-combo-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mkbd-combo-empty{color:var(--mkbd-disabled)}.mkbd-combo-caret{font-size:18px;color:var(--mkbd-muted);transition:transform var(--mkbd-dur) var(--mkbd-ease)}.mkbd-field-combo:focus-within{border-color:var(--mkbd-primary);border-width:1.5px;padding:0 9.5px}.mkbd-field-combo:focus-within>.mkbd-label{color:var(--mkbd-primary)}.mkbd-combo-open .mkbd-combo-caret{transform:rotate(180deg)}.mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;margin-right:10px;border:1.5px solid var(--mkbd-border-strong);border-radius:4px;flex:none}.mkbd-menu-check-on{background:var(--mkbd-primary);border-color:var(--mkbd-primary)}.mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--mkbd-on-primary);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}\n", ":host{display:flex;flex-direction:column;height:100%;min-height:0;background:var(--mkbd-surface)}.mkbd-toolbar{flex:none;display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:14px 20px 12px;background:var(--mkbd-panel);border-bottom:1px solid var(--mkbd-border-soft)}.mkbd-title{margin:0;font:500 17px var(--mkbd-font);letter-spacing:-.2px}.mkbd-toolbar-actions{margin-left:auto;display:flex;align-items:center;gap:8px;flex-wrap:wrap}.mkbd-toolbar-sep{width:1px;height:26px;background:var(--mkbd-border)}.mkbd-menu-item{display:flex;flex-direction:column;line-height:1.35}.mkbd-menu-item strong{font:500 13px var(--mkbd-font)}.mkbd-menu-item small{font-size:11px;color:var(--mkbd-muted)}.mkbd-banner{flex:none;display:flex;align-items:flex-start;gap:10px;margin:12px 20px 0;padding:12px 14px;border:1px solid var(--mkbd-error);border-radius:var(--mkbd-radius-lg);background:var(--mkbd-error-container);color:var(--mkbd-error);font-size:12px}.mkbd-banner>mkb-icon{font-size:20px;margin-top:1px}.mkbd-banner ul{margin:4px 0 0;padding-left:18px}.mkbd-banner strong{font:500 13px var(--mkbd-font)}.mkbd-banner>.mkbd-icon-btn{margin-left:auto;color:inherit}.mkbd-body{display:flex;flex:1;min-height:0}.mkbd-editors{flex:1;display:flex;flex-direction:column;min-width:0;background:var(--mkbd-canvas);border-right:1px solid var(--mkbd-border)}.mkbd-pane{padding:18px 20px 28px}.mkbd-tabs{flex:1;min-height:0}.mkbd-tabs ::ng-deep .mat-mdc-tab-header{background:var(--mkbd-panel);padding:0 12px;flex:none;border-bottom:1px solid var(--mkbd-border-soft)}.mkbd-tabs ::ng-deep .mat-mdc-tab{min-width:0;padding:0 14px}.mkbd-tabs ::ng-deep .mdc-tab__text-label{font:500 13.5px var(--mkbd-font);letter-spacing:0;color:var(--mkbd-muted);transition:color var(--mkbd-dur) var(--mkbd-ease)}.mkbd-tabs ::ng-deep .mdc-tab--active .mdc-tab__text-label{color:var(--mkbd-primary)}.mkbd-tabs ::ng-deep .mdc-tab-indicator__content--underline{border-top-width:3px;border-radius:3px 3px 0 0;border-color:var(--mkbd-primary)}.mkbd-tabs ::ng-deep .mat-mdc-tab-body-wrapper{flex:1;min-height:0}.mkbd-tabs ::ng-deep .mat-mdc-tab-body-content{overflow:auto}.mkbd-preview{flex:none;width:clamp(360px,42%,560px);display:flex;flex-direction:column;min-width:0;background:var(--mkbd-surface)}.mkbd-preview-head{flex:none;display:flex;align-items:center;gap:8px;padding:14px 18px 10px}.mkbd-preview-eye{font-size:16px;color:var(--mkbd-success)}.mkbd-preview-note{margin:0;text-transform:none}.mkbd-preview-board{flex:1;min-height:0;overflow:auto;padding:0 18px 16px}.mkbd-preview-board>mos-kanban-board{display:block;height:100%}.mkbd-issues{margin:0 18px 8px;padding:8px 12px 8px 26px;font-size:11.5px;color:var(--mkbd-error);background:var(--mkbd-error-container);border-radius:var(--mkbd-radius-md)}.mkbd-issues code,.mkbd-banner code{font-family:var(--mkbd-font-mono)}.mkbd-json{display:block;width:100%;margin-bottom:12px;padding:12px;border:1px solid var(--mkbd-border-strong);border-radius:var(--mkbd-radius-md);background:var(--mkbd-panel);color:var(--mkbd-fg);font:400 12px/1.5 var(--mkbd-font-mono);box-sizing:border-box;resize:vertical}.mkbd-json:focus-visible{outline:none;border-color:var(--mkbd-primary);box-shadow:var(--mkbd-focus-ring)}::ng-deep .mat-mdc-menu-panel.mkbd-menu{min-width:176px;padding:6px;border:1px solid var(--color-border, #e6e8ee);border-radius:var(--radius-xl, 14px);background:var(--color-panel, #ffffff);box-shadow:var(--elevation-2, 0 1px 2px rgba(20, 22, 30, .1), 0 2px 6px rgba(20, 22, 30, .08))}::ng-deep .mkbd-menu .mat-mdc-menu-content{padding:0;max-height:285px;overflow-y:auto;overscroll-behavior:contain}::ng-deep .mkbd-menu .mkbd-menu-search{position:sticky;top:0;z-index:1;display:flex;align-items:center;gap:8px;padding:2px 4px 8px;background:var(--color-panel, #ffffff)}::ng-deep .mkbd-menu .mkbd-menu-search input{flex:1;min-width:0;height:34px;padding:0 10px;border:1px solid var(--color-border-strong, #c9cdd6);border-radius:var(--radius-sm, 8px);background:var(--color-panel, #ffffff);color:var(--color-foreground, #1e1f24);font:400 12.5px var(--font-sans, \"Roboto\", system-ui, sans-serif);outline:none}::ng-deep .mkbd-menu .mkbd-menu-search input:focus{border-color:var(--color-primary, #5e35b1);box-shadow:var(--focus-ring, 0 0 0 3px rgba(94, 53, 177, .4))}::ng-deep .mkbd-menu .mkbd-menu-count{font:500 10px var(--font-mono, ui-monospace, monospace);color:var(--color-muted, #8b909c);padding-right:4px}::ng-deep .mkbd-menu .mkbd-menu-empty{margin:0;padding:10px;font-size:12px;color:var(--color-muted, #8b909c)}::ng-deep .mkbd-menu .mat-mdc-menu-item{display:flex;align-items:center;gap:12px;min-height:38px;padding:0 10px;border-radius:var(--radius-md, 10px);color:var(--color-secondary, #4a4d57);font:400 12.5px var(--font-sans, \"Roboto\", system-ui, sans-serif);letter-spacing:0}::ng-deep .mkbd-menu .mat-mdc-menu-item .mat-mdc-menu-item-text{font:inherit;display:flex;align-items:center;gap:10px}::ng-deep .mkbd-menu .mat-mdc-menu-item:hover:not([disabled]){background:color-mix(in srgb,var(--color-foreground, #1e1f24) 8%,transparent)}::ng-deep .mkbd-menu .mkbd-menu-item-active{background:var(--color-primary-container, #ede7f6);color:var(--color-on-primary-container, #2a1258);font-weight:500}::ng-deep .mkbd-menu .mat-mdc-menu-item[disabled]{color:var(--color-disabled-fg, #b3b7c1)}::ng-deep .mkbd-menu .mkbd-menu-item{display:flex;flex-direction:column;line-height:1.35}::ng-deep .mkbd-menu .mkbd-menu-item strong{font:500 13px var(--font-sans, sans-serif)}::ng-deep .mkbd-menu .mkbd-menu-item small{font-size:11px;color:var(--color-muted, #8b909c)}::ng-deep .mkbd-menu .mkbd-menu-check{display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;flex:none;border:1.5px solid var(--color-border-strong, #c9cdd6);border-radius:4px}::ng-deep .mkbd-menu .mkbd-menu-check-on{background:var(--color-primary, #5e35b1);border-color:var(--color-primary, #5e35b1)}::ng-deep .mkbd-menu .mkbd-menu-check-on:after{content:\"\";width:4px;height:8px;margin-top:-2px;border:solid var(--color-on-primary, #ffffff);border-width:0 1.8px 1.8px 0;transform:rotate(45deg)}@media(max-width:900px){.mkbd-body{flex-direction:column}.mkbd-editors{border-right:none;border-bottom:1px solid var(--mkbd-border)}.mkbd-preview{width:auto;flex:1}}\n"] }]
2556
3537
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], theme: [{ type: i0.Input, args: [{ isSignal: true, alias: "theme", required: false }] }], registry: [{ type: i0.Input, args: [{ isSignal: true, alias: "registry", required: false }] }], storageKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "storageKey", required: false }] }], configChange: [{ type: i0.Output, args: ["configChange"] }], themeChange: [{ type: i0.Output, args: ["themeChange"] }] } });
2557
3538
 
2558
3539
  /**