@cedx/base 0.15.3 → 0.17.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 (36) hide show
  1. package/ReadMe.md +4 -4
  2. package/lib/UI/Alignment.d.ts +22 -0
  3. package/lib/UI/Alignment.d.ts.map +1 -0
  4. package/lib/UI/Alignment.js +17 -0
  5. package/lib/UI/Components/DialogButton.d.ts +82 -0
  6. package/lib/UI/Components/DialogButton.d.ts.map +1 -0
  7. package/lib/UI/Components/DialogButton.js +142 -0
  8. package/lib/UI/Components/KeyboardAccelerator.js +1 -1
  9. package/lib/UI/Components/ThemeDropdown.d.ts +3 -3
  10. package/lib/UI/Components/ThemeDropdown.d.ts.map +1 -1
  11. package/lib/UI/Components/ThemeDropdown.js +4 -8
  12. package/lib/UI/Components/Toast.d.ts +47 -10
  13. package/lib/UI/Components/Toast.d.ts.map +1 -1
  14. package/lib/UI/Components/Toast.js +37 -41
  15. package/lib/UI/Components/Toaster.d.ts +5 -41
  16. package/lib/UI/Components/Toaster.d.ts.map +1 -1
  17. package/lib/UI/Components/Toaster.js +9 -14
  18. package/lib/UI/DialogResult.d.ts +42 -0
  19. package/lib/UI/DialogResult.d.ts.map +1 -0
  20. package/lib/UI/DialogResult.js +37 -0
  21. package/package.json +2 -3
  22. package/src/Client/UI/Alignment.ts +25 -0
  23. package/src/Client/UI/Components/DialogButton.ts +187 -0
  24. package/src/Client/UI/Components/KeyboardAccelerator.ts +1 -1
  25. package/src/Client/UI/Components/ThemeDropdown.ts +8 -10
  26. package/src/Client/UI/Components/Toast.ts +89 -50
  27. package/src/Client/UI/Components/Toaster.ts +12 -58
  28. package/src/Client/UI/DialogResult.ts +50 -0
  29. package/lib/UI/Components/ComponentBase.d.ts +0 -24
  30. package/lib/UI/Components/ComponentBase.d.ts.map +0 -1
  31. package/lib/UI/Components/ComponentBase.js +0 -29
  32. package/lib/UI/MenuAlignment.d.ts +0 -18
  33. package/lib/UI/MenuAlignment.d.ts.map +0 -1
  34. package/lib/UI/MenuAlignment.js +0 -13
  35. package/src/Client/UI/Components/ComponentBase.ts +0 -34
  36. package/src/Client/UI/MenuAlignment.ts +0 -20
@@ -1,6 +1,52 @@
1
1
  import {Toast as BootstrapToast} from "bootstrap";
2
2
  import {Context, getIcon, toCss} from "../Context.js";
3
3
 
4
+ /**
5
+ * Represents a notification.
6
+ */
7
+ export interface IToast {
8
+
9
+ /**
10
+ * Value indicating whether to apply a fade transition.
11
+ */
12
+ animation?: boolean;
13
+
14
+ /**
15
+ * Value indicating whether to automatically hide the toast.
16
+ */
17
+ autoHide?: boolean;
18
+
19
+ /**
20
+ * The child content displayed in the body.
21
+ */
22
+ body: DocumentFragment|string;
23
+
24
+ /**
25
+ * The title displayed in the header.
26
+ */
27
+ caption: string;
28
+
29
+ /**
30
+ * The default contextual modifier.
31
+ */
32
+ context?: Context;
33
+
34
+ /**
35
+ * The culture used to format the relative time.
36
+ */
37
+ culture?: Intl.Locale;
38
+
39
+ /**
40
+ * The delay, in milliseconds, to hide the toast.
41
+ */
42
+ delay?: number;
43
+
44
+ /**
45
+ * The icon displayed next to the caption.
46
+ */
47
+ icon?: string|null;
48
+ }
49
+
4
50
  /**
5
51
  * Represents a notification.
6
52
  */
@@ -9,7 +55,7 @@ export class Toast extends HTMLElement {
9
55
  /**
10
56
  * The list of observed attributes.
11
57
  */
12
- static readonly observedAttributes = ["caption", "context", "culture", "icon", "open"];
58
+ static readonly observedAttributes = ["animation", "caption", "context", "culture", "icon", "open"];
13
59
 
14
60
  /**
15
61
  * The time units.
@@ -50,8 +96,7 @@ export class Toast extends HTMLElement {
50
96
  return this.hasAttribute("animation");
51
97
  }
52
98
  set animation(value: boolean) {
53
- if (value) this.setAttribute("animation", "");
54
- else this.removeAttribute("animation");
99
+ this.toggleAttribute("animation", value);
55
100
  }
56
101
 
57
102
  /**
@@ -61,8 +106,14 @@ export class Toast extends HTMLElement {
61
106
  return this.hasAttribute("autohide");
62
107
  }
63
108
  set autoHide(value: boolean) {
64
- if (value) this.setAttribute("autohide", "");
65
- else this.removeAttribute("autohide");
109
+ this.toggleAttribute("autohide", value);
110
+ }
111
+
112
+ /**
113
+ * The child content displayed in the body.
114
+ */
115
+ set body(value: DocumentFragment) { // eslint-disable-line accessor-pairs
116
+ this.querySelector(".toast-body")!.replaceChildren(...value.childNodes);
66
117
  }
67
118
 
68
119
  /**
@@ -75,13 +126,6 @@ export class Toast extends HTMLElement {
75
126
  this.setAttribute("caption", value);
76
127
  }
77
128
 
78
- /**
79
- * The child content displayed in the body.
80
- */
81
- set childContent(value: DocumentFragment) { // eslint-disable-line accessor-pairs
82
- this.querySelector(".toast-body")!.replaceChildren(...value.childNodes);
83
- }
84
-
85
129
  /**
86
130
  * A contextual modifier.
87
131
  */
@@ -125,12 +169,12 @@ export class Toast extends HTMLElement {
125
169
  /**
126
170
  * The icon displayed next to the caption.
127
171
  */
128
- get icon(): string {
172
+ get icon(): string|null {
129
173
  const value = this.getAttribute("icon") ?? "";
130
- return value.trim() || getIcon(this.context);
174
+ return value.trim() || null;
131
175
  }
132
- set icon(value: string) {
133
- this.setAttribute("icon", value);
176
+ set icon(value: string|null) {
177
+ this.toggleAttribute("icon", Boolean(value));
134
178
  }
135
179
 
136
180
  /**
@@ -140,8 +184,7 @@ export class Toast extends HTMLElement {
140
184
  return this.hasAttribute("open");
141
185
  }
142
186
  set open(value: boolean) {
143
- if (value) this.setAttribute("open", "");
144
- else this.removeAttribute("open");
187
+ this.toggleAttribute("open", value);
145
188
  }
146
189
 
147
190
  /**
@@ -152,29 +195,28 @@ export class Toast extends HTMLElement {
152
195
  */
153
196
  attributeChangedCallback(attribute: string, oldValue: string|null, newValue: string|null): void {
154
197
  if (newValue != oldValue) switch (attribute) {
155
- case "caption":
156
- this.#updateCaption(newValue ?? "");
157
- break;
158
- case "context":
159
- this.#updateContext(Object.values(Context).includes(newValue as Context) ? newValue as Context : Context.Info);
160
- break;
161
- case "culture":
162
- this.#formatter = new Intl.RelativeTimeFormat((newValue ?? "").trim() || navigator.language, {style: "long"});
163
- break;
164
- case "icon":
165
- this.#updateIcon(newValue ?? "");
166
- break;
167
- case "open":
168
- this.#updateVisibility();
198
+ case "animation": this.#updateAnimation(newValue != null); break;
199
+ case "caption": this.#updateCaption(newValue ?? ""); break;
200
+ case "context": this.#updateContext(Object.values(Context).includes(newValue as Context) ? newValue as Context : Context.Info); break;
201
+ case "culture": this.#formatter = new Intl.RelativeTimeFormat((newValue ?? "").trim() || navigator.language, {style: "long"}); break;
202
+ case "icon": this.#updateIcon(newValue); break;
203
+ case "open": this.#updateVisibility(newValue != null); break;
169
204
  // No default
170
205
  }
171
206
  }
172
207
 
208
+ /**
209
+ * Closes this toast.
210
+ */
211
+ close(): void {
212
+ this.#toast.hide();
213
+ }
214
+
173
215
  /**
174
216
  * Method invoked when this component is connected.
175
217
  */
176
218
  connectedCallback(): void {
177
- const toast = this.querySelector(".toast")!;
219
+ const toast = this.firstElementChild!;
178
220
  toast.addEventListener("hidden.bs.toast", () => clearInterval(this.#timer));
179
221
  toast.addEventListener("show.bs.toast", () => this.#timer = window.setInterval(this.#updateElapsedTime, 1_000));
180
222
 
@@ -190,13 +232,6 @@ export class Toast extends HTMLElement {
190
232
  this.#toast.dispose();
191
233
  }
192
234
 
193
- /**
194
- * Hides this toast.
195
- */
196
- hide(): void {
197
- this.#toast.hide();
198
- }
199
-
200
235
  /**
201
236
  * Shows this toast.
202
237
  */
@@ -224,6 +259,14 @@ export class Toast extends HTMLElement {
224
259
  return this.#formatter.format(Math.ceil(-elapsed), Toast.#timeUnits[index]);
225
260
  }
226
261
 
262
+ /**
263
+ * Updates the toast animation.
264
+ * @param value The new value.
265
+ */
266
+ #updateAnimation(value: boolean): void {
267
+ this.firstElementChild!.classList.toggle("fade", value);
268
+ }
269
+
227
270
  /**
228
271
  * Updates the title displayed in the header.
229
272
  * @param value The new value.
@@ -233,7 +276,7 @@ export class Toast extends HTMLElement {
233
276
  }
234
277
 
235
278
  /**
236
- * Updates the title displayed in the header.
279
+ * Updates the contextual modifier.
237
280
  * @param value The new value.
238
281
  */
239
282
  #updateContext(value: Context): void {
@@ -260,20 +303,16 @@ export class Toast extends HTMLElement {
260
303
  * Updates the icon displayed next to the caption.
261
304
  * @param value The new value.
262
305
  */
263
- #updateIcon(value: string): void {
264
- this.querySelector(".toast-header .icon")!.textContent = value.trim() || getIcon(this.context);
306
+ #updateIcon(value: string|null): void {
307
+ this.querySelector(".toast-header .icon")!.textContent = (value ?? "").trim() || getIcon(this.context);
265
308
  }
266
309
 
267
310
  /**
268
311
  * Updates the toast visibility.
312
+ * @param value The new value.
269
313
  */
270
- #updateVisibility(): void {
271
- const {classList} = this.firstElementChild!;
272
- if (!this.open) classList.remove("show");
273
- else {
274
- if (this.animation) classList.add("fade");
275
- classList.add("show");
276
- }
314
+ #updateVisibility(value: boolean): void {
315
+ this.firstElementChild!.classList.toggle("show", value);
277
316
  }
278
317
  }
279
318
 
@@ -1,52 +1,7 @@
1
1
  import {Context} from "../Context.js";
2
2
  import {createDocumentFragment} from "../ElementExtensions.js";
3
3
  import {Position, toCss} from "../Position.js";
4
-
5
- /**
6
- * Represents a notification.
7
- */
8
- export interface IToast {
9
-
10
- /**
11
- * Value indicating whether to apply a fade transition.
12
- */
13
- animation?: boolean;
14
-
15
- /**
16
- * Value indicating whether to automatically hide the toast.
17
- */
18
- autoHide?: boolean;
19
-
20
- /**
21
- * The title displayed in the header.
22
- */
23
- caption: string;
24
-
25
- /**
26
- * The child content displayed in the body.
27
- */
28
- childContent: DocumentFragment|string;
29
-
30
- /**
31
- * The default contextual modifier.
32
- */
33
- context?: Context;
34
-
35
- /**
36
- * The culture used to format the relative time.
37
- */
38
- culture?: Intl.Locale;
39
-
40
- /**
41
- * The delay, in milliseconds, to hide the toast.
42
- */
43
- delay?: number;
44
-
45
- /**
46
- * The icon displayed next to the caption.
47
- */
48
- icon?: string;
49
- }
4
+ import type {IToast} from "./Toast.js";
50
5
 
51
6
  /**
52
7
  * Manages the notifications.
@@ -77,8 +32,7 @@ export class Toaster extends HTMLElement {
77
32
  return this.hasAttribute("animation");
78
33
  }
79
34
  set animation(value: boolean) {
80
- if (value) this.setAttribute("animation", "");
81
- else this.removeAttribute("animation");
35
+ this.toggleAttribute("animation", value);
82
36
  }
83
37
 
84
38
  /**
@@ -88,8 +42,7 @@ export class Toaster extends HTMLElement {
88
42
  return this.hasAttribute("autohide");
89
43
  }
90
44
  set autoHide(value: boolean) {
91
- if (value) this.setAttribute("autohide", "");
92
- else this.removeAttribute("autohide");
45
+ this.toggleAttribute("autohide", value);
93
46
  }
94
47
 
95
48
  /**
@@ -128,11 +81,12 @@ export class Toaster extends HTMLElement {
128
81
  /**
129
82
  * The default icon displayed next to the captions.
130
83
  */
131
- get icon(): string {
132
- return (this.getAttribute("icon") ?? "").trim();
84
+ get icon(): string|null {
85
+ const value = this.getAttribute("icon") ?? "";
86
+ return value.trim() || null;
133
87
  }
134
- set icon(value: string) {
135
- this.setAttribute("icon", value);
88
+ set icon(value: string|null) {
89
+ this.toggleAttribute("icon", Boolean(value));
136
90
  }
137
91
 
138
92
  /**
@@ -165,10 +119,10 @@ export class Toaster extends HTMLElement {
165
119
  * Shows a toast.
166
120
  * @param context The contextual modifier.
167
121
  * @param caption The title displayed in the toast header.
168
- * @param childContent The child content displayed in the toast body.
122
+ * @param body The child content displayed in the toast body.
169
123
  */
170
- notify(context: Context, caption: string, childContent: DocumentFragment|string): void {
171
- this.show({context, caption, childContent});
124
+ notify(context: Context, caption: string, body: DocumentFragment|string): void {
125
+ this.show({context, caption, body});
172
126
  }
173
127
 
174
128
  /**
@@ -182,8 +136,8 @@ export class Toaster extends HTMLElement {
182
136
 
183
137
  item.animation = toast.animation ?? this.animation;
184
138
  item.autoHide = toast.autoHide ?? this.autoHide;
139
+ item.body = typeof toast.body == "string" ? createDocumentFragment(toast.body) : toast.body;
185
140
  item.caption = toast.caption;
186
- item.childContent = typeof toast.childContent == "string" ? createDocumentFragment(toast.childContent) : toast.childContent;
187
141
  item.context = toast.context ?? this.context;
188
142
  item.culture = toast.culture ?? this.culture;
189
143
  item.delay = toast.delay ?? this.delay;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Specifies the return value of a dialog box.
3
+ */
4
+ export const DialogResult = Object.freeze({
5
+
6
+ /**
7
+ * The dialog box does not return any value.
8
+ */
9
+ None: "None",
10
+
11
+ /**
12
+ * The return value of the dialog box is "OK".
13
+ */
14
+ OK: "OK",
15
+
16
+ /**
17
+ * The return value of the dialog box is "Cancel".
18
+ */
19
+ Cancel: "Cancel",
20
+
21
+ /**
22
+ * The return value of the dialog box is "Abort".
23
+ */
24
+ Abort: "Abort",
25
+
26
+ /**
27
+ * The return value of the dialog box is "Retry".
28
+ */
29
+ Retry: "Retry",
30
+
31
+ /**
32
+ * The return value of the dialog box is "Ignore".
33
+ */
34
+ Ignore: "Ignore",
35
+
36
+ /**
37
+ * The return value of the dialog box is "Yes".
38
+ */
39
+ Yes: "Yes",
40
+
41
+ /**
42
+ * The return value of the dialog box is "No".
43
+ */
44
+ No: "No"
45
+ });
46
+
47
+ /**
48
+ * Specifies the return value of a dialog box.
49
+ */
50
+ export type DialogResult = typeof DialogResult[keyof typeof DialogResult];
@@ -1,24 +0,0 @@
1
- import { LitElement, type CSSResultGroup } from "lit";
2
- /**
3
- * Optional base class for UI components. Alternatively, components may extend {@link LitElement} directly.
4
- */
5
- export declare abstract class ComponentBase extends LitElement {
6
- #private;
7
- /**
8
- * The component styles.
9
- */
10
- static styles: CSSResultGroup;
11
- /**
12
- * Creates a new component.
13
- * @param options Value indicating whether a shadow DOM tree should be attached to this component.
14
- */
15
- constructor(options?: {
16
- attachShadow?: boolean;
17
- });
18
- /**
19
- * Returns the node into which this component should render.
20
- * @returns The node into which this component should render.
21
- */
22
- protected createRenderRoot(): DocumentFragment | HTMLElement;
23
- }
24
- //# sourceMappingURL=ComponentBase.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ComponentBase.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/ComponentBase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,KAAK,cAAc,EAAC,MAAM,KAAK,CAAC;AAEpD;;GAEG;AACH,8BAAsB,aAAc,SAAQ,UAAU;;IAErD;;OAEG;IACH,OAAgB,MAAM,EAAE,cAAc,CAAiC;IAOvE;;;OAGG;gBACS,OAAO,GAAE;QAAC,YAAY,CAAC,EAAE,OAAO,CAAA;KAAM;IAKlD;;;OAGG;cACgB,gBAAgB,IAAI,gBAAgB,GAAC,WAAW;CAGnE"}
@@ -1,29 +0,0 @@
1
- import { LitElement } from "lit";
2
- /**
3
- * Optional base class for UI components. Alternatively, components may extend {@link LitElement} directly.
4
- */
5
- export class ComponentBase extends LitElement {
6
- /**
7
- * The component styles.
8
- */
9
- static styles = [document.adoptedStyleSheets];
10
- /**
11
- * Value indicating whether a shadow DOM tree should be attached to this component.
12
- */
13
- #attachShadow;
14
- /**
15
- * Creates a new component.
16
- * @param options Value indicating whether a shadow DOM tree should be attached to this component.
17
- */
18
- constructor(options = {}) {
19
- super();
20
- this.#attachShadow = options.attachShadow ?? false;
21
- }
22
- /**
23
- * Returns the node into which this component should render.
24
- * @returns The node into which this component should render.
25
- */
26
- createRenderRoot() {
27
- return this.#attachShadow ? super.createRenderRoot() : this;
28
- }
29
- }
@@ -1,18 +0,0 @@
1
- /**
2
- * Defines the alignment of a dropdown menu.
3
- */
4
- export declare const MenuAlignment: Readonly<{
5
- /**
6
- * The dropdown menu is left aligned.
7
- */
8
- Start: "Start";
9
- /**
10
- * The dropdown menu is right aligned.
11
- */
12
- End: "End";
13
- }>;
14
- /**
15
- * Defines the alignment of a dropdown menu.
16
- */
17
- export type MenuAlignment = typeof MenuAlignment[keyof typeof MenuAlignment];
18
- //# sourceMappingURL=MenuAlignment.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"MenuAlignment.d.ts","sourceRoot":"","sources":["../../src/Client/UI/MenuAlignment.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,aAAa;IAEzB;;OAEG;;IAGH;;OAEG;;EAEF,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC"}
@@ -1,13 +0,0 @@
1
- /**
2
- * Defines the alignment of a dropdown menu.
3
- */
4
- export const MenuAlignment = Object.freeze({
5
- /**
6
- * The dropdown menu is left aligned.
7
- */
8
- Start: "Start",
9
- /**
10
- * The dropdown menu is right aligned.
11
- */
12
- End: "End"
13
- });
@@ -1,34 +0,0 @@
1
- import {LitElement, type CSSResultGroup} from "lit";
2
-
3
- /**
4
- * Optional base class for UI components. Alternatively, components may extend {@link LitElement} directly.
5
- */
6
- export abstract class ComponentBase extends LitElement {
7
-
8
- /**
9
- * The component styles.
10
- */
11
- static override styles: CSSResultGroup = [document.adoptedStyleSheets];
12
-
13
- /**
14
- * Value indicating whether a shadow DOM tree should be attached to this component.
15
- */
16
- readonly #attachShadow: boolean;
17
-
18
- /**
19
- * Creates a new component.
20
- * @param options Value indicating whether a shadow DOM tree should be attached to this component.
21
- */
22
- constructor(options: {attachShadow?: boolean} = {}) {
23
- super();
24
- this.#attachShadow = options.attachShadow ?? false;
25
- }
26
-
27
- /**
28
- * Returns the node into which this component should render.
29
- * @returns The node into which this component should render.
30
- */
31
- protected override createRenderRoot(): DocumentFragment|HTMLElement {
32
- return this.#attachShadow ? super.createRenderRoot() : this;
33
- }
34
- }
@@ -1,20 +0,0 @@
1
- /**
2
- * Defines the alignment of a dropdown menu.
3
- */
4
- export const MenuAlignment = Object.freeze({
5
-
6
- /**
7
- * The dropdown menu is left aligned.
8
- */
9
- Start: "Start",
10
-
11
- /**
12
- * The dropdown menu is right aligned.
13
- */
14
- End: "End"
15
- });
16
-
17
- /**
18
- * Defines the alignment of a dropdown menu.
19
- */
20
- export type MenuAlignment = typeof MenuAlignment[keyof typeof MenuAlignment];