@cedx/base 0.17.0 → 0.18.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.
package/ReadMe.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Cédric Belin's Base
2
- ![.NET](https://badgen.net/badge/.net/%3E%3D9.0/green) ![Version](https://badgen.net/badge/project/v0.17.0/blue) ![Licence](https://badgen.net/badge/licence/MIT/blue)
2
+ ![.NET](https://badgen.net/badge/.net/%3E%3D9.0/green) ![Version](https://badgen.net/badge/project/v0.18.0/blue) ![Licence](https://badgen.net/badge/licence/MIT/blue)
3
3
 
4
4
  Base library by [Cédric Belin](https://cedric-belin.fr), full stack developer,
5
5
  implemented in [C#](https://learn.microsoft.com/en-us/dotnet/csharp) and [TypeScript](https://www.typescriptlang.org).
@@ -1 +1 @@
1
- {"version":3,"file":"DialogButton.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/DialogButton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAsB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAC,OAAO,EAAsB,MAAM,eAAe,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,aAAa;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,GAAC,IAAI,CAAC;IAEvB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,GAAC,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,WAAW;;IAE5C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAoD;IAStF;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,GAAC,IAAI,CAG1B;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,GAAC,IAAI,EAE9B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAC,IAAI,CAGtB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAC,IAAI,EAE1B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,YAAY,CAGxB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,YAAY,EAE5B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,GAAC,IAAI,CAG1B;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,GAAC,IAAI,EAE9B;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;CA6D/F;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,eAAe,EAAE,YAAY,CAAC;KAC9B;CACD"}
1
+ {"version":3,"file":"DialogButton.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/DialogButton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAsB,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAC,OAAO,EAAsB,MAAM,eAAe,CAAC;AAE3D;;GAEG;AACH,MAAM,WAAW,aAAa;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,GAAC,IAAI,CAAC;IAEvB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;IAEnB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC;IAErB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,GAAC,IAAI,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,YAAa,SAAQ,WAAW;;IAE5C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAoD;IAStF;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,GAAC,IAAI,CAG1B;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,GAAC,IAAI,EAG9B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAC,IAAI,CAGtB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAC,IAAI,EAG1B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAElB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,YAAY,CAGxB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,YAAY,EAE5B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,GAAC,IAAI,CAG1B;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,GAAC,IAAI,EAG9B;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;CA6D/F;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,eAAe,EAAE,YAAY,CAAC;KAC9B;CACD"}
@@ -23,7 +23,10 @@ export class DialogButton extends HTMLElement {
23
23
  return Object.values(Context).includes(value) ? value : null;
24
24
  }
25
25
  set context(value) {
26
- this.toggleAttribute("context", Boolean(value));
26
+ if (value)
27
+ this.setAttribute("context", value);
28
+ else
29
+ this.removeAttribute("context");
27
30
  }
28
31
  /**
29
32
  * The button icon.
@@ -33,7 +36,10 @@ export class DialogButton extends HTMLElement {
33
36
  return value.trim() || null;
34
37
  }
35
38
  set icon(value) {
36
- this.toggleAttribute("icon", Boolean(value));
39
+ if (value)
40
+ this.setAttribute("icon", value);
41
+ else
42
+ this.removeAttribute("icon");
37
43
  }
38
44
  /**
39
45
  * The button label.
@@ -62,7 +68,10 @@ export class DialogButton extends HTMLElement {
62
68
  return Object.values(Variant).includes(value) ? value : null;
63
69
  }
64
70
  set variant(value) {
65
- this.toggleAttribute("context", Boolean(value));
71
+ if (value)
72
+ this.setAttribute("variant", value);
73
+ else
74
+ this.removeAttribute("variant");
66
75
  }
67
76
  /**
68
77
  * Method invoked when an attribute has been changed.
@@ -0,0 +1,165 @@
1
+ import { Context } from "../Context.js";
2
+ import { DialogResult } from "../DialogResult.js";
3
+ import type { IDialogButton } from "./DialogButton.js";
4
+ /**
5
+ * Represents a message to display in a dialog box.
6
+ */
7
+ export interface IMessage {
8
+ /**
9
+ * Value indicating whether to apply a fade transition.
10
+ */
11
+ animation?: boolean;
12
+ /**
13
+ * The child content displayed in the body.
14
+ */
15
+ body: DocumentFragment | string;
16
+ /**
17
+ * The title displayed in the header.
18
+ */
19
+ caption: string;
20
+ /**
21
+ * Value indicating whether to vertically center this message box.
22
+ */
23
+ centered?: boolean;
24
+ /**
25
+ * A contextual modifier.
26
+ */
27
+ context?: Context;
28
+ /**
29
+ * The child content displayed in the footer.
30
+ */
31
+ footer?: DocumentFragment | string;
32
+ /**
33
+ * The icon displayed next to the body.
34
+ */
35
+ icon?: string | null;
36
+ /**
37
+ * Value indicating whether the body is scrollable.
38
+ */
39
+ scrollable?: boolean;
40
+ }
41
+ /**
42
+ * Displays a message window, also known as dialog box, which presents a message to the user.
43
+ */
44
+ export declare class MessageBox extends HTMLElement {
45
+ #private;
46
+ /**
47
+ * The list of observed attributes.
48
+ */
49
+ static readonly observedAttributes: string[];
50
+ /**
51
+ * Creates a new message box.
52
+ */
53
+ constructor();
54
+ /**
55
+ * Value indicating whether to apply a fade transition.
56
+ */
57
+ get animation(): boolean;
58
+ set animation(value: boolean);
59
+ /**
60
+ * The child content displayed in the body.
61
+ */
62
+ set body(value: DocumentFragment);
63
+ /**
64
+ * The title displayed in the header.
65
+ */
66
+ get caption(): string;
67
+ set caption(value: string);
68
+ /**
69
+ * Value indicating whether to vertically center this message box.
70
+ */
71
+ get centered(): boolean;
72
+ set centered(value: boolean);
73
+ /**
74
+ * A contextual modifier.
75
+ */
76
+ get context(): Context;
77
+ set context(value: Context);
78
+ /**
79
+ * The child content displayed in the footer.
80
+ */
81
+ set footer(value: DocumentFragment);
82
+ /**
83
+ * The icon displayed next to the body.
84
+ */
85
+ get icon(): string | null;
86
+ set icon(value: string | null);
87
+ /**
88
+ * Value indicating whether to this message box will not close when clicking outside of it.
89
+ */
90
+ get modal(): boolean;
91
+ set modal(value: boolean);
92
+ /**
93
+ * Value indicating whether to initially show this message box.
94
+ */
95
+ get open(): boolean;
96
+ set open(value: boolean);
97
+ /**
98
+ * Value indicating whether the body is scrollable.
99
+ */
100
+ get scrollable(): boolean;
101
+ set scrollable(value: boolean);
102
+ /**
103
+ * Method invoked when an attribute has been changed.
104
+ * @param attribute The attribute name.
105
+ * @param oldValue The previous attribute value.
106
+ * @param newValue The new attribute value.
107
+ */
108
+ attributeChangedCallback(attribute: string, oldValue: string | null, newValue: string | null): void;
109
+ /**
110
+ * Shows an alert message with an "OK" button.
111
+ * @param context The contextual modifier.
112
+ * @param caption The title displayed in the header.
113
+ * @param body The child content displayed in the body.
114
+ * @returns The dialog box result.
115
+ */
116
+ alert(context: Context, caption: string, body: DocumentFragment | string): Promise<DialogResult>;
117
+ /**
118
+ * Closes this message box.
119
+ * @param result The dialog box result.
120
+ */
121
+ close(result?: DialogResult): void;
122
+ /**
123
+ * Shows a confirmation message with two buttons, "OK" and "Cancel".
124
+ * @param context The contextual modifier.
125
+ * @param caption The title displayed in the header.
126
+ * @param body The child content displayed in the body.
127
+ * @returns The dialog box result.
128
+ */
129
+ confirm(context: Context, caption: string, body: DocumentFragment | string): Promise<DialogResult>;
130
+ /**
131
+ * Method invoked when this component is connected.
132
+ */
133
+ connectedCallback(): void;
134
+ /**
135
+ * Method invoked when this component is disconnected.
136
+ */
137
+ disconnectedCallback(): void;
138
+ /**
139
+ * Shows a message.
140
+ * @param message The message to show.
141
+ * @returns The dialog box result.
142
+ */
143
+ show(message?: IMessage): Promise<DialogResult>;
144
+ /**
145
+ * Shows a message.
146
+ * @param context The contextual modifier.
147
+ * @param caption The title displayed in the header.
148
+ * @param body The child content displayed in the body.
149
+ * @param buttons The buttons displayed in the footer.
150
+ * @returns The dialog box result.
151
+ */
152
+ show(context: Context, caption: string, body: DocumentFragment | string, buttons?: IDialogButton[]): Promise<DialogResult>;
153
+ }
154
+ /**
155
+ * Declaration merging.
156
+ */
157
+ declare global {
158
+ /**
159
+ * The map of HTML tag names.
160
+ */
161
+ interface HTMLElementTagNameMap {
162
+ "message-box": MessageBox;
163
+ }
164
+ }
165
+ //# sourceMappingURL=MessageBox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageBox.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/MessageBox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,320 @@
1
+ import { Modal } from "bootstrap";
2
+ import { Context, getIcon, toCss } from "../Context.js";
3
+ import { DialogResult } from "../DialogResult.js";
4
+ import { createDocumentFragment } from "../ElementExtensions.js";
5
+ import { Variant } from "../Variant.js";
6
+ /**
7
+ * Displays a message window, also known as dialog box, which presents a message to the user.
8
+ */
9
+ export class MessageBox extends HTMLElement {
10
+ /**
11
+ * The list of observed attributes.
12
+ */
13
+ static observedAttributes = ["animation", "caption", "centered", "context", "icon", "modal", "scrollable"];
14
+ /**
15
+ * The template for a button.
16
+ */
17
+ #buttonTemplate = this.querySelector("template").content;
18
+ /**
19
+ * The underlying Bootstrap modal.
20
+ */
21
+ #modal;
22
+ /**
23
+ * The function invoked to return the dialog box result.
24
+ */
25
+ #resolve = () => { };
26
+ /**
27
+ * The dialog result.
28
+ */
29
+ #result = DialogResult.None;
30
+ /**
31
+ * Creates a new message box.
32
+ */
33
+ constructor() {
34
+ super();
35
+ this.firstElementChild.addEventListener("hidden.bs.modal", () => this.#resolve(this.#result));
36
+ this.querySelector(".btn-close").addEventListener("click", this.#close);
37
+ for (const button of this.querySelectorAll(".modal-footer button"))
38
+ button.addEventListener("click", this.#close);
39
+ }
40
+ /**
41
+ * Registers the component.
42
+ */
43
+ static {
44
+ customElements.define("message-box", this);
45
+ }
46
+ /**
47
+ * Value indicating whether to apply a fade transition.
48
+ */
49
+ get animation() {
50
+ return this.hasAttribute("animation");
51
+ }
52
+ set animation(value) {
53
+ this.toggleAttribute("animation", value);
54
+ }
55
+ /**
56
+ * The child content displayed in the body.
57
+ */
58
+ set body(value) {
59
+ this.querySelector(".modal-body > div").replaceChildren(...value.childNodes);
60
+ }
61
+ /**
62
+ * The title displayed in the header.
63
+ */
64
+ get caption() {
65
+ return (this.getAttribute("caption") ?? "").trim();
66
+ }
67
+ set caption(value) {
68
+ this.setAttribute("caption", value);
69
+ }
70
+ /**
71
+ * Value indicating whether to vertically center this message box.
72
+ */
73
+ get centered() {
74
+ return this.hasAttribute("centered");
75
+ }
76
+ set centered(value) {
77
+ this.toggleAttribute("centered", value);
78
+ }
79
+ /**
80
+ * A contextual modifier.
81
+ */
82
+ get context() {
83
+ const value = this.getAttribute("context");
84
+ return Object.values(Context).includes(value) ? value : Context.Info;
85
+ }
86
+ set context(value) {
87
+ this.setAttribute("context", value);
88
+ }
89
+ /**
90
+ * The child content displayed in the footer.
91
+ */
92
+ set footer(value) {
93
+ const footer = this.querySelector(".modal-footer");
94
+ footer.hidden = !value.hasChildNodes();
95
+ footer.replaceChildren(...value.childNodes);
96
+ }
97
+ /**
98
+ * The icon displayed next to the body.
99
+ */
100
+ get icon() {
101
+ const value = this.getAttribute("icon") ?? "";
102
+ return value.trim() || null;
103
+ }
104
+ set icon(value) {
105
+ this.toggleAttribute("icon", Boolean(value));
106
+ }
107
+ /**
108
+ * Value indicating whether to this message box will not close when clicking outside of it.
109
+ */
110
+ get modal() {
111
+ return this.hasAttribute("modal");
112
+ }
113
+ set modal(value) {
114
+ this.toggleAttribute("modal", value);
115
+ }
116
+ /**
117
+ * Value indicating whether to initially show this message box.
118
+ */
119
+ get open() {
120
+ return this.hasAttribute("open");
121
+ }
122
+ set open(value) {
123
+ this.toggleAttribute("open", value);
124
+ }
125
+ /**
126
+ * Value indicating whether the body is scrollable.
127
+ */
128
+ get scrollable() {
129
+ return this.hasAttribute("scrollable");
130
+ }
131
+ set scrollable(value) {
132
+ this.toggleAttribute("scrollable", value);
133
+ }
134
+ /**
135
+ * Method invoked when an attribute has been changed.
136
+ * @param attribute The attribute name.
137
+ * @param oldValue The previous attribute value.
138
+ * @param newValue The new attribute value.
139
+ */
140
+ attributeChangedCallback(attribute, oldValue, newValue) {
141
+ if (newValue != oldValue)
142
+ switch (attribute) {
143
+ case "animation":
144
+ this.#updateAnimation(newValue != null);
145
+ break;
146
+ case "caption":
147
+ this.#updateCaption(newValue ?? "");
148
+ break;
149
+ case "centered":
150
+ this.#updateCentered(newValue != null);
151
+ break;
152
+ case "context":
153
+ this.#updateContext(Object.values(Context).includes(newValue) ? newValue : Context.Info);
154
+ break;
155
+ case "icon":
156
+ this.#updateIcon(newValue);
157
+ break;
158
+ case "modal":
159
+ this.#updateModal(newValue != null);
160
+ break;
161
+ case "scrollable":
162
+ this.#updateScrolling(newValue != null);
163
+ break;
164
+ // No default
165
+ }
166
+ }
167
+ /**
168
+ * Shows an alert message with an "OK" button.
169
+ * @param context The contextual modifier.
170
+ * @param caption The title displayed in the header.
171
+ * @param body The child content displayed in the body.
172
+ * @returns The dialog box result.
173
+ */
174
+ async alert(context, caption, body) {
175
+ return await this.show(context, caption, body, [
176
+ { label: "OK", value: DialogResult.OK, variant: Variant.Primary }
177
+ ]);
178
+ }
179
+ /**
180
+ * Closes this message box.
181
+ * @param result The dialog box result.
182
+ */
183
+ close(result = DialogResult.None) {
184
+ this.#result = result;
185
+ this.#modal.hide();
186
+ }
187
+ /**
188
+ * Shows a confirmation message with two buttons, "OK" and "Cancel".
189
+ * @param context The contextual modifier.
190
+ * @param caption The title displayed in the header.
191
+ * @param body The child content displayed in the body.
192
+ * @returns The dialog box result.
193
+ */
194
+ async confirm(context, caption, body) {
195
+ return await this.show(context, caption, body, [
196
+ { label: "OK", value: DialogResult.OK, variant: Variant.Primary },
197
+ { label: "Annuler", value: DialogResult.Cancel, variant: Variant.Secondary }
198
+ ]);
199
+ }
200
+ /**
201
+ * Method invoked when this component is connected.
202
+ */
203
+ connectedCallback() {
204
+ this.#modal = new Modal(this.firstElementChild);
205
+ if (this.open)
206
+ void this.show();
207
+ }
208
+ /**
209
+ * Method invoked when this component is disconnected.
210
+ */
211
+ disconnectedCallback() {
212
+ this.#modal.dispose();
213
+ }
214
+ /**
215
+ * Shows a message.
216
+ * @param message The message to show, or the contextual modifier.
217
+ * @param caption The title displayed in the header.
218
+ * @param body The child content displayed in the body.
219
+ * @param buttons The buttons displayed in the footer.
220
+ * @returns The dialog box result.
221
+ */
222
+ show(message = null, caption = "", body = "", buttons = []) {
223
+ if (typeof message == "string") {
224
+ const footer = document.createDocumentFragment();
225
+ footer.append(...buttons.map(button => this.#createButton(button)));
226
+ message = { context: message, caption, body, footer };
227
+ }
228
+ if (typeof message == "object" && message) {
229
+ this.body = typeof message.body == "string" ? createDocumentFragment(message.body) : message.body;
230
+ this.caption = message.caption;
231
+ this.context = message.context ?? Context.Info;
232
+ this.icon = message.icon ?? getIcon(this.context);
233
+ const footer = typeof message.footer == "string" ? createDocumentFragment(message.footer) : (message.footer ?? document.createDocumentFragment());
234
+ for (const button of footer.querySelectorAll("button"))
235
+ button.addEventListener("click", this.#close);
236
+ this.footer = footer;
237
+ }
238
+ const { promise, resolve } = Promise.withResolvers();
239
+ this.#resolve = resolve;
240
+ this.#result = DialogResult.None;
241
+ this.#modal.show();
242
+ return promise;
243
+ }
244
+ /**
245
+ * Closes this message box.
246
+ * @param event The dispatched event.
247
+ */
248
+ #close = event => {
249
+ const button = event.target.closest("button");
250
+ this.close(Object.values(DialogResult).includes(button.value) ? button.value : DialogResult.None);
251
+ };
252
+ /**
253
+ * Creates the component instance corresponding to the specified button.
254
+ * @param button An object describing the appearance of the button.
255
+ * @returns The component instance corresponding to the specified button.
256
+ */
257
+ #createButton(button) {
258
+ const element = document.createElement("dialog-button");
259
+ const childContent = this.#buttonTemplate.cloneNode(true).querySelector("button");
260
+ childContent.addEventListener("click", this.#close);
261
+ element.appendChild(childContent);
262
+ element.context = button.context ?? null;
263
+ element.icon = button.icon ?? null;
264
+ element.label = button.label ?? "";
265
+ element.value = button.value ?? DialogResult.None;
266
+ element.variant = button.variant ?? null;
267
+ return element;
268
+ }
269
+ /**
270
+ * Updates the message box animation.
271
+ * @param value The new value.
272
+ */
273
+ #updateAnimation(value) {
274
+ this.firstElementChild.classList.toggle("fade", value);
275
+ }
276
+ /**
277
+ * Updates the title displayed in the header.
278
+ * @param value The new value.
279
+ */
280
+ #updateCaption(value) {
281
+ this.querySelector(".modal-title").textContent = value.trim();
282
+ }
283
+ /**
284
+ * Updates the value indicating whether to vertically center this message box.
285
+ * @param value The new value.
286
+ */
287
+ #updateCentered(value) {
288
+ this.querySelector(".modal-dialog").classList.toggle("modal-dialog-centered", value);
289
+ }
290
+ /**
291
+ * Updates the contextual modifier.
292
+ * @param value The new value.
293
+ */
294
+ #updateContext(value) {
295
+ const { classList } = this.querySelector(".modal-body > .icon");
296
+ classList.remove(...Object.values(Context).map(context => `text-${toCss(context)}`));
297
+ classList.add(`text-${toCss(value)}`);
298
+ }
299
+ /**
300
+ * Updates the icon displayed next to the body.
301
+ * @param value The new value.
302
+ */
303
+ #updateIcon(value) {
304
+ this.querySelector(".modal-body > .icon").textContent = (value ?? "").trim() || getIcon(this.context);
305
+ }
306
+ /**
307
+ * Updates the value indicating whether to this message box will not close when clicking outside of it.
308
+ * @param value The new value.
309
+ */
310
+ #updateModal(value) {
311
+ this.firstElementChild.dataset.bsBackdrop = value ? "static" : "true";
312
+ }
313
+ /**
314
+ * Updates the body scrolling.
315
+ * @param value The new value.
316
+ */
317
+ #updateScrolling(value) {
318
+ this.querySelector(".modal-dialog").classList.toggle("modal-dialog-scrollable", value);
319
+ }
320
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeDropdown.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/ThemeDropdown.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAC,QAAQ,EAAU,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;;IAE7C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAsC;IAYxE;;OAEG;;IAaH;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,CAGzB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,EAE7B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,QAAQ,CAGvB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAE3B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAGlB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAGvB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;IAe/F;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAK5B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;CAgDZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,gBAAgB,EAAE,aAAa,CAAC;KAChC;CACD"}
1
+ {"version":3,"file":"ThemeDropdown.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/ThemeDropdown.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1C,OAAO,EAAC,QAAQ,EAAU,MAAM,gBAAgB,CAAC;AAEjD;;GAEG;AACH,qBAAa,aAAc,SAAQ,WAAW;;IAE7C;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAsC;IAYxE;;OAEG;;IAaH;;OAEG;IACH,IAAI,SAAS,IAAI,SAAS,CAGzB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,SAAS,EAE7B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,QAAQ,CAGvB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAE3B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAGlB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAGvB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;IAS/F;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,iBAAiB,IAAI,IAAI;IAQzB;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAK5B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;CAgDZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,gBAAgB,EAAE,aAAa,CAAC;KAChC;CACD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/Toast.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAiB,MAAM,eAAe,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,MAAM;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,gBAAgB,GAAC,MAAM,CAAC;IAE9B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,KAAM,SAAQ,WAAW;;IAErC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAkE;IAkCpG;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAE3B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED;;OAEG;IACH,IAAI,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAE/B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAExB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAGrB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,CAGzB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAE7B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAGlB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAC,IAAI,CAGtB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAC,IAAI,EAE1B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;IAY/F;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,iBAAiB,IAAI,IAAI;IASzB;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAK5B;;OAEG;IACH,IAAI,IAAI,IAAI;CA+EZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,cAAc,EAAE,KAAK,CAAC;KACtB;CACD"}
1
+ {"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/Toast.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,OAAO,EAAiB,MAAM,eAAe,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,MAAM;IAEtB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,gBAAgB,GAAC,MAAM,CAAC;IAE9B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC;IAEtB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,GAAC,IAAI,CAAC;CACnB;AAED;;GAEG;AACH,qBAAa,KAAM,SAAQ,WAAW;;IAErC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAA+E;IAkCjH;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IACD,IAAI,SAAS,CAAC,KAAK,EAAE,OAAO,EAE3B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;IAED;;OAEG;IACH,IAAI,IAAI,CAAC,KAAK,EAAE,gBAAgB,EAE/B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,MAAM,EAExB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAGrB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAEzB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,CAGzB;IACD,IAAI,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,EAE7B;IAED;;OAEG;IACH,IAAI,KAAK,IAAI,MAAM,CAGlB;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,MAAM,EAEtB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,MAAM,CAExB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAC,IAAI,CAGtB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAC,IAAI,EAG1B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;IAa/F;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb;;OAEG;IACH,iBAAiB,IAAI,IAAI;IASzB;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAK5B;;OAEG;IACH,IAAI,IAAI,IAAI;CAwFZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,cAAc,EAAE,KAAK,CAAC;KACtB;CACD"}
@@ -7,7 +7,7 @@ export class Toast extends HTMLElement {
7
7
  /**
8
8
  * The list of observed attributes.
9
9
  */
10
- static observedAttributes = ["animation", "caption", "context", "culture", "icon", "open"];
10
+ static observedAttributes = ["animation", "autohide", "caption", "context", "culture", "delay", "icon"];
11
11
  /**
12
12
  * The time units.
13
13
  */
@@ -111,7 +111,10 @@ export class Toast extends HTMLElement {
111
111
  return value.trim() || null;
112
112
  }
113
113
  set icon(value) {
114
- this.toggleAttribute("icon", Boolean(value));
114
+ if (value)
115
+ this.setAttribute("icon", value);
116
+ else
117
+ this.removeAttribute("icon");
115
118
  }
116
119
  /**
117
120
  * Value indicating whether to initially show this toast.
@@ -134,6 +137,9 @@ export class Toast extends HTMLElement {
134
137
  case "animation":
135
138
  this.#updateAnimation(newValue != null);
136
139
  break;
140
+ case "autohide":
141
+ this.#updateAutoHide(newValue != null);
142
+ break;
137
143
  case "caption":
138
144
  this.#updateCaption(newValue ?? "");
139
145
  break;
@@ -143,12 +149,12 @@ export class Toast extends HTMLElement {
143
149
  case "culture":
144
150
  this.#formatter = new Intl.RelativeTimeFormat((newValue ?? "").trim() || navigator.language, { style: "long" });
145
151
  break;
152
+ case "delay":
153
+ this.#updateDelay(Number(newValue));
154
+ break;
146
155
  case "icon":
147
156
  this.#updateIcon(newValue);
148
157
  break;
149
- case "open":
150
- this.#updateVisibility(newValue != null);
151
- break;
152
158
  // No default
153
159
  }
154
160
  }
@@ -165,8 +171,9 @@ export class Toast extends HTMLElement {
165
171
  const toast = this.firstElementChild;
166
172
  toast.addEventListener("hidden.bs.toast", () => clearInterval(this.#timer));
167
173
  toast.addEventListener("show.bs.toast", () => this.#timer = window.setInterval(this.#updateElapsedTime, 1_000));
168
- const { animation, autoHide: autohide, delay } = this;
169
- this.#toast = new BootstrapToast(toast, { animation, autohide, delay });
174
+ this.#toast = new BootstrapToast(toast);
175
+ if (this.open)
176
+ this.show();
170
177
  }
171
178
  /**
172
179
  * Method invoked when this component is disconnected.
@@ -199,11 +206,18 @@ export class Toast extends HTMLElement {
199
206
  return this.#formatter.format(Math.ceil(-elapsed), Toast.#timeUnits[index]);
200
207
  }
201
208
  /**
202
- * Updates the toast animation.
209
+ * Updates the value indicating whether to apply a fade transition.
203
210
  * @param value The new value.
204
211
  */
205
212
  #updateAnimation(value) {
206
- this.firstElementChild.classList.toggle("fade", value);
213
+ this.firstElementChild.dataset.bsAnimation = value ? "true" : "false";
214
+ }
215
+ /**
216
+ * Updates the value indicating whether to automatically hide this toast.
217
+ * @param value The new value.
218
+ */
219
+ #updateAutoHide(value) {
220
+ this.firstElementChild.dataset.bsAutohide = value ? "true" : "false";
207
221
  }
208
222
  /**
209
223
  * Updates the title displayed in the header.
@@ -225,6 +239,14 @@ export class Toast extends HTMLElement {
225
239
  classList.remove(...contexts.map(context => `text-${toCss(context)}`));
226
240
  classList.add(`text-${toCss(value)}`);
227
241
  }
242
+ /**
243
+ * Updates the delay to hide the toast.
244
+ * @param value The new value.
245
+ */
246
+ #updateDelay(value) {
247
+ const delay = Math.max(0, Number.isNaN(value) ? 5_000 : value);
248
+ this.firstElementChild.dataset.bsDelay = delay.toString();
249
+ }
228
250
  /**
229
251
  * Updates the label corresponding to the elapsed time.
230
252
  */
@@ -239,11 +261,4 @@ export class Toast extends HTMLElement {
239
261
  #updateIcon(value) {
240
262
  this.querySelector(".toast-header .icon").textContent = (value ?? "").trim() || getIcon(this.context);
241
263
  }
242
- /**
243
- * Updates the toast visibility.
244
- * @param value The new value.
245
- */
246
- #updateVisibility(value) {
247
- this.firstElementChild.classList.toggle("show", value);
248
- }
249
264
  }