@cosmicdrift/kumiko-document-designer 0.363.0 → 0.364.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/constants.d.ts +3 -0
  2. package/dist/constants.js +4 -0
  3. package/dist/i18n.js +144 -50
  4. package/dist/web/cells.js +1 -1
  5. package/dist/web/editor-header.d.ts +37 -0
  6. package/dist/web/editor-header.js +43 -0
  7. package/dist/web/editor-shell.d.ts +40 -0
  8. package/dist/web/editor-shell.js +36 -0
  9. package/dist/web/i18n.js +35 -59
  10. package/dist/web/layout-editor-body.d.ts +2 -2
  11. package/dist/web/layout-editor-body.js +94 -49
  12. package/dist/web/layout-editor.js +8 -6
  13. package/dist/web/layout-html.d.ts +2 -0
  14. package/dist/web/layout-html.js +13 -1
  15. package/dist/web/layout-meta.d.ts +29 -0
  16. package/dist/web/layout-meta.js +32 -0
  17. package/dist/web/layout-rails.d.ts +15 -5
  18. package/dist/web/layout-rails.js +61 -68
  19. package/dist/web/layout-types.d.ts +4 -0
  20. package/dist/web/layout-users.d.ts +1 -0
  21. package/dist/web/layout-users.js +4 -1
  22. package/dist/web/mail-dialogs.d.ts +1 -6
  23. package/dist/web/mail-dialogs.js +2 -2
  24. package/dist/web/mail-draft.d.ts +8 -6
  25. package/dist/web/mail-draft.js +33 -11
  26. package/dist/web/mail-edit-center.d.ts +3 -1
  27. package/dist/web/mail-edit-center.js +5 -4
  28. package/dist/web/mail-editor-body.d.ts +0 -1
  29. package/dist/web/mail-editor-body.js +57 -41
  30. package/dist/web/mail-editor.js +2 -5
  31. package/dist/web/mail-footer.d.ts +3 -14
  32. package/dist/web/mail-footer.js +12 -13
  33. package/dist/web/mail-left-rail.d.ts +9 -4
  34. package/dist/web/mail-left-rail.js +18 -15
  35. package/dist/web/mail-missing-locale.d.ts +10 -0
  36. package/dist/web/mail-missing-locale.js +45 -0
  37. package/dist/web/mail-origin-bar.d.ts +3 -5
  38. package/dist/web/mail-origin-bar.js +26 -50
  39. package/dist/web/mail-preview-side.d.ts +12 -5
  40. package/dist/web/mail-preview-side.js +14 -5
  41. package/dist/web/mail-preview.d.ts +9 -5
  42. package/dist/web/mail-preview.js +24 -13
  43. package/dist/web/mail-right-rail.js +23 -13
  44. package/dist/web/mail-types.d.ts +6 -1
  45. package/dist/web/mail-versions.js +3 -3
  46. package/dist/web/origin-bar.d.ts +11 -2
  47. package/dist/web/origin-bar.js +46 -24
  48. package/dist/web/overrides-drawer.d.ts +3 -2
  49. package/dist/web/overrides-drawer.js +87 -11
  50. package/dist/web/overview-row.d.ts +2 -0
  51. package/dist/web/overview-row.js +2 -1
  52. package/dist/web/page-canvas.d.ts +1 -0
  53. package/dist/web/page-canvas.js +23 -13
  54. package/dist/web/pdf-footer.d.ts +13 -0
  55. package/dist/web/pdf-footer.js +34 -0
  56. package/dist/web/pdf-left-rail.d.ts +9 -0
  57. package/dist/web/pdf-left-rail.js +16 -0
  58. package/dist/web/pdf-meta.d.ts +3 -5
  59. package/dist/web/pdf-meta.js +10 -16
  60. package/dist/web/pdf-preview.js +21 -8
  61. package/dist/web/pdf-template-editor.js +90 -76
  62. package/dist/web/rail.d.ts +13 -1
  63. package/dist/web/rail.js +15 -7
  64. package/dist/web/relative-time.d.ts +1 -0
  65. package/dist/web/relative-time.js +18 -0
  66. package/dist/web/settings-panel.d.ts +11 -5
  67. package/dist/web/settings-panel.js +24 -13
  68. package/dist/web/status-label.d.ts +7 -0
  69. package/dist/web/status-label.js +8 -0
  70. package/dist/web/types.d.ts +23 -0
  71. package/dist/web/use-insert-targets.d.ts +1 -1
  72. package/dist/web/use-mail-persistence.d.ts +0 -1
  73. package/dist/web/use-mail-persistence.js +1 -1
  74. package/dist/web/use-own-address.d.ts +5 -0
  75. package/dist/web/use-own-address.js +14 -0
  76. package/package.json +8 -8
  77. package/src/changes.json +24 -0
  78. package/dist/web/mail-header.d.ts +0 -23
  79. package/dist/web/mail-header.js +0 -16
  80. package/dist/web/placeholder-panel.d.ts +0 -21
  81. package/dist/web/placeholder-panel.js +0 -35
@@ -8,6 +8,9 @@ export declare const TEMPLATES_NAV_ID: "templates";
8
8
  export declare const PLATFORM_TEMPLATES_NAV_ID: "platform-templates";
9
9
  export declare const BRANDING_SCREEN_QN: "managed-pages:screen:branding-settings";
10
10
  export declare const BRANDING_QUERY_QN: "managed-pages:query:branding";
11
+ export declare const USER_ME_QUERY_QN: "user:query:user:me";
12
+ export declare const PROFILE_FEATURE_NAME: "user-profile";
13
+ export declare const PROFILE_SCREEN_ID: "profile";
11
14
  export declare const DEFAULT_LAYOUT_SLUG: "default";
12
15
  export type TemplateEditorKind = "mail" | "document-pdf" | "mail-layout" | "pdf-layout";
13
16
  export declare const TEMPLATE_EDITOR_SCREENS: Partial<Record<TemplateEditorKind, string>>;
package/dist/constants.js CHANGED
@@ -10,6 +10,10 @@ export const TEMPLATES_NAV_ID = "templates";
10
10
  export const PLATFORM_TEMPLATES_NAV_ID = "platform-templates";
11
11
  export const BRANDING_SCREEN_QN = "managed-pages:screen:branding-settings";
12
12
  export const BRANDING_QUERY_QN = "managed-pages:query:branding";
13
+ // Pinned like the branding names: the user features' constants are not exported to the web barrel.
14
+ export const USER_ME_QUERY_QN = "user:query:user:me";
15
+ export const PROFILE_FEATURE_NAME = "user-profile";
16
+ export const PROFILE_SCREEN_ID = "profile";
13
17
  export const DEFAULT_LAYOUT_SLUG = "default";
14
18
  // Short screen id per template kind. A kind without an entry gets no "Edit" row action.
15
19
  // The mail editor adds `mail` here and declares its screen in this feature, because the
package/dist/i18n.js CHANGED
@@ -29,6 +29,8 @@ export const DOCUMENT_DESIGNER_I18N = {
29
29
  "documentDesigner.kind.layout": { en: "Layout", de: "Layout" },
30
30
  "documentDesigner.source.system": { en: "System", de: "System" },
31
31
  "documentDesigner.source.tenant": { en: "Tenant", de: "Mandant" },
32
+ "documentDesigner.origin.system": { en: "System template", de: "System-Vorlage" },
33
+ "documentDesigner.origin.override": { en: "Customised", de: "Mandanten-Anpassung" },
32
34
  "documentDesigner.status.active": { en: "Active", de: "Aktiv" },
33
35
  "documentDesigner.status.draft": { en: "Draft", de: "Entwurf" },
34
36
  "documentDesigner.status.archived": { en: "Archived", de: "Archiviert" },
@@ -77,19 +79,55 @@ export const DOCUMENT_DESIGNER_I18N = {
77
79
  "documentDesigner.appearance.title": { en: "Appearance", de: "Darstellung" },
78
80
  "documentDesigner.appearance.width": { en: "Width", de: "Breite" },
79
81
  "documentDesigner.appearance.font": { en: "Font", de: "Schrift" },
80
- "documentDesigner.appearance.systemFont": {
81
- en: "System font (Helvetica, Arial)",
82
- de: "Systemschrift (Helvetica, Arial)",
83
- },
84
82
  "documentDesigner.appearance.background": { en: "Outer background", de: "Hintergrund außen" },
85
- "documentDesigner.appearance.backgroundValue": { en: "#f5f5f5", de: "#f5f5f5" },
86
- "documentDesigner.appearance.pageFormat": { en: "Page format", de: "Seitenformat" },
87
- "documentDesigner.appearance.hint": {
88
- en: "The appearance is fixed. Custom fonts and colours will follow.",
89
- de: "Darstellung ist fest vorgegeben. Eigene Schriften und Farben kommen später.",
83
+ "documentDesigner.appearance.font.sans": {
84
+ en: "System font (Arial, Helvetica)",
85
+ de: "Systemschrift (Arial, Helvetica)",
86
+ },
87
+ "documentDesigner.appearance.font.serif": {
88
+ en: "Serif font (Georgia)",
89
+ de: "Serifenschrift (Georgia)",
90
+ },
91
+ "documentDesigner.appearance.fontHint": {
92
+ en: "Custom fonts in mails come later. PDF uses the bundled framework font.",
93
+ de: "Eigene Schriften in Mails kommen sp\u00e4ter. PDF nutzt die geb\u00fcndelte Schrift des Frameworks.",
94
+ },
95
+ "documentDesigner.appearance.backgroundInvalid": {
96
+ en: "Enter a colour like #f3f2ee.",
97
+ de: "Eine Farbe wie #f3f2ee angeben.",
98
+ },
99
+ "documentDesigner.appearance.accentLine": {
100
+ en: "Accent line at the top",
101
+ de: "Akzentlinie oben",
102
+ },
103
+ "documentDesigner.appearance.accentLine.branding": {
104
+ en: "Accent colour from branding",
105
+ de: "Akzentfarbe aus Branding",
106
+ },
107
+ "documentDesigner.appearance.accentLine.none": { en: "None", de: "Keine" },
108
+ "documentDesigner.appearance.buttonStyle": { en: "Button style", de: "Button-Stil" },
109
+ "documentDesigner.appearance.buttonStyle.filled-rounded": {
110
+ en: "Filled, rounded",
111
+ de: "Gef\u00fcllt, abgerundet",
112
+ },
113
+ "documentDesigner.appearance.buttonStyle.filled-square": {
114
+ en: "Filled, square",
115
+ de: "Gef\u00fcllt, eckig",
116
+ },
117
+ "documentDesigner.appearance.buttonStyle.outline": { en: "Outline", de: "Umriss" },
118
+ "documentDesigner.appearance.fromMjml": {
119
+ en: "The appearance comes from this layout's MJML source.",
120
+ de: "Die Darstellung kommt aus der MJML-Quelle dieses Layouts.",
90
121
  },
91
122
  "documentDesigner.mjml.title": { en: "MJML source", de: "MJML-Quelle" },
92
- "documentDesigner.editor.crumb": { en: "Templates", de: "Vorlagen" },
123
+ "documentDesigner.mjml.hint": {
124
+ en: "Platform admins can edit the MJML source directly. Tenants only see the draft mode.",
125
+ de: "Plattform-Admins k\u00f6nnen die MJML-Quelle direkt bearbeiten. Mandanten sehen nur den Entwurfs-Modus.",
126
+ },
127
+ "documentDesigner.renderer.title": { en: "Renderer", de: "Renderer" },
128
+ "documentDesigner.renderer.mjml": { en: "MJML", de: "MJML" },
129
+ "documentDesigner.renderer.chromium": { en: "Chromium (PDF)", de: "Chromium (PDF)" },
130
+ "documentDesigner.renderer.active": { en: "active", de: "aktiv" },
93
131
  "documentDesigner.editor.title.mail": { en: "Mail layout", de: "Mail-Layout" },
94
132
  "documentDesigner.editor.title.pdf": { en: "Letterhead", de: "Briefpapier" },
95
133
  "documentDesigner.editor.kindSwitch": { en: "Layout kind", de: "Layout-Art" },
@@ -136,8 +174,8 @@ export const DOCUMENT_DESIGNER_I18N = {
136
174
  de: "System-Layout v{version} · {active} von {total} Mandanten haben eine eigene Fassung",
137
175
  },
138
176
  "documentDesigner.editor.diff.open": {
139
- en: "Difference to the system layout",
140
- de: "Unterschied zum System-Layout",
177
+ en: "Show difference",
178
+ de: "Unterschied anzeigen",
141
179
  },
142
180
  "documentDesigner.editor.diff.title": {
143
181
  en: "Difference to the system layout",
@@ -148,8 +186,8 @@ export const DOCUMENT_DESIGNER_I18N = {
148
186
  de: "Ihr Layout entspricht dem System-Layout.",
149
187
  },
150
188
  "documentDesigner.editor.reset.open": {
151
- en: "Reset to system layout",
152
- de: "Auf System-Layout zurücksetzen",
189
+ en: "Reset",
190
+ de: "Zurücksetzen",
153
191
  },
154
192
  "documentDesigner.editor.reset.title": {
155
193
  en: "Reset to system layout?",
@@ -161,6 +199,10 @@ export const DOCUMENT_DESIGNER_I18N = {
161
199
  },
162
200
  "documentDesigner.editor.reset.confirm": { en: "Reset", de: "Zurücksetzen" },
163
201
  "documentDesigner.editor.region.header": { en: "Header", de: "Kopf" },
202
+ "documentDesigner.editor.logoCaption": {
203
+ en: "Logo · from branding, max. 180 px wide",
204
+ de: "Logo · aus Branding, max. 180 px breit",
205
+ },
164
206
  "documentDesigner.editor.region.content": { en: "Template content", de: "Inhalt der Vorlage" },
165
207
  "documentDesigner.editor.region.signature": { en: "Signature area", de: "Signatur-Bereich" },
166
208
  "documentDesigner.editor.region.footer": { en: "Footer", de: "Fuß" },
@@ -223,10 +265,6 @@ export const DOCUMENT_DESIGNER_I18N = {
223
265
  en: "Preview",
224
266
  de: "Vorschau",
225
267
  },
226
- "documentDesigner.mail.header.testMail": {
227
- en: "Send test mail to me",
228
- de: "Test-Mail an mich",
229
- },
230
268
  "documentDesigner.mail.language.de": {
231
269
  en: "German",
232
270
  de: "Deutsch",
@@ -240,8 +278,8 @@ export const DOCUMENT_DESIGNER_I18N = {
240
278
  de: "Spanisch",
241
279
  },
242
280
  "documentDesigner.mail.origin.overrides": {
243
- en: 'Overrides the system template "{title}" v{version}.',
244
- de: "Überschreibt die System-Vorlage „{title}“ v{version}.",
281
+ en: "Overrides the system template v{version}.",
282
+ de: "Überschreibt die System-Vorlage v{version}.",
245
283
  },
246
284
  "documentDesigner.mail.origin.tenantOnly": {
247
285
  en: "This template exists only for your tenant.",
@@ -260,8 +298,8 @@ export const DOCUMENT_DESIGNER_I18N = {
260
298
  de: "Archiviert.",
261
299
  },
262
300
  "documentDesigner.mail.origin.reset": {
263
- en: "Reset to system template",
264
- de: "Auf System-Vorlage zurücksetzen",
301
+ en: "Reset",
302
+ de: "Zurücksetzen",
265
303
  },
266
304
  "documentDesigner.mail.origin.system": {
267
305
  en: "You are viewing the system template v{version}. Saving creates a customisation for your tenant.",
@@ -272,21 +310,37 @@ export const DOCUMENT_DESIGNER_I18N = {
272
310
  de: "System-Vorlage v{version}. Speichern ändert sie für alle Mandanten ohne eigene Anpassung.",
273
311
  },
274
312
  "documentDesigner.mail.origin.missing": {
275
- en: "There is no own version for {language}. Recipients with language {locale} get the {fallback} version.",
276
- de: "Für {language} gibt es keine eigene Fassung. Empfänger mit Sprache {locale} bekommen die Fassung {fallback}.",
313
+ en: "There is no version for {language} yet.",
314
+ de: "Für {language} gibt es noch keine Fassung.",
315
+ },
316
+ "documentDesigner.mail.missing.text": {
317
+ en: "There is no version for {language} yet. Recipients with language {locale} get the {fallbackAdjective} version.",
318
+ de: "Für {language} gibt es noch keine Fassung. Empfänger mit Sprache {locale} bekommen die {fallbackAdjective} Fassung.",
319
+ },
320
+ "documentDesigner.mail.missing.textNoFallback": {
321
+ en: "There is no version for {language} yet.",
322
+ de: "Für {language} gibt es noch keine Fassung.",
323
+ },
324
+ "documentDesigner.mail.missing.copy": {
325
+ en: "Copy from {language}",
326
+ de: "Aus {language} kopieren",
327
+ },
328
+ "documentDesigner.mail.languageAdjective.de": {
329
+ en: "German",
330
+ de: "deutsche",
277
331
  },
278
- "documentDesigner.mail.origin.missingNoFallback": {
279
- en: "There is no own version for {language}.",
280
- de: "Für {language} gibt es keine eigene Fassung.",
332
+ "documentDesigner.mail.languageAdjective.en": {
333
+ en: "English",
334
+ de: "englische",
335
+ },
336
+ "documentDesigner.mail.languageAdjective.es": {
337
+ en: "Spanish",
338
+ de: "spanische",
281
339
  },
282
340
  "documentDesigner.mail.origin.copyNote": {
283
341
  en: "Copying a system version does not bring images or attachments along; upload them again afterwards.",
284
342
  de: "Beim Kopieren einer System-Fassung kommen Bilder und Anhänge nicht mit; laden Sie sie danach neu hoch.",
285
343
  },
286
- "documentDesigner.mail.origin.copyFrom": {
287
- en: "Copy from {fallback}",
288
- de: "Aus {fallback} kopieren",
289
- },
290
344
  "documentDesigner.mail.origin.createBlank": {
291
345
  en: "Start empty",
292
346
  de: "Leer anlegen",
@@ -323,6 +377,14 @@ export const DOCUMENT_DESIGNER_I18N = {
323
377
  en: "System placeholders",
324
378
  de: "System-Platzhalter",
325
379
  },
380
+ "documentDesigner.mail.system.layout": {
381
+ en: "Layout",
382
+ de: "Layout",
383
+ },
384
+ "documentDesigner.mail.system.hint": {
385
+ en: "Filled in by the platform. Imprint and unsubscribe link come from the layout.",
386
+ de: "Füllt die Plattform. Impressum und Abmeldelink liefert das Layout.",
387
+ },
326
388
  "documentDesigner.mail.resource.title": {
327
389
  en: "Resources",
328
390
  de: "Ressourcen",
@@ -352,8 +414,8 @@ export const DOCUMENT_DESIGNER_I18N = {
352
414
  de: "Entfernen",
353
415
  },
354
416
  "documentDesigner.mail.resource.caption": {
355
- en: "{key} · embedded as CID",
356
- de: "{key} · als CID eingebettet",
417
+ en: "{key} · {size} · embedded as CID",
418
+ de: "{key} · {size} · als CID eingebettet",
357
419
  },
358
420
  "documentDesigner.mail.resource.hint": {
359
421
  en: "Inline images are sent as CID. Attachments from PDF templates are generated when the mail is sent.",
@@ -431,6 +493,18 @@ export const DOCUMENT_DESIGNER_I18N = {
431
493
  en: "Default sender of the tenant",
432
494
  de: "Standard-Absender des Mandanten",
433
495
  },
496
+ "documentDesigner.mail.props.senderPlaceholder": {
497
+ en: "Name shown to recipients",
498
+ de: "Name, den Empfänger sehen",
499
+ },
500
+ "documentDesigner.mail.props.senderHint": {
501
+ en: "The address comes from the platform's mail delivery.",
502
+ de: "Die Adresse kommt vom Mail-Versand der Plattform.",
503
+ },
504
+ "documentDesigner.mail.props.replyTo": {
505
+ en: "Reply to",
506
+ de: "Antwort an",
507
+ },
434
508
  "documentDesigner.mail.props.category": {
435
509
  en: "Category",
436
510
  de: "Kategorie",
@@ -467,6 +541,10 @@ export const DOCUMENT_DESIGNER_I18N = {
467
541
  en: "File",
468
542
  de: "Datei",
469
543
  },
544
+ "documentDesigner.mail.attachments.hint": {
545
+ en: "PDF templates are generated when the mail is sent; files go out as uploaded.",
546
+ de: "PDF-Vorlagen werden beim Versand erzeugt, Dateien gehen so mit, wie sie hochgeladen wurden.",
547
+ },
470
548
  "documentDesigner.mail.pdfLink.title": {
471
549
  en: "Attachment from PDF template",
472
550
  de: "Anhang aus PDF-Vorlage",
@@ -511,6 +589,10 @@ export const DOCUMENT_DESIGNER_I18N = {
511
589
  en: "v{version} {when}, {name}",
512
590
  de: "v{version} {when}, {name}",
513
591
  },
592
+ "documentDesigner.mail.versions.hint": {
593
+ en: "Every save creates a new version. The active one is what recipients get.",
594
+ de: "Jedes Speichern legt eine neue Version an. Aktiv ist die Version, die Empfänger bekommen.",
595
+ },
514
596
  "documentDesigner.mail.footer.missing": {
515
597
  en: 'Required placeholder "{names}" is missing in subject, preview text and content. Publishing is blocked.',
516
598
  de: "Pflicht-Platzhalter „{names}“ fehlt in Betreff, Vorschautext und Inhalt. Veröffentlichen ist gesperrt.",
@@ -539,17 +621,9 @@ export const DOCUMENT_DESIGNER_I18N = {
539
621
  en: "Discard",
540
622
  de: "Verwerfen",
541
623
  },
542
- "documentDesigner.mail.activeSave.title": {
543
- en: "Save as draft?",
544
- de: "Als Entwurf speichern?",
545
- },
546
- "documentDesigner.mail.activeSave.description": {
547
- en: "Saving as a draft takes the active customisation offline until you publish. Publish instead?",
548
- de: "Speichern als Entwurf nimmt die aktive Anpassung offline, bis Sie veröffentlichen. Stattdessen veröffentlichen?",
549
- },
550
- "documentDesigner.mail.activeSave.confirm": {
551
- en: "Save as draft",
552
- de: "Als Entwurf speichern",
624
+ "documentDesigner.origin.draftBesideActive": {
625
+ en: "Version {active} is sent, your draft (version {draft}) is not published yet.",
626
+ de: "Verschickt wird Version {active}, Ihr Entwurf (Version {draft}) ist noch nicht veröffentlicht.",
553
627
  },
554
628
  "documentDesigner.mail.leave.title": {
555
629
  en: "Unsaved changes",
@@ -568,8 +642,8 @@ export const DOCUMENT_DESIGNER_I18N = {
568
642
  de: "Verwerfen",
569
643
  },
570
644
  "documentDesigner.mail.preview.bar": {
571
- en: 'Preview with sample values from the placeholder schema. Rendered through "{layout}".',
572
- de: "Vorschau mit Beispielwerten aus dem Platzhalter-Schema. Gerendert über „{layout}“.",
645
+ en: 'Preview with sample values from the placeholder schema. Rendered through "Mail layout v{version}", renderer: MJML.',
646
+ de: "Vorschau mit Beispielwerten aus dem Platzhalter-Schema. Gerendert über „Mail-Layout v{version}“, Renderer: MJML.",
573
647
  },
574
648
  "documentDesigner.mail.preview.barPlain": {
575
649
  en: "Preview with sample values from the placeholder schema.",
@@ -611,6 +685,14 @@ export const DOCUMENT_DESIGNER_I18N = {
611
685
  en: "Mail preview",
612
686
  de: "Mail-Vorschau",
613
687
  },
688
+ "documentDesigner.mail.preview.from": {
689
+ en: "From",
690
+ de: "Von",
691
+ },
692
+ "documentDesigner.mail.preview.to": {
693
+ en: "To",
694
+ de: "An",
695
+ },
614
696
  "documentDesigner.mail.preview.samples": {
615
697
  en: "Sample values",
616
698
  de: "Beispielwerte",
@@ -631,6 +713,10 @@ export const DOCUMENT_DESIGNER_I18N = {
631
713
  en: "Checks",
632
714
  de: "Prüfung",
633
715
  },
716
+ "documentDesigner.mail.preview.checksHint": {
717
+ en: "What the server found while rendering this mail.",
718
+ de: "Das hat der Server beim Rendern dieser Mail gefunden.",
719
+ },
634
720
  "documentDesigner.mail.testMail.title": {
635
721
  en: "Test mail",
636
722
  de: "Test-Mail",
@@ -643,13 +729,21 @@ export const DOCUMENT_DESIGNER_I18N = {
643
729
  en: "Your address",
644
730
  de: "Ihre Adresse",
645
731
  },
646
- "documentDesigner.mail.testMail.prefix": {
647
- en: "Subject with [TEST] prefix",
732
+ "documentDesigner.mail.testMail.changeAddress": {
733
+ en: "Change address",
734
+ de: "Adresse ändern",
735
+ },
736
+ "documentDesigner.mail.testMail.prefixSubject": {
737
+ en: "Prefix the subject with [TEST]",
648
738
  de: "Betreff mit Präfix [TEST]",
649
739
  },
650
740
  "documentDesigner.mail.testMail.attachments": {
651
- en: "Attachments are sent along",
652
- de: "Anhänge werden mitgesendet",
741
+ en: "Send attachments along",
742
+ de: "Anhang mitsenden",
743
+ },
744
+ "documentDesigner.mail.testMail.noAttachments": {
745
+ en: "This template has no attachments",
746
+ de: "Diese Vorlage hat keine Anhänge",
653
747
  },
654
748
  "documentDesigner.mail.testMail.send": {
655
749
  en: "Send test mail",
package/dist/web/cells.js CHANGED
@@ -44,7 +44,7 @@ export function createLocalesCell(appLocales) {
44
44
  }
45
45
  export function StatusCell({ row }) {
46
46
  const t = useTranslation();
47
- return withRow(row, (r) => (_jsx(StatusBadge, { tone: statusTone(r.status), testId: "document-designer-status", children: statusLabel(t, r.status, r.version) })));
47
+ return withRow(row, (r) => (_jsxs("span", { className: "flex flex-col items-start gap-1", children: [_jsx(StatusBadge, { tone: statusTone(r.status), testId: "document-designer-status", children: statusLabel(t, r.status, r.version) }), r.status === "active" && r.draftVersion !== null && (_jsx(StatusBadge, { tone: statusTone("draft"), testId: "document-designer-draft-status", children: statusLabel(t, "draft", r.draftVersion) }))] })));
48
48
  }
49
49
  export function UsedByCell({ row }) {
50
50
  const t = useTranslation();
@@ -0,0 +1,37 @@
1
+ import type { ReactNode } from "react";
2
+ export type EditorMode = "edit" | "preview";
3
+ /** "override" is a tenant row that replaces a system version; "tenant" has no system counterpart. */
4
+ export type EditorOrigin = "system" | "override" | "tenant";
5
+ export declare function originOf(isSystemRow: boolean, hasSystemVersion: boolean): EditorOrigin;
6
+ export declare function OriginBadge({ origin }: {
7
+ readonly origin: EditorOrigin;
8
+ }): ReactNode;
9
+ export declare function EditorModeSwitch({ testIdPrefix, mode, onMode, }: {
10
+ readonly testIdPrefix: string;
11
+ readonly mode: EditorMode;
12
+ readonly onMode: (mode: EditorMode) => void;
13
+ }): ReactNode;
14
+ export declare function EditorLocaleSwitch({ testIdPrefix, locales, locale, onLocale, }: {
15
+ readonly testIdPrefix: string;
16
+ readonly locales: readonly string[];
17
+ readonly locale: string;
18
+ readonly onLocale: (locale: string) => void;
19
+ }): ReactNode;
20
+ export type StoredVersion = {
21
+ readonly status: string;
22
+ readonly version: number;
23
+ };
24
+ export type EditorSaveActions = {
25
+ readonly busy: boolean;
26
+ readonly canSave: boolean;
27
+ readonly canPublish: boolean;
28
+ readonly onSave: () => void;
29
+ readonly onPublish: () => void;
30
+ };
31
+ export declare function EditorHeader({ title, stored, actions, children, }: {
32
+ readonly title: string;
33
+ readonly stored: StoredVersion | null;
34
+ readonly actions: EditorSaveActions;
35
+ /** View controls left of the save actions (mode or kind switch). */
36
+ readonly children: ReactNode;
37
+ }): ReactNode;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // @runtime client
3
+ import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
4
+ import { ModeSwitch, StatusBadge } from "@cosmicdrift/kumiko-renderer-web";
5
+ import { asRowStatus, statusLabel, statusTone } from "./status-label.js";
6
+ const ORIGIN_LABEL = {
7
+ system: "documentDesigner.origin.system",
8
+ override: "documentDesigner.origin.override",
9
+ tenant: "documentDesigner.source.tenant",
10
+ };
11
+ export function originOf(isSystemRow, hasSystemVersion) {
12
+ return isSystemRow ? "system" : hasSystemVersion ? "override" : "tenant";
13
+ }
14
+ export function OriginBadge({ origin }) {
15
+ const t = useTranslation();
16
+ return (_jsx(StatusBadge, { tone: origin === "system" ? "muted" : "accent", testId: "document-designer-editor-origin", children: t(ORIGIN_LABEL[origin]) }));
17
+ }
18
+ export function EditorModeSwitch({ testIdPrefix, mode, onMode, }) {
19
+ const t = useTranslation();
20
+ return (_jsx(ModeSwitch, { value: mode, onChange: onMode, ariaLabel: t("documentDesigner.mail.header.modeSwitch"), testId: `${testIdPrefix}-mode-switch`, options: [
21
+ { value: "edit", label: t("documentDesigner.mail.header.edit") },
22
+ { value: "preview", label: t("documentDesigner.mail.header.preview") },
23
+ ] }));
24
+ }
25
+ export function EditorLocaleSwitch({ testIdPrefix, locales, locale, onLocale, }) {
26
+ const t = useTranslation();
27
+ return (_jsx(ModeSwitch, { value: locale, onChange: onLocale, ariaLabel: t("documentDesigner.mail.header.localeSwitch"), testId: `${testIdPrefix}-locale-switch`, options: locales.map((code) => ({ value: code, label: code })) }));
28
+ }
29
+ function StoredStatus({ stored }) {
30
+ const t = useTranslation();
31
+ const status = asRowStatus(stored.status);
32
+ return (_jsx(StatusBadge, { tone: statusTone(status), testId: "document-designer-editor-status", children: statusLabel(t, status, stored.version) }));
33
+ }
34
+ // Title, status and the save/publish actions live in the shell header. The origin badge, the
35
+ // locale switch and the secondary action sit in the info bar below: at 1280px next to the
36
+ // sidebar, assistant and theme toggle the header has no room for them and the title would clip.
37
+ export function EditorHeader({ title, stored, actions, children, }) {
38
+ const t = useTranslation();
39
+ const { Button, PageHeader } = usePrimitives();
40
+ if (PageHeader === undefined)
41
+ return null;
42
+ return (_jsx(PageHeader, { title: title, status: stored !== null && _jsx(StoredStatus, { stored: stored }), actions: _jsxs("span", { className: "flex items-center gap-2 [&_button]:px-2.5 [&_button]:text-sm", children: [children, _jsx(Button, { variant: "secondary", size: "sm", disabled: !actions.canSave, loading: actions.busy, onClick: actions.onSave, testId: "document-designer-header-save", children: t("documentDesigner.editor.save") }), _jsx(Button, { size: "sm", disabled: !actions.canPublish, onClick: actions.onPublish, testId: "document-designer-header-publish", children: t("documentDesigner.editor.publish") })] }) }));
43
+ }
@@ -0,0 +1,40 @@
1
+ import type { ReactNode } from "react";
2
+ import { type EditorOrigin } from "./editor-header.js";
3
+ export type InfoBarTone = "active" | "muted" | "warn";
4
+ export type FooterTone = "bad" | "warn" | "ok";
5
+ export declare function EditorFrame({ testId, children, }: {
6
+ readonly testId: string;
7
+ readonly children: ReactNode;
8
+ }): ReactNode;
9
+ export declare function EditorInfoBar({ tone, testId, origin, controls, links, overlays, children, }: {
10
+ readonly tone: InfoBarTone;
11
+ readonly testId: string;
12
+ readonly origin?: EditorOrigin | null;
13
+ /** Right side, before the links: locale switch and the editor's secondary action. */
14
+ readonly controls?: ReactNode;
15
+ readonly links?: ReactNode;
16
+ readonly overlays?: ReactNode;
17
+ readonly children: ReactNode;
18
+ }): ReactNode;
19
+ export declare function EditorBody({ left, center, right, testId, }: {
20
+ readonly left?: ReactNode;
21
+ readonly center: ReactNode;
22
+ readonly right: ReactNode;
23
+ readonly testId?: string;
24
+ }): ReactNode;
25
+ export declare function EditorFooter({ testIdPrefix, message, saveError, modifiedAt, dirty, busy, canSave, canPublish, onDiscard, onSave, onPublish, }: {
26
+ readonly testIdPrefix: string;
27
+ readonly message: {
28
+ readonly tone: FooterTone;
29
+ readonly text: string;
30
+ } | null;
31
+ readonly saveError: string | null;
32
+ readonly modifiedAt: string | null;
33
+ readonly dirty: boolean;
34
+ readonly busy: boolean;
35
+ readonly canSave: boolean;
36
+ readonly canPublish: boolean;
37
+ readonly onDiscard: () => void;
38
+ readonly onSave: () => void;
39
+ readonly onPublish: () => void;
40
+ }): ReactNode;
@@ -0,0 +1,36 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // @runtime client
3
+ import { usePrimitives, useTranslation } from "@cosmicdrift/kumiko-renderer";
4
+ import { cn } from "@cosmicdrift/kumiko-renderer-web";
5
+ import { OriginBadge } from "./editor-header.js";
6
+ import { formatRelativeWhen } from "./relative-time.js";
7
+ const INFO_BAR_TONE = {
8
+ active: "bg-primary/10",
9
+ muted: "bg-muted",
10
+ warn: "bg-status-warn-surface",
11
+ };
12
+ const FOOTER_TONE = {
13
+ ok: { text: "text-status-ok", glyph: "✓" },
14
+ warn: { text: "text-status-warn", glyph: "!" },
15
+ bad: { text: "text-status-bad", glyph: "!" },
16
+ };
17
+ // Height below the shell header: the rails and the center scroll on their own.
18
+ export function EditorFrame({ testId, children, }) {
19
+ return (_jsx("div", { className: "flex h-[calc(100svh-var(--shell-header-height))] min-h-[600px] flex-col", "data-testid": testId, children: children }));
20
+ }
21
+ export function EditorInfoBar({ tone, testId, origin, controls, links, overlays, children, }) {
22
+ return (_jsxs(_Fragment, { children: [_jsxs("div", { className: cn("flex items-start gap-4 border-b px-6 py-2 text-sm", INFO_BAR_TONE[tone]), "data-testid": testId, "data-variant": tone === "warn" ? "warn" : undefined, children: [_jsxs("span", { className: "min-w-0 flex-1", children: [origin != null && _jsx(OriginBadge, { origin: origin }), " ", children] }), controls !== undefined && (_jsx("div", { className: "flex shrink-0 items-center gap-2", children: controls })), links !== undefined && _jsx("div", { className: "flex shrink-0 items-center gap-4", children: links })] }), overlays] }));
23
+ }
24
+ export function EditorBody({ left, center, right, testId, }) {
25
+ return (_jsxs("div", { className: cn("grid min-h-0 flex-1", left === undefined
26
+ ? "grid-cols-[minmax(0,1fr)_280px]"
27
+ : "grid-cols-[240px_minmax(0,1fr)_280px]"), "data-testid": testId, children: [left !== undefined && (_jsx("aside", { className: "min-h-0 overflow-y-auto border-r bg-background", children: left })), _jsx("div", { className: "flex min-h-0 min-w-0 flex-col overflow-hidden bg-muted", children: center }), _jsx("aside", { className: "min-h-0 overflow-y-auto border-l bg-background", children: right })] }));
28
+ }
29
+ export function EditorFooter({ testIdPrefix, message, saveError, modifiedAt, dirty, busy, canSave, canPublish, onDiscard, onSave, onPublish, }) {
30
+ const t = useTranslation();
31
+ const { Banner, Button, Text } = usePrimitives();
32
+ const tone = message === null ? null : FOOTER_TONE[message.tone];
33
+ return (_jsxs("div", { className: "flex items-center gap-4 border-t bg-background px-6 py-3", "data-testid": `${testIdPrefix}-footer`, children: [_jsxs("div", { className: "min-w-0 flex-1 text-sm", children: [saveError !== null ? (_jsx(Banner, { variant: "error", testId: `${testIdPrefix}-save-error`, children: saveError })) : (_jsx("span", { className: cn(tone === null ? "text-muted-foreground" : tone.text), "data-testid": `${testIdPrefix}-footer-message`, "data-tone": message?.tone, children: message === null
34
+ ? t("documentDesigner.editor.footer.checking")
35
+ : `${tone?.glyph ?? ""} ${message.text}` })), modifiedAt !== null && (_jsxs(_Fragment, { children: [" ", _jsx(Text, { variant: "muted", testId: `${testIdPrefix}-saved-at`, children: t("documentDesigner.mail.footer.savedAt", { when: formatRelativeWhen(modifiedAt) }) })] }))] }), _jsxs("div", { className: "flex shrink-0 items-center gap-3", children: [_jsx(Button, { variant: "ghost", disabled: !dirty, onClick: onDiscard, testId: "document-designer-discard", children: t("documentDesigner.editor.discard") }), _jsx(Button, { variant: "secondary", disabled: !canSave, loading: busy, onClick: onSave, testId: "document-designer-save", children: t("documentDesigner.editor.save") }), _jsx(Button, { disabled: !canPublish, onClick: onPublish, testId: "document-designer-publish", children: t("documentDesigner.editor.publish") })] })] }));
36
+ }