@cedx/base 0.18.0 → 0.20.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 (82) hide show
  1. package/ReadMe.md +1 -1
  2. package/lib/{DateExtensions.d.ts → Date.d.ts} +9 -9
  3. package/lib/Date.d.ts.map +1 -0
  4. package/lib/{DateExtensions.js → Date.js} +12 -10
  5. package/lib/{FileExtensions.d.ts → File.d.ts} +1 -1
  6. package/lib/File.d.ts.map +1 -0
  7. package/lib/{NumberExtensions.d.ts → Number.d.ts} +1 -1
  8. package/lib/Number.d.ts.map +1 -0
  9. package/lib/{StringExtensions.d.ts → String.d.ts} +1 -19
  10. package/lib/String.d.ts.map +1 -0
  11. package/lib/{StringExtensions.js → String.js} +0 -40
  12. package/lib/UI/Components/LoadingIndicator.d.ts +16 -0
  13. package/lib/UI/Components/LoadingIndicator.d.ts.map +1 -1
  14. package/lib/UI/Components/LoadingIndicator.js +41 -2
  15. package/lib/UI/Components/MessageBox.d.ts +7 -7
  16. package/lib/UI/Components/MessageBox.d.ts.map +1 -1
  17. package/lib/UI/Components/MessageBox.js +4 -5
  18. package/lib/UI/Components/OfflineIndicator.d.ts +16 -0
  19. package/lib/UI/Components/OfflineIndicator.d.ts.map +1 -1
  20. package/lib/UI/Components/OfflineIndicator.js +39 -1
  21. package/lib/UI/Components/Toast.d.ts +3 -3
  22. package/lib/UI/Components/Toast.d.ts.map +1 -1
  23. package/lib/UI/Components/Toast.js +2 -2
  24. package/lib/UI/Components/Toaster.d.ts +2 -2
  25. package/lib/UI/Components/Toaster.d.ts.map +1 -1
  26. package/lib/UI/Components/Toaster.js +3 -4
  27. package/lib/UI/{FormExtensions.d.ts → Form.d.ts} +1 -1
  28. package/lib/UI/Form.d.ts.map +1 -0
  29. package/lib/UI/Tag.d.ts +15 -0
  30. package/lib/UI/Tag.d.ts.map +1 -0
  31. package/lib/UI/Tag.js +42 -0
  32. package/package.json +2 -2
  33. package/src/Client/{DateExtensions.ts → Date.ts} +13 -10
  34. package/src/Client/{StringExtensions.ts → String.ts} +0 -40
  35. package/src/Client/UI/Components/LoadingIndicator.ts +42 -2
  36. package/src/Client/UI/Components/MessageBox.ts +10 -11
  37. package/src/Client/UI/Components/OfflineIndicator.ts +40 -1
  38. package/src/Client/UI/Components/Toast.ts +4 -4
  39. package/src/Client/UI/Components/Toaster.ts +4 -5
  40. package/src/Client/UI/Tag.ts +50 -0
  41. package/src/Client/tsconfig.json +0 -2
  42. package/lib/DateExtensions.d.ts.map +0 -1
  43. package/lib/FileExtensions.d.ts.map +0 -1
  44. package/lib/Hosting/Environment.d.ts +0 -22
  45. package/lib/Hosting/Environment.d.ts.map +0 -1
  46. package/lib/Hosting/Environment.js +0 -17
  47. package/lib/Hosting/HostEnvironment.d.ts +0 -61
  48. package/lib/Hosting/HostEnvironment.d.ts.map +0 -1
  49. package/lib/Hosting/HostEnvironment.js +0 -56
  50. package/lib/Net/Http/HttpMethod.d.ts +0 -46
  51. package/lib/Net/Http/HttpMethod.d.ts.map +0 -1
  52. package/lib/Net/Http/HttpMethod.js +0 -41
  53. package/lib/Net/Http/StatusCode.d.ts +0 -122
  54. package/lib/Net/Http/StatusCode.d.ts.map +0 -1
  55. package/lib/Net/Http/StatusCode.js +0 -117
  56. package/lib/Net/Mime/DispositionType.d.ts +0 -18
  57. package/lib/Net/Mime/DispositionType.d.ts.map +0 -1
  58. package/lib/Net/Mime/DispositionType.js +0 -13
  59. package/lib/Net/Mime/MediaType.d.ts +0 -151
  60. package/lib/Net/Mime/MediaType.d.ts.map +0 -1
  61. package/lib/Net/Mime/MediaType.js +0 -150
  62. package/lib/NumberExtensions.d.ts.map +0 -1
  63. package/lib/StringExtensions.d.ts.map +0 -1
  64. package/lib/UI/ElementExtensions.d.ts +0 -13
  65. package/lib/UI/ElementExtensions.d.ts.map +0 -1
  66. package/lib/UI/ElementExtensions.js +0 -18
  67. package/lib/UI/FormExtensions.d.ts.map +0 -1
  68. package/src/Client/Hosting/Environment.ts +0 -25
  69. package/src/Client/Hosting/HostEnvironment.ts +0 -86
  70. package/src/Client/Hosting/tsconfig.json +0 -13
  71. package/src/Client/Net/Http/HttpMethod.ts +0 -55
  72. package/src/Client/Net/Http/StatusCode.ts +0 -150
  73. package/src/Client/Net/Mime/DispositionType.ts +0 -20
  74. package/src/Client/Net/Mime/MediaType.ts +0 -185
  75. package/src/Client/Net/tsconfig.json +0 -13
  76. package/src/Client/UI/ElementExtensions.ts +0 -19
  77. /package/lib/{FileExtensions.js → File.js} +0 -0
  78. /package/lib/{NumberExtensions.js → Number.js} +0 -0
  79. /package/lib/UI/{FormExtensions.js → Form.js} +0 -0
  80. /package/src/Client/{FileExtensions.ts → File.ts} +0 -0
  81. /package/src/Client/{NumberExtensions.ts → Number.ts} +0 -0
  82. /package/src/Client/UI/{FormExtensions.ts → Form.ts} +0 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Creates a CSS stylesheet from the specified template literal.
3
+ * @param fragments The string fragments.
4
+ * @param values The interpolated values.
5
+ * @returns The CSS stylesheet corresponding to the specified template literal.
6
+ */
7
+ export declare function css(fragments: TemplateStringsArray, ...values: unknown[]): CSSStyleSheet;
8
+ /**
9
+ * Creates a document fragment from the specified template literal.
10
+ * @param fragments The string fragments.
11
+ * @param values The interpolated values.
12
+ * @returns The document fragment corresponding to the specified template literal.
13
+ */
14
+ export declare function html(fragments: TemplateStringsArray, ...values: unknown[]): DocumentFragment;
15
+ //# sourceMappingURL=Tag.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tag.d.ts","sourceRoot":"","sources":["../../src/Client/UI/Tag.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,wBAAgB,GAAG,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,aAAa,CAQxF;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,GAAG,gBAAgB,CAK5F"}
package/lib/UI/Tag.js ADDED
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Creates a CSS stylesheet from the specified template literal.
3
+ * @param fragments The string fragments.
4
+ * @param values The interpolated values.
5
+ * @returns The CSS stylesheet corresponding to the specified template literal.
6
+ */
7
+ export function css(fragments, ...values) {
8
+ const styleSheet = new CSSStyleSheet;
9
+ styleSheet.replaceSync(fragments.length == 1 ? fragments[0] : values.reduce((fragment, value, index) => fragment + stringFromCss(value) + fragments[index + 1], fragments[0]));
10
+ return styleSheet;
11
+ }
12
+ /**
13
+ * Creates a document fragment from the specified template literal.
14
+ * @param fragments The string fragments.
15
+ * @param values The interpolated values.
16
+ * @returns The document fragment corresponding to the specified template literal.
17
+ */
18
+ export function html(fragments, ...values) {
19
+ return document.createRange().createContextualFragment(fragments.length == 1 ? fragments[0] : values.reduce((fragment, value, index) => fragment + stringFromHtml(value) + fragments[index + 1], fragments[0]));
20
+ }
21
+ /**
22
+ * Converts the specified value to a CSS string.
23
+ * @param value A value representing a CSS fragment.
24
+ * @returns The CSS string corresponding to the specified value.
25
+ */
26
+ function stringFromCss(value) {
27
+ if (!(value instanceof CSSStyleSheet))
28
+ return String(value);
29
+ return Array.from(value.cssRules).map(cssRule => cssRule.cssText).join("\n");
30
+ }
31
+ /**
32
+ * Converts the specified value to an HTML string.
33
+ * @param value A value representing an HTML fragment.
34
+ * @returns The HTML string corresponding to the specified value.
35
+ */
36
+ function stringFromHtml(value) {
37
+ if (!(value instanceof DocumentFragment))
38
+ return String(value);
39
+ const element = document.createElement("div");
40
+ element.appendChild(value);
41
+ return element.innerHTML;
42
+ }
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "name": "@cedx/base",
8
8
  "repository": "cedx/base",
9
9
  "type": "module",
10
- "version": "0.18.0",
10
+ "version": "0.20.0",
11
11
  "devDependencies": {
12
12
  "@playwright/browser-chromium": "^1.55.0",
13
13
  "@types/bootstrap": "^5.2.10",
@@ -23,7 +23,7 @@
23
23
  "serve-handler": "^6.1.6",
24
24
  "typedoc": "^0.28.11",
25
25
  "typescript": "^5.9.2",
26
- "typescript-eslint": "^8.40.0"
26
+ "typescript-eslint": "^8.41.0"
27
27
  },
28
28
  "engines": {
29
29
  "node": ">=24.0.0"
@@ -19,11 +19,13 @@ export function daysInMonth(date: Date): number {
19
19
  }
20
20
 
21
21
  /**
22
- * Gets the date of Easter for a given year.
23
- * @param year The year.
24
- * @returns The date of Easter for the specified year.
22
+ * Gets the date of Easter for the year corresponding to the specified date.
23
+ * @param date The date.
24
+ * @returns The date of Easter for the year corresponding to the specified date.
25
25
  */
26
- export function getEaster(year = new Date().getFullYear()): Date {
26
+ export function getEaster(date: Date): Date {
27
+ const year = date.getFullYear();
28
+
27
29
  /* eslint-disable id-length */
28
30
  const n = year % 19;
29
31
  const c = Math.trunc(year / 100);
@@ -38,12 +40,13 @@ export function getEaster(year = new Date().getFullYear()): Date {
38
40
  }
39
41
 
40
42
  /**
41
- * Gets the list of holidays for a given year.
42
- * @param year The year.
43
- * @returns The list of holidays for the specified year.
43
+ * Gets the list of holidays for the year corresponding to the specified date.
44
+ * @param date The date.
45
+ * @returns The list of holidays for the year corresponding to the specified date.
44
46
  */
45
- export function getHolidays(year = new Date().getFullYear()): Date[] {
47
+ export function getHolidays(date: Date): Date[] {
46
48
  const holidays = [];
49
+ const year = date.getFullYear();
47
50
 
48
51
  // Fixed holidays.
49
52
  holidays.push(new Date(year, 0, 1)); // New year.
@@ -56,7 +59,7 @@ export function getHolidays(year = new Date().getFullYear()): Date[] {
56
59
  holidays.push(new Date(year, 11, 25)); // Christmas.
57
60
 
58
61
  // Holidays depending on Easter.
59
- const easter = getEaster(year);
62
+ const easter = getEaster(date);
60
63
  holidays.push(new Date(easter.getTime() + Duration.Day)); // Easter monday.
61
64
  holidays.push(new Date(easter.getTime() + (39 * Duration.Day))); // Ascension thursday.
62
65
  holidays.push(new Date(easter.getTime() + (50 * Duration.Day))); // Pentecost monday.
@@ -101,7 +104,7 @@ export function inLeapYear(date: Date): boolean {
101
104
  */
102
105
  export function isHoliday(date: Date): boolean {
103
106
  const timestamp = atMidnight(date).getTime();
104
- return getHolidays(date.getFullYear()).some(holiday => holiday.getTime() == timestamp);
107
+ return getHolidays(date).some(holiday => holiday.getTime() == timestamp);
105
108
  }
106
109
 
107
110
  /**
@@ -1,14 +1,3 @@
1
- /**
2
- * The mapping between special characters and the corresponding XML entities.
3
- */
4
- const xmlEntities = new Map([
5
- ["&", "&"],
6
- ["<", "&lt;"],
7
- [">", "&gt;"],
8
- ['"', "&quot;"],
9
- ["'", "&#39;"]
10
- ]);
11
-
12
1
  /**
13
2
  * Converts the first character to uppercase.
14
3
  * @param value The string to process.
@@ -56,26 +45,6 @@ export function stripTags(value: string): string {
56
45
  return value.replace(/<[^>]+>/g, "");
57
46
  }
58
47
 
59
- /**
60
- * Removes whitespace from both ends of the items of the specified array.
61
- * @param array The array to process.
62
- * @returns The input array.
63
- */
64
- export function trimArray<T>(array: T[]): T[] {
65
- for (const [index, value] of array.entries()) if (typeof value == "string") Reflect.set(array, index, value.trim());
66
- return array;
67
- }
68
-
69
- /**
70
- * Removes whitespace from both ends of the properties of the specified object.
71
- * @param object The object to process.
72
- * @returns The input object.
73
- */
74
- export function trimObject<T>(object: Record<string, T>): Record<string, T> {
75
- for (const [key, value] of Object.entries(object)) if (typeof value == "string") Reflect.set(object, key, value.trim());
76
- return object;
77
- }
78
-
79
48
  /**
80
49
  * Truncates the specified string to the given number of characters.
81
50
  * @param value The string to be truncated.
@@ -86,12 +55,3 @@ export function trimObject<T>(object: Record<string, T>): Record<string, T> {
86
55
  export function truncate(value: string, length: number, ellipsis = "..."): string {
87
56
  return value.length > length ? value.slice(0, length) + ellipsis : value;
88
57
  }
89
-
90
- /**
91
- * Replaces invalid XML characters in a string with their valid XML equivalent.
92
- * @param value The string to process.
93
- * @returns The processed string.
94
- */
95
- export function xmlEscape(value: string): string {
96
- return value.replace(/[&<>"']/g, character => xmlEntities.get(character) ?? character);
97
- }
@@ -3,6 +3,11 @@
3
3
  */
4
4
  export class LoadingIndicator extends HTMLElement {
5
5
 
6
+ /**
7
+ * The list of observed attributes.
8
+ */
9
+ static readonly observedAttributes = ["animation"];
10
+
6
11
  /**
7
12
  * The number of concurrent HTTP requests.
8
13
  */
@@ -15,6 +20,29 @@ export class LoadingIndicator extends HTMLElement {
15
20
  customElements.define("loading-indicator", this);
16
21
  }
17
22
 
23
+ /**
24
+ * Value indicating whether to apply a transition.
25
+ */
26
+ get animation(): boolean {
27
+ return this.hasAttribute("animation");
28
+ }
29
+ set animation(value: boolean) {
30
+ this.toggleAttribute("animation", value);
31
+ }
32
+
33
+ /**
34
+ * Method invoked when an attribute has been changed.
35
+ * @param attribute The attribute name.
36
+ * @param oldValue The previous attribute value.
37
+ * @param newValue The new attribute value.
38
+ */
39
+ attributeChangedCallback(attribute: string, oldValue: string|null, newValue: string|null): void {
40
+ if (newValue != oldValue) switch (attribute) {
41
+ case "animation": this.#updateAnimation(newValue != null); break;
42
+ // No default
43
+ }
44
+ }
45
+
18
46
  /**
19
47
  * Hides the loading indicator.
20
48
  * @param options Value indicating whether to force the loading indicator to hide.
@@ -23,7 +51,9 @@ export class LoadingIndicator extends HTMLElement {
23
51
  this.#requestCount--;
24
52
  if (this.#requestCount <= 0 || options.force) {
25
53
  this.#requestCount = 0;
26
- this.hidden = true;
54
+ this.classList.add("hide");
55
+ this.classList.remove("show");
56
+ document.body.classList.remove("loading");
27
57
  }
28
58
  }
29
59
 
@@ -32,7 +62,17 @@ export class LoadingIndicator extends HTMLElement {
32
62
  */
33
63
  show(): void {
34
64
  this.#requestCount++;
35
- this.hidden = false;
65
+ this.classList.remove("hide");
66
+ this.classList.add("show");
67
+ document.body.classList.add("loading");
68
+ }
69
+
70
+ /**
71
+ * Updates the value indicating whether to apply a transition.
72
+ * @param value The new value.
73
+ */
74
+ #updateAnimation(value: boolean): void {
75
+ this.classList.toggle("fade", value);
36
76
  }
37
77
  }
38
78
 
@@ -1,7 +1,6 @@
1
1
  import {Modal} from "bootstrap";
2
2
  import {Context, getIcon, toCss} from "../Context.js";
3
3
  import {DialogResult} from "../DialogResult.js";
4
- import {createDocumentFragment} from "../ElementExtensions.js";
5
4
  import {Variant} from "../Variant.js";
6
5
  import type {DialogButton, IDialogButton} from "./DialogButton.js";
7
6
 
@@ -11,14 +10,14 @@ import type {DialogButton, IDialogButton} from "./DialogButton.js";
11
10
  export interface IMessage {
12
11
 
13
12
  /**
14
- * Value indicating whether to apply a fade transition.
13
+ * Value indicating whether to apply a transition.
15
14
  */
16
15
  animation?: boolean;
17
16
 
18
17
  /**
19
18
  * The child content displayed in the body.
20
19
  */
21
- body: DocumentFragment|string;
20
+ body: DocumentFragment;
22
21
 
23
22
  /**
24
23
  * The title displayed in the header.
@@ -38,7 +37,7 @@ export interface IMessage {
38
37
  /**
39
38
  * The child content displayed in the footer.
40
39
  */
41
- footer?: DocumentFragment|string;
40
+ footer?: DocumentFragment;
42
41
 
43
42
  /**
44
43
  * The icon displayed next to the body.
@@ -99,7 +98,7 @@ export class MessageBox extends HTMLElement {
99
98
  }
100
99
 
101
100
  /**
102
- * Value indicating whether to apply a fade transition.
101
+ * Value indicating whether to apply a transition.
103
102
  */
104
103
  get animation(): boolean {
105
104
  return this.hasAttribute("animation");
@@ -222,7 +221,7 @@ export class MessageBox extends HTMLElement {
222
221
  * @param body The child content displayed in the body.
223
222
  * @returns The dialog box result.
224
223
  */
225
- async alert(context: Context, caption: string, body: DocumentFragment|string): Promise<DialogResult> {
224
+ async alert(context: Context, caption: string, body: DocumentFragment): Promise<DialogResult> {
226
225
  return await this.show(context, caption, body, [
227
226
  {label: "OK", value: DialogResult.OK, variant: Variant.Primary}
228
227
  ]);
@@ -244,7 +243,7 @@ export class MessageBox extends HTMLElement {
244
243
  * @param body The child content displayed in the body.
245
244
  * @returns The dialog box result.
246
245
  */
247
- async confirm(context: Context, caption: string, body: DocumentFragment|string): Promise<DialogResult> {
246
+ async confirm(context: Context, caption: string, body: DocumentFragment): Promise<DialogResult> {
248
247
  return await this.show(context, caption, body, [
249
248
  {label: "OK", value: DialogResult.OK, variant: Variant.Primary},
250
249
  {label: "Annuler", value: DialogResult.Cancel, variant: Variant.Secondary}
@@ -281,7 +280,7 @@ export class MessageBox extends HTMLElement {
281
280
  * @param buttons The buttons displayed in the footer.
282
281
  * @returns The dialog box result.
283
282
  */
284
- show(context: Context, caption: string, body: DocumentFragment|string, buttons?: IDialogButton[]): Promise<DialogResult>;
283
+ show(context: Context, caption: string, body: DocumentFragment, buttons?: IDialogButton[]): Promise<DialogResult>;
285
284
 
286
285
  /**
287
286
  * Shows a message.
@@ -291,7 +290,7 @@ export class MessageBox extends HTMLElement {
291
290
  * @param buttons The buttons displayed in the footer.
292
291
  * @returns The dialog box result.
293
292
  */
294
- show(message: IMessage|Context|null = null, caption = "", body: DocumentFragment|string = "", buttons: IDialogButton[] = []): Promise<DialogResult> {
293
+ show(message: IMessage|Context|null = null, caption = "", body = document.createDocumentFragment(), buttons: IDialogButton[] = []): Promise<DialogResult> {
295
294
  if (typeof message == "string") {
296
295
  const footer = document.createDocumentFragment();
297
296
  footer.append(...buttons.map(button => this.#createButton(button)));
@@ -299,12 +298,12 @@ export class MessageBox extends HTMLElement {
299
298
  }
300
299
 
301
300
  if (typeof message == "object" && message) {
302
- this.body = typeof message.body == "string" ? createDocumentFragment(message.body) : message.body;
301
+ this.body = message.body;
303
302
  this.caption = message.caption;
304
303
  this.context = message.context ?? Context.Info;
305
304
  this.icon = message.icon ?? getIcon(this.context);
306
305
 
307
- const footer = typeof message.footer == "string" ? createDocumentFragment(message.footer) : (message.footer ?? document.createDocumentFragment());
306
+ const footer = message.footer ?? document.createDocumentFragment();
308
307
  for (const button of footer.querySelectorAll("button")) button.addEventListener("click", this.#close);
309
308
  this.footer = footer;
310
309
  }
@@ -3,6 +3,11 @@
3
3
  */
4
4
  export class OfflineIndicator extends HTMLElement {
5
5
 
6
+ /**
7
+ * The list of observed attributes.
8
+ */
9
+ static readonly observedAttributes = ["animation"];
10
+
6
11
  /**
7
12
  * Registers the component.
8
13
  */
@@ -10,6 +15,29 @@ export class OfflineIndicator extends HTMLElement {
10
15
  customElements.define("offline-indicator", this);
11
16
  }
12
17
 
18
+ /**
19
+ * Value indicating whether to apply a transition.
20
+ */
21
+ get animation(): boolean {
22
+ return this.hasAttribute("animation");
23
+ }
24
+ set animation(value: boolean) {
25
+ this.toggleAttribute("animation", value);
26
+ }
27
+
28
+ /**
29
+ * Method invoked when an attribute has been changed.
30
+ * @param attribute The attribute name.
31
+ * @param oldValue The previous attribute value.
32
+ * @param newValue The new attribute value.
33
+ */
34
+ attributeChangedCallback(attribute: string, oldValue: string|null, newValue: string|null): void {
35
+ if (newValue != oldValue) switch (attribute) {
36
+ case "animation": this.#updateAnimation(newValue != null); break;
37
+ // No default
38
+ }
39
+ }
40
+
13
41
  /**
14
42
  * Method invoked when this component is connected.
15
43
  */
@@ -25,10 +53,21 @@ export class OfflineIndicator extends HTMLElement {
25
53
  for (const event of ["online", "offline"]) removeEventListener(event, this.#update);
26
54
  }
27
55
 
56
+ /**
57
+ * Updates the value indicating whether to apply a transition.
58
+ * @param value The new value.
59
+ */
60
+ #updateAnimation(value: boolean): void {
61
+ this.classList.toggle("fade", value);
62
+ }
63
+
28
64
  /**
29
65
  * Updates this component.
30
66
  */
31
- readonly #update: () => void = () => this.hidden = navigator.onLine;
67
+ readonly #update: () => void = () => {
68
+ this.classList.toggle("hide", navigator.onLine);
69
+ this.classList.toggle("show", !navigator.onLine);
70
+ }
32
71
  }
33
72
 
34
73
  /**
@@ -7,7 +7,7 @@ import {Context, getIcon, toCss} from "../Context.js";
7
7
  export interface IToast {
8
8
 
9
9
  /**
10
- * Value indicating whether to apply a fade transition.
10
+ * Value indicating whether to apply a transition.
11
11
  */
12
12
  animation?: boolean;
13
13
 
@@ -19,7 +19,7 @@ export interface IToast {
19
19
  /**
20
20
  * The child content displayed in the body.
21
21
  */
22
- body: DocumentFragment|string;
22
+ body: DocumentFragment;
23
23
 
24
24
  /**
25
25
  * The title displayed in the header.
@@ -90,7 +90,7 @@ export class Toast extends HTMLElement {
90
90
  }
91
91
 
92
92
  /**
93
- * Value indicating whether to apply a fade transition.
93
+ * Value indicating whether to apply a transition.
94
94
  */
95
95
  get animation(): boolean {
96
96
  return this.hasAttribute("animation");
@@ -262,7 +262,7 @@ export class Toast extends HTMLElement {
262
262
  }
263
263
 
264
264
  /**
265
- * Updates the value indicating whether to apply a fade transition.
265
+ * Updates the value indicating whether to apply a transition.
266
266
  * @param value The new value.
267
267
  */
268
268
  #updateAnimation(value: boolean): void {
@@ -1,5 +1,4 @@
1
1
  import {Context} from "../Context.js";
2
- import {createDocumentFragment} from "../ElementExtensions.js";
3
2
  import {Position, toCss} from "../Position.js";
4
3
  import type {IToast} from "./Toast.js";
5
4
 
@@ -34,7 +33,7 @@ export class Toaster extends HTMLElement {
34
33
  }
35
34
 
36
35
  /**
37
- * Value indicating whether to apply a fade transition.
36
+ * Value indicating whether to apply a transition.
38
37
  */
39
38
  get animation(): boolean {
40
39
  return this.hasAttribute("animation");
@@ -128,7 +127,7 @@ export class Toaster extends HTMLElement {
128
127
  * @param caption The title displayed in the toast header.
129
128
  * @param body The child content displayed in the toast body.
130
129
  */
131
- show(context: Context, caption: string, body: DocumentFragment|string): void;
130
+ show(context: Context, caption: string, body: DocumentFragment): void;
132
131
 
133
132
  /**
134
133
  * Shows a toast.
@@ -142,7 +141,7 @@ export class Toaster extends HTMLElement {
142
141
  * @param caption The title displayed in the toast header.
143
142
  * @param body The child content displayed in the toast body.
144
143
  */
145
- show(toast: IToast|Context, caption = "", body: DocumentFragment|string = ""): void {
144
+ show(toast: IToast|Context, caption = "", body = document.createDocumentFragment()): void {
146
145
  if (typeof toast == "string") toast = {context: toast, caption, body};
147
146
 
148
147
  const item = document.createElement("toaster-item");
@@ -152,7 +151,7 @@ export class Toaster extends HTMLElement {
152
151
 
153
152
  item.animation = toast.animation ?? this.animation;
154
153
  item.autoHide = toast.autoHide ?? this.autoHide;
155
- item.body = typeof toast.body == "string" ? createDocumentFragment(toast.body) : toast.body;
154
+ item.body = toast.body;
156
155
  item.caption = toast.caption;
157
156
  item.context = toast.context ?? this.context;
158
157
  item.culture = toast.culture ?? this.culture;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Creates a CSS stylesheet from the specified template literal.
3
+ * @param fragments The string fragments.
4
+ * @param values The interpolated values.
5
+ * @returns The CSS stylesheet corresponding to the specified template literal.
6
+ */
7
+ export function css(fragments: TemplateStringsArray, ...values: unknown[]): CSSStyleSheet {
8
+ const styleSheet = new CSSStyleSheet;
9
+ styleSheet.replaceSync(fragments.length == 1 ? fragments[0] : values.reduce(
10
+ (fragment: string, value: unknown, index: number) => fragment + stringFromCss(value) + fragments[index + 1],
11
+ fragments[0]
12
+ ));
13
+
14
+ return styleSheet;
15
+ }
16
+
17
+ /**
18
+ * Creates a document fragment from the specified template literal.
19
+ * @param fragments The string fragments.
20
+ * @param values The interpolated values.
21
+ * @returns The document fragment corresponding to the specified template literal.
22
+ */
23
+ export function html(fragments: TemplateStringsArray, ...values: unknown[]): DocumentFragment {
24
+ return document.createRange().createContextualFragment(fragments.length == 1 ? fragments[0] : values.reduce(
25
+ (fragment: string, value: unknown, index: number) => fragment + stringFromHtml(value) + fragments[index + 1],
26
+ fragments[0]
27
+ ));
28
+ }
29
+
30
+ /**
31
+ * Converts the specified value to a CSS string.
32
+ * @param value A value representing a CSS fragment.
33
+ * @returns The CSS string corresponding to the specified value.
34
+ */
35
+ function stringFromCss(value: unknown): string {
36
+ if (!(value instanceof CSSStyleSheet)) return String(value);
37
+ return Array.from(value.cssRules).map(cssRule => cssRule.cssText).join("\n");
38
+ }
39
+
40
+ /**
41
+ * Converts the specified value to an HTML string.
42
+ * @param value A value representing an HTML fragment.
43
+ * @returns The HTML string corresponding to the specified value.
44
+ */
45
+ function stringFromHtml(value: unknown): string {
46
+ if (!(value instanceof DocumentFragment)) return String(value);
47
+ const element = document.createElement("div");
48
+ element.appendChild(value);
49
+ return element.innerHTML;
50
+ }
@@ -3,8 +3,6 @@
3
3
  "references": [
4
4
  {"path": "Base/tsconfig.json"},
5
5
  {"path": "Data/tsconfig.json"},
6
- {"path": "Hosting/tsconfig.json"},
7
- {"path": "Net/tsconfig.json"},
8
6
  {"path": "UI/tsconfig.json"}
9
7
  ]
10
8
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"DateExtensions.d.ts","sourceRoot":"","sources":["../src/Client/DateExtensions.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAE3C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE9C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,SAA2B,GAAG,IAAI,CAY/D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,SAA2B,GAAG,IAAI,EAAE,CAoBnE;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE7C;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAIhD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAG9C;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAG7C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAGhD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAM,GAAG,MAAM,CAM7H"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"FileExtensions.d.ts","sourceRoot":"","sources":["../src/Client/FileExtensions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAUzC;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,GAAE;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAM,GAAG,IAAI,CAkBvE;AAED;;;GAGG;AACH,wBAAgB,KAAK,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAatC;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAOlD"}
@@ -1,22 +0,0 @@
1
- /**
2
- * Commonly used environment names.
3
- */
4
- export declare const Environment: Readonly<{
5
- /**
6
- * Specifies the development environment.
7
- */
8
- Development: "Development";
9
- /**
10
- * Specifies the production environment.
11
- */
12
- Production: "Production";
13
- /**
14
- * Specifies the staging environment.
15
- */
16
- Staging: "Staging";
17
- }>;
18
- /**
19
- * Commonly used environment names.
20
- */
21
- export type Environment = typeof Environment[keyof typeof Environment];
22
- //# sourceMappingURL=Environment.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Environment.d.ts","sourceRoot":"","sources":["../../src/Client/Hosting/Environment.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,WAAW;IAEvB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;EAEF,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,MAAM,OAAO,WAAW,CAAC,CAAC"}
@@ -1,17 +0,0 @@
1
- /**
2
- * Commonly used environment names.
3
- */
4
- export const Environment = Object.freeze({
5
- /**
6
- * Specifies the development environment.
7
- */
8
- Development: "Development",
9
- /**
10
- * Specifies the production environment.
11
- */
12
- Production: "Production",
13
- /**
14
- * Specifies the staging environment.
15
- */
16
- Staging: "Staging"
17
- });
@@ -1,61 +0,0 @@
1
- /**
2
- * Provides information about the hosting environment an application is running in.
3
- */
4
- export declare class HostEnvironment {
5
- /**
6
- * The name of the application.
7
- */
8
- readonly applicationName: string;
9
- /**
10
- * The path to the directory that contains the application content files.
11
- */
12
- readonly contentRootPath: string;
13
- /**
14
- * The name of the environment.
15
- */
16
- readonly environmentName: string;
17
- /**
18
- * Creates a new host environment.
19
- * @param options An object providing values to initialize this instance.
20
- */
21
- constructor(options?: HostEnvironmentOptions);
22
- /**
23
- * Checks if the current environment name is {@link Environment.Development}.
24
- * @returns `true` if the environment name is {@link Environment.Development}, otherwise `false`.
25
- */
26
- get isDevelopment(): boolean;
27
- /**
28
- * Checks if the current environment name is {@link Environment.Production}.
29
- * @returns `true` if the environment name is {@link Environment.Production}, otherwise `false`.
30
- */
31
- get isProduction(): boolean;
32
- /**
33
- * Checks if the current environment name is {@link Environment.Staging}.
34
- * @returns `true` if the environment name is {@link Environment.Staging}, otherwise `false`.
35
- */
36
- get isStaging(): boolean;
37
- /**
38
- * Compares the current host environment name against the specified value.
39
- * @param environmentName The environment name to validate against.
40
- * @returns `true` if the specified name is the same as the current environment, otherwise `false`.
41
- */
42
- isEnvironment(environmentName: string): boolean;
43
- }
44
- /**
45
- * Defines the options of a {@link HostEnvironment} instance.
46
- */
47
- export type HostEnvironmentOptions = Partial<{
48
- /**
49
- * The name of the application.
50
- */
51
- applicationName: string;
52
- /**
53
- * The path to the directory that contains the application content files.
54
- */
55
- contentRootPath: string;
56
- /**
57
- * The name of the environment.
58
- */
59
- environmentName: string;
60
- }>;
61
- //# sourceMappingURL=HostEnvironment.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HostEnvironment.d.ts","sourceRoot":"","sources":["../../src/Client/Hosting/HostEnvironment.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,qBAAa,eAAe;IAE3B;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC;;OAEG;IACH,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IAEjC;;;OAGG;gBACS,OAAO,GAAE,sBAA2B;IAMhD;;;OAGG;IACH,IAAI,aAAa,IAAI,OAAO,CAE3B;IAED;;;OAGG;IACH,IAAI,YAAY,IAAI,OAAO,CAE1B;IAED;;;OAGG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;;;OAIG;IACH,aAAa,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;CAG/C;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC;IAE5C;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IAExB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;CACxB,CAAC,CAAC"}