@starterlib/ui 0.7.2 → 0.9.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 (55) hide show
  1. package/LICENCES-TIERCES.md +236 -0
  2. package/README.md +163 -56
  3. package/assets/icones/catalogue.json +3296 -0
  4. package/assets/icones/sprite.svg +235 -35
  5. package/fesm2022/starterlib-ui-arbre.mjs +475 -0
  6. package/fesm2022/starterlib-ui-arbre.mjs.map +1 -0
  7. package/fesm2022/starterlib-ui-donnees.mjs +3561 -0
  8. package/fesm2022/starterlib-ui-donnees.mjs.map +1 -0
  9. package/fesm2022/starterlib-ui-formulaires.mjs +3186 -442
  10. package/fesm2022/starterlib-ui-formulaires.mjs.map +1 -1
  11. package/fesm2022/starterlib-ui-libelles-en.mjs +383 -0
  12. package/fesm2022/starterlib-ui-libelles-en.mjs.map +1 -0
  13. package/fesm2022/starterlib-ui-listes.mjs +5367 -0
  14. package/fesm2022/starterlib-ui-listes.mjs.map +1 -0
  15. package/fesm2022/starterlib-ui-messagerie.mjs +737 -0
  16. package/fesm2022/starterlib-ui-messagerie.mjs.map +1 -0
  17. package/fesm2022/starterlib-ui-navigation.mjs +509 -0
  18. package/fesm2022/starterlib-ui-navigation.mjs.map +1 -0
  19. package/fesm2022/starterlib-ui-onglets.mjs +371 -0
  20. package/fesm2022/starterlib-ui-onglets.mjs.map +1 -0
  21. package/fesm2022/starterlib-ui-parcours.mjs +2449 -0
  22. package/fesm2022/starterlib-ui-parcours.mjs.map +1 -0
  23. package/fesm2022/starterlib-ui-qr.mjs +907 -0
  24. package/fesm2022/starterlib-ui-qr.mjs.map +1 -0
  25. package/fesm2022/starterlib-ui-saisie.mjs +8609 -0
  26. package/fesm2022/starterlib-ui-saisie.mjs.map +1 -0
  27. package/fesm2022/starterlib-ui-selection.mjs +1341 -0
  28. package/fesm2022/starterlib-ui-selection.mjs.map +1 -0
  29. package/fesm2022/starterlib-ui-sens.mjs +59 -0
  30. package/fesm2022/starterlib-ui-sens.mjs.map +1 -0
  31. package/fesm2022/starterlib-ui-surfaces.mjs +5140 -1387
  32. package/fesm2022/starterlib-ui-surfaces.mjs.map +1 -1
  33. package/fesm2022/starterlib-ui.mjs +10729 -5689
  34. package/fesm2022/starterlib-ui.mjs.map +1 -1
  35. package/package.json +58 -17
  36. package/styles/amorce.css +69 -0
  37. package/styles/couches.css +178 -0
  38. package/types/starterlib-ui-arbre.d.ts +225 -0
  39. package/types/starterlib-ui-donnees.d.ts +1489 -0
  40. package/types/starterlib-ui-formulaires.d.ts +1174 -138
  41. package/types/starterlib-ui-libelles-en.d.ts +5 -0
  42. package/types/starterlib-ui-listes.d.ts +2487 -0
  43. package/types/starterlib-ui-messagerie.d.ts +317 -0
  44. package/types/starterlib-ui-navigation.d.ts +242 -0
  45. package/types/starterlib-ui-onglets.d.ts +212 -0
  46. package/types/starterlib-ui-parcours.d.ts +916 -0
  47. package/types/starterlib-ui-qr.d.ts +105 -0
  48. package/types/starterlib-ui-saisie.d.ts +3806 -0
  49. package/types/starterlib-ui-selection.d.ts +488 -0
  50. package/types/starterlib-ui-sens.d.ts +44 -0
  51. package/types/starterlib-ui-surfaces.d.ts +1899 -510
  52. package/types/starterlib-ui.d.ts +4731 -2678
  53. package/fesm2022/starterlib-ui-interactions.mjs +0 -598
  54. package/fesm2022/starterlib-ui-interactions.mjs.map +0 -1
  55. package/types/starterlib-ui-interactions.d.ts +0 -316
@@ -0,0 +1,737 @@
1
+ import * as i0 from "@angular/core";
2
+ import { ChangeDetectionStrategy, Component, DOCUMENT, DestroyRef, ElementRef, InjectionToken, Injector, afterNextRender, booleanAttribute, computed, effect, inject, input, output, signal, untracked, viewChild } from "@angular/core";
3
+ import { AnnonceLocale, FUSEAU_PAR_DEFAUT, ST_LOCALE, StButton, StFormActions, StIcon, StSpinner, catalogueDuPointDEntree } from "@starterlib/ui";
4
+ import { StPerson } from "@starterlib/ui/donnees";
5
+ import { StAttachment } from "@starterlib/ui/listes";
6
+ import { lireInstant, sansCommandesDeDirection } from "@starterlib/util";
7
+ import { NgTemplateOutlet } from "@angular/common";
8
+ import { delai } from "@starterlib/tokens";
9
+ import { StFileUpload, StTextarea } from "@starterlib/ui/saisie";
10
+ const LIBELLES_MESSAGERIE_FR = {
11
+ afficherLesMessagesPrecedents: "Afficher les messages précédents",
12
+ messagesPrecedentsAffiches: (nombre) => nombre > 1 ? `${String(nombre)} messages pr\u00e9c\u00e9dents affich\u00e9s` : `${String(nombre)} message pr\u00e9c\u00e9dent affich\u00e9`,
13
+ messageDe: (auteur, quand) => `${auteur}, ${quand}`,
14
+ noteInterne: "Note interne",
15
+ envoiEnCours: "Envoi en cours",
16
+ envoye: "Envoyé",
17
+ lu: "Lu",
18
+ echecDeLEnvoi: "Échec de l’envoi",
19
+ reessayer: "Réessayer",
20
+ reessayerLEnvoiDu: (quand) => `R\u00e9essayer l\u2019envoi du message du ${quand}`,
21
+ piecesJointes: "Pièces jointes",
22
+ votreMessage: "Votre message",
23
+ joindreDesFichiers: "Joindre des fichiers",
24
+ envoyer: "Envoyer",
25
+ raccourciDEnvoi: "Ctrl+Entrée pour envoyer."
26
+ };
27
+ const LIBELLES_MESSAGERIE_EN = {
28
+ afficherLesMessagesPrecedents: "Show earlier messages",
29
+ messagesPrecedentsAffiches: (nombre) => `${String(nombre)} earlier message${nombre > 1 ? "s" : ""} shown`,
30
+ messageDe: (auteur, quand) => `${auteur}, ${quand}`,
31
+ noteInterne: "Internal note",
32
+ envoiEnCours: "Sending",
33
+ envoye: "Sent",
34
+ lu: "Read",
35
+ echecDeLEnvoi: "Not sent",
36
+ reessayer: "Retry",
37
+ reessayerLEnvoiDu: (quand) => `Retry sending the message of ${quand}`,
38
+ piecesJointes: "Attachments",
39
+ votreMessage: "Your message",
40
+ joindreDesFichiers: "Attach files",
41
+ envoyer: "Send",
42
+ raccourciDEnvoi: "Ctrl+Enter to send."
43
+ };
44
+ const ST_LIBELLES_MESSAGERIE = new InjectionToken("ST_LIBELLES_MESSAGERIE", {
45
+ providedIn: "root",
46
+ factory: () => ({
47
+ fr: LIBELLES_MESSAGERIE_FR,
48
+ en: LIBELLES_MESSAGERIE_EN
49
+ })
50
+ });
51
+ function fournirLibellesMessagerie(catalogues) {
52
+ return {
53
+ provide: ST_LIBELLES_MESSAGERIE,
54
+ useValue: {
55
+ fr: LIBELLES_MESSAGERIE_FR,
56
+ en: LIBELLES_MESSAGERIE_EN,
57
+ ...catalogues
58
+ }
59
+ };
60
+ }
61
+ function libellesDeLaMessagerie() {
62
+ const catalogue = catalogueDeLaMessagerie();
63
+ return computed(() => catalogue().libelles);
64
+ }
65
+ function catalogueDeLaMessagerie() {
66
+ return catalogueDuPointDEntree("@starterlib/ui/messagerie", inject(ST_LIBELLES_MESSAGERIE), LIBELLES_MESSAGERIE_FR, "fournirLibellesMessagerie");
67
+ }
68
+ var StMessage = class StMessage {
69
+ locale = inject(ST_LOCALE);
70
+ fuseau = inject(FUSEAU_PAR_DEFAUT);
71
+ element = inject(ElementRef);
72
+ document = inject(DOCUMENT);
73
+ injecteur = inject(Injector);
74
+ article = viewChild.required("article", ...ngDevMode ? [{ debugName: "article" }] : /* istanbul ignore next */ []);
75
+ catalogue = catalogueDeLaMessagerie();
76
+ libelles = computed(() => this.catalogue().libelles, ...ngDevMode ? [{ debugName: "libelles" }] : /* istanbul ignore next */ []);
77
+ langueDeRepli = computed(() => this.catalogue().langueDeRepli, ...ngDevMode ? [{ debugName: "langueDeRepli" }] : /* istanbul ignore next */ []);
78
+ message = input.required(...ngDevMode ? [{ debugName: "message" }] : /* istanbul ignore next */ []);
79
+ reessai = output();
80
+ nature = computed(() => this.message().nature ?? "ordinaire", ...ngDevMode ? [{ debugName: "nature" }] : /* istanbul ignore next */ []);
81
+ statut = computed(() => this.message().statut ?? null, ...ngDevMode ? [{ debugName: "statut" }] : /* istanbul ignore next */ []);
82
+ repriseDemandee = signal(false, ...ngDevMode ? [{ debugName: "repriseDemandee" }] : /* istanbul ignore next */ []);
83
+ repriseVisible = computed(() => {
84
+ const statut = this.statut();
85
+ return statut === "echec" || statut === "envoi" && this.repriseDemandee();
86
+ }, ...ngDevMode ? [{ debugName: "repriseVisible" }] : /* istanbul ignore next */ []);
87
+ constructor() {
88
+ effect(() => {
89
+ const statut = this.statut();
90
+ untracked(() => {
91
+ if (statut !== "envoi" && statut !== "echec") this.repriseDemandee.set(false);
92
+ if (!this.element.nativeElement.contains(this.document.activeElement)) return;
93
+ afterNextRender(() => {
94
+ const actif = this.document.activeElement;
95
+ if (actif === null || actif === this.document.body || !actif.isConnected) this.article().nativeElement.focus();
96
+ }, { injector: this.injecteur });
97
+ });
98
+ });
99
+ }
100
+ instant = computed(() => lireInstant(this.message().envoyeLe, this.fuseau), ...ngDevMode ? [{ debugName: "instant" }] : /* istanbul ignore next */ []);
101
+ heure = computed(() => this.formater({
102
+ hour: "2-digit",
103
+ minute: "2-digit"
104
+ }), ...ngDevMode ? [{ debugName: "heure" }] : /* istanbul ignore next */ []);
105
+ quand = computed(() => this.formater({
106
+ day: "2-digit",
107
+ month: "2-digit",
108
+ hour: "2-digit",
109
+ minute: "2-digit"
110
+ }), ...ngDevMode ? [{ debugName: "quand" }] : /* istanbul ignore next */ []);
111
+ nom = computed(() => this.libelles().messageDe(sansCommandesDeDirection(this.message().auteur), this.quand()), ...ngDevMode ? [{ debugName: "nom" }] : /* istanbul ignore next */ []);
112
+ paragraphes = computed(() => sansCommandesDeDirection(this.message().corps).split(/\n[ \t]*\n/).map((paragraphe) => paragraphe.trim()).filter((paragraphe) => paragraphe !== ""), ...ngDevMode ? [{ debugName: "paragraphes" }] : /* istanbul ignore next */ []);
113
+ pieces = computed(() => this.message().piecesJointes ?? [], ...ngDevMode ? [{ debugName: "pieces" }] : /* istanbul ignore next */ []);
114
+ reprendre() {
115
+ this.repriseDemandee.set(true);
116
+ this.reessai.emit(this.message().id);
117
+ }
118
+ formater(options) {
119
+ const instant = this.instant();
120
+ if (instant === null) return this.message().envoyeLe;
121
+ return new Intl.DateTimeFormat(this.locale(), {
122
+ ...options,
123
+ timeZone: this.fuseau
124
+ }).format(instant);
125
+ }
126
+ static ɵfac = i0.ɵɵngDeclareFactory({
127
+ minVersion: "12.0.0",
128
+ version: "22.2.0",
129
+ ngImport: i0,
130
+ type: StMessage,
131
+ deps: [],
132
+ target: i0.ɵɵFactoryTarget.Component
133
+ });
134
+ static ɵcmp = i0.ɵɵngDeclareComponent({
135
+ minVersion: "17.0.0",
136
+ version: "22.2.0",
137
+ type: StMessage,
138
+ isStandalone: true,
139
+ selector: "st-message",
140
+ inputs: { message: {
141
+ classPropertyName: "message",
142
+ publicName: "message",
143
+ isSignal: true,
144
+ isRequired: true,
145
+ transformFunction: null
146
+ } },
147
+ outputs: { reessai: "reessai" },
148
+ host: {
149
+ properties: {
150
+ "attr.data-nature": "nature()",
151
+ "attr.data-soi": "message().soi === true ? \"\" : null"
152
+ },
153
+ classAttribute: "st-message"
154
+ },
155
+ viewQueries: [{
156
+ propertyName: "article",
157
+ first: true,
158
+ predicate: ["article"],
159
+ descendants: true,
160
+ isSignal: true
161
+ }],
162
+ ngImport: i0,
163
+ template: "<!-- tabindex -1 : l'article recoit le focus quand le bouton qui l'avait part avec le statut (la\n reprise aboutie), hors tabulation (audit UI du 2026-09-27, D-24). -->\n<article #article class=\"st-message__article\" tabindex=\"-1\" [attr.aria-label]=\"nom()\">\n @if (nature() === 'systeme') {\n <!-- Un evenement du dossier : centre, sans auteur ; son heure le suit. -->\n <p class=\"st-message__systeme\">\n @for (paragraphe of paragraphes(); track $index) {\n <span class=\"st-message__ligne\" dir=\"auto\">{{ paragraphe }}</span>\n }\n <time class=\"st-message__heure\" [attr.datetime]=\"message().envoyeLe\">{{ heure() }}</time>\n </p>\n } @else {\n <header class=\"st-message__entete\">\n <st-person\n taille=\"sm\"\n [nom]=\"message().auteur\"\n [precision]=\"message().precision ?? null\"\n [sourceImage]=\"message().avatar ?? null\"\n [soi]=\"message().soi === true\"\n />\n <time class=\"st-message__heure\" [attr.datetime]=\"message().envoyeLe\">{{ heure() }}</time>\n <!-- `lang` : sur ce que le catalogue ecrit seul, quand il retombe sur le francais (D-29). -->\n @if (nature() === 'interne') {\n <span class=\"st-message__interne\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"cadenas\" taille=\"sm\" />\n {{ libelles().noteInterne }}\n </span>\n }\n </header>\n\n <!-- Texte brut interpole : aucun HTML n'entre ni ne sort (SEC-6). -->\n <div class=\"st-message__corps\">\n @for (paragraphe of paragraphes(); track $index) {\n <p class=\"st-message__paragraphe\" dir=\"auto\">{{ paragraphe }}</p>\n }\n </div>\n\n @if (pieces().length > 0) {\n <ul class=\"st-message__pieces\" role=\"list\" [attr.aria-label]=\"libelles().piecesJointes\">\n @for (piece of pieces(); track $index) {\n <li>\n <st-attachment\n [nom]=\"piece.nom\"\n [type]=\"piece.type\"\n [taille]=\"piece.taille ?? null\"\n [lien]=\"piece.lien ?? null\"\n />\n </li>\n }\n </ul>\n }\n\n <!-- Un statut ne parle pas (`aria-live=\"off\"`, D-19) : dans le fil vivant, chaque passage\n serait une insertion lue, et « Lu » se repeterait message apres message. L'echec seul\n parle, par le fil. -->\n @switch (statut()) {\n @case ('envoi') {\n @if (!repriseVisible()) {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <!-- Muet : le texte qui le suit dit deja l'envoi. -->\n <st-spinner taille=\"sm\" aria-hidden=\"true\" />\n {{ libelles().envoiEnCours }}\n </p>\n }\n }\n @case ('envoye') {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"coche\" taille=\"sm\" />\n {{ libelles().envoye }}\n </p>\n }\n @case ('lu') {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"double-coche\" taille=\"sm\" />\n {{ libelles().lu }}\n </p>\n }\n }\n @if (repriseVisible()) {\n <!-- L'echec, puis la reprise qu'il a lancee : le MEME bouton garde le focus et tourne\n pendant l'envoi (D-24, modele de st-file-upload) ; la reprise ne parle pas. Tout vient\n du catalogue, le nom du bouton compris : sa date n'est que des chiffres. -->\n <p\n class=\"st-message__statut\"\n [attr.lang]=\"langueDeRepli()\"\n [attr.data-echec]=\"statut() === 'echec' ? '' : null\"\n [attr.aria-live]=\"statut() === 'echec' ? null : 'off'\"\n >\n @if (statut() === 'echec') {\n <st-icon nom=\"cercle-alerte\" taille=\"sm\" />\n {{ libelles().echecDeLEnvoi }}\n } @else {\n {{ libelles().envoiEnCours }}\n }\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"statut() === 'envoi'\"\n [attr.aria-label]=\"libelles().reessayerLEnvoiDu(quand())\"\n (click)=\"reprendre()\"\n >\n {{ libelles().reessayer }}\n </button>\n </p>\n }\n }\n</article>\n",
164
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;min-inline-size:0}.st-message__article:focus-visible{outline:var(--st-focus-epaisseur) solid var(--st-couleur-anneau-focus);outline-offset:var(--st-focus-decalage);box-shadow:0 0 0 var(--st-focus-lisere) var(--st-couleur-lisere-focus)}.st-message__article{display:flex;flex-direction:column;gap:var(--st-espacement-2);max-inline-size:min(100%,40rem);padding:var(--st-espacement-3) var(--st-espacement-4);color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:var(--st-epaisseur-fine) solid var(--st-couleur-bordure);border-radius:var(--st-rayon-lg)}:host([data-soi]) .st-message__article{margin-inline-start:auto;background:var(--st-couleur-surface-conteneur-bas)}:host([data-nature=interne]) .st-message__article{background:var(--st-couleur-avertissement-discret);border-style:dashed}:host([data-nature=systeme]) .st-message__article{align-items:center;max-inline-size:100%;padding-block:var(--st-espacement-1);background:transparent;border:0}.st-message__entete{display:flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-3);align-items:center}.st-message__heure{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);font-variant-numeric:var(--st-chiffres-alignes);color:var(--st-couleur-texte-discret)}.st-message__interne{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:inline-flex;gap:var(--st-espacement-1);align-items:center;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-avertissement-discret)}.st-message__corps{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-message__paragraphe{font-size:var(--st-taille-md);line-height:var(--st-interligne-md);font-weight:var(--st-graisse-normale);letter-spacing:var(--st-interlettrage-normal);margin:0;overflow-wrap:anywhere;white-space:pre-line}.st-message__pieces{display:flex;flex-direction:column;gap:var(--st-espacement-2);padding:0;margin:0;list-style:none}.st-message__statut{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:inline-flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-2);align-items:center;align-self:flex-end;margin:0;color:var(--st-couleur-texte-discret)}.st-message__statut[data-echec]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-danger)}.st-message__systeme{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-2);justify-content:center;margin:0;color:var(--st-couleur-texte-discret);text-align:center}@media(forced-colors:active){.st-message__article{border-color:CanvasText}}\n"],
165
+ dependencies: [
166
+ {
167
+ kind: "component",
168
+ type: StAttachment,
169
+ selector: "st-attachment",
170
+ inputs: [
171
+ "nom",
172
+ "type",
173
+ "taille",
174
+ "lien",
175
+ "date",
176
+ "nouvelOnglet",
177
+ "enAttente"
178
+ ],
179
+ outputs: ["telechargement"]
180
+ },
181
+ {
182
+ kind: "component",
183
+ type: StButton,
184
+ selector: "button[stButton]",
185
+ inputs: [
186
+ "variante",
187
+ "taille",
188
+ "pleineLargeur",
189
+ "iconeAvant",
190
+ "iconeApres",
191
+ "chargement",
192
+ "indisponible",
193
+ "raisonIndisponible"
194
+ ]
195
+ },
196
+ {
197
+ kind: "component",
198
+ type: StIcon,
199
+ selector: "st-icon",
200
+ inputs: [
201
+ "icone",
202
+ "nom",
203
+ "variante",
204
+ "sprite",
205
+ "nomMetier",
206
+ "taille",
207
+ "ton",
208
+ "etiquette",
209
+ "miroir"
210
+ ]
211
+ },
212
+ {
213
+ kind: "component",
214
+ type: StPerson,
215
+ selector: "st-person",
216
+ inputs: [
217
+ "nom",
218
+ "precision",
219
+ "sourceImage",
220
+ "lien",
221
+ "taille",
222
+ "disposition",
223
+ "ton",
224
+ "soi"
225
+ ]
226
+ },
227
+ {
228
+ kind: "component",
229
+ type: StSpinner,
230
+ selector: "st-spinner",
231
+ inputs: [
232
+ "taille",
233
+ "ton",
234
+ "etiquette",
235
+ "icone"
236
+ ]
237
+ }
238
+ ],
239
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
240
+ });
241
+ };
242
+ i0.ɵɵngDeclareClassMetadata({
243
+ minVersion: "12.0.0",
244
+ version: "22.2.0",
245
+ ngImport: i0,
246
+ type: StMessage,
247
+ decorators: [{
248
+ type: Component,
249
+ args: [{
250
+ selector: "st-message",
251
+ changeDetection: ChangeDetectionStrategy.OnPush,
252
+ imports: [
253
+ StAttachment,
254
+ StButton,
255
+ StIcon,
256
+ StPerson,
257
+ StSpinner
258
+ ],
259
+ host: {
260
+ class: "st-message",
261
+ "[attr.data-nature]": "nature()",
262
+ "[attr.data-soi]": "message().soi === true ? \"\" : null"
263
+ },
264
+ template: "<!-- tabindex -1 : l'article recoit le focus quand le bouton qui l'avait part avec le statut (la\n reprise aboutie), hors tabulation (audit UI du 2026-09-27, D-24). -->\n<article #article class=\"st-message__article\" tabindex=\"-1\" [attr.aria-label]=\"nom()\">\n @if (nature() === 'systeme') {\n <!-- Un evenement du dossier : centre, sans auteur ; son heure le suit. -->\n <p class=\"st-message__systeme\">\n @for (paragraphe of paragraphes(); track $index) {\n <span class=\"st-message__ligne\" dir=\"auto\">{{ paragraphe }}</span>\n }\n <time class=\"st-message__heure\" [attr.datetime]=\"message().envoyeLe\">{{ heure() }}</time>\n </p>\n } @else {\n <header class=\"st-message__entete\">\n <st-person\n taille=\"sm\"\n [nom]=\"message().auteur\"\n [precision]=\"message().precision ?? null\"\n [sourceImage]=\"message().avatar ?? null\"\n [soi]=\"message().soi === true\"\n />\n <time class=\"st-message__heure\" [attr.datetime]=\"message().envoyeLe\">{{ heure() }}</time>\n <!-- `lang` : sur ce que le catalogue ecrit seul, quand il retombe sur le francais (D-29). -->\n @if (nature() === 'interne') {\n <span class=\"st-message__interne\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"cadenas\" taille=\"sm\" />\n {{ libelles().noteInterne }}\n </span>\n }\n </header>\n\n <!-- Texte brut interpole : aucun HTML n'entre ni ne sort (SEC-6). -->\n <div class=\"st-message__corps\">\n @for (paragraphe of paragraphes(); track $index) {\n <p class=\"st-message__paragraphe\" dir=\"auto\">{{ paragraphe }}</p>\n }\n </div>\n\n @if (pieces().length > 0) {\n <ul class=\"st-message__pieces\" role=\"list\" [attr.aria-label]=\"libelles().piecesJointes\">\n @for (piece of pieces(); track $index) {\n <li>\n <st-attachment\n [nom]=\"piece.nom\"\n [type]=\"piece.type\"\n [taille]=\"piece.taille ?? null\"\n [lien]=\"piece.lien ?? null\"\n />\n </li>\n }\n </ul>\n }\n\n <!-- Un statut ne parle pas (`aria-live=\"off\"`, D-19) : dans le fil vivant, chaque passage\n serait une insertion lue, et « Lu » se repeterait message apres message. L'echec seul\n parle, par le fil. -->\n @switch (statut()) {\n @case ('envoi') {\n @if (!repriseVisible()) {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <!-- Muet : le texte qui le suit dit deja l'envoi. -->\n <st-spinner taille=\"sm\" aria-hidden=\"true\" />\n {{ libelles().envoiEnCours }}\n </p>\n }\n }\n @case ('envoye') {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"coche\" taille=\"sm\" />\n {{ libelles().envoye }}\n </p>\n }\n @case ('lu') {\n <p class=\"st-message__statut\" aria-live=\"off\" [attr.lang]=\"langueDeRepli()\">\n <st-icon nom=\"double-coche\" taille=\"sm\" />\n {{ libelles().lu }}\n </p>\n }\n }\n @if (repriseVisible()) {\n <!-- L'echec, puis la reprise qu'il a lancee : le MEME bouton garde le focus et tourne\n pendant l'envoi (D-24, modele de st-file-upload) ; la reprise ne parle pas. Tout vient\n du catalogue, le nom du bouton compris : sa date n'est que des chiffres. -->\n <p\n class=\"st-message__statut\"\n [attr.lang]=\"langueDeRepli()\"\n [attr.data-echec]=\"statut() === 'echec' ? '' : null\"\n [attr.aria-live]=\"statut() === 'echec' ? null : 'off'\"\n >\n @if (statut() === 'echec') {\n <st-icon nom=\"cercle-alerte\" taille=\"sm\" />\n {{ libelles().echecDeLEnvoi }}\n } @else {\n {{ libelles().envoiEnCours }}\n }\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [chargement]=\"statut() === 'envoi'\"\n [attr.aria-label]=\"libelles().reessayerLEnvoiDu(quand())\"\n (click)=\"reprendre()\"\n >\n {{ libelles().reessayer }}\n </button>\n </p>\n }\n }\n</article>\n",
265
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;min-inline-size:0}.st-message__article:focus-visible{outline:var(--st-focus-epaisseur) solid var(--st-couleur-anneau-focus);outline-offset:var(--st-focus-decalage);box-shadow:0 0 0 var(--st-focus-lisere) var(--st-couleur-lisere-focus)}.st-message__article{display:flex;flex-direction:column;gap:var(--st-espacement-2);max-inline-size:min(100%,40rem);padding:var(--st-espacement-3) var(--st-espacement-4);color:var(--st-couleur-texte);background:var(--st-couleur-surface);border:var(--st-epaisseur-fine) solid var(--st-couleur-bordure);border-radius:var(--st-rayon-lg)}:host([data-soi]) .st-message__article{margin-inline-start:auto;background:var(--st-couleur-surface-conteneur-bas)}:host([data-nature=interne]) .st-message__article{background:var(--st-couleur-avertissement-discret);border-style:dashed}:host([data-nature=systeme]) .st-message__article{align-items:center;max-inline-size:100%;padding-block:var(--st-espacement-1);background:transparent;border:0}.st-message__entete{display:flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-3);align-items:center}.st-message__heure{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);font-variant-numeric:var(--st-chiffres-alignes);color:var(--st-couleur-texte-discret)}.st-message__interne{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:inline-flex;gap:var(--st-espacement-1);align-items:center;font-weight:var(--st-graisse-semi);color:var(--st-couleur-sur-avertissement-discret)}.st-message__corps{display:flex;flex-direction:column;gap:var(--st-espacement-2)}.st-message__paragraphe{font-size:var(--st-taille-md);line-height:var(--st-interligne-md);font-weight:var(--st-graisse-normale);letter-spacing:var(--st-interlettrage-normal);margin:0;overflow-wrap:anywhere;white-space:pre-line}.st-message__pieces{display:flex;flex-direction:column;gap:var(--st-espacement-2);padding:0;margin:0;list-style:none}.st-message__statut{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:inline-flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-2);align-items:center;align-self:flex-end;margin:0;color:var(--st-couleur-texte-discret)}.st-message__statut[data-echec]{font-weight:var(--st-graisse-semi);color:var(--st-couleur-danger)}.st-message__systeme{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:flex;flex-wrap:wrap;gap:var(--st-espacement-1) var(--st-espacement-2);justify-content:center;margin:0;color:var(--st-couleur-texte-discret);text-align:center}@media(forced-colors:active){.st-message__article{border-color:CanvasText}}\n"]
266
+ }]
267
+ }],
268
+ ctorParameters: () => [],
269
+ propDecorators: {
270
+ article: [{
271
+ type: i0.ViewChild,
272
+ args: ["article", { isSignal: true }]
273
+ }],
274
+ message: [{
275
+ type: i0.Input,
276
+ args: [{
277
+ isSignal: true,
278
+ alias: "message",
279
+ required: true
280
+ }]
281
+ }],
282
+ reessai: [{
283
+ type: i0.Output,
284
+ args: ["reessai"]
285
+ }]
286
+ }
287
+ });
288
+ var StMessageThread = class StMessageThread {
289
+ locale = inject(ST_LOCALE);
290
+ fuseau = inject(FUSEAU_PAR_DEFAUT);
291
+ element = inject(ElementRef);
292
+ document = inject(DOCUMENT);
293
+ injecteur = inject(Injector);
294
+ catalogue = catalogueDeLaMessagerie();
295
+ libelles = computed(() => this.catalogue().libelles, ...ngDevMode ? [{ debugName: "libelles" }] : /* istanbul ignore next */ []);
296
+ langueDeRepli = computed(() => this.catalogue().langueDeRepli, ...ngDevMode ? [{ debugName: "langueDeRepli" }] : /* istanbul ignore next */ []);
297
+ etiquette = input.required(...ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []);
298
+ messages = input.required(...ngDevMode ? [{ debugName: "messages" }] : /* istanbul ignore next */ []);
299
+ fige = input(false, {
300
+ ...ngDevMode ? { debugName: "fige" } : /* istanbul ignore next */ {},
301
+ transform: booleanAttribute
302
+ });
303
+ precedents = input(false, {
304
+ ...ngDevMode ? { debugName: "precedents" } : /* istanbul ignore next */ {},
305
+ transform: booleanAttribute
306
+ });
307
+ chargementDesPrecedents = input(false, {
308
+ ...ngDevMode ? { debugName: "chargementDesPrecedents" } : /* istanbul ignore next */ {},
309
+ transform: booleanAttribute
310
+ });
311
+ chargerPrecedents = output();
312
+ reessai = output();
313
+ annonce = new AnnonceLocale(inject(DestroyRef));
314
+ insertionEnCours = signal(false, ...ngDevMode ? [{ debugName: "insertionEnCours" }] : /* istanbul ignore next */ []);
315
+ occupe = computed(() => this.chargementDesPrecedents() || this.insertionEnCours(), ...ngDevMode ? [{ debugName: "occupe" }] : /* istanbul ignore next */ []);
316
+ constructor() {
317
+ let levee;
318
+ inject(DestroyRef).onDestroy(() => {
319
+ clearTimeout(levee);
320
+ });
321
+ let premierConnu = null;
322
+ effect(() => {
323
+ const messages = this.messages();
324
+ untracked(() => {
325
+ const avant = premierConnu;
326
+ premierConnu = messages[0]?.id ?? null;
327
+ const ajoutes = avant === null ? 0 : messages.findIndex((message) => message.id === avant);
328
+ if (ajoutes <= 0) return;
329
+ this.insertionEnCours.set(true);
330
+ clearTimeout(levee);
331
+ levee = setTimeout(() => {
332
+ this.insertionEnCours.set(false);
333
+ }, delai.annonce);
334
+ this.annonce.annoncer(this.libelles().messagesPrecedentsAffiches(ajoutes));
335
+ });
336
+ });
337
+ effect(() => {
338
+ const precedents = this.precedents();
339
+ untracked(() => {
340
+ const hote = this.element.nativeElement;
341
+ if (precedents || !hote.contains(this.document.activeElement)) return;
342
+ afterNextRender(() => {
343
+ const actif = this.document.activeElement;
344
+ if (actif !== null && actif !== this.document.body && actif.isConnected) return;
345
+ hote.querySelector(".st-message__article")?.focus();
346
+ }, { injector: this.injecteur });
347
+ });
348
+ });
349
+ }
350
+ jours = computed(() => {
351
+ const cle = new Intl.DateTimeFormat("en-CA", {
352
+ timeZone: this.fuseau,
353
+ year: "numeric",
354
+ month: "2-digit",
355
+ day: "2-digit"
356
+ });
357
+ const titre = new Intl.DateTimeFormat(this.locale(), {
358
+ timeZone: this.fuseau,
359
+ weekday: "long",
360
+ day: "numeric",
361
+ month: "long",
362
+ year: "numeric"
363
+ });
364
+ const jours = [];
365
+ for (const message of this.messages()) {
366
+ const instant = lireInstant(message.envoyeLe, this.fuseau);
367
+ const jour = instant === null ? "" : cle.format(instant);
368
+ const dernier = jours.at(-1);
369
+ if (dernier?.jour === jour) dernier.messages.push(message);
370
+ else jours.push({
371
+ jour,
372
+ titre: instant === null ? "" : titre.format(instant),
373
+ messages: [message]
374
+ });
375
+ }
376
+ return jours;
377
+ }, ...ngDevMode ? [{ debugName: "jours" }] : /* istanbul ignore next */ []);
378
+ static ɵfac = i0.ɵɵngDeclareFactory({
379
+ minVersion: "12.0.0",
380
+ version: "22.2.0",
381
+ ngImport: i0,
382
+ type: StMessageThread,
383
+ deps: [],
384
+ target: i0.ɵɵFactoryTarget.Component
385
+ });
386
+ static ɵcmp = i0.ɵɵngDeclareComponent({
387
+ minVersion: "17.0.0",
388
+ version: "22.2.0",
389
+ type: StMessageThread,
390
+ isStandalone: true,
391
+ selector: "st-message-thread",
392
+ inputs: {
393
+ etiquette: {
394
+ classPropertyName: "etiquette",
395
+ publicName: "etiquette",
396
+ isSignal: true,
397
+ isRequired: true,
398
+ transformFunction: null
399
+ },
400
+ messages: {
401
+ classPropertyName: "messages",
402
+ publicName: "messages",
403
+ isSignal: true,
404
+ isRequired: true,
405
+ transformFunction: null
406
+ },
407
+ fige: {
408
+ classPropertyName: "fige",
409
+ publicName: "fige",
410
+ isSignal: true,
411
+ isRequired: false,
412
+ transformFunction: null
413
+ },
414
+ precedents: {
415
+ classPropertyName: "precedents",
416
+ publicName: "precedents",
417
+ isSignal: true,
418
+ isRequired: false,
419
+ transformFunction: null
420
+ },
421
+ chargementDesPrecedents: {
422
+ classPropertyName: "chargementDesPrecedents",
423
+ publicName: "chargementDesPrecedents",
424
+ isSignal: true,
425
+ isRequired: false,
426
+ transformFunction: null
427
+ }
428
+ },
429
+ outputs: {
430
+ chargerPrecedents: "chargerPrecedents",
431
+ reessai: "reessai"
432
+ },
433
+ host: { classAttribute: "st-message-thread" },
434
+ ngImport: i0,
435
+ template: "@if (precedents()) {\n <div class=\"st-message-thread__precedents\">\n <!-- `lang` : le bouton et l'annonce du bas sont tout entiers au catalogue (D-29). -->\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [attr.lang]=\"langueDeRepli()\"\n [chargement]=\"chargementDesPrecedents()\"\n (click)=\"chargerPrecedents.emit()\"\n >\n {{ libelles().afficherLesMessagesPrecedents }}\n </button>\n </div>\n}\n\n<ng-template #jourDuFil let-jour>\n @if (jour.titre !== '') {\n <p class=\"st-message-thread__jour\">\n <time [attr.datetime]=\"jour.jour\">{{ jour.titre }}</time>\n </p>\n }\n</ng-template>\n\n@if (fige()) {\n <!-- Un historique clos : une liste, sans region vivante ; chaque message y est un element. -->\n <ol\n class=\"st-message-thread__liste\"\n role=\"list\"\n [attr.aria-label]=\"etiquette()\"\n [attr.aria-busy]=\"occupe() ? 'true' : null\"\n >\n @for (jour of jours(); track jour.jour) {\n @for (message of jour.messages; track message.id; let premier = $first) {\n <li class=\"st-message-thread__element\">\n @if (premier) {\n <ng-container *ngTemplateOutlet=\"jourDuFil; context: { $implicit: jour }\" />\n }\n <st-message [message]=\"message\" (reessai)=\"reessai.emit($event)\" />\n </li>\n }\n }\n </ol>\n} @else {\n <!-- Le fil vivant : un message ajoute s'annonce poliment, sans voler le focus. Occupe\n (`aria-busy`) pendant le chargement des precedents et leur insertion en tete : ils ne\n s'annoncent pas comme nouveaux ; leur nombre se dit une fois, hors du fil (D-19). -->\n <section\n class=\"st-message-thread__liste\"\n role=\"log\"\n [attr.aria-label]=\"etiquette()\"\n [attr.aria-busy]=\"occupe() ? 'true' : null\"\n >\n @for (jour of jours(); track jour.jour) {\n <ng-container *ngTemplateOutlet=\"jourDuFil; context: { $implicit: jour }\" />\n @for (message of jour.messages; track message.id) {\n <st-message [message]=\"message\" (reessai)=\"reessai.emit($event)\" />\n }\n }\n </section>\n}\n<span class=\"st-vh\" aria-live=\"polite\" [attr.lang]=\"langueDeRepli()\">{{ annonce.texte() }}</span>\n",
436
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-3);min-inline-size:0}.st-message-thread__precedents{display:flex;justify-content:center}.st-message-thread__liste{display:flex;flex-direction:column;gap:var(--st-espacement-3);padding:0;margin:0;list-style:none}.st-message-thread__element{display:flex;flex-direction:column;gap:var(--st-espacement-3)}.st-message-thread__jour{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:flex;gap:var(--st-espacement-3);align-items:center;margin:var(--st-espacement-2) 0 0;color:var(--st-couleur-texte-discret)}.st-message-thread__jour:before,.st-message-thread__jour:after{flex:1;block-size:var(--st-epaisseur-capillaire);content:\"\";background:var(--st-couleur-bordure)}@media(forced-colors:active){.st-message-thread__jour:before,.st-message-thread__jour:after{background:CanvasText}}\n"],
437
+ dependencies: [
438
+ {
439
+ kind: "directive",
440
+ type: NgTemplateOutlet,
441
+ selector: "[ngTemplateOutlet]",
442
+ inputs: [
443
+ "ngTemplateOutletContext",
444
+ "ngTemplateOutlet",
445
+ "ngTemplateOutletInjector"
446
+ ]
447
+ },
448
+ {
449
+ kind: "component",
450
+ type: StButton,
451
+ selector: "button[stButton]",
452
+ inputs: [
453
+ "variante",
454
+ "taille",
455
+ "pleineLargeur",
456
+ "iconeAvant",
457
+ "iconeApres",
458
+ "chargement",
459
+ "indisponible",
460
+ "raisonIndisponible"
461
+ ]
462
+ },
463
+ {
464
+ kind: "component",
465
+ type: StMessage,
466
+ selector: "st-message",
467
+ inputs: ["message"],
468
+ outputs: ["reessai"]
469
+ }
470
+ ],
471
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
472
+ });
473
+ };
474
+ i0.ɵɵngDeclareClassMetadata({
475
+ minVersion: "12.0.0",
476
+ version: "22.2.0",
477
+ ngImport: i0,
478
+ type: StMessageThread,
479
+ decorators: [{
480
+ type: Component,
481
+ args: [{
482
+ selector: "st-message-thread",
483
+ changeDetection: ChangeDetectionStrategy.OnPush,
484
+ imports: [
485
+ NgTemplateOutlet,
486
+ StButton,
487
+ StMessage
488
+ ],
489
+ host: { class: "st-message-thread" },
490
+ template: "@if (precedents()) {\n <div class=\"st-message-thread__precedents\">\n <!-- `lang` : le bouton et l'annonce du bas sont tout entiers au catalogue (D-29). -->\n <button\n stButton\n type=\"button\"\n variante=\"discret\"\n taille=\"sm\"\n [attr.lang]=\"langueDeRepli()\"\n [chargement]=\"chargementDesPrecedents()\"\n (click)=\"chargerPrecedents.emit()\"\n >\n {{ libelles().afficherLesMessagesPrecedents }}\n </button>\n </div>\n}\n\n<ng-template #jourDuFil let-jour>\n @if (jour.titre !== '') {\n <p class=\"st-message-thread__jour\">\n <time [attr.datetime]=\"jour.jour\">{{ jour.titre }}</time>\n </p>\n }\n</ng-template>\n\n@if (fige()) {\n <!-- Un historique clos : une liste, sans region vivante ; chaque message y est un element. -->\n <ol\n class=\"st-message-thread__liste\"\n role=\"list\"\n [attr.aria-label]=\"etiquette()\"\n [attr.aria-busy]=\"occupe() ? 'true' : null\"\n >\n @for (jour of jours(); track jour.jour) {\n @for (message of jour.messages; track message.id; let premier = $first) {\n <li class=\"st-message-thread__element\">\n @if (premier) {\n <ng-container *ngTemplateOutlet=\"jourDuFil; context: { $implicit: jour }\" />\n }\n <st-message [message]=\"message\" (reessai)=\"reessai.emit($event)\" />\n </li>\n }\n }\n </ol>\n} @else {\n <!-- Le fil vivant : un message ajoute s'annonce poliment, sans voler le focus. Occupe\n (`aria-busy`) pendant le chargement des precedents et leur insertion en tete : ils ne\n s'annoncent pas comme nouveaux ; leur nombre se dit une fois, hors du fil (D-19). -->\n <section\n class=\"st-message-thread__liste\"\n role=\"log\"\n [attr.aria-label]=\"etiquette()\"\n [attr.aria-busy]=\"occupe() ? 'true' : null\"\n >\n @for (jour of jours(); track jour.jour) {\n <ng-container *ngTemplateOutlet=\"jourDuFil; context: { $implicit: jour }\" />\n @for (message of jour.messages; track message.id) {\n <st-message [message]=\"message\" (reessai)=\"reessai.emit($event)\" />\n }\n }\n </section>\n}\n<span class=\"st-vh\" aria-live=\"polite\" [attr.lang]=\"langueDeRepli()\">{{ annonce.texte() }}</span>\n",
491
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:flex;flex-direction:column;gap:var(--st-espacement-3);min-inline-size:0}.st-message-thread__precedents{display:flex;justify-content:center}.st-message-thread__liste{display:flex;flex-direction:column;gap:var(--st-espacement-3);padding:0;margin:0;list-style:none}.st-message-thread__element{display:flex;flex-direction:column;gap:var(--st-espacement-3)}.st-message-thread__jour{font-size:var(--st-taille-xs);line-height:var(--st-interligne-xs);font-weight:var(--st-graisse-moyenne);letter-spacing:var(--st-interlettrage-large);display:flex;gap:var(--st-espacement-3);align-items:center;margin:var(--st-espacement-2) 0 0;color:var(--st-couleur-texte-discret)}.st-message-thread__jour:before,.st-message-thread__jour:after{flex:1;block-size:var(--st-epaisseur-capillaire);content:\"\";background:var(--st-couleur-bordure)}@media(forced-colors:active){.st-message-thread__jour:before,.st-message-thread__jour:after{background:CanvasText}}\n"]
492
+ }]
493
+ }],
494
+ ctorParameters: () => [],
495
+ propDecorators: {
496
+ etiquette: [{
497
+ type: i0.Input,
498
+ args: [{
499
+ isSignal: true,
500
+ alias: "etiquette",
501
+ required: true
502
+ }]
503
+ }],
504
+ messages: [{
505
+ type: i0.Input,
506
+ args: [{
507
+ isSignal: true,
508
+ alias: "messages",
509
+ required: true
510
+ }]
511
+ }],
512
+ fige: [{
513
+ type: i0.Input,
514
+ args: [{
515
+ isSignal: true,
516
+ alias: "fige",
517
+ required: false
518
+ }]
519
+ }],
520
+ precedents: [{
521
+ type: i0.Input,
522
+ args: [{
523
+ isSignal: true,
524
+ alias: "precedents",
525
+ required: false
526
+ }]
527
+ }],
528
+ chargementDesPrecedents: [{
529
+ type: i0.Input,
530
+ args: [{
531
+ isSignal: true,
532
+ alias: "chargementDesPrecedents",
533
+ required: false
534
+ }]
535
+ }],
536
+ chargerPrecedents: [{
537
+ type: i0.Output,
538
+ args: ["chargerPrecedents"]
539
+ }],
540
+ reessai: [{
541
+ type: i0.Output,
542
+ args: ["reessai"]
543
+ }]
544
+ }
545
+ });
546
+ var StMessageComposer = class StMessageComposer {
547
+ catalogue = catalogueDeLaMessagerie();
548
+ libelles = computed(() => this.catalogue().libelles, ...ngDevMode ? [{ debugName: "libelles" }] : /* istanbul ignore next */ []);
549
+ langueDeRepli = computed(() => this.catalogue().langueDeRepli, ...ngDevMode ? [{ debugName: "langueDeRepli" }] : /* istanbul ignore next */ []);
550
+ etiquette = input(null, ...ngDevMode ? [{ debugName: "etiquette" }] : /* istanbul ignore next */ []);
551
+ piecesJointes = input("", ...ngDevMode ? [{ debugName: "piecesJointes" }] : /* istanbul ignore next */ []);
552
+ tailleMax = input(null, ...ngDevMode ? [{ debugName: "tailleMax" }] : /* istanbul ignore next */ []);
553
+ envoiEnCours = input(false, {
554
+ ...ngDevMode ? { debugName: "envoiEnCours" } : /* istanbul ignore next */ {},
555
+ transform: booleanAttribute
556
+ });
557
+ envoi = output();
558
+ texte = signal("", ...ngDevMode ? [{ debugName: "texte" }] : /* istanbul ignore next */ []);
559
+ fichiers = signal([], ...ngDevMode ? [{ debugName: "fichiers" }] : /* istanbul ignore next */ []);
560
+ nom = computed(() => this.etiquette() ?? this.libelles().votreMessage, ...ngDevMode ? [{ debugName: "nom" }] : /* istanbul ignore next */ []);
561
+ vide = computed(() => this.texte().trim() === "" && this.fichiers().length === 0, ...ngDevMode ? [{ debugName: "vide" }] : /* istanbul ignore next */ []);
562
+ envoyer(evenement) {
563
+ evenement?.preventDefault();
564
+ if (this.vide() || this.envoiEnCours()) return;
565
+ this.envoi.emit({
566
+ texte: this.texte().trim(),
567
+ fichiers: this.fichiers()
568
+ });
569
+ this.texte.set("");
570
+ this.fichiers.set([]);
571
+ }
572
+ auClavier(evenement) {
573
+ if (evenement.key === "Enter" && (evenement.ctrlKey || evenement.metaKey)) this.envoyer(evenement);
574
+ }
575
+ static ɵfac = i0.ɵɵngDeclareFactory({
576
+ minVersion: "12.0.0",
577
+ version: "22.2.0",
578
+ ngImport: i0,
579
+ type: StMessageComposer,
580
+ deps: [],
581
+ target: i0.ɵɵFactoryTarget.Component
582
+ });
583
+ static ɵcmp = i0.ɵɵngDeclareComponent({
584
+ minVersion: "17.0.0",
585
+ version: "22.2.0",
586
+ type: StMessageComposer,
587
+ isStandalone: true,
588
+ selector: "st-message-composer",
589
+ inputs: {
590
+ etiquette: {
591
+ classPropertyName: "etiquette",
592
+ publicName: "etiquette",
593
+ isSignal: true,
594
+ isRequired: false,
595
+ transformFunction: null
596
+ },
597
+ piecesJointes: {
598
+ classPropertyName: "piecesJointes",
599
+ publicName: "piecesJointes",
600
+ isSignal: true,
601
+ isRequired: false,
602
+ transformFunction: null
603
+ },
604
+ tailleMax: {
605
+ classPropertyName: "tailleMax",
606
+ publicName: "tailleMax",
607
+ isSignal: true,
608
+ isRequired: false,
609
+ transformFunction: null
610
+ },
611
+ envoiEnCours: {
612
+ classPropertyName: "envoiEnCours",
613
+ publicName: "envoiEnCours",
614
+ isSignal: true,
615
+ isRequired: false,
616
+ transformFunction: null
617
+ }
618
+ },
619
+ outputs: { envoi: "envoi" },
620
+ host: { classAttribute: "st-message-composer" },
621
+ ngImport: i0,
622
+ template: "<form class=\"st-message-composer__formulaire\" (submit)=\"envoyer($event)\">\n <st-textarea\n [libelle]=\"nom()\"\n [aide]=\"libelles().raccourciDEnvoi\"\n [lignes]=\"3\"\n [(value)]=\"texte\"\n (keydown)=\"auClavier($event)\"\n />\n @if (piecesJointes() !== '') {\n <st-file-upload\n multiple\n [libelle]=\"libelles().joindreDesFichiers\"\n [accept]=\"piecesJointes()\"\n [tailleMax]=\"tailleMax()\"\n [(value)]=\"fichiers\"\n />\n }\n <st-form-actions disposition=\"pied\">\n <!-- `lang` : « Envoyer » vient seul du catalogue (D-29) ; jamais sur la zone de saisie. -->\n <button\n stButton\n type=\"submit\"\n variante=\"primaire\"\n iconeApres=\"envoyer\"\n [attr.lang]=\"langueDeRepli()\"\n [indisponible]=\"vide()\"\n [chargement]=\"envoiEnCours()\"\n >\n {{ libelles().envoyer }}\n </button>\n </st-form-actions>\n</form>\n",
623
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;min-inline-size:0}.st-message-composer__formulaire{display:flex;flex-direction:column;gap:var(--st-espacement-3)}\n"],
624
+ dependencies: [
625
+ {
626
+ kind: "component",
627
+ type: StButton,
628
+ selector: "button[stButton]",
629
+ inputs: [
630
+ "variante",
631
+ "taille",
632
+ "pleineLargeur",
633
+ "iconeAvant",
634
+ "iconeApres",
635
+ "chargement",
636
+ "indisponible",
637
+ "raisonIndisponible"
638
+ ]
639
+ },
640
+ {
641
+ kind: "component",
642
+ type: StFileUpload,
643
+ selector: "st-file-upload",
644
+ inputs: [
645
+ "value",
646
+ "accept",
647
+ "multiple",
648
+ "tailleMax",
649
+ "nombreMax",
650
+ "libelleDuChoix",
651
+ "etats"
652
+ ],
653
+ outputs: [
654
+ "valueChange",
655
+ "annulation",
656
+ "remplacement"
657
+ ]
658
+ },
659
+ {
660
+ kind: "component",
661
+ type: StFormActions,
662
+ selector: "st-form-actions",
663
+ inputs: ["disposition"]
664
+ },
665
+ {
666
+ kind: "component",
667
+ type: StTextarea,
668
+ selector: "st-textarea",
669
+ inputs: ["lignes", "lignesMax"]
670
+ }
671
+ ],
672
+ changeDetection: i0.ChangeDetectionStrategy.OnPush
673
+ });
674
+ };
675
+ i0.ɵɵngDeclareClassMetadata({
676
+ minVersion: "12.0.0",
677
+ version: "22.2.0",
678
+ ngImport: i0,
679
+ type: StMessageComposer,
680
+ decorators: [{
681
+ type: Component,
682
+ args: [{
683
+ selector: "st-message-composer",
684
+ changeDetection: ChangeDetectionStrategy.OnPush,
685
+ imports: [
686
+ StButton,
687
+ StFileUpload,
688
+ StFormActions,
689
+ StTextarea
690
+ ],
691
+ host: { class: "st-message-composer" },
692
+ template: "<form class=\"st-message-composer__formulaire\" (submit)=\"envoyer($event)\">\n <st-textarea\n [libelle]=\"nom()\"\n [aide]=\"libelles().raccourciDEnvoi\"\n [lignes]=\"3\"\n [(value)]=\"texte\"\n (keydown)=\"auClavier($event)\"\n />\n @if (piecesJointes() !== '') {\n <st-file-upload\n multiple\n [libelle]=\"libelles().joindreDesFichiers\"\n [accept]=\"piecesJointes()\"\n [tailleMax]=\"tailleMax()\"\n [(value)]=\"fichiers\"\n />\n }\n <st-form-actions disposition=\"pied\">\n <!-- `lang` : « Envoyer » vient seul du catalogue (D-29) ; jamais sur la zone de saisie. -->\n <button\n stButton\n type=\"submit\"\n variante=\"primaire\"\n iconeApres=\"envoyer\"\n [attr.lang]=\"langueDeRepli()\"\n [indisponible]=\"vide()\"\n [chargement]=\"envoiEnCours()\"\n >\n {{ libelles().envoyer }}\n </button>\n </st-form-actions>\n</form>\n",
693
+ styles: [".st-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}:host([hidden]){display:none!important}:host{display:block;min-inline-size:0}.st-message-composer__formulaire{display:flex;flex-direction:column;gap:var(--st-espacement-3)}\n"]
694
+ }]
695
+ }],
696
+ propDecorators: {
697
+ etiquette: [{
698
+ type: i0.Input,
699
+ args: [{
700
+ isSignal: true,
701
+ alias: "etiquette",
702
+ required: false
703
+ }]
704
+ }],
705
+ piecesJointes: [{
706
+ type: i0.Input,
707
+ args: [{
708
+ isSignal: true,
709
+ alias: "piecesJointes",
710
+ required: false
711
+ }]
712
+ }],
713
+ tailleMax: [{
714
+ type: i0.Input,
715
+ args: [{
716
+ isSignal: true,
717
+ alias: "tailleMax",
718
+ required: false
719
+ }]
720
+ }],
721
+ envoiEnCours: [{
722
+ type: i0.Input,
723
+ args: [{
724
+ isSignal: true,
725
+ alias: "envoiEnCours",
726
+ required: false
727
+ }]
728
+ }],
729
+ envoi: [{
730
+ type: i0.Output,
731
+ args: ["envoi"]
732
+ }]
733
+ }
734
+ });
735
+ export { LIBELLES_MESSAGERIE_EN, LIBELLES_MESSAGERIE_FR, ST_LIBELLES_MESSAGERIE, StMessage, StMessageComposer, StMessageThread, catalogueDeLaMessagerie, fournirLibellesMessagerie, libellesDeLaMessagerie };
736
+
737
+ //# sourceMappingURL=starterlib-ui-messagerie.mjs.map