@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.
Files changed (32) hide show
  1. package/dist/manifest.json +2 -2
  2. package/dist/smrt-knowledge.json +4 -4
  3. package/dist/svelte/components/AccountCard.svelte +22 -13
  4. package/dist/svelte/components/AttachmentChip.svelte +26 -7
  5. package/dist/svelte/components/AttachmentChip.svelte.d.ts +0 -3
  6. package/dist/svelte/components/AttachmentChip.svelte.d.ts.map +1 -1
  7. package/dist/svelte/components/AttachmentUpload.svelte +19 -7
  8. package/dist/svelte/components/AttachmentUpload.svelte.d.ts.map +1 -1
  9. package/dist/svelte/components/ComposeForm.svelte +66 -75
  10. package/dist/svelte/components/ComposeForm.svelte.d.ts.map +1 -1
  11. package/dist/svelte/components/EmailAccountManager.svelte +81 -115
  12. package/dist/svelte/components/EmailAccountManager.svelte.d.ts.map +1 -1
  13. package/dist/svelte/components/EmailFilterManager.svelte +94 -127
  14. package/dist/svelte/components/EmailFilterManager.svelte.d.ts.map +1 -1
  15. package/dist/svelte/components/FolderNav.svelte +22 -15
  16. package/dist/svelte/components/FolderNav.svelte.d.ts.map +1 -1
  17. package/dist/svelte/components/ForwardForm.svelte +16 -48
  18. package/dist/svelte/components/ForwardForm.svelte.d.ts.map +1 -1
  19. package/dist/svelte/components/MessageCard.svelte +14 -6
  20. package/dist/svelte/components/MessageCard.svelte.d.ts.map +1 -1
  21. package/dist/svelte/components/MessageDetail.svelte +19 -12
  22. package/dist/svelte/components/MessageFilters.svelte +47 -43
  23. package/dist/svelte/components/MessageFilters.svelte.d.ts.map +1 -1
  24. package/dist/svelte/components/MessageToolbar.svelte +28 -20
  25. package/dist/svelte/components/MessageToolbar.svelte.d.ts.map +1 -1
  26. package/dist/svelte/components/RecipientInput.svelte +32 -9
  27. package/dist/svelte/components/RecipientInput.svelte.d.ts.map +1 -1
  28. package/dist/svelte/components/ReplyForm.svelte +16 -48
  29. package/dist/svelte/components/ReplyForm.svelte.d.ts.map +1 -1
  30. package/dist/svelte/components/ThreadView.svelte +19 -12
  31. package/dist/svelte/components/ThreadView.svelte.d.ts.map +1 -1
  32. package/package.json +8 -7
@@ -5,7 +5,9 @@
5
5
  * Reusable component for adding, editing, testing, and removing
6
6
  * email accounts. 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 { EmailAccountData } from '../types.js';
11
13
 
@@ -171,10 +173,12 @@ function getProviderLabel(type: string): string {
171
173
  {t(M['messages.email_account_manager.section_description'])}
172
174
  </div>
173
175
  {#if !isReadonly && onsave}
174
- <button
176
+ <Button
177
+ variant="secondary"
178
+ size="sm"
175
179
  class="add-btn"
176
180
  onclick={() => { resetForm(); showForm = true; }}
177
- >{t(M['messages.email_account_manager.add_account'])}</button>
181
+ >{t(M['messages.email_account_manager.add_account'])}</Button>
178
182
  {/if}
179
183
  </div>
180
184
 
@@ -185,20 +189,20 @@ function getProviderLabel(type: string): string {
185
189
  <div class="form-row">
186
190
  <div class="form-field" style="flex: 1;">
187
191
  <label class="form-label" for="ea-name">{t(M['messages.email_account_manager.account_name'])}</label>
188
- <input id="ea-name" class="form-input" type="text" bind:value={maName} placeholder={t(M['messages.email_account_manager.account_name_placeholder'])} />
192
+ <Input id="ea-name" class="form-input" type="text" bind:value={maName} placeholder={t(M['messages.email_account_manager.account_name_placeholder'])} />
189
193
  </div>
190
194
  <div class="form-field" style="flex: 1;">
191
195
  <label class="form-label" for="ea-email">{t(M['messages.email_account_manager.email_address'])}</label>
192
- <input id="ea-email" class="form-input" type="email" bind:value={maEmail} placeholder={t(M['messages.email_account_manager.email_placeholder'])} />
196
+ <Input id="ea-email" class="form-input" type="email" bind:value={maEmail} placeholder={t(M['messages.email_account_manager.email_placeholder'])} />
193
197
  </div>
194
198
  <div class="form-field" style="flex: 0 0 130px;">
195
199
  <label class="form-label" for="ea-provider">Provider</label>
196
- <select id="ea-provider" class="form-select" bind:value={maProviderType}>
200
+ <Select id="ea-provider" class="form-select" bind:value={maProviderType}>
197
201
  <option value="imap">IMAP</option>
198
202
  <option value="gmail">Gmail</option>
199
203
  <option value="outlook">Outlook</option>
200
204
  <option value="exchange">Exchange</option>
201
- </select>
205
+ </Select>
202
206
  </div>
203
207
  </div>
204
208
 
@@ -206,19 +210,19 @@ function getProviderLabel(type: string): string {
206
210
  <div class="form-row">
207
211
  <div class="form-field" style="flex: 2;">
208
212
  <label class="form-label" for="ea-imap-host">Host</label>
209
- <input id="ea-imap-host" class="form-input" type="text" bind:value={maImapHost} placeholder={t(M['messages.email_account_manager.imap_host_placeholder'])} />
213
+ <Input id="ea-imap-host" class="form-input" type="text" bind:value={maImapHost} placeholder={t(M['messages.email_account_manager.imap_host_placeholder'])} />
210
214
  </div>
211
215
  <div class="form-field" style="flex: 0 0 90px;">
212
216
  <label class="form-label" for="ea-imap-port">Port</label>
213
- <input id="ea-imap-port" class="form-input" type="number" bind:value={maImapPort} />
217
+ <Input id="ea-imap-port" class="form-input" type="number" bind:value={maImapPort} />
214
218
  </div>
215
219
  <div class="form-field" style="flex: 0 0 120px;">
216
220
  <label class="form-label" for="ea-imap-sec">Security</label>
217
- <select id="ea-imap-sec" class="form-select" bind:value={maImapSecurity}>
221
+ <Select id="ea-imap-sec" class="form-select" bind:value={maImapSecurity}>
218
222
  <option value="ssl">SSL/TLS</option>
219
223
  <option value="starttls">STARTTLS</option>
220
224
  <option value="none">None</option>
221
- </select>
225
+ </Select>
222
226
  </div>
223
227
  </div>
224
228
 
@@ -226,19 +230,19 @@ function getProviderLabel(type: string): string {
226
230
  <div class="form-row">
227
231
  <div class="form-field" style="flex: 2;">
228
232
  <label class="form-label" for="ea-smtp-host">Host</label>
229
- <input id="ea-smtp-host" class="form-input" type="text" bind:value={maSmtpHost} placeholder={t(M['messages.email_account_manager.smtp_host_placeholder'])} />
233
+ <Input id="ea-smtp-host" class="form-input" type="text" bind:value={maSmtpHost} placeholder={t(M['messages.email_account_manager.smtp_host_placeholder'])} />
230
234
  </div>
231
235
  <div class="form-field" style="flex: 0 0 90px;">
232
236
  <label class="form-label" for="ea-smtp-port">Port</label>
233
- <input id="ea-smtp-port" class="form-input" type="number" bind:value={maSmtpPort} />
237
+ <Input id="ea-smtp-port" class="form-input" type="number" bind:value={maSmtpPort} />
234
238
  </div>
235
239
  <div class="form-field" style="flex: 0 0 120px;">
236
240
  <label class="form-label" for="ea-smtp-sec">Security</label>
237
- <select id="ea-smtp-sec" class="form-select" bind:value={maSmtpSecurity}>
241
+ <Select id="ea-smtp-sec" class="form-select" bind:value={maSmtpSecurity}>
238
242
  <option value="ssl">SSL/TLS</option>
239
243
  <option value="starttls">STARTTLS</option>
240
244
  <option value="none">None</option>
241
- </select>
245
+ </Select>
242
246
  </div>
243
247
  </div>
244
248
 
@@ -246,14 +250,15 @@ function getProviderLabel(type: string): string {
246
250
  <div class="form-row">
247
251
  <div class="form-field" style="flex: 1;">
248
252
  <label class="form-label" for="ea-username">Username</label>
249
- <input id="ea-username" class="form-input" type="text" bind:value={maUsername} placeholder={t(M['messages.email_account_manager.username_placeholder'])} />
253
+ <Input id="ea-username" class="form-input" type="text" bind:value={maUsername} placeholder={t(M['messages.email_account_manager.username_placeholder'])} />
250
254
  </div>
251
255
  <div class="form-field" style="flex: 1;">
252
256
  <label class="form-label" for="ea-password">Password</label>
253
- <input id="ea-password" class="form-input" type="password" bind:value={maPassword} placeholder={editingId ? '(unchanged)' : ''} />
257
+ <Input id="ea-password" class="form-input" type="password" bind:value={maPassword} placeholder={editingId ? '(unchanged)' : ''} />
254
258
  </div>
255
259
  <div class="form-field checkbox-field">
256
260
  <label class="form-label checkbox-label">
261
+ <!-- raw-primitive-allow: native checkbox; no Provider-free checkbox primitive (Toggle is a switch with different semantics, CheckboxInput requires a Provider) -->
257
262
  <input type="checkbox" bind:checked={maIsActive} />
258
263
  Active
259
264
  </label>
@@ -261,10 +266,10 @@ function getProviderLabel(type: string): string {
261
266
  </div>
262
267
 
263
268
  <div class="form-actions">
264
- <button class="cancel-btn" onclick={resetForm} disabled={saving}>Cancel</button>
265
- <button class="save-btn" onclick={save} disabled={saving || !maName.trim() || !maEmail.trim()}>
269
+ <Button variant="secondary" size="sm" class="cancel-btn" onclick={resetForm} disabled={saving}>Cancel</Button>
270
+ <Button variant="primary" size="sm" class="save-btn" onclick={save} disabled={saving || !maName.trim() || !maEmail.trim()}>
266
271
  {saving ? 'Saving...' : editingId ? 'Update' : 'Add Account'}
267
- </button>
272
+ </Button>
268
273
  </div>
269
274
  </div>
270
275
  {/if}
@@ -272,12 +277,13 @@ function getProviderLabel(type: string): string {
272
277
  {#if actionError}
273
278
  <div class="test-result failure" role="alert" aria-live="assertive">
274
279
  {actionError}
275
- <button
276
- type="button"
280
+ <Button
281
+ variant="ghost"
282
+ size="sm"
277
283
  class="dismiss-btn"
278
284
  aria-label={t(M['messages.email_account_manager.dismiss_error'])}
279
285
  onclick={() => actionError = null}
280
- >&times;</button>
286
+ >&times;</Button>
281
287
  </div>
282
288
  {/if}
283
289
 
@@ -288,7 +294,7 @@ function getProviderLabel(type: string): string {
288
294
  {:else}
289
295
  {t(M['messages.email_account_manager.connection_failed'])} {testResult.error ?? 'Unknown error'}
290
296
  {/if}
291
- <button class="dismiss-btn" onclick={() => testResult = null}>&times;</button>
297
+ <Button variant="ghost" size="sm" class="dismiss-btn" onclick={() => testResult = null}>&times;</Button>
292
298
  </div>
293
299
  {/if}
294
300
 
@@ -327,21 +333,25 @@ function getProviderLabel(type: string): string {
327
333
  {#if !isReadonly}
328
334
  <div class="entry-actions">
329
335
  {#if ontest}
330
- <button
336
+ <Button
337
+ variant="ghost"
338
+ size="sm"
331
339
  class="test-btn"
332
340
  onclick={(e) => { e.stopPropagation(); testConnection(acct); }}
333
341
  disabled={testingId === acct.id}
334
342
  title={t(M['messages.email_account_manager.test_connection'])}
335
343
  >
336
344
  {testingId === acct.id ? '...' : 'Test'}
337
- </button>
345
+ </Button>
338
346
  {/if}
339
347
  {#if ondelete}
340
- <button
348
+ <Button
349
+ variant="ghost"
350
+ size="sm"
341
351
  class="delete-btn"
342
352
  onclick={(e) => { e.stopPropagation(); remove(acct); }}
343
353
  title={t(M['messages.email_account_manager.remove'])}
344
- >&times;</button>
354
+ >&times;</Button>
345
355
  {/if}
346
356
  </div>
347
357
  {/if}
@@ -370,25 +380,17 @@ function getProviderLabel(type: string): string {
370
380
  color: var(--smrt-color-on-surface-variant, #43474e);
371
381
  }
372
382
 
373
- .add-btn {
374
- padding: 0.375rem 0.75rem;
383
+ /*
384
+ * The add button now renders through smrt-ui's <Button variant="secondary">.
385
+ * The variant owns the outlined-primary look + hover; `.section-header-row
386
+ * :global(.add-btn)` only re-asserts radius and the flex-shrink so the button
387
+ * keeps its place in the header row (issue #1589).
388
+ */
389
+ .section-header-row :global(.add-btn) {
375
390
  border-radius: var(--smrt-radius-md, 8px);
376
- border: 1px solid var(--smrt-color-primary, #005ac1);
377
- background: transparent;
378
- color: var(--smrt-color-primary, #005ac1);
379
- cursor: pointer;
380
- font-size: var(--smrt-typography-label-large-size, 0.8125rem);
381
- font-family: inherit;
382
- font-weight: var(--smrt-typography-weight-medium, 500);
383
- transition: all 150ms ease;
384
391
  flex-shrink: 0;
385
392
  }
386
393
 
387
- .add-btn:hover {
388
- background: var(--smrt-color-primary, #005ac1);
389
- color: var(--smrt-color-on-primary, #fff);
390
- }
391
-
392
394
  .entry-form {
393
395
  background: var(--smrt-color-surface-container, #f0f1f9);
394
396
  border: 1px solid var(--smrt-color-primary, #005ac1);
@@ -432,29 +434,14 @@ function getProviderLabel(type: string): string {
432
434
  color: var(--smrt-color-on-surface-variant, #43474e);
433
435
  }
434
436
 
435
- .form-input,
436
- .form-select {
437
- padding: 0.5rem 0.625rem;
438
- border-radius: var(--smrt-radius-md, 8px);
439
- border: 1px solid var(--smrt-color-outline-variant, #c2c7cf);
440
- background: var(--smrt-color-surface, #fefbff);
441
- color: var(--smrt-color-on-surface, #1a1c1e);
442
- font-size: var(--smrt-typography-body-medium-size, 0.8125rem);
443
- font-family: inherit;
444
- transition: border-color 150ms ease;
445
- }
446
-
447
- .form-input:focus,
448
- .form-select:focus {
449
- outline: none;
450
- border-color: var(--smrt-color-primary, #005ac1);
451
- }
452
-
453
- .form-input::placeholder {
454
- color: var(--smrt-color-on-surface-variant, #43474e);
455
- opacity: 0.5;
456
- }
457
-
437
+ /*
438
+ * The account-form fields now render through smrt-ui's <Input> / <Select>,
439
+ * which bring their own tokenised border / background / focus / placeholder
440
+ * styling and honor prefers-reduced-motion themselves. The old `.form-input` /
441
+ * `.form-select` rules (and their :focus / ::placeholder overrides) are dropped
442
+ * as dead — they targeted the raw elements that now live inside the primitive
443
+ * child scopes (issue #1589).
444
+ */
458
445
  .checkbox-field {
459
446
  justify-content: flex-end;
460
447
  padding-bottom: 0.5rem;
@@ -481,42 +468,20 @@ function getProviderLabel(type: string): string {
481
468
  padding-top: 0.25rem;
482
469
  }
483
470
 
484
- .cancel-btn {
485
- padding: 0.375rem 0.75rem;
486
- border-radius: var(--smrt-radius-md, 8px);
487
- border: 1px solid var(--smrt-color-outline-variant, #c2c7cf);
488
- background: transparent;
489
- color: var(--smrt-color-on-surface-variant, #43474e);
490
- cursor: pointer;
491
- font-size: var(--smrt-typography-label-large-size, 0.8125rem);
492
- font-family: inherit;
493
- transition: all 150ms ease;
494
- }
495
-
496
- .cancel-btn:hover {
497
- background: var(--smrt-color-surface-container-high, #e6e7ef);
498
- }
499
-
500
- .save-btn {
501
- padding: 0.375rem 0.75rem;
471
+ /*
472
+ * Cancel/Save now use Button's secondary/primary variants (dead bespoke CSS
473
+ * removed). `.form-actions :global(...)` only re-asserts the rounded radius so
474
+ * they match the form's other controls (issue #1589). Cancel's neutral outline
475
+ * color override keeps it from picking up secondary's primary border color.
476
+ */
477
+ .form-actions :global(.cancel-btn),
478
+ .form-actions :global(.save-btn) {
502
479
  border-radius: var(--smrt-radius-md, 8px);
503
- border: 1px solid var(--smrt-color-primary, #005ac1);
504
- background: var(--smrt-color-primary, #005ac1);
505
- color: var(--smrt-color-on-primary, #fff);
506
- cursor: pointer;
507
- font-size: var(--smrt-typography-label-large-size, 0.8125rem);
508
- font-family: inherit;
509
- font-weight: var(--smrt-typography-weight-medium, 500);
510
- transition: all 150ms ease;
511
480
  }
512
481
 
513
- .save-btn:hover:not(:disabled) {
514
- opacity: 0.9;
515
- }
516
-
517
- .save-btn:disabled {
518
- opacity: 0.5;
519
- cursor: not-allowed;
482
+ .form-actions :global(.cancel-btn) {
483
+ border-color: var(--smrt-color-outline-variant, #c2c7cf);
484
+ color: var(--smrt-color-on-surface-variant, #43474e);
520
485
  }
521
486
 
522
487
  .test-result {
@@ -538,11 +503,16 @@ function getProviderLabel(type: string): string {
538
503
  color: var(--smrt-color-error, #ba1a1a);
539
504
  }
540
505
 
541
- .dismiss-btn {
506
+ /*
507
+ * The dismiss button now renders through smrt-ui's <Button variant="ghost">.
508
+ * `.test-result :global(.dismiss-btn)` anchors on the real `.test-result`
509
+ * element and pierces the Button child scope. `color: inherit` keeps the icon
510
+ * matching the success/failure banner color (issue #1589).
511
+ */
512
+ .test-result :global(.dismiss-btn) {
542
513
  background: transparent;
543
514
  border: none;
544
515
  font-size: var(--smrt-typography-body-large-size, 1rem);
545
- cursor: pointer;
546
516
  color: inherit;
547
517
  padding: 0 0.25rem;
548
518
  }
@@ -661,29 +631,28 @@ function getProviderLabel(type: string): string {
661
631
  flex-shrink: 0;
662
632
  }
663
633
 
664
- .test-btn {
634
+ /*
635
+ * The test and delete buttons now render through smrt-ui's <Button
636
+ * variant="ghost">. The <button> is emitted inside the Button child, so
637
+ * `.entry-actions :global(...)` anchors on the real `.entry-actions` element
638
+ * and pierces the child scope to keep the original outlined-pill styling and
639
+ * the delete button's red-on-hover affordance (issue #1589).
640
+ */
641
+ .entry-actions :global(.test-btn) {
665
642
  padding: 0.25rem 0.5rem;
666
643
  border-radius: var(--smrt-radius-sm, 4px);
667
644
  border: 1px solid var(--smrt-color-outline-variant, #c2c7cf);
668
645
  background: transparent;
669
646
  color: var(--smrt-color-on-surface-variant, #43474e);
670
- cursor: pointer;
671
647
  font-size: var(--smrt-typography-label-small-size, 0.6875rem);
672
- font-family: inherit;
673
- transition: all 150ms ease;
674
648
  }
675
649
 
676
- .test-btn:hover:not(:disabled) {
650
+ .entry-actions :global(.test-btn):hover:not(:disabled) {
677
651
  border-color: var(--smrt-color-primary, #005ac1);
678
652
  color: var(--smrt-color-primary, #005ac1);
679
653
  }
680
654
 
681
- .test-btn:disabled {
682
- opacity: 0.5;
683
- cursor: not-allowed;
684
- }
685
-
686
- .delete-btn {
655
+ .entry-actions :global(.delete-btn) {
687
656
  font-size: var(--smrt-typography-body-large-size, 1rem);
688
657
  line-height: 1;
689
658
  padding: 0.125rem 0.5rem;
@@ -691,13 +660,10 @@ function getProviderLabel(type: string): string {
691
660
  border: 1px solid transparent;
692
661
  background: transparent;
693
662
  color: var(--smrt-color-on-surface-variant, #43474e);
694
- cursor: pointer;
695
- font-family: inherit;
696
- transition: all 150ms ease;
697
663
  flex-shrink: 0;
698
664
  }
699
665
 
700
- .delete-btn:hover {
666
+ .entry-actions :global(.delete-btn):hover {
701
667
  background: var(--smrt-color-error-container, #fce4ec);
702
668
  color: var(--smrt-color-error, #ba1a1a);
703
669
  border-color: var(--smrt-color-error, #ba1a1a);
@@ -1 +1 @@
1
- {"version":3,"file":"EmailAccountManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/EmailAccountManager.svelte.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AA+TD,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"EmailAccountManager.svelte.d.ts","sourceRoot":"","sources":["../../../src/svelte/components/EmailAccountManager.svelte.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGpD,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzE,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,EAAE,CACP,OAAO,EAAE,gBAAgB,KACtB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACpD;AAkUD,QAAA,MAAM,mBAAmB,2CAAwC,CAAC;AAClE,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAClE,eAAe,mBAAmB,CAAC"}