@happyvertical/smrt-messages 0.34.5 → 0.34.7
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/dist/manifest.json +2 -2
- package/dist/smrt-knowledge.json +4 -4
- package/dist/svelte/components/AccountCard.svelte +22 -13
- package/dist/svelte/components/AttachmentChip.svelte +26 -7
- package/dist/svelte/components/AttachmentChip.svelte.d.ts +0 -3
- package/dist/svelte/components/AttachmentChip.svelte.d.ts.map +1 -1
- package/dist/svelte/components/AttachmentUpload.svelte +19 -7
- package/dist/svelte/components/AttachmentUpload.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ComposeForm.svelte +66 -75
- package/dist/svelte/components/ComposeForm.svelte.d.ts.map +1 -1
- package/dist/svelte/components/EmailAccountManager.svelte +81 -115
- package/dist/svelte/components/EmailAccountManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/EmailFilterManager.svelte +94 -127
- package/dist/svelte/components/EmailFilterManager.svelte.d.ts.map +1 -1
- package/dist/svelte/components/FolderNav.svelte +22 -15
- package/dist/svelte/components/FolderNav.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ForwardForm.svelte +16 -48
- package/dist/svelte/components/ForwardForm.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MessageCard.svelte +14 -6
- package/dist/svelte/components/MessageCard.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MessageDetail.svelte +19 -12
- package/dist/svelte/components/MessageFilters.svelte +47 -43
- package/dist/svelte/components/MessageFilters.svelte.d.ts.map +1 -1
- package/dist/svelte/components/MessageToolbar.svelte +28 -20
- package/dist/svelte/components/MessageToolbar.svelte.d.ts.map +1 -1
- package/dist/svelte/components/RecipientInput.svelte +32 -9
- package/dist/svelte/components/RecipientInput.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ReplyForm.svelte +16 -48
- package/dist/svelte/components/ReplyForm.svelte.d.ts.map +1 -1
- package/dist/svelte/components/ThreadView.svelte +19 -12
- package/dist/svelte/components/ThreadView.svelte.d.ts.map +1 -1
- package/package.json +8 -7
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
* Reusable component for managing email allow/block lists.
|
|
6
6
|
* Works with any backend via callback props.
|
|
7
7
|
*/
|
|
8
|
+
import { Input, Select } from '@happyvertical/smrt-ui/forms';
|
|
8
9
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
10
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
9
11
|
import { M } from '../i18n.js';
|
|
10
12
|
import type { BlacklistEntry, WhitelistEntry } from '../types.js';
|
|
11
13
|
|
|
@@ -158,33 +160,36 @@ function getPatternPlaceholder(type: string): string {
|
|
|
158
160
|
|
|
159
161
|
<div class="email-filter-manager">
|
|
160
162
|
<div class="section-toggle">
|
|
161
|
-
<
|
|
163
|
+
<Button
|
|
164
|
+
variant={activeSection === 'whitelist' ? 'primary' : 'ghost'}
|
|
165
|
+
size="sm"
|
|
162
166
|
class="section-btn"
|
|
163
|
-
class:active={activeSection === 'whitelist'}
|
|
164
167
|
onclick={() => activeSection = 'whitelist'}
|
|
165
168
|
>
|
|
166
169
|
Whitelist
|
|
167
170
|
<span class="count">{whitelist.length}</span>
|
|
168
|
-
</
|
|
169
|
-
<
|
|
171
|
+
</Button>
|
|
172
|
+
<Button
|
|
173
|
+
variant={activeSection === 'blacklist' ? 'primary' : 'ghost'}
|
|
174
|
+
size="sm"
|
|
170
175
|
class="section-btn"
|
|
171
|
-
class:active={activeSection === 'blacklist'}
|
|
172
176
|
onclick={() => activeSection = 'blacklist'}
|
|
173
177
|
>
|
|
174
178
|
Blacklist
|
|
175
179
|
<span class="count">{blacklist.length}</span>
|
|
176
|
-
</
|
|
180
|
+
</Button>
|
|
177
181
|
</div>
|
|
178
182
|
|
|
179
183
|
{#if filterError}
|
|
180
184
|
<div class="filter-error" role="alert" aria-live="assertive">
|
|
181
185
|
{filterError}
|
|
182
|
-
<
|
|
183
|
-
|
|
186
|
+
<Button
|
|
187
|
+
variant="ghost"
|
|
188
|
+
size="sm"
|
|
184
189
|
class="dismiss-btn"
|
|
185
190
|
aria-label={t(M['messages.email_filter_manager.dismiss_error'])}
|
|
186
191
|
onclick={() => filterError = null}
|
|
187
|
-
>×</
|
|
192
|
+
>×</Button>
|
|
188
193
|
</div>
|
|
189
194
|
{/if}
|
|
190
195
|
|
|
@@ -196,10 +201,12 @@ function getPatternPlaceholder(type: string): string {
|
|
|
196
201
|
{t(M['messages.email_filter_manager.whitelist_description'])}
|
|
197
202
|
</div>
|
|
198
203
|
{#if !isReadonly && onaddwhitelist}
|
|
199
|
-
<
|
|
204
|
+
<Button
|
|
205
|
+
variant="secondary"
|
|
206
|
+
size="sm"
|
|
200
207
|
class="add-btn"
|
|
201
208
|
onclick={() => { resetWhitelistForm(); showWhitelistForm = true; }}
|
|
202
|
-
>+ Add</
|
|
209
|
+
>+ Add</Button>
|
|
203
210
|
{/if}
|
|
204
211
|
</div>
|
|
205
212
|
|
|
@@ -209,15 +216,15 @@ function getPatternPlaceholder(type: string): string {
|
|
|
209
216
|
<div class="form-row">
|
|
210
217
|
<div class="form-field" style="flex: 0 0 120px;">
|
|
211
218
|
<label class="form-label" for="wl-type">Type</label>
|
|
212
|
-
<
|
|
219
|
+
<Select id="wl-type" class="form-select" bind:value={wlType}>
|
|
213
220
|
<option value="email">Email</option>
|
|
214
221
|
<option value="domain">Domain</option>
|
|
215
222
|
<option value="regex">Regex</option>
|
|
216
|
-
</
|
|
223
|
+
</Select>
|
|
217
224
|
</div>
|
|
218
225
|
<div class="form-field" style="flex: 1;">
|
|
219
226
|
<label class="form-label" for="wl-pattern">Pattern</label>
|
|
220
|
-
<
|
|
227
|
+
<Input
|
|
221
228
|
id="wl-pattern"
|
|
222
229
|
class="form-input"
|
|
223
230
|
type="text"
|
|
@@ -229,7 +236,7 @@ function getPatternPlaceholder(type: string): string {
|
|
|
229
236
|
<div class="form-row">
|
|
230
237
|
<div class="form-field" style="flex: 1;">
|
|
231
238
|
<label class="form-label" for="wl-category">Category <span class="optional">(optional)</span></label>
|
|
232
|
-
<
|
|
239
|
+
<Input
|
|
233
240
|
id="wl-category"
|
|
234
241
|
class="form-input"
|
|
235
242
|
type="text"
|
|
@@ -239,7 +246,7 @@ function getPatternPlaceholder(type: string): string {
|
|
|
239
246
|
</div>
|
|
240
247
|
<div class="form-field" style="flex: 2;">
|
|
241
248
|
<label class="form-label" for="wl-desc">Description</label>
|
|
242
|
-
<
|
|
249
|
+
<Input
|
|
243
250
|
id="wl-desc"
|
|
244
251
|
class="form-input"
|
|
245
252
|
type="text"
|
|
@@ -249,10 +256,10 @@ function getPatternPlaceholder(type: string): string {
|
|
|
249
256
|
</div>
|
|
250
257
|
</div>
|
|
251
258
|
<div class="form-actions">
|
|
252
|
-
<
|
|
253
|
-
<
|
|
259
|
+
<Button variant="secondary" size="sm" class="cancel-btn" onclick={resetWhitelistForm} disabled={savingWhitelist}>Cancel</Button>
|
|
260
|
+
<Button variant="primary" size="sm" class="save-btn" onclick={saveWhitelistEntry} disabled={savingWhitelist || !wlPattern.trim()}>
|
|
254
261
|
{savingWhitelist ? 'Saving...' : 'Add'}
|
|
255
|
-
</
|
|
262
|
+
</Button>
|
|
256
263
|
</div>
|
|
257
264
|
</div>
|
|
258
265
|
{/if}
|
|
@@ -276,11 +283,13 @@ function getPatternPlaceholder(type: string): string {
|
|
|
276
283
|
{/if}
|
|
277
284
|
</div>
|
|
278
285
|
{#if !isReadonly && onremovewhitelist}
|
|
279
|
-
<
|
|
286
|
+
<Button
|
|
287
|
+
variant="ghost"
|
|
288
|
+
size="sm"
|
|
280
289
|
class="delete-btn"
|
|
281
290
|
onclick={() => removeWhitelistEntry(entry)}
|
|
282
291
|
title={t(M['messages.email_filter_manager.whitelist_remove'])}
|
|
283
|
-
>×</
|
|
292
|
+
>×</Button>
|
|
284
293
|
{/if}
|
|
285
294
|
</div>
|
|
286
295
|
{/each}
|
|
@@ -296,10 +305,12 @@ function getPatternPlaceholder(type: string): string {
|
|
|
296
305
|
{t(M['messages.email_filter_manager.blacklist_description'])}
|
|
297
306
|
</div>
|
|
298
307
|
{#if !isReadonly && onaddblacklist}
|
|
299
|
-
<
|
|
308
|
+
<Button
|
|
309
|
+
variant="secondary"
|
|
310
|
+
size="sm"
|
|
300
311
|
class="add-btn"
|
|
301
312
|
onclick={() => { resetBlacklistForm(); showBlacklistForm = true; }}
|
|
302
|
-
>+ Add</
|
|
313
|
+
>+ Add</Button>
|
|
303
314
|
{/if}
|
|
304
315
|
</div>
|
|
305
316
|
|
|
@@ -309,15 +320,15 @@ function getPatternPlaceholder(type: string): string {
|
|
|
309
320
|
<div class="form-row">
|
|
310
321
|
<div class="form-field" style="flex: 0 0 120px;">
|
|
311
322
|
<label class="form-label" for="bl-type">Type</label>
|
|
312
|
-
<
|
|
323
|
+
<Select id="bl-type" class="form-select" bind:value={blType}>
|
|
313
324
|
<option value="email">Email</option>
|
|
314
325
|
<option value="domain">Domain</option>
|
|
315
326
|
<option value="regex">Regex</option>
|
|
316
|
-
</
|
|
327
|
+
</Select>
|
|
317
328
|
</div>
|
|
318
329
|
<div class="form-field" style="flex: 1;">
|
|
319
330
|
<label class="form-label" for="bl-pattern">Pattern</label>
|
|
320
|
-
<
|
|
331
|
+
<Input
|
|
321
332
|
id="bl-pattern"
|
|
322
333
|
class="form-input"
|
|
323
334
|
type="text"
|
|
@@ -329,7 +340,7 @@ function getPatternPlaceholder(type: string): string {
|
|
|
329
340
|
<div class="form-row">
|
|
330
341
|
<div class="form-field" style="flex: 1;">
|
|
331
342
|
<label class="form-label" for="bl-reason">Reason</label>
|
|
332
|
-
<
|
|
343
|
+
<Input
|
|
333
344
|
id="bl-reason"
|
|
334
345
|
class="form-input"
|
|
335
346
|
type="text"
|
|
@@ -339,16 +350,17 @@ function getPatternPlaceholder(type: string): string {
|
|
|
339
350
|
</div>
|
|
340
351
|
<div class="form-field checkbox-field">
|
|
341
352
|
<label class="form-label checkbox-label">
|
|
353
|
+
<!-- raw-primitive-allow: native checkbox; no Provider-free checkbox primitive (Toggle is a switch with different semantics, CheckboxInput requires a Provider) -->
|
|
342
354
|
<input type="checkbox" bind:checked={blAutoArchive} />
|
|
343
355
|
Auto-archive
|
|
344
356
|
</label>
|
|
345
357
|
</div>
|
|
346
358
|
</div>
|
|
347
359
|
<div class="form-actions">
|
|
348
|
-
<
|
|
349
|
-
<
|
|
360
|
+
<Button variant="secondary" size="sm" class="cancel-btn" onclick={resetBlacklistForm} disabled={savingBlacklist}>Cancel</Button>
|
|
361
|
+
<Button variant="primary" size="sm" class="save-btn" onclick={saveBlacklistEntry} disabled={savingBlacklist || !blPattern.trim()}>
|
|
350
362
|
{savingBlacklist ? 'Saving...' : 'Add'}
|
|
351
|
-
</
|
|
363
|
+
</Button>
|
|
352
364
|
</div>
|
|
353
365
|
</div>
|
|
354
366
|
{/if}
|
|
@@ -372,11 +384,13 @@ function getPatternPlaceholder(type: string): string {
|
|
|
372
384
|
{/if}
|
|
373
385
|
</div>
|
|
374
386
|
{#if !isReadonly && onremoveblacklist}
|
|
375
|
-
<
|
|
387
|
+
<Button
|
|
388
|
+
variant="ghost"
|
|
389
|
+
size="sm"
|
|
376
390
|
class="delete-btn"
|
|
377
391
|
onclick={() => removeBlacklistEntry(entry)}
|
|
378
392
|
title={t(M['messages.email_filter_manager.blacklist_remove'])}
|
|
379
|
-
>×</
|
|
393
|
+
>×</Button>
|
|
380
394
|
{/if}
|
|
381
395
|
</div>
|
|
382
396
|
{/each}
|
|
@@ -401,28 +415,19 @@ function getPatternPlaceholder(type: string): string {
|
|
|
401
415
|
border-radius: var(--smrt-radius-md, 8px);
|
|
402
416
|
}
|
|
403
417
|
|
|
404
|
-
|
|
418
|
+
/*
|
|
419
|
+
* The whitelist/blacklist toggle now renders through smrt-ui's <Button>,
|
|
420
|
+
* driven by `variant={active ? 'primary' : 'ghost'}` (a plain class:active view
|
|
421
|
+
* toggle, not an ARIA tablist). The variants own background/color/hover;
|
|
422
|
+
* `.section-toggle :global(.section-btn)` only re-asserts the row layout
|
|
423
|
+
* (flex/gap/radius) inside the pierced Button child scope (issue #1589).
|
|
424
|
+
*/
|
|
425
|
+
.section-toggle :global(.section-btn) {
|
|
405
426
|
display: flex;
|
|
406
427
|
align-items: center;
|
|
407
428
|
gap: 0.375rem;
|
|
408
|
-
padding: 0.375rem 0.75rem;
|
|
409
|
-
border: none;
|
|
410
429
|
border-radius: var(--smrt-radius-md, 8px);
|
|
411
|
-
background: transparent;
|
|
412
|
-
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
413
430
|
font-size: var(--smrt-typography-label-large-size, 0.8125rem);
|
|
414
|
-
font-family: inherit;
|
|
415
|
-
cursor: pointer;
|
|
416
|
-
transition: all 150ms ease;
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
.section-btn.active {
|
|
420
|
-
background: var(--smrt-color-primary-container, #d8e2ff);
|
|
421
|
-
color: var(--smrt-color-primary, #005ac1);
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.section-btn:hover:not(.active) {
|
|
425
|
-
background: var(--smrt-color-surface-container-high, #e6e7ef);
|
|
426
431
|
}
|
|
427
432
|
|
|
428
433
|
.count {
|
|
@@ -450,25 +455,16 @@ function getPatternPlaceholder(type: string): string {
|
|
|
450
455
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
451
456
|
}
|
|
452
457
|
|
|
453
|
-
|
|
454
|
-
|
|
458
|
+
/*
|
|
459
|
+
* The add button now renders through smrt-ui's <Button variant="secondary">.
|
|
460
|
+
* The variant owns the outlined-primary look + hover; `.section-header-row
|
|
461
|
+
* :global(.add-btn)` only re-asserts radius and flex-shrink (issue #1589).
|
|
462
|
+
*/
|
|
463
|
+
.section-header-row :global(.add-btn) {
|
|
455
464
|
border-radius: var(--smrt-radius-md, 8px);
|
|
456
|
-
border: 1px solid var(--smrt-color-primary, #005ac1);
|
|
457
|
-
background: transparent;
|
|
458
|
-
color: var(--smrt-color-primary, #005ac1);
|
|
459
|
-
cursor: pointer;
|
|
460
|
-
font-size: var(--smrt-typography-label-large-size, 0.8125rem);
|
|
461
|
-
font-family: inherit;
|
|
462
|
-
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
463
|
-
transition: all 150ms ease;
|
|
464
465
|
flex-shrink: 0;
|
|
465
466
|
}
|
|
466
467
|
|
|
467
|
-
.add-btn:hover {
|
|
468
|
-
background: var(--smrt-color-primary, #005ac1);
|
|
469
|
-
color: var(--smrt-color-on-primary, #fff);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
468
|
.entry-form {
|
|
473
469
|
background: var(--smrt-color-surface-container, #f0f1f9);
|
|
474
470
|
border: 1px solid var(--smrt-color-primary, #005ac1);
|
|
@@ -508,29 +504,14 @@ function getPatternPlaceholder(type: string): string {
|
|
|
508
504
|
opacity: 0.7;
|
|
509
505
|
}
|
|
510
506
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
font-family: inherit;
|
|
520
|
-
transition: border-color 150ms ease;
|
|
521
|
-
}
|
|
522
|
-
|
|
523
|
-
.form-input:focus,
|
|
524
|
-
.form-select:focus {
|
|
525
|
-
outline: none;
|
|
526
|
-
border-color: var(--smrt-color-primary, #005ac1);
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
.form-input::placeholder {
|
|
530
|
-
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
531
|
-
opacity: 0.5;
|
|
532
|
-
}
|
|
533
|
-
|
|
507
|
+
/*
|
|
508
|
+
* The form fields now render through smrt-ui's <Input> / <Select>, which bring
|
|
509
|
+
* their own tokenised border / background / focus / placeholder styling and
|
|
510
|
+
* honor prefers-reduced-motion themselves. The old `.form-input` / `.form-select`
|
|
511
|
+
* rules (and their :focus / ::placeholder overrides) are dropped as dead — they
|
|
512
|
+
* targeted the raw elements that now live inside the primitive child scopes
|
|
513
|
+
* (issue #1589).
|
|
514
|
+
*/
|
|
534
515
|
.checkbox-field {
|
|
535
516
|
justify-content: flex-end;
|
|
536
517
|
padding-bottom: 0.5rem;
|
|
@@ -557,42 +538,20 @@ function getPatternPlaceholder(type: string): string {
|
|
|
557
538
|
padding-top: 0.25rem;
|
|
558
539
|
}
|
|
559
540
|
|
|
560
|
-
|
|
561
|
-
|
|
541
|
+
/*
|
|
542
|
+
* Cancel/Save now use Button's secondary/primary variants (dead bespoke CSS
|
|
543
|
+
* removed). `.form-actions :global(...)` only re-asserts the rounded radius;
|
|
544
|
+
* Cancel's neutral outline override keeps it from picking up secondary's
|
|
545
|
+
* primary border color (issue #1589).
|
|
546
|
+
*/
|
|
547
|
+
.form-actions :global(.cancel-btn),
|
|
548
|
+
.form-actions :global(.save-btn) {
|
|
562
549
|
border-radius: var(--smrt-radius-md, 8px);
|
|
563
|
-
border: 1px solid var(--smrt-color-outline-variant, #c2c7cf);
|
|
564
|
-
background: transparent;
|
|
565
|
-
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
566
|
-
cursor: pointer;
|
|
567
|
-
font-size: var(--smrt-typography-label-large-size, 0.8125rem);
|
|
568
|
-
font-family: inherit;
|
|
569
|
-
transition: all 150ms ease;
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
.cancel-btn:hover {
|
|
573
|
-
background: var(--smrt-color-surface-container-high, #e6e7ef);
|
|
574
550
|
}
|
|
575
551
|
|
|
576
|
-
.
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
border: 1px solid var(--smrt-color-primary, #005ac1);
|
|
580
|
-
background: var(--smrt-color-primary, #005ac1);
|
|
581
|
-
color: var(--smrt-color-on-primary, #fff);
|
|
582
|
-
cursor: pointer;
|
|
583
|
-
font-size: var(--smrt-typography-label-large-size, 0.8125rem);
|
|
584
|
-
font-family: inherit;
|
|
585
|
-
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
586
|
-
transition: all 150ms ease;
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
.save-btn:hover:not(:disabled) {
|
|
590
|
-
opacity: 0.9;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
.save-btn:disabled {
|
|
594
|
-
opacity: 0.5;
|
|
595
|
-
cursor: not-allowed;
|
|
552
|
+
.form-actions :global(.cancel-btn) {
|
|
553
|
+
border-color: var(--smrt-color-outline-variant, #c2c7cf);
|
|
554
|
+
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
596
555
|
}
|
|
597
556
|
|
|
598
557
|
.entries-list {
|
|
@@ -684,7 +643,13 @@ function getPatternPlaceholder(type: string): string {
|
|
|
684
643
|
flex-shrink: 0;
|
|
685
644
|
}
|
|
686
645
|
|
|
687
|
-
|
|
646
|
+
/*
|
|
647
|
+
* The remove button now renders through smrt-ui's <Button variant="ghost">.
|
|
648
|
+
* `.entry-card :global(.delete-btn)` anchors on the real `.entry-card` element
|
|
649
|
+
* and pierces the Button child scope to keep the round icon button and its
|
|
650
|
+
* red-on-hover affordance (issue #1589).
|
|
651
|
+
*/
|
|
652
|
+
.entry-card :global(.delete-btn) {
|
|
688
653
|
font-size: var(--smrt-typography-body-large-size, 1rem);
|
|
689
654
|
line-height: 1;
|
|
690
655
|
padding: 0.125rem 0.5rem;
|
|
@@ -692,13 +657,10 @@ function getPatternPlaceholder(type: string): string {
|
|
|
692
657
|
border: 1px solid transparent;
|
|
693
658
|
background: transparent;
|
|
694
659
|
color: var(--smrt-color-on-surface-variant, #43474e);
|
|
695
|
-
cursor: pointer;
|
|
696
|
-
font-family: inherit;
|
|
697
|
-
transition: all 150ms ease;
|
|
698
660
|
flex-shrink: 0;
|
|
699
661
|
}
|
|
700
662
|
|
|
701
|
-
.delete-btn:hover {
|
|
663
|
+
.entry-card :global(.delete-btn):hover {
|
|
702
664
|
background: var(--smrt-color-error-container, #fce4ec);
|
|
703
665
|
color: var(--smrt-color-error, #ba1a1a);
|
|
704
666
|
border-color: var(--smrt-color-error, #ba1a1a);
|
|
@@ -724,11 +686,16 @@ function getPatternPlaceholder(type: string): string {
|
|
|
724
686
|
font-size: var(--smrt-typography-body-medium-size, 0.8125rem);
|
|
725
687
|
}
|
|
726
688
|
|
|
727
|
-
|
|
689
|
+
/*
|
|
690
|
+
* The dismiss button now renders through smrt-ui's <Button variant="ghost">.
|
|
691
|
+
* `.filter-error :global(.dismiss-btn)` anchors on the real `.filter-error`
|
|
692
|
+
* element and pierces the Button child scope. `color: inherit` keeps the icon
|
|
693
|
+
* matching the error banner color (issue #1589).
|
|
694
|
+
*/
|
|
695
|
+
.filter-error :global(.dismiss-btn) {
|
|
728
696
|
background: transparent;
|
|
729
697
|
border: none;
|
|
730
698
|
font-size: var(--smrt-typography-body-large-size, 1rem);
|
|
731
|
-
cursor: pointer;
|
|
732
699
|
color: inherit;
|
|
733
700
|
padding: 0 0.25rem;
|
|
734
701
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmailFilterManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/EmailFilterManager.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EmailFilterManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/EmailFilterManager.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAGlE,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9D;AAsUD,QAAA,MAAM,kBAAkB,2CAAwC,CAAC;AACjE,KAAK,kBAAkB,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAChE,eAAe,kBAAkB,CAAC"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* FolderNav - Folder/label navigation sidebar
|
|
4
4
|
*/
|
|
5
5
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
6
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
6
7
|
import { M } from '../i18n.messages.js';
|
|
7
8
|
import type { FolderData } from '../types.js';
|
|
8
9
|
|
|
@@ -50,10 +51,10 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
50
51
|
<ul class="folder-list" role="list">
|
|
51
52
|
{#each _systemFolders as folder (folder.id)}
|
|
52
53
|
<li>
|
|
53
|
-
<
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
<Button
|
|
55
|
+
variant="ghost"
|
|
56
|
+
fullWidth
|
|
57
|
+
class={folder.id === activeFolderId ? 'folder-item folder-item--active' : 'folder-item'}
|
|
57
58
|
onclick={() => onfolderclick?.(folder)}
|
|
58
59
|
aria-current={folder.id === activeFolderId ? 'true' : undefined}
|
|
59
60
|
>
|
|
@@ -62,7 +63,7 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
62
63
|
{#if showCounts && folder.unreadCount > 0}
|
|
63
64
|
<span class="unread-badge">{folder.unreadCount}</span>
|
|
64
65
|
{/if}
|
|
65
|
-
</
|
|
66
|
+
</Button>
|
|
66
67
|
</li>
|
|
67
68
|
{/each}
|
|
68
69
|
</ul>
|
|
@@ -75,10 +76,10 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
75
76
|
<ul class="folder-list" role="list">
|
|
76
77
|
{#each _userFolders as folder (folder.id)}
|
|
77
78
|
<li>
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
<Button
|
|
80
|
+
variant="ghost"
|
|
81
|
+
fullWidth
|
|
82
|
+
class={folder.id === activeFolderId ? 'folder-item folder-item--active' : 'folder-item'}
|
|
82
83
|
onclick={() => onfolderclick?.(folder)}
|
|
83
84
|
aria-current={folder.id === activeFolderId ? 'true' : undefined}
|
|
84
85
|
>
|
|
@@ -87,7 +88,7 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
87
88
|
{#if showCounts && folder.unreadCount > 0}
|
|
88
89
|
<span class="unread-badge">{folder.unreadCount}</span>
|
|
89
90
|
{/if}
|
|
90
|
-
</
|
|
91
|
+
</Button>
|
|
91
92
|
</li>
|
|
92
93
|
{/each}
|
|
93
94
|
</ul>
|
|
@@ -107,7 +108,14 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
107
108
|
padding: 0;
|
|
108
109
|
}
|
|
109
110
|
|
|
110
|
-
|
|
111
|
+
/*
|
|
112
|
+
* Folder rows now render through smrt-ui's <Button variant="ghost" fullWidth>.
|
|
113
|
+
* The <button> is emitted inside the Button child, so `.folder-list :global(.folder-item)`
|
|
114
|
+
* anchors on the real `.folder-list` element and pierces the child scope to keep
|
|
115
|
+
* the nav-row layout, neutral color, hover and active styling (issue #1589). The
|
|
116
|
+
* active modifier is `folder-item--active`, NOT a Button variant class.
|
|
117
|
+
*/
|
|
118
|
+
.folder-list :global(.folder-item) {
|
|
111
119
|
display: flex;
|
|
112
120
|
align-items: center;
|
|
113
121
|
gap: 0.5rem;
|
|
@@ -115,7 +123,6 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
115
123
|
padding: 0.5rem 0.75rem;
|
|
116
124
|
border: none;
|
|
117
125
|
background: none;
|
|
118
|
-
cursor: pointer;
|
|
119
126
|
font: var(--smrt-typography-body-medium-font, 0.875rem / 1.25 sans-serif);
|
|
120
127
|
color: var(--smrt-color-on-surface, #1a1c1e);
|
|
121
128
|
border-radius: var(--smrt-radius-small, 0.25rem);
|
|
@@ -123,16 +130,16 @@ function getFolderIcon(specialUse?: string): string {
|
|
|
123
130
|
text-align: left;
|
|
124
131
|
}
|
|
125
132
|
|
|
126
|
-
.folder-item:hover {
|
|
133
|
+
.folder-list :global(.folder-item):hover {
|
|
127
134
|
background: var(--smrt-color-surface-variant, #e1e2ec);
|
|
128
135
|
}
|
|
129
136
|
|
|
130
|
-
.folder-item--active {
|
|
137
|
+
.folder-list :global(.folder-item--active) {
|
|
131
138
|
background: var(--smrt-color-secondary-container, #d7e3f7);
|
|
132
139
|
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
133
140
|
}
|
|
134
141
|
|
|
135
|
-
.folder-item:focus-visible {
|
|
142
|
+
.folder-list :global(.folder-item):focus-visible {
|
|
136
143
|
outline: 2px solid var(--smrt-color-primary, #005ac1);
|
|
137
144
|
outline-offset: -2px;
|
|
138
145
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderNav.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FolderNav.svelte.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"FolderNav.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/FolderNav.svelte.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAG9C,MAAM,WAAW,KAAK;IACpB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;CAC9C;AAkFD,QAAA,MAAM,SAAS,2CAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
|
|
@@ -10,6 +10,8 @@ export interface Props {
|
|
|
10
10
|
|
|
11
11
|
<script lang="ts">
|
|
12
12
|
import { useI18n } from '@happyvertical/smrt-ui/i18n';
|
|
13
|
+
import { Textarea } from '@happyvertical/smrt-ui/forms';
|
|
14
|
+
import { Button } from '@happyvertical/smrt-ui/ui';
|
|
13
15
|
import { M } from '../i18n.js';
|
|
14
16
|
import RecipientInput from './RecipientInput.svelte';
|
|
15
17
|
|
|
@@ -67,12 +69,11 @@ export interface Props {
|
|
|
67
69
|
onchange={(r) => { to = r; }}
|
|
68
70
|
/>
|
|
69
71
|
|
|
70
|
-
<
|
|
71
|
-
class="forward-body"
|
|
72
|
+
<Textarea
|
|
72
73
|
bind:value={body}
|
|
73
74
|
placeholder={t(M['messages.forward_form.note_placeholder'])}
|
|
74
75
|
rows={3}
|
|
75
|
-
|
|
76
|
+
/>
|
|
76
77
|
|
|
77
78
|
<div class="forwarded-original">
|
|
78
79
|
<pre class="forwarded-text">{forwardedBlock}</pre>
|
|
@@ -85,17 +86,16 @@ export interface Props {
|
|
|
85
86
|
{/if}
|
|
86
87
|
|
|
87
88
|
<div class="actions">
|
|
88
|
-
<
|
|
89
|
-
|
|
90
|
-
class="btn-primary"
|
|
89
|
+
<Button
|
|
90
|
+
variant="primary"
|
|
91
91
|
disabled={isSending || to.length === 0}
|
|
92
92
|
onclick={handleSend}
|
|
93
93
|
>
|
|
94
94
|
{isSending ? 'Sending...' : 'Forward'}
|
|
95
|
-
</
|
|
96
|
-
<
|
|
95
|
+
</Button>
|
|
96
|
+
<Button variant="ghost" class="btn-text" onclick={() => oncancel?.()}>
|
|
97
97
|
Cancel
|
|
98
|
-
</
|
|
98
|
+
</Button>
|
|
99
99
|
</div>
|
|
100
100
|
</div>
|
|
101
101
|
|
|
@@ -117,22 +117,6 @@ export interface Props {
|
|
|
117
117
|
font-weight: var(--smrt-typography-weight-medium, 500);
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
.forward-body {
|
|
121
|
-
width: 100%;
|
|
122
|
-
border: 1px solid var(--smrt-color-outline-variant, #cac4d0);
|
|
123
|
-
border-radius: var(--smrt-radius-sm, 8px);
|
|
124
|
-
padding: var(--smrt-spacing-2, 8px);
|
|
125
|
-
font-family: var(--smrt-font-family, system-ui);
|
|
126
|
-
font-size: var(--smrt-typography-body-medium-size, 14px);
|
|
127
|
-
resize: vertical;
|
|
128
|
-
box-sizing: border-box;
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
.forward-body:focus {
|
|
132
|
-
outline: 2px solid var(--smrt-color-primary, #6750a4);
|
|
133
|
-
outline-offset: -1px;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
120
|
.forwarded-original {
|
|
137
121
|
padding: var(--smrt-spacing-2, 8px);
|
|
138
122
|
background: var(--smrt-color-surface-variant, #e7e0ec);
|
|
@@ -162,29 +146,13 @@ export interface Props {
|
|
|
162
146
|
gap: var(--smrt-spacing-2, 8px);
|
|
163
147
|
}
|
|
164
148
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
font-size: var(--smrt-typography-label-large-size, 14px);
|
|
173
|
-
cursor: pointer;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
.btn-primary:disabled {
|
|
177
|
-
opacity: 0.6;
|
|
178
|
-
cursor: not-allowed;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
.btn-text {
|
|
182
|
-
padding: var(--smrt-spacing-2, 8px) var(--smrt-spacing-4, 16px);
|
|
183
|
-
border: none;
|
|
184
|
-
background: transparent;
|
|
149
|
+
/*
|
|
150
|
+
* Forward now uses Button's primary variant directly (dead .btn-primary CSS
|
|
151
|
+
* removed). The Cancel button keeps its neutral on-surface-variant text via
|
|
152
|
+
* `.actions :global(.btn-text)` (Button's ghost uses the primary color) —
|
|
153
|
+
* issue #1589.
|
|
154
|
+
*/
|
|
155
|
+
.actions :global(.btn-text) {
|
|
185
156
|
color: var(--smrt-color-on-surface-variant, #49454f);
|
|
186
|
-
font-family: var(--smrt-font-family, system-ui);
|
|
187
|
-
font-size: var(--smrt-typography-label-large-size, 14px);
|
|
188
|
-
cursor: pointer;
|
|
189
157
|
}
|
|
190
158
|
</style>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ForwardForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ForwardForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,KAAK;IACpB,eAAe,EAAE,WAAW,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;
|
|
1
|
+
{"version":3,"file":"ForwardForm.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/ForwardForm.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,KAAK;IACpB,eAAe,EAAE,WAAW,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,cAAc,EAAE,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB;AA8FD,QAAA,MAAM,WAAW,2CAAwC,CAAC;AAC1D,KAAK,WAAW,GAAG,UAAU,CAAC,OAAO,WAAW,CAAC,CAAC;AAClD,eAAe,WAAW,CAAC"}
|