@inchurch/matcha-theme 22.40.0 → 22.40.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/abstracts/_colors.scss +291 -291
- package/abstracts/_elevation.scss +108 -108
- package/abstracts/_functions.scss +321 -321
- package/abstracts/_media-breakpoint.scss +26 -26
- package/abstracts/_theme-api.scss +224 -224
- package/abstracts/_typography.scss +128 -128
- package/base/_reset.scss +487 -487
- package/components/app-page-header.scss +260 -260
- package/components/matcha-accordion.scss +297 -297
- package/components/matcha-audio-player.scss +31 -31
- package/components/matcha-autocomplete.scss +145 -145
- package/components/matcha-avatar.scss +426 -426
- package/components/matcha-badge.scss +120 -120
- package/components/matcha-breadcrumb.scss +231 -231
- package/components/matcha-button-toggle.scss +484 -484
- package/components/matcha-buttons.scss +973 -973
- package/components/matcha-calendar.scss +253 -253
- package/components/matcha-cards.scss +212 -212
- package/components/matcha-chart-card.scss +53 -53
- package/components/matcha-checkbox.scss +266 -266
- package/components/matcha-chip.scss +311 -311
- package/components/matcha-color-pick.scss +34 -34
- package/components/matcha-command-palette.scss +316 -316
- package/components/matcha-crop.scss +419 -419
- package/components/matcha-date.scss +81 -81
- package/components/matcha-divider.scss +100 -100
- package/components/matcha-draggable.scss +23 -23
- package/components/matcha-drawer.scss +376 -376
- package/components/matcha-drop-image.scss +14 -14
- package/components/matcha-drop-list.scss +430 -430
- package/components/matcha-emoji.scss +69 -69
- package/components/matcha-empty-state.scss +230 -230
- package/components/matcha-file-uploader.scss +650 -650
- package/components/matcha-flag.scss +103 -103
- package/components/matcha-footer.scss +91 -91
- package/components/matcha-form-field.scss +883 -883
- package/components/matcha-form-section.scss +100 -100
- package/components/matcha-header.scss +135 -135
- package/components/matcha-highlight.scss +164 -164
- package/components/matcha-hint-text.scss +90 -90
- package/components/matcha-horizontal-tree.scss +247 -247
- package/components/matcha-icon.scss +111 -111
- package/components/matcha-image.scss +60 -60
- package/components/matcha-list.scss +211 -211
- package/components/matcha-menu.scss +99 -99
- package/components/matcha-modal.scss +210 -210
- package/components/matcha-nav.scss +770 -770
- package/components/matcha-notification.scss +417 -417
- package/components/matcha-option.scss +170 -170
- package/components/matcha-page-builder.scss +4196 -4196
- package/components/matcha-paginator.scss +699 -699
- package/components/matcha-panel.scss +216 -216
- package/components/matcha-period.scss +174 -174
- package/components/matcha-profile-card.scss +50 -50
- package/components/matcha-progress-bar.scss +355 -355
- package/components/matcha-radio.scss +325 -325
- package/components/matcha-ripple.scss +7 -7
- package/components/matcha-scrollbar.scss +33 -33
- package/components/matcha-scrollbox-shadow.scss +120 -120
- package/components/matcha-section.scss +102 -102
- package/components/matcha-select-multiple.scss +56 -56
- package/components/matcha-select.scss +643 -629
- package/components/matcha-skeleton.scss +182 -182
- package/components/matcha-slide-toggle.scss +369 -369
- package/components/matcha-slider.scss +285 -285
- package/components/matcha-snack-bar.scss +259 -259
- package/components/matcha-spin.scss +164 -164
- package/components/matcha-spinner.scss +97 -97
- package/components/matcha-stepper.scss +376 -376
- package/components/matcha-table-cell.scss +107 -107
- package/components/matcha-table.scss +722 -722
- package/components/matcha-tabs.scss +642 -642
- package/components/matcha-text-editor.scss +111 -111
- package/components/matcha-time.scss +33 -33
- package/components/matcha-timepicker.scss +13 -13
- package/components/matcha-toolbar.scss +366 -366
- package/components/matcha-tooltip.scss +235 -235
- package/components/matcha-tree-view.scss +658 -658
- package/layout/matcha-page-layout.scss +778 -778
- package/main.scss +334 -334
- package/package.json +1 -1
- package/tokens/_animations-tokens.scss +37 -37
- package/tokens/_breakpoints-tokens.scss +35 -35
- package/tokens/_color-tokens.scss +288 -288
- package/tokens/_elevation-tokens.scss +33 -33
- package/tokens/_emit-tokens.scss +329 -329
- package/tokens/_material-palette.scss +1149 -1149
- package/tokens/_primitives.scss +98 -98
- package/tokens/_semantic-aliases.scss +120 -120
- package/tokens/_spacing-tokens.scss +94 -94
- package/tokens/_static-tokens.scss +137 -137
- package/tokens/_typography-tokens.scss +65 -65
- package/vendors/charts.scss +90 -90
|
@@ -1,650 +1,650 @@
|
|
|
1
|
-
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
-
@use "sass:map";
|
|
3
|
-
|
|
4
|
-
// =============================================================================
|
|
5
|
-
// matcha-file-uploader.scss — File upload component (matcha/file-uploader no Figma DSV3)
|
|
6
|
-
//
|
|
7
|
-
// 3 estados canon (16152:254):
|
|
8
|
-
// Estado=Dropzone (16152:209) — área vazia com icon pill + title + hint + 2 botões
|
|
9
|
-
// Estado=Enviando (16152:227) — thumb 64×36 + nome + progress + % + cancel
|
|
10
|
-
// Estado=Completo (16152:242) — thumb 64×36 + nome + size + delete (trash)
|
|
11
|
-
//
|
|
12
|
-
// Width canon: 480px (component se adapta via max-width: 480px + width: 100%)
|
|
13
|
-
// =============================================================================
|
|
14
|
-
|
|
15
|
-
@mixin matcha-file-uploader-theme($theme) {
|
|
16
|
-
|
|
17
|
-
// ── Shell (modo múltiplo: moldura única em volta de dropzone + lista) ──
|
|
18
|
-
// Recebe o mesmo tratamento visual da dropzone porque é ELE que passa a ser
|
|
19
|
-
// a "área de upload" quando a lista mora dentro — inclusive o realce de
|
|
20
|
-
// dragover, já que os handlers de drag vivem aqui.
|
|
21
|
-
.matcha-file-uploader-shell {
|
|
22
|
-
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
23
|
-
border-color: var(--matcha-color-surface-border);
|
|
24
|
-
|
|
25
|
-
&.matcha-file-uploader-dragover {
|
|
26
|
-
background: var(--matcha-color-accent-alpha);
|
|
27
|
-
border-color: var(--matcha-color-accent);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
&.matcha-file-uploader-disabled {
|
|
31
|
-
opacity: 0.5;
|
|
32
|
-
// pointer-events + cursor default, não `not-allowed`: constraint #14 do
|
|
33
|
-
// INTERACTION-SYSTEM (o lint de CSS avisa). A dropzone legada abaixo ainda
|
|
34
|
-
// usa not-allowed — rastreado no backlog, fora do escopo desta mudança.
|
|
35
|
-
pointer-events: none;
|
|
36
|
-
cursor: default;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ── Dropzone ──
|
|
41
|
-
.matcha-file-uploader-dropzone {
|
|
42
|
-
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
43
|
-
border-color: var(--matcha-color-surface-border);
|
|
44
|
-
|
|
45
|
-
&.matcha-file-uploader-dragover {
|
|
46
|
-
background: var(--matcha-color-accent-alpha);
|
|
47
|
-
border-color: var(--matcha-color-accent);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
&.matcha-file-uploader-disabled {
|
|
51
|
-
opacity: 0.5;
|
|
52
|
-
cursor: not-allowed;
|
|
53
|
-
pointer-events: none;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// Dentro do shell a moldura e o fundo são do shell — a dropzone é só a
|
|
57
|
-
// afordância de clique. Duas classes de propósito: precisa vencer o bloco
|
|
58
|
-
// acima, que tem a mesma especificidade.
|
|
59
|
-
&.matcha-file-uploader-dropzone--inset {
|
|
60
|
-
background: transparent;
|
|
61
|
-
border-color: transparent;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.matcha-file-uploader-dropzone__icon-pill {
|
|
66
|
-
background: var(--matcha-color-interaction-disabled-bg, #282c34);
|
|
67
|
-
color: var(--matcha-color-text-secondary);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
.matcha-file-uploader-dropzone__title {
|
|
71
|
-
color: var(--matcha-color-text-primary);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
.matcha-file-uploader-dropzone__optional {
|
|
75
|
-
color: var(--matcha-color-interaction-disabled-fg, rgba(232, 234, 237, 0.38));
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
.matcha-file-uploader-dropzone__hint {
|
|
79
|
-
color: var(--matcha-color-text-secondary);
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// ── File item ──
|
|
83
|
-
.matcha-file-uploader-file {
|
|
84
|
-
background: var(--matcha-color-surface-card);
|
|
85
|
-
border-color: var(--matcha-color-surface-border);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.matcha-file-uploader-file__thumb {
|
|
89
|
-
// interaction-disabled-bg, e nao elevation-surface-3: a moldura do arquivo nao e uma
|
|
90
|
-
// superficie elevada, e um fundo neutro atras de um icone — e o surface-3 desaparecia
|
|
91
|
-
// sobre o card em que a linha vive.
|
|
92
|
-
background: var(--matcha-color-interaction-disabled-bg);
|
|
93
|
-
color: var(--matcha-color-text-muted);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
.matcha-file-uploader-file__name {
|
|
97
|
-
color: var(--matcha-color-text-primary);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.matcha-file-uploader-file__size {
|
|
101
|
-
color: var(--matcha-color-text-secondary);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.matcha-file-uploader-file__progress {
|
|
105
|
-
background: var(--matcha-color-surface-border);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
.matcha-file-uploader-file__progress-fill {
|
|
109
|
-
background: var(--matcha-color-accent);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
.matcha-file-uploader-file__percent {
|
|
113
|
-
color: var(--matcha-color-text-secondary);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
.matcha-file-uploader-file__error-text {
|
|
117
|
-
color: var(--matcha-color-danger);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
.matcha-file-uploader-file__action {
|
|
121
|
-
color: var(--matcha-color-text-secondary);
|
|
122
|
-
|
|
123
|
-
&:hover {
|
|
124
|
-
background: var(--matcha-color-surface-hover, transparent);
|
|
125
|
-
color: var(--matcha-color-text-primary);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Apagar é vermelho EM REPOUSO, não só no hover: remover arquivo é
|
|
129
|
-
// destrutivo e irreversível, e num modo múltiplo com vários itens
|
|
130
|
-
// empilhados a ação precisa ser distinguível antes de o ponteiro chegar
|
|
131
|
-
// nela (em touch não há hover nenhum). `danger` é papel, não hue —
|
|
132
|
-
// o tema pode remapear.
|
|
133
|
-
//
|
|
134
|
-
// `--matcha-icon-color` é obrigatório, e não redundante com o `color`: o
|
|
135
|
-
// matcha-icon resolve o glyph por `var(--matcha-icon-color, …-icon-default)`
|
|
136
|
-
// (matcha-icon.scss:97) e NÃO herda o `color` do pai. Era por isso que o
|
|
137
|
-
// vermelho antigo de hover nunca chegou a pintar a lixeira.
|
|
138
|
-
&.matcha-file-uploader-file__action--delete {
|
|
139
|
-
color: var(--matcha-color-danger);
|
|
140
|
-
--matcha-icon-color: var(--matcha-color-danger);
|
|
141
|
-
|
|
142
|
-
// Fundo tinted em vez de surface-hover neutro, e a cor é reafirmada
|
|
143
|
-
// porque o :hover genérico acima empurraria text-primary.
|
|
144
|
-
&:hover {
|
|
145
|
-
background: var(--matcha-color-danger-alpha);
|
|
146
|
-
color: var(--matcha-color-danger);
|
|
147
|
-
--matcha-icon-color: var(--matcha-color-danger);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// ── Card layout (preview preenchido) ──
|
|
153
|
-
.matcha-file-uploader-card {
|
|
154
|
-
border-color: var(--matcha-color-surface-border);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// contain (logo/transparência): fundo neutro atrás da imagem inteira
|
|
158
|
-
.matcha-file-uploader-card--contain {
|
|
159
|
-
background: var(--matcha-color-surface-card);
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
.matcha-file-uploader-card__action {
|
|
163
|
-
background: var(--matcha-color-surface-card-alpha, var(--matcha-color-surface-card));
|
|
164
|
-
color: var(--matcha-color-text-primary);
|
|
165
|
-
|
|
166
|
-
&:hover {
|
|
167
|
-
background: var(--matcha-color-surface-card);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Mesma regra do delete na linha. Aqui só o GLYPH vira danger: o fundo
|
|
171
|
-
// continua sendo a pastilha de surface-card, que é o que garante contraste
|
|
172
|
-
// do ícone sobre uma imagem qualquer — trocá-lo por danger-alpha (10%)
|
|
173
|
-
// deixaria o vermelho competir com a foto atrás.
|
|
174
|
-
&.matcha-file-uploader-card__action--delete {
|
|
175
|
-
color: var(--matcha-color-danger);
|
|
176
|
-
--matcha-icon-color: var(--matcha-color-danger);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
182
|
-
// LAYOUT — independente de tema
|
|
183
|
-
// ──────────────────────────────────────────────────────────────────────────────
|
|
184
|
-
|
|
185
|
-
// Host — full-width; consumer aplica max-width externamente se quiser cap
|
|
186
|
-
.matcha-file-uploader {
|
|
187
|
-
display: block;
|
|
188
|
-
width: 100%;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// ── Empty state wrapper (dropzone + ação secundária FORA do drop) ──────────
|
|
192
|
-
.matcha-file-uploader-empty {
|
|
193
|
-
display: flex;
|
|
194
|
-
flex-direction: column;
|
|
195
|
-
gap: var(--matcha-space-150, 12px);
|
|
196
|
-
width: 100%;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ── Shell (modo múltiplo) ────────────────────────────────────────────────────
|
|
200
|
-
// A "área de upload" quando a lista mora dentro: uma moldura tracejada só,
|
|
201
|
-
// com a dropzone no topo e a lista rolável embaixo. Sem arquivo nenhum o
|
|
202
|
-
// resultado é visualmente idêntico à dropzone solta — só a moldura mudou de
|
|
203
|
-
// dono, do filho para o pai.
|
|
204
|
-
.matcha-file-uploader-shell {
|
|
205
|
-
display: flex;
|
|
206
|
-
flex-direction: column;
|
|
207
|
-
width: 100%;
|
|
208
|
-
box-sizing: border-box;
|
|
209
|
-
border: var(--matcha-border-thin, 2px) dashed transparent;
|
|
210
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
211
|
-
overflow: hidden; // o radius precisa cortar a lista que rola por dentro
|
|
212
|
-
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
213
|
-
border-color var(--matcha-duration-instant, 80ms) linear;
|
|
214
|
-
|
|
215
|
-
// Classe de dimensionamento posta NO HOST tem que alcancar o shell — mesmo
|
|
216
|
-
// padrao (e mesmo racional) do matcha-grid, grid.component.scss:11-18. Sem
|
|
217
|
-
// isto, `<matcha-file-uploader class="h-400">` esticaria o host e deixaria o
|
|
218
|
-
// shell na altura do conteudo, e a area continuaria crescendo por dentro.
|
|
219
|
-
//
|
|
220
|
-
// `height: 100%` contra host de altura auto resolve pra `auto`: e no-op para
|
|
221
|
-
// quem nao define altura, portanto value-preserving nos usos existentes.
|
|
222
|
-
height: 100%;
|
|
223
|
-
|
|
224
|
-
// O foco visível é da dropzone interna (o elemento focável), não do shell.
|
|
225
|
-
&:focus-within {
|
|
226
|
-
outline: none;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// Com altura definida no host, e a DROPZONE que absorve a sobra: com 1 arquivo
|
|
230
|
-
// ela fica grande e a area nao tem buraco; conforme a lista cresce, cede
|
|
231
|
-
// espaco ate o proprio conteudo (pill + dois textos), que o min-height auto
|
|
232
|
-
// do flex protege de ser esmagado. Sem altura definida, nao ha sobra para
|
|
233
|
-
// distribuir e o resultado e o mesmo de antes.
|
|
234
|
-
.matcha-file-uploader-dropzone--inset {
|
|
235
|
-
flex: 1 1 auto;
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// ── Lista de arquivos rolável (dentro do shell) ──────────────────────────────
|
|
240
|
-
// max-height em custom property com fallback, igual --matcha-panel-max-height
|
|
241
|
-
// (280px é o mesmo teto que select/autocomplete/panel já usam para "lista com
|
|
242
|
-
// mais conteúdo abaixo"). Passar `none` devolve o crescimento ilimitado antigo.
|
|
243
|
-
.matcha-file-uploader-list {
|
|
244
|
-
display: flex;
|
|
245
|
-
flex-direction: column;
|
|
246
|
-
gap: var(--matcha-space-100, 8px);
|
|
247
|
-
min-height: 0; // sem isso o floor de min-content impede o scroll no flex
|
|
248
|
-
// Pede o tamanho do conteudo e ENCOLHE quando falta espaco — e ai o scroll
|
|
249
|
-
// interno assume. E o que faz a lista caber quando o host tem altura definida
|
|
250
|
-
// e o teto de 280px seria maior do que sobrou.
|
|
251
|
-
flex: 0 1 auto;
|
|
252
|
-
max-height: var(--matcha-file-uploader-list-max-height, 280px);
|
|
253
|
-
overflow-y: auto;
|
|
254
|
-
overflow-x: hidden; // scrollbar vertical + nowrap gera barra horizontal fantasma
|
|
255
|
-
overscroll-behavior: contain; // o scroll não vaza pra página ao chegar no fim
|
|
256
|
-
-webkit-overflow-scrolling: touch;
|
|
257
|
-
padding: 0 var(--matcha-space-100, 8px) var(--matcha-space-100, 8px);
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Dentro da lista o espaçamento é do `gap` — o margin-top do item rolaria
|
|
261
|
-
// junto e daria um respiro fantasma no topo do scroll.
|
|
262
|
-
.matcha-file-uploader-list > .matcha-file-uploader-file,
|
|
263
|
-
.matcha-file-uploader-list > .matcha-file-uploader-card {
|
|
264
|
-
margin-top: 0;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
// ── Dropzone box (Estado=Dropzone — Figma 16152:209) — a zona INTEIRA é o alvo
|
|
269
|
-
.matcha-file-uploader-dropzone {
|
|
270
|
-
display: flex;
|
|
271
|
-
flex-direction: column;
|
|
272
|
-
align-items: center;
|
|
273
|
-
justify-content: center;
|
|
274
|
-
gap: var(--matcha-space-200, 16px);
|
|
275
|
-
padding: var(--matcha-space-400, 32px) var(--matcha-space-300, 24px);
|
|
276
|
-
border: var(--matcha-border-thin, 2px) dashed transparent;
|
|
277
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
278
|
-
cursor: pointer;
|
|
279
|
-
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
280
|
-
border-color var(--matcha-duration-instant, 80ms) linear;
|
|
281
|
-
|
|
282
|
-
&:focus-visible {
|
|
283
|
-
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent, #009400);
|
|
284
|
-
outline-offset: 2px;
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Dropzone dentro do shell: sem moldura própria (é do shell) e sem o radius
|
|
289
|
-
// que arredondaria um canto interno. Mantém padding, cursor e foco.
|
|
290
|
-
// Precisa vir DEPOIS do bloco base: mesma especificidade (uma classe), então é
|
|
291
|
-
// a ordem que decide — declarado antes, o `border: 2px dashed` do base vencia e
|
|
292
|
-
// sobravam 2px de borda transparente dentro do shell.
|
|
293
|
-
.matcha-file-uploader-dropzone--inset {
|
|
294
|
-
border-width: 0;
|
|
295
|
-
border-radius: 0;
|
|
296
|
-
|
|
297
|
-
// Anel de foco PARA DENTRO. A dropzone inset ocupa a largura toda do shell,
|
|
298
|
-
// que tem `overflow: hidden` (o radius precisa cortar a lista rolável): com o
|
|
299
|
-
// `outline-offset: 2px` do bloco base o anel cai fora da caixa e é ceifado,
|
|
300
|
-
// deixando o alvo de teclado sem indicação visível nas laterais.
|
|
301
|
-
&:focus-visible {
|
|
302
|
-
outline-offset: -2px;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// layout="card": dropzone vazio compartilha a proporção do card preenchido
|
|
307
|
-
// (aspect-ratio aplicado inline via previewRatio) pra empty e filled terem a
|
|
308
|
-
// MESMA altura lado a lado. Sem isso, vazio é dimensionado por padding/conteúdo
|
|
309
|
-
// e preenchido por aspect-ratio → alturas divergentes.
|
|
310
|
-
.matcha-file-uploader-dropzone--card {
|
|
311
|
-
width: 100%;
|
|
312
|
-
overflow: hidden;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
// Icon pill (bg interaction/disabled-bg + padding 40h/16v · icon 24×24)
|
|
316
|
-
.matcha-file-uploader-dropzone__icon-pill {
|
|
317
|
-
display: inline-flex;
|
|
318
|
-
align-items: center;
|
|
319
|
-
justify-content: center;
|
|
320
|
-
padding: var(--matcha-space-200, 16px) var(--matcha-space-500, 40px);
|
|
321
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
322
|
-
flex-shrink: 0;
|
|
323
|
-
|
|
324
|
-
matcha-icon {
|
|
325
|
-
--matcha-icon-size: 24px;
|
|
326
|
-
width: 24px;
|
|
327
|
-
height: 24px;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Text block — column gap 4px, center
|
|
332
|
-
.matcha-file-uploader-dropzone__text {
|
|
333
|
-
display: flex;
|
|
334
|
-
flex-direction: column;
|
|
335
|
-
align-items: center;
|
|
336
|
-
gap: var(--matcha-space-050, 4px);
|
|
337
|
-
text-align: center;
|
|
338
|
-
width: 100%;
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
// Title row (inline: title + optional)
|
|
342
|
-
.matcha-file-uploader-dropzone__title-row {
|
|
343
|
-
display: inline-flex;
|
|
344
|
-
align-items: center;
|
|
345
|
-
justify-content: center;
|
|
346
|
-
gap: var(--matcha-space-050, 4px);
|
|
347
|
-
white-space: nowrap;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
.matcha-file-uploader-dropzone__title {
|
|
351
|
-
font-family: var(--matcha-font-family);
|
|
352
|
-
font-size: var(--matcha-text-label-md, 14px);
|
|
353
|
-
font-weight: var(--matcha-weight-medium, 500);
|
|
354
|
-
line-height: var(--matcha-leading-label-md, 20px);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
.matcha-file-uploader-dropzone__optional {
|
|
358
|
-
font-family: var(--matcha-font-family);
|
|
359
|
-
font-size: var(--matcha-text-label-md, 14px);
|
|
360
|
-
font-weight: var(--matcha-weight-medium, 500);
|
|
361
|
-
line-height: var(--matcha-leading-label-md, 20px);
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
.matcha-file-uploader-dropzone__hint {
|
|
365
|
-
margin: 0;
|
|
366
|
-
font-family: var(--matcha-font-family);
|
|
367
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
368
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
369
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
370
|
-
white-space: pre-line; // suporta \n pra hint multi-linha (1280×720 px... \n Clique pra selecionar...)
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
// Actions row (slot secondary + select arquivo)
|
|
374
|
-
// Hidden input
|
|
375
|
-
.matcha-file-uploader-input {
|
|
376
|
-
display: none;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// ── File Item — Estados Enviando (16152:227) e Completo (16152:242) ──────────
|
|
380
|
-
.matcha-file-uploader-file {
|
|
381
|
-
display: flex;
|
|
382
|
-
align-items: center;
|
|
383
|
-
gap: var(--matcha-space-200, 16px);
|
|
384
|
-
border: var(--matcha-border-hairline, 1px) solid transparent;
|
|
385
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
386
|
-
margin-top: var(--matcha-space-100, 8px);
|
|
387
|
-
width: 100%;
|
|
388
|
-
|
|
389
|
-
// Enviando: padding 20/24 (mais respiro vs. Figma original 16)
|
|
390
|
-
&.matcha-file-uploader-file--uploading {
|
|
391
|
-
padding: var(--matcha-space-250, 20px) var(--matcha-space-300, 24px);
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
// Completo/Erro: padding 20/24 (mais respiro vs. Figma original 12/16)
|
|
395
|
-
&.matcha-file-uploader-file--completed,
|
|
396
|
-
&.matcha-file-uploader-file--error {
|
|
397
|
-
padding: var(--matcha-space-250, 20px) var(--matcha-space-300, 24px);
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
// Thumbnail 64×36 (16:9 · radius lg)
|
|
402
|
-
.matcha-file-uploader-file__thumb {
|
|
403
|
-
display: flex;
|
|
404
|
-
align-items: center;
|
|
405
|
-
justify-content: center;
|
|
406
|
-
width: 64px;
|
|
407
|
-
height: 36px;
|
|
408
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
409
|
-
flex-shrink: 0;
|
|
410
|
-
overflow: hidden;
|
|
411
|
-
|
|
412
|
-
img {
|
|
413
|
-
width: 100%;
|
|
414
|
-
height: 100%;
|
|
415
|
-
object-fit: cover;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
matcha-icon {
|
|
419
|
-
--matcha-icon-size: 20px;
|
|
420
|
-
width: 20px;
|
|
421
|
-
height: 20px;
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
// Info column (flex-1)
|
|
426
|
-
.matcha-file-uploader-file__info {
|
|
427
|
-
display: flex;
|
|
428
|
-
flex-direction: column;
|
|
429
|
-
flex: 1 1 0;
|
|
430
|
-
min-width: 0;
|
|
431
|
-
overflow: hidden;
|
|
432
|
-
|
|
433
|
-
// Enviando: gap 6 (entre nome e progress bar)
|
|
434
|
-
.matcha-file-uploader-file--uploading & {
|
|
435
|
-
gap: var(--matcha-space-075, 6px);
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
// Completo: gap 4 (entre nome e size)
|
|
439
|
-
.matcha-file-uploader-file--completed &,
|
|
440
|
-
.matcha-file-uploader-file--error & {
|
|
441
|
-
gap: var(--matcha-space-050, 4px);
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
// File name — Manrope Medium 13/19 letter 0.2 (text/button-sm)
|
|
446
|
-
.matcha-file-uploader-file__name {
|
|
447
|
-
font-family: var(--matcha-font-family);
|
|
448
|
-
font-size: var(--matcha-text-label-sm, 12px);
|
|
449
|
-
font-weight: var(--matcha-weight-medium, 500);
|
|
450
|
-
line-height: var(--matcha-leading-label-sm, 16px);
|
|
451
|
-
letter-spacing: 0.2px;
|
|
452
|
-
white-space: nowrap;
|
|
453
|
-
overflow: hidden;
|
|
454
|
-
text-overflow: ellipsis;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
// Nome como ancora: mesma tipografia, aparencia de link. `display: block` porque o
|
|
458
|
-
// ellipsis do nome depende de o elemento ser bloco, e <a> e inline por padrao.
|
|
459
|
-
.matcha-file-uploader-file__name--link {
|
|
460
|
-
display: block;
|
|
461
|
-
color: var(--matcha-color-accent);
|
|
462
|
-
text-decoration: underline;
|
|
463
|
-
|
|
464
|
-
&:hover,
|
|
465
|
-
&:focus-visible {
|
|
466
|
-
text-decoration: none;
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
// File size — Manrope Regular 11/14 letter 0.3 (text/caption)
|
|
471
|
-
.matcha-file-uploader-file__size {
|
|
472
|
-
font-family: var(--matcha-font-family);
|
|
473
|
-
font-size: var(--matcha-text-p-tiny, 11px);
|
|
474
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
475
|
-
line-height: var(--matcha-leading-p-tiny, 14px);
|
|
476
|
-
letter-spacing: 0.3px;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// Error text — body-sm danger
|
|
480
|
-
.matcha-file-uploader-file__error-text {
|
|
481
|
-
font-family: var(--matcha-font-family);
|
|
482
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
483
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
484
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// ── Progress bar (height 4px · radius sm) ─────────────────────────────────────
|
|
488
|
-
.matcha-file-uploader-file__progress {
|
|
489
|
-
width: 100%;
|
|
490
|
-
height: 4px;
|
|
491
|
-
border-radius: var(--matcha-radius-sm, 2px);
|
|
492
|
-
overflow: hidden;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
.matcha-file-uploader-file__progress-fill {
|
|
496
|
-
height: 100%;
|
|
497
|
-
border-radius: var(--matcha-radius-sm, 2px);
|
|
498
|
-
transition: width var(--matcha-duration-moderate, 300ms) ease;
|
|
499
|
-
}
|
|
500
|
-
|
|
501
|
-
// Percent label — body-sm text-secondary
|
|
502
|
-
.matcha-file-uploader-file__percent {
|
|
503
|
-
font-family: var(--matcha-font-family);
|
|
504
|
-
font-size: var(--matcha-text-body-sm, 12px);
|
|
505
|
-
font-weight: var(--matcha-weight-regular, 400);
|
|
506
|
-
line-height: var(--matcha-leading-body-sm, 16px);
|
|
507
|
-
flex-shrink: 0;
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
// Cancel/Delete action button — 20×20 (icon size + bg transparent + hover)
|
|
511
|
-
.matcha-file-uploader-file__action {
|
|
512
|
-
display: inline-flex;
|
|
513
|
-
align-items: center;
|
|
514
|
-
justify-content: center;
|
|
515
|
-
width: 20px;
|
|
516
|
-
height: 20px;
|
|
517
|
-
padding: 0;
|
|
518
|
-
background: transparent;
|
|
519
|
-
border: none;
|
|
520
|
-
border-radius: var(--matcha-radius-sm, 2px);
|
|
521
|
-
cursor: pointer;
|
|
522
|
-
flex-shrink: 0;
|
|
523
|
-
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
524
|
-
color var(--matcha-duration-instant, 80ms) linear;
|
|
525
|
-
|
|
526
|
-
matcha-icon {
|
|
527
|
-
--matcha-icon-size: 20px;
|
|
528
|
-
width: 20px;
|
|
529
|
-
height: 20px;
|
|
530
|
-
}
|
|
531
|
-
// Com o uploader desabilitado a linha continua legivel, mas as acoes saem de
|
|
532
|
-
// operacao. `pointer-events: none` + `cursor: default` em vez de
|
|
533
|
-
// `not-allowed`: constraint #14 do INTERACTION-SYSTEM.
|
|
534
|
-
&:disabled {
|
|
535
|
-
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
536
|
-
pointer-events: none;
|
|
537
|
-
cursor: default;
|
|
538
|
-
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
// ── Card layout — preview preenchido 16:9 + ações no hover (Estado=Drop filled) ──
|
|
542
|
-
.matcha-file-uploader-card {
|
|
543
|
-
position: relative;
|
|
544
|
-
width: 100%;
|
|
545
|
-
// SEM margin-top: o card preenchido tem que alinhar o topo com o dropzone
|
|
546
|
-
// vazio quando lado a lado (layout card). margin-top desalinhava em 8px.
|
|
547
|
-
border: var(--matcha-border-hairline, 1px) solid transparent;
|
|
548
|
-
border-radius: var(--matcha-radius-lg, 8px);
|
|
549
|
-
overflow: hidden;
|
|
550
|
-
aspect-ratio: 16 / 9; // fallback; sobrescrito por [style.aspect-ratio]="previewRatio"
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
.matcha-file-uploader-card__img {
|
|
554
|
-
display: block;
|
|
555
|
-
width: 100%;
|
|
556
|
-
height: 100%;
|
|
557
|
-
object-fit: cover; // sobrescrito por [style.object-fit]="previewFit"
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
.matcha-file-uploader-card__actions {
|
|
561
|
-
position: absolute;
|
|
562
|
-
top: var(--matcha-space-100, 8px);
|
|
563
|
-
right: var(--matcha-space-100, 8px);
|
|
564
|
-
display: flex;
|
|
565
|
-
gap: var(--matcha-space-100, 8px);
|
|
566
|
-
opacity: 1; // persistente — descobrÃvel e operável em touch (canon 20252:2253)
|
|
567
|
-
transition: opacity var(--matcha-duration-instant, 80ms) linear;
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Em dispositivos com hover, atenua no resting e destaca no hover/foco — mantém
|
|
571
|
-
// a tela limpa sem esconder a affordance onde não há hover (touch/totem).
|
|
572
|
-
@media (hover: hover) {
|
|
573
|
-
.matcha-file-uploader-card__actions { opacity: 0.72; }
|
|
574
|
-
|
|
575
|
-
.matcha-file-uploader-card:hover .matcha-file-uploader-card__actions,
|
|
576
|
-
.matcha-file-uploader-card:focus-within .matcha-file-uploader-card__actions {
|
|
577
|
-
opacity: 1;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
.matcha-file-uploader-card__action {
|
|
582
|
-
display: inline-flex;
|
|
583
|
-
align-items: center;
|
|
584
|
-
justify-content: center;
|
|
585
|
-
width: 32px;
|
|
586
|
-
height: 32px;
|
|
587
|
-
padding: 0;
|
|
588
|
-
border: none;
|
|
589
|
-
border-radius: var(--matcha-radius-pill, 9999px);
|
|
590
|
-
cursor: pointer;
|
|
591
|
-
backdrop-filter: blur(8px);
|
|
592
|
-
transition: background-color var(--matcha-duration-instant, 80ms) linear;
|
|
593
|
-
|
|
594
|
-
matcha-icon {
|
|
595
|
-
--matcha-icon-size: 18px;
|
|
596
|
-
width: 18px;
|
|
597
|
-
height: 18px;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
// Mesma regra da acao da linha: desabilitado sai de operacao sem virar
|
|
601
|
-
// `not-allowed` (constraint #14 do INTERACTION-SYSTEM).
|
|
602
|
-
&:disabled {
|
|
603
|
-
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
604
|
-
pointer-events: none;
|
|
605
|
-
cursor: default;
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
// ── Cropper inline (modo crop: imagem única) ──────────────────────────────
|
|
610
|
-
.matcha-file-uploader-cropper {
|
|
611
|
-
display: flex;
|
|
612
|
-
flex-direction: column;
|
|
613
|
-
gap: var(--matcha-space-150, 12px);
|
|
614
|
-
margin-top: var(--matcha-space-100, 8px);
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
.matcha-file-uploader-cropper matcha-crop {
|
|
618
|
-
display: block;
|
|
619
|
-
width: 100%;
|
|
620
|
-
min-height: 280px;
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
.matcha-file-uploader-cropper__actions {
|
|
624
|
-
display: flex;
|
|
625
|
-
justify-content: flex-end;
|
|
626
|
-
gap: var(--matcha-space-100, 8px);
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
// ── Responsive ───────────────────────────────────────────────────────────────
|
|
630
|
-
@include media-breakpoint('xs') {
|
|
631
|
-
.matcha-file-uploader-dropzone {
|
|
632
|
-
padding: var(--matcha-space-300, 24px) var(--matcha-space-200, 16px);
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
.matcha-file-uploader-dropzone__icon-pill {
|
|
636
|
-
padding: var(--matcha-space-150, 12px) var(--matcha-space-400, 32px);
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
// ── Reduced motion ───────────────────────────────────────────────────────────
|
|
641
|
-
@media (prefers-reduced-motion: reduce) {
|
|
642
|
-
.matcha-file-uploader-shell,
|
|
643
|
-
.matcha-file-uploader-dropzone,
|
|
644
|
-
.matcha-file-uploader-file__progress-fill,
|
|
645
|
-
.matcha-file-uploader-file__action,
|
|
646
|
-
.matcha-file-uploader-card__actions,
|
|
647
|
-
.matcha-file-uploader-card__action {
|
|
648
|
-
transition: none;
|
|
649
|
-
}
|
|
650
|
-
}
|
|
1
|
+
@use "../abstracts/media-breakpoint" as *;
|
|
2
|
+
@use "sass:map";
|
|
3
|
+
|
|
4
|
+
// =============================================================================
|
|
5
|
+
// matcha-file-uploader.scss — File upload component (matcha/file-uploader no Figma DSV3)
|
|
6
|
+
//
|
|
7
|
+
// 3 estados canon (16152:254):
|
|
8
|
+
// Estado=Dropzone (16152:209) — área vazia com icon pill + title + hint + 2 botões
|
|
9
|
+
// Estado=Enviando (16152:227) — thumb 64×36 + nome + progress + % + cancel
|
|
10
|
+
// Estado=Completo (16152:242) — thumb 64×36 + nome + size + delete (trash)
|
|
11
|
+
//
|
|
12
|
+
// Width canon: 480px (component se adapta via max-width: 480px + width: 100%)
|
|
13
|
+
// =============================================================================
|
|
14
|
+
|
|
15
|
+
@mixin matcha-file-uploader-theme($theme) {
|
|
16
|
+
|
|
17
|
+
// ── Shell (modo múltiplo: moldura única em volta de dropzone + lista) ──
|
|
18
|
+
// Recebe o mesmo tratamento visual da dropzone porque é ELE que passa a ser
|
|
19
|
+
// a "área de upload" quando a lista mora dentro — inclusive o realce de
|
|
20
|
+
// dragover, já que os handlers de drag vivem aqui.
|
|
21
|
+
.matcha-file-uploader-shell {
|
|
22
|
+
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
23
|
+
border-color: var(--matcha-color-surface-border);
|
|
24
|
+
|
|
25
|
+
&.matcha-file-uploader-dragover {
|
|
26
|
+
background: var(--matcha-color-accent-alpha);
|
|
27
|
+
border-color: var(--matcha-color-accent);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&.matcha-file-uploader-disabled {
|
|
31
|
+
opacity: 0.5;
|
|
32
|
+
// pointer-events + cursor default, não `not-allowed`: constraint #14 do
|
|
33
|
+
// INTERACTION-SYSTEM (o lint de CSS avisa). A dropzone legada abaixo ainda
|
|
34
|
+
// usa not-allowed — rastreado no backlog, fora do escopo desta mudança.
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
cursor: default;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── Dropzone ──
|
|
41
|
+
.matcha-file-uploader-dropzone {
|
|
42
|
+
background: var(--matcha-color-surface-background, var(--matcha-color-surface-bg));
|
|
43
|
+
border-color: var(--matcha-color-surface-border);
|
|
44
|
+
|
|
45
|
+
&.matcha-file-uploader-dragover {
|
|
46
|
+
background: var(--matcha-color-accent-alpha);
|
|
47
|
+
border-color: var(--matcha-color-accent);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
&.matcha-file-uploader-disabled {
|
|
51
|
+
opacity: 0.5;
|
|
52
|
+
cursor: not-allowed;
|
|
53
|
+
pointer-events: none;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Dentro do shell a moldura e o fundo são do shell — a dropzone é só a
|
|
57
|
+
// afordância de clique. Duas classes de propósito: precisa vencer o bloco
|
|
58
|
+
// acima, que tem a mesma especificidade.
|
|
59
|
+
&.matcha-file-uploader-dropzone--inset {
|
|
60
|
+
background: transparent;
|
|
61
|
+
border-color: transparent;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.matcha-file-uploader-dropzone__icon-pill {
|
|
66
|
+
background: var(--matcha-color-interaction-disabled-bg, #282c34);
|
|
67
|
+
color: var(--matcha-color-text-secondary);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.matcha-file-uploader-dropzone__title {
|
|
71
|
+
color: var(--matcha-color-text-primary);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.matcha-file-uploader-dropzone__optional {
|
|
75
|
+
color: var(--matcha-color-interaction-disabled-fg, rgba(232, 234, 237, 0.38));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.matcha-file-uploader-dropzone__hint {
|
|
79
|
+
color: var(--matcha-color-text-secondary);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ── File item ──
|
|
83
|
+
.matcha-file-uploader-file {
|
|
84
|
+
background: var(--matcha-color-surface-card);
|
|
85
|
+
border-color: var(--matcha-color-surface-border);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.matcha-file-uploader-file__thumb {
|
|
89
|
+
// interaction-disabled-bg, e nao elevation-surface-3: a moldura do arquivo nao e uma
|
|
90
|
+
// superficie elevada, e um fundo neutro atras de um icone — e o surface-3 desaparecia
|
|
91
|
+
// sobre o card em que a linha vive.
|
|
92
|
+
background: var(--matcha-color-interaction-disabled-bg);
|
|
93
|
+
color: var(--matcha-color-text-muted);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.matcha-file-uploader-file__name {
|
|
97
|
+
color: var(--matcha-color-text-primary);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.matcha-file-uploader-file__size {
|
|
101
|
+
color: var(--matcha-color-text-secondary);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.matcha-file-uploader-file__progress {
|
|
105
|
+
background: var(--matcha-color-surface-border);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.matcha-file-uploader-file__progress-fill {
|
|
109
|
+
background: var(--matcha-color-accent);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.matcha-file-uploader-file__percent {
|
|
113
|
+
color: var(--matcha-color-text-secondary);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.matcha-file-uploader-file__error-text {
|
|
117
|
+
color: var(--matcha-color-danger);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.matcha-file-uploader-file__action {
|
|
121
|
+
color: var(--matcha-color-text-secondary);
|
|
122
|
+
|
|
123
|
+
&:hover {
|
|
124
|
+
background: var(--matcha-color-surface-hover, transparent);
|
|
125
|
+
color: var(--matcha-color-text-primary);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Apagar é vermelho EM REPOUSO, não só no hover: remover arquivo é
|
|
129
|
+
// destrutivo e irreversível, e num modo múltiplo com vários itens
|
|
130
|
+
// empilhados a ação precisa ser distinguível antes de o ponteiro chegar
|
|
131
|
+
// nela (em touch não há hover nenhum). `danger` é papel, não hue —
|
|
132
|
+
// o tema pode remapear.
|
|
133
|
+
//
|
|
134
|
+
// `--matcha-icon-color` é obrigatório, e não redundante com o `color`: o
|
|
135
|
+
// matcha-icon resolve o glyph por `var(--matcha-icon-color, …-icon-default)`
|
|
136
|
+
// (matcha-icon.scss:97) e NÃO herda o `color` do pai. Era por isso que o
|
|
137
|
+
// vermelho antigo de hover nunca chegou a pintar a lixeira.
|
|
138
|
+
&.matcha-file-uploader-file__action--delete {
|
|
139
|
+
color: var(--matcha-color-danger);
|
|
140
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
141
|
+
|
|
142
|
+
// Fundo tinted em vez de surface-hover neutro, e a cor é reafirmada
|
|
143
|
+
// porque o :hover genérico acima empurraria text-primary.
|
|
144
|
+
&:hover {
|
|
145
|
+
background: var(--matcha-color-danger-alpha);
|
|
146
|
+
color: var(--matcha-color-danger);
|
|
147
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ── Card layout (preview preenchido) ──
|
|
153
|
+
.matcha-file-uploader-card {
|
|
154
|
+
border-color: var(--matcha-color-surface-border);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// contain (logo/transparência): fundo neutro atrás da imagem inteira
|
|
158
|
+
.matcha-file-uploader-card--contain {
|
|
159
|
+
background: var(--matcha-color-surface-card);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.matcha-file-uploader-card__action {
|
|
163
|
+
background: var(--matcha-color-surface-card-alpha, var(--matcha-color-surface-card));
|
|
164
|
+
color: var(--matcha-color-text-primary);
|
|
165
|
+
|
|
166
|
+
&:hover {
|
|
167
|
+
background: var(--matcha-color-surface-card);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Mesma regra do delete na linha. Aqui só o GLYPH vira danger: o fundo
|
|
171
|
+
// continua sendo a pastilha de surface-card, que é o que garante contraste
|
|
172
|
+
// do ícone sobre uma imagem qualquer — trocá-lo por danger-alpha (10%)
|
|
173
|
+
// deixaria o vermelho competir com a foto atrás.
|
|
174
|
+
&.matcha-file-uploader-card__action--delete {
|
|
175
|
+
color: var(--matcha-color-danger);
|
|
176
|
+
--matcha-icon-color: var(--matcha-color-danger);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
182
|
+
// LAYOUT — independente de tema
|
|
183
|
+
// ──────────────────────────────────────────────────────────────────────────────
|
|
184
|
+
|
|
185
|
+
// Host — full-width; consumer aplica max-width externamente se quiser cap
|
|
186
|
+
.matcha-file-uploader {
|
|
187
|
+
display: block;
|
|
188
|
+
width: 100%;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ── Empty state wrapper (dropzone + ação secundária FORA do drop) ──────────
|
|
192
|
+
.matcha-file-uploader-empty {
|
|
193
|
+
display: flex;
|
|
194
|
+
flex-direction: column;
|
|
195
|
+
gap: var(--matcha-space-150, 12px);
|
|
196
|
+
width: 100%;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ── Shell (modo múltiplo) ────────────────────────────────────────────────────
|
|
200
|
+
// A "área de upload" quando a lista mora dentro: uma moldura tracejada só,
|
|
201
|
+
// com a dropzone no topo e a lista rolável embaixo. Sem arquivo nenhum o
|
|
202
|
+
// resultado é visualmente idêntico à dropzone solta — só a moldura mudou de
|
|
203
|
+
// dono, do filho para o pai.
|
|
204
|
+
.matcha-file-uploader-shell {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
width: 100%;
|
|
208
|
+
box-sizing: border-box;
|
|
209
|
+
border: var(--matcha-border-thin, 2px) dashed transparent;
|
|
210
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
211
|
+
overflow: hidden; // o radius precisa cortar a lista que rola por dentro
|
|
212
|
+
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
213
|
+
border-color var(--matcha-duration-instant, 80ms) linear;
|
|
214
|
+
|
|
215
|
+
// Classe de dimensionamento posta NO HOST tem que alcancar o shell — mesmo
|
|
216
|
+
// padrao (e mesmo racional) do matcha-grid, grid.component.scss:11-18. Sem
|
|
217
|
+
// isto, `<matcha-file-uploader class="h-400">` esticaria o host e deixaria o
|
|
218
|
+
// shell na altura do conteudo, e a area continuaria crescendo por dentro.
|
|
219
|
+
//
|
|
220
|
+
// `height: 100%` contra host de altura auto resolve pra `auto`: e no-op para
|
|
221
|
+
// quem nao define altura, portanto value-preserving nos usos existentes.
|
|
222
|
+
height: 100%;
|
|
223
|
+
|
|
224
|
+
// O foco visível é da dropzone interna (o elemento focável), não do shell.
|
|
225
|
+
&:focus-within {
|
|
226
|
+
outline: none;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Com altura definida no host, e a DROPZONE que absorve a sobra: com 1 arquivo
|
|
230
|
+
// ela fica grande e a area nao tem buraco; conforme a lista cresce, cede
|
|
231
|
+
// espaco ate o proprio conteudo (pill + dois textos), que o min-height auto
|
|
232
|
+
// do flex protege de ser esmagado. Sem altura definida, nao ha sobra para
|
|
233
|
+
// distribuir e o resultado e o mesmo de antes.
|
|
234
|
+
.matcha-file-uploader-dropzone--inset {
|
|
235
|
+
flex: 1 1 auto;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ── Lista de arquivos rolável (dentro do shell) ──────────────────────────────
|
|
240
|
+
// max-height em custom property com fallback, igual --matcha-panel-max-height
|
|
241
|
+
// (280px é o mesmo teto que select/autocomplete/panel já usam para "lista com
|
|
242
|
+
// mais conteúdo abaixo"). Passar `none` devolve o crescimento ilimitado antigo.
|
|
243
|
+
.matcha-file-uploader-list {
|
|
244
|
+
display: flex;
|
|
245
|
+
flex-direction: column;
|
|
246
|
+
gap: var(--matcha-space-100, 8px);
|
|
247
|
+
min-height: 0; // sem isso o floor de min-content impede o scroll no flex
|
|
248
|
+
// Pede o tamanho do conteudo e ENCOLHE quando falta espaco — e ai o scroll
|
|
249
|
+
// interno assume. E o que faz a lista caber quando o host tem altura definida
|
|
250
|
+
// e o teto de 280px seria maior do que sobrou.
|
|
251
|
+
flex: 0 1 auto;
|
|
252
|
+
max-height: var(--matcha-file-uploader-list-max-height, 280px);
|
|
253
|
+
overflow-y: auto;
|
|
254
|
+
overflow-x: hidden; // scrollbar vertical + nowrap gera barra horizontal fantasma
|
|
255
|
+
overscroll-behavior: contain; // o scroll não vaza pra página ao chegar no fim
|
|
256
|
+
-webkit-overflow-scrolling: touch;
|
|
257
|
+
padding: 0 var(--matcha-space-100, 8px) var(--matcha-space-100, 8px);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Dentro da lista o espaçamento é do `gap` — o margin-top do item rolaria
|
|
261
|
+
// junto e daria um respiro fantasma no topo do scroll.
|
|
262
|
+
.matcha-file-uploader-list > .matcha-file-uploader-file,
|
|
263
|
+
.matcha-file-uploader-list > .matcha-file-uploader-card {
|
|
264
|
+
margin-top: 0;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
// ── Dropzone box (Estado=Dropzone — Figma 16152:209) — a zona INTEIRA é o alvo
|
|
269
|
+
.matcha-file-uploader-dropzone {
|
|
270
|
+
display: flex;
|
|
271
|
+
flex-direction: column;
|
|
272
|
+
align-items: center;
|
|
273
|
+
justify-content: center;
|
|
274
|
+
gap: var(--matcha-space-200, 16px);
|
|
275
|
+
padding: var(--matcha-space-400, 32px) var(--matcha-space-300, 24px);
|
|
276
|
+
border: var(--matcha-border-thin, 2px) dashed transparent;
|
|
277
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
278
|
+
cursor: pointer;
|
|
279
|
+
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
280
|
+
border-color var(--matcha-duration-instant, 80ms) linear;
|
|
281
|
+
|
|
282
|
+
&:focus-visible {
|
|
283
|
+
outline: var(--matcha-border-thin, 2px) solid var(--matcha-color-accent, #009400);
|
|
284
|
+
outline-offset: 2px;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Dropzone dentro do shell: sem moldura própria (é do shell) e sem o radius
|
|
289
|
+
// que arredondaria um canto interno. Mantém padding, cursor e foco.
|
|
290
|
+
// Precisa vir DEPOIS do bloco base: mesma especificidade (uma classe), então é
|
|
291
|
+
// a ordem que decide — declarado antes, o `border: 2px dashed` do base vencia e
|
|
292
|
+
// sobravam 2px de borda transparente dentro do shell.
|
|
293
|
+
.matcha-file-uploader-dropzone--inset {
|
|
294
|
+
border-width: 0;
|
|
295
|
+
border-radius: 0;
|
|
296
|
+
|
|
297
|
+
// Anel de foco PARA DENTRO. A dropzone inset ocupa a largura toda do shell,
|
|
298
|
+
// que tem `overflow: hidden` (o radius precisa cortar a lista rolável): com o
|
|
299
|
+
// `outline-offset: 2px` do bloco base o anel cai fora da caixa e é ceifado,
|
|
300
|
+
// deixando o alvo de teclado sem indicação visível nas laterais.
|
|
301
|
+
&:focus-visible {
|
|
302
|
+
outline-offset: -2px;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// layout="card": dropzone vazio compartilha a proporção do card preenchido
|
|
307
|
+
// (aspect-ratio aplicado inline via previewRatio) pra empty e filled terem a
|
|
308
|
+
// MESMA altura lado a lado. Sem isso, vazio é dimensionado por padding/conteúdo
|
|
309
|
+
// e preenchido por aspect-ratio → alturas divergentes.
|
|
310
|
+
.matcha-file-uploader-dropzone--card {
|
|
311
|
+
width: 100%;
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Icon pill (bg interaction/disabled-bg + padding 40h/16v · icon 24×24)
|
|
316
|
+
.matcha-file-uploader-dropzone__icon-pill {
|
|
317
|
+
display: inline-flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
justify-content: center;
|
|
320
|
+
padding: var(--matcha-space-200, 16px) var(--matcha-space-500, 40px);
|
|
321
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
322
|
+
flex-shrink: 0;
|
|
323
|
+
|
|
324
|
+
matcha-icon {
|
|
325
|
+
--matcha-icon-size: 24px;
|
|
326
|
+
width: 24px;
|
|
327
|
+
height: 24px;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Text block — column gap 4px, center
|
|
332
|
+
.matcha-file-uploader-dropzone__text {
|
|
333
|
+
display: flex;
|
|
334
|
+
flex-direction: column;
|
|
335
|
+
align-items: center;
|
|
336
|
+
gap: var(--matcha-space-050, 4px);
|
|
337
|
+
text-align: center;
|
|
338
|
+
width: 100%;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Title row (inline: title + optional)
|
|
342
|
+
.matcha-file-uploader-dropzone__title-row {
|
|
343
|
+
display: inline-flex;
|
|
344
|
+
align-items: center;
|
|
345
|
+
justify-content: center;
|
|
346
|
+
gap: var(--matcha-space-050, 4px);
|
|
347
|
+
white-space: nowrap;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.matcha-file-uploader-dropzone__title {
|
|
351
|
+
font-family: var(--matcha-font-family);
|
|
352
|
+
font-size: var(--matcha-text-label-md, 14px);
|
|
353
|
+
font-weight: var(--matcha-weight-medium, 500);
|
|
354
|
+
line-height: var(--matcha-leading-label-md, 20px);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
.matcha-file-uploader-dropzone__optional {
|
|
358
|
+
font-family: var(--matcha-font-family);
|
|
359
|
+
font-size: var(--matcha-text-label-md, 14px);
|
|
360
|
+
font-weight: var(--matcha-weight-medium, 500);
|
|
361
|
+
line-height: var(--matcha-leading-label-md, 20px);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.matcha-file-uploader-dropzone__hint {
|
|
365
|
+
margin: 0;
|
|
366
|
+
font-family: var(--matcha-font-family);
|
|
367
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
368
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
369
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
370
|
+
white-space: pre-line; // suporta \n pra hint multi-linha (1280×720 px... \n Clique pra selecionar...)
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Actions row (slot secondary + select arquivo)
|
|
374
|
+
// Hidden input
|
|
375
|
+
.matcha-file-uploader-input {
|
|
376
|
+
display: none;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// ── File Item — Estados Enviando (16152:227) e Completo (16152:242) ──────────
|
|
380
|
+
.matcha-file-uploader-file {
|
|
381
|
+
display: flex;
|
|
382
|
+
align-items: center;
|
|
383
|
+
gap: var(--matcha-space-200, 16px);
|
|
384
|
+
border: var(--matcha-border-hairline, 1px) solid transparent;
|
|
385
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
386
|
+
margin-top: var(--matcha-space-100, 8px);
|
|
387
|
+
width: 100%;
|
|
388
|
+
|
|
389
|
+
// Enviando: padding 20/24 (mais respiro vs. Figma original 16)
|
|
390
|
+
&.matcha-file-uploader-file--uploading {
|
|
391
|
+
padding: var(--matcha-space-250, 20px) var(--matcha-space-300, 24px);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// Completo/Erro: padding 20/24 (mais respiro vs. Figma original 12/16)
|
|
395
|
+
&.matcha-file-uploader-file--completed,
|
|
396
|
+
&.matcha-file-uploader-file--error {
|
|
397
|
+
padding: var(--matcha-space-250, 20px) var(--matcha-space-300, 24px);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Thumbnail 64×36 (16:9 · radius lg)
|
|
402
|
+
.matcha-file-uploader-file__thumb {
|
|
403
|
+
display: flex;
|
|
404
|
+
align-items: center;
|
|
405
|
+
justify-content: center;
|
|
406
|
+
width: 64px;
|
|
407
|
+
height: 36px;
|
|
408
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
409
|
+
flex-shrink: 0;
|
|
410
|
+
overflow: hidden;
|
|
411
|
+
|
|
412
|
+
img {
|
|
413
|
+
width: 100%;
|
|
414
|
+
height: 100%;
|
|
415
|
+
object-fit: cover;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
matcha-icon {
|
|
419
|
+
--matcha-icon-size: 20px;
|
|
420
|
+
width: 20px;
|
|
421
|
+
height: 20px;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// Info column (flex-1)
|
|
426
|
+
.matcha-file-uploader-file__info {
|
|
427
|
+
display: flex;
|
|
428
|
+
flex-direction: column;
|
|
429
|
+
flex: 1 1 0;
|
|
430
|
+
min-width: 0;
|
|
431
|
+
overflow: hidden;
|
|
432
|
+
|
|
433
|
+
// Enviando: gap 6 (entre nome e progress bar)
|
|
434
|
+
.matcha-file-uploader-file--uploading & {
|
|
435
|
+
gap: var(--matcha-space-075, 6px);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Completo: gap 4 (entre nome e size)
|
|
439
|
+
.matcha-file-uploader-file--completed &,
|
|
440
|
+
.matcha-file-uploader-file--error & {
|
|
441
|
+
gap: var(--matcha-space-050, 4px);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// File name — Manrope Medium 13/19 letter 0.2 (text/button-sm)
|
|
446
|
+
.matcha-file-uploader-file__name {
|
|
447
|
+
font-family: var(--matcha-font-family);
|
|
448
|
+
font-size: var(--matcha-text-label-sm, 12px);
|
|
449
|
+
font-weight: var(--matcha-weight-medium, 500);
|
|
450
|
+
line-height: var(--matcha-leading-label-sm, 16px);
|
|
451
|
+
letter-spacing: 0.2px;
|
|
452
|
+
white-space: nowrap;
|
|
453
|
+
overflow: hidden;
|
|
454
|
+
text-overflow: ellipsis;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
// Nome como ancora: mesma tipografia, aparencia de link. `display: block` porque o
|
|
458
|
+
// ellipsis do nome depende de o elemento ser bloco, e <a> e inline por padrao.
|
|
459
|
+
.matcha-file-uploader-file__name--link {
|
|
460
|
+
display: block;
|
|
461
|
+
color: var(--matcha-color-accent);
|
|
462
|
+
text-decoration: underline;
|
|
463
|
+
|
|
464
|
+
&:hover,
|
|
465
|
+
&:focus-visible {
|
|
466
|
+
text-decoration: none;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// File size — Manrope Regular 11/14 letter 0.3 (text/caption)
|
|
471
|
+
.matcha-file-uploader-file__size {
|
|
472
|
+
font-family: var(--matcha-font-family);
|
|
473
|
+
font-size: var(--matcha-text-p-tiny, 11px);
|
|
474
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
475
|
+
line-height: var(--matcha-leading-p-tiny, 14px);
|
|
476
|
+
letter-spacing: 0.3px;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// Error text — body-sm danger
|
|
480
|
+
.matcha-file-uploader-file__error-text {
|
|
481
|
+
font-family: var(--matcha-font-family);
|
|
482
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
483
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
484
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// ── Progress bar (height 4px · radius sm) ─────────────────────────────────────
|
|
488
|
+
.matcha-file-uploader-file__progress {
|
|
489
|
+
width: 100%;
|
|
490
|
+
height: 4px;
|
|
491
|
+
border-radius: var(--matcha-radius-sm, 2px);
|
|
492
|
+
overflow: hidden;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
.matcha-file-uploader-file__progress-fill {
|
|
496
|
+
height: 100%;
|
|
497
|
+
border-radius: var(--matcha-radius-sm, 2px);
|
|
498
|
+
transition: width var(--matcha-duration-moderate, 300ms) ease;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Percent label — body-sm text-secondary
|
|
502
|
+
.matcha-file-uploader-file__percent {
|
|
503
|
+
font-family: var(--matcha-font-family);
|
|
504
|
+
font-size: var(--matcha-text-body-sm, 12px);
|
|
505
|
+
font-weight: var(--matcha-weight-regular, 400);
|
|
506
|
+
line-height: var(--matcha-leading-body-sm, 16px);
|
|
507
|
+
flex-shrink: 0;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// Cancel/Delete action button — 20×20 (icon size + bg transparent + hover)
|
|
511
|
+
.matcha-file-uploader-file__action {
|
|
512
|
+
display: inline-flex;
|
|
513
|
+
align-items: center;
|
|
514
|
+
justify-content: center;
|
|
515
|
+
width: 20px;
|
|
516
|
+
height: 20px;
|
|
517
|
+
padding: 0;
|
|
518
|
+
background: transparent;
|
|
519
|
+
border: none;
|
|
520
|
+
border-radius: var(--matcha-radius-sm, 2px);
|
|
521
|
+
cursor: pointer;
|
|
522
|
+
flex-shrink: 0;
|
|
523
|
+
transition: background-color var(--matcha-duration-instant, 80ms) linear,
|
|
524
|
+
color var(--matcha-duration-instant, 80ms) linear;
|
|
525
|
+
|
|
526
|
+
matcha-icon {
|
|
527
|
+
--matcha-icon-size: 20px;
|
|
528
|
+
width: 20px;
|
|
529
|
+
height: 20px;
|
|
530
|
+
}
|
|
531
|
+
// Com o uploader desabilitado a linha continua legivel, mas as acoes saem de
|
|
532
|
+
// operacao. `pointer-events: none` + `cursor: default` em vez de
|
|
533
|
+
// `not-allowed`: constraint #14 do INTERACTION-SYSTEM.
|
|
534
|
+
&:disabled {
|
|
535
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
536
|
+
pointer-events: none;
|
|
537
|
+
cursor: default;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// ── Card layout — preview preenchido 16:9 + ações no hover (Estado=Drop filled) ──
|
|
542
|
+
.matcha-file-uploader-card {
|
|
543
|
+
position: relative;
|
|
544
|
+
width: 100%;
|
|
545
|
+
// SEM margin-top: o card preenchido tem que alinhar o topo com o dropzone
|
|
546
|
+
// vazio quando lado a lado (layout card). margin-top desalinhava em 8px.
|
|
547
|
+
border: var(--matcha-border-hairline, 1px) solid transparent;
|
|
548
|
+
border-radius: var(--matcha-radius-lg, 8px);
|
|
549
|
+
overflow: hidden;
|
|
550
|
+
aspect-ratio: 16 / 9; // fallback; sobrescrito por [style.aspect-ratio]="previewRatio"
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
.matcha-file-uploader-card__img {
|
|
554
|
+
display: block;
|
|
555
|
+
width: 100%;
|
|
556
|
+
height: 100%;
|
|
557
|
+
object-fit: cover; // sobrescrito por [style.object-fit]="previewFit"
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.matcha-file-uploader-card__actions {
|
|
561
|
+
position: absolute;
|
|
562
|
+
top: var(--matcha-space-100, 8px);
|
|
563
|
+
right: var(--matcha-space-100, 8px);
|
|
564
|
+
display: flex;
|
|
565
|
+
gap: var(--matcha-space-100, 8px);
|
|
566
|
+
opacity: 1; // persistente — descobrÃvel e operável em touch (canon 20252:2253)
|
|
567
|
+
transition: opacity var(--matcha-duration-instant, 80ms) linear;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// Em dispositivos com hover, atenua no resting e destaca no hover/foco — mantém
|
|
571
|
+
// a tela limpa sem esconder a affordance onde não há hover (touch/totem).
|
|
572
|
+
@media (hover: hover) {
|
|
573
|
+
.matcha-file-uploader-card__actions { opacity: 0.72; }
|
|
574
|
+
|
|
575
|
+
.matcha-file-uploader-card:hover .matcha-file-uploader-card__actions,
|
|
576
|
+
.matcha-file-uploader-card:focus-within .matcha-file-uploader-card__actions {
|
|
577
|
+
opacity: 1;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
.matcha-file-uploader-card__action {
|
|
582
|
+
display: inline-flex;
|
|
583
|
+
align-items: center;
|
|
584
|
+
justify-content: center;
|
|
585
|
+
width: 32px;
|
|
586
|
+
height: 32px;
|
|
587
|
+
padding: 0;
|
|
588
|
+
border: none;
|
|
589
|
+
border-radius: var(--matcha-radius-pill, 9999px);
|
|
590
|
+
cursor: pointer;
|
|
591
|
+
backdrop-filter: blur(8px);
|
|
592
|
+
transition: background-color var(--matcha-duration-instant, 80ms) linear;
|
|
593
|
+
|
|
594
|
+
matcha-icon {
|
|
595
|
+
--matcha-icon-size: 18px;
|
|
596
|
+
width: 18px;
|
|
597
|
+
height: 18px;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
// Mesma regra da acao da linha: desabilitado sai de operacao sem virar
|
|
601
|
+
// `not-allowed` (constraint #14 do INTERACTION-SYSTEM).
|
|
602
|
+
&:disabled {
|
|
603
|
+
opacity: var(--matcha-opacity-disabled, 0.38);
|
|
604
|
+
pointer-events: none;
|
|
605
|
+
cursor: default;
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// ── Cropper inline (modo crop: imagem única) ──────────────────────────────
|
|
610
|
+
.matcha-file-uploader-cropper {
|
|
611
|
+
display: flex;
|
|
612
|
+
flex-direction: column;
|
|
613
|
+
gap: var(--matcha-space-150, 12px);
|
|
614
|
+
margin-top: var(--matcha-space-100, 8px);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
.matcha-file-uploader-cropper matcha-crop {
|
|
618
|
+
display: block;
|
|
619
|
+
width: 100%;
|
|
620
|
+
min-height: 280px;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
.matcha-file-uploader-cropper__actions {
|
|
624
|
+
display: flex;
|
|
625
|
+
justify-content: flex-end;
|
|
626
|
+
gap: var(--matcha-space-100, 8px);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// ── Responsive ───────────────────────────────────────────────────────────────
|
|
630
|
+
@include media-breakpoint('xs') {
|
|
631
|
+
.matcha-file-uploader-dropzone {
|
|
632
|
+
padding: var(--matcha-space-300, 24px) var(--matcha-space-200, 16px);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
.matcha-file-uploader-dropzone__icon-pill {
|
|
636
|
+
padding: var(--matcha-space-150, 12px) var(--matcha-space-400, 32px);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// ── Reduced motion ───────────────────────────────────────────────────────────
|
|
641
|
+
@media (prefers-reduced-motion: reduce) {
|
|
642
|
+
.matcha-file-uploader-shell,
|
|
643
|
+
.matcha-file-uploader-dropzone,
|
|
644
|
+
.matcha-file-uploader-file__progress-fill,
|
|
645
|
+
.matcha-file-uploader-file__action,
|
|
646
|
+
.matcha-file-uploader-card__actions,
|
|
647
|
+
.matcha-file-uploader-card__action {
|
|
648
|
+
transition: none;
|
|
649
|
+
}
|
|
650
|
+
}
|