@cedx/base 0.30.0 → 0.32.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 +1 -1
- package/lib/Date.d.ts.map +1 -1
- package/lib/DateRange.d.ts +106 -0
- package/lib/DateRange.d.ts.map +1 -0
- package/lib/DateRange.js +136 -0
- package/lib/File.d.ts.map +1 -1
- package/lib/Number.d.ts.map +1 -1
- package/lib/String.d.ts +7 -4
- package/lib/String.d.ts.map +1 -1
- package/lib/String.js +7 -6
- package/lib/TimeSpan.d.ts.map +1 -1
- package/lib/UI/Components/BackButton.d.ts +1 -1
- package/lib/UI/Components/BackButton.d.ts.map +1 -1
- package/lib/UI/Components/BackButton.js +3 -3
- package/lib/UI/Components/DialogBox.js +5 -5
- package/lib/UI/Components/FullScreenToggler.d.ts +1 -1
- package/lib/UI/Components/FullScreenToggler.d.ts.map +1 -1
- package/lib/UI/Components/FullScreenToggler.js +10 -7
- package/lib/UI/Components/KeyboardAccelerator.d.ts.map +1 -1
- package/lib/UI/Components/KeyboardAccelerator.js +6 -2
- package/lib/UI/Components/LoadingIndicator.d.ts +4 -0
- package/lib/UI/Components/LoadingIndicator.d.ts.map +1 -1
- package/lib/UI/Components/LoadingIndicator.js +6 -0
- package/lib/UI/Components/MenuActivator.d.ts.map +1 -1
- package/lib/UI/Components/MenuActivator.js +7 -4
- package/lib/UI/Components/OfflineIndicator.d.ts +4 -0
- package/lib/UI/Components/OfflineIndicator.d.ts.map +1 -1
- package/lib/UI/Components/OfflineIndicator.js +12 -3
- package/lib/UI/Components/TabActivator.d.ts.map +1 -1
- package/lib/UI/Components/ThemeDropdown.d.ts.map +1 -1
- package/lib/UI/Components/ThemeDropdown.js +9 -5
- package/lib/UI/Components/Toast.d.ts.map +1 -1
- package/lib/UI/Components/Toast.js +7 -5
- package/lib/UI/Components/Toaster.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/Client/Base/DateRange.ts +173 -0
- package/src/Client/{String.ts → Base/String.ts} +7 -6
- package/src/Client/Base/tsconfig.json +2 -2
- package/src/Client/UI/Components/BackButton.ts +3 -3
- package/src/Client/UI/Components/DialogBox.ts +5 -5
- package/src/Client/UI/Components/FullScreenToggler.ts +11 -7
- package/src/Client/UI/Components/KeyboardAccelerator.ts +7 -2
- package/src/Client/UI/Components/LoadingIndicator.ts +7 -0
- package/src/Client/UI/Components/MenuActivator.ts +8 -4
- package/src/Client/UI/Components/OfflineIndicator.ts +14 -2
- package/src/Client/UI/Components/TabActivator.ts +1 -0
- package/src/Client/UI/Components/ThemeDropdown.ts +10 -6
- package/src/Client/UI/Components/Toast.ts +8 -6
- package/src/Client/UI/Components/Toaster.ts +1 -2
- /package/src/Client/{Date.ts → Base/Date.ts} +0 -0
- /package/src/Client/{File.ts → Base/File.ts} +0 -0
- /package/src/Client/{Number.ts → Base/Number.ts} +0 -0
- /package/src/Client/{TimeSpan.ts → Base/TimeSpan.ts} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TabActivator.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/TabActivator.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE9C;;GAEG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAE5C;;OAEG;;
|
|
1
|
+
{"version":3,"file":"TabActivator.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/TabActivator.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,mBAAmB,CAAC;AAE9C;;GAEG;AACH,qBAAa,YAAa,SAAQ,WAAW;IAE5C;;OAEG;;IAgBH;;OAEG;IACH,IAAI,cAAc,IAAI,MAAM,CAG3B;IACD,IAAI,cAAc,CAAC,KAAK,EAAE,MAAM,EAE/B;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,UAAU,CAAC,OAAO,CAEhC;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,WAAW,CAG7B;IACD,IAAI,WAAW,CAAC,KAAK,EAAE,WAAW,EAEjC;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAGvB;IACD,IAAI,UAAU,CAAC,KAAK,EAAE,MAAM,EAE3B;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,UAAU,CAAC,WAAW,CAAC,CAElC;IAED;;OAEG;IACH,iBAAiB,IAAI,IAAI;CAGzB;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,eAAe,EAAE,YAAY,CAAC;KAC9B;CACD"}
|
|
@@ -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;
|
|
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;IAiBxE;;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,MAAM,IAAI,OAAO,CAEpB;IACD,IAAI,MAAM,CAAC,KAAK,EAAE,OAAO,EAExB;IAED;;OAEG;IACH,IAAI,YAAY,IAAI,MAAM,CAEzB;IACD,IAAI,YAAY,CAAC,KAAK,EAAE,MAAM,EAE7B;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;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAYxC;;OAEG;IACH,oBAAoB,IAAI,IAAI;IAK5B;;OAEG;IACH,IAAI,IAAI,IAAI;IAIZ;;OAEG;IACH,IAAI,IAAI,IAAI;CAwDZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,gBAAgB,EAAE,aAAa,CAAC;KAChC;CACD"}
|
|
@@ -9,6 +9,10 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
9
9
|
* The list of observed attributes.
|
|
10
10
|
*/
|
|
11
11
|
static observedAttributes = ["alignment", "apptheme", "label"];
|
|
12
|
+
/**
|
|
13
|
+
* The abort controller used to remove the event listeners.
|
|
14
|
+
*/
|
|
15
|
+
#abortController = new AbortController;
|
|
12
16
|
/**
|
|
13
17
|
* The dropdown menu.
|
|
14
18
|
*/
|
|
@@ -23,7 +27,7 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
23
27
|
constructor() {
|
|
24
28
|
super();
|
|
25
29
|
for (const button of this.querySelectorAll(".dropdown-menu button"))
|
|
26
|
-
button.addEventListener("click", this.#setAppTheme
|
|
30
|
+
button.addEventListener("click", this.#setAppTheme);
|
|
27
31
|
}
|
|
28
32
|
/**
|
|
29
33
|
* Registers the component.
|
|
@@ -122,7 +126,7 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
122
126
|
*/
|
|
123
127
|
async connectedCallback() {
|
|
124
128
|
this.#dropdown = new Dropdown(this.querySelector(".dropdown-toggle"));
|
|
125
|
-
this.#mediaQuery.addEventListener("change", this.#applyToDocument);
|
|
129
|
+
this.#mediaQuery.addEventListener("change", this.#applyToDocument, { signal: this.#abortController.signal });
|
|
126
130
|
const cookie = this.cookie ? await cookieStore.get(this.storageKey) : null;
|
|
127
131
|
if (cookie)
|
|
128
132
|
this.appTheme = cookie.value;
|
|
@@ -136,8 +140,8 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
136
140
|
* Method invoked when this component is disconnected.
|
|
137
141
|
*/
|
|
138
142
|
disconnectedCallback() {
|
|
143
|
+
this.#abortController.abort();
|
|
139
144
|
this.#dropdown.dispose();
|
|
140
|
-
this.#mediaQuery.removeEventListener("change", this.#applyToDocument);
|
|
141
145
|
}
|
|
142
146
|
/**
|
|
143
147
|
* Opens the dropdown menu.
|
|
@@ -171,11 +175,11 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
171
175
|
* Changes the current application theme.
|
|
172
176
|
* @param event The dispatched event.
|
|
173
177
|
*/
|
|
174
|
-
#setAppTheme
|
|
178
|
+
#setAppTheme = event => {
|
|
175
179
|
event.preventDefault();
|
|
176
180
|
this.appTheme = event.currentTarget.value;
|
|
177
181
|
this.save();
|
|
178
|
-
}
|
|
182
|
+
};
|
|
179
183
|
/**
|
|
180
184
|
* Updates the alignment of the dropdown menu.
|
|
181
185
|
* @param value The new value.
|
|
@@ -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,qBAAa,KAAM,SAAQ,WAAW;;IAErC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAA0E;
|
|
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,qBAAa,KAAM,SAAQ,WAAW;;IAErC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAA0E;IAuC5G;;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,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;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;IAM5B;;OAEG;IACH,IAAI,IAAI,IAAI;CAoGZ;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,cAAc,EAAE,KAAK,CAAC;KACtB;CACD"}
|
|
@@ -12,6 +12,10 @@ export class Toast extends HTMLElement {
|
|
|
12
12
|
* The time units.
|
|
13
13
|
*/
|
|
14
14
|
static #timeUnits = ["second", "minute", "hour"];
|
|
15
|
+
/**
|
|
16
|
+
* The abort controller used to remove the event listeners.
|
|
17
|
+
*/
|
|
18
|
+
#abortController = new AbortController;
|
|
15
19
|
/**
|
|
16
20
|
* The formatter used to format the relative time.
|
|
17
21
|
*/
|
|
@@ -169,8 +173,8 @@ export class Toast extends HTMLElement {
|
|
|
169
173
|
*/
|
|
170
174
|
connectedCallback() {
|
|
171
175
|
const root = this.firstElementChild;
|
|
172
|
-
root.addEventListener("hide.bs.toast", this.#stopTimer);
|
|
173
|
-
root.addEventListener("show.bs.toast", this.#startTimer);
|
|
176
|
+
root.addEventListener("hide.bs.toast", this.#stopTimer, { signal: this.#abortController.signal });
|
|
177
|
+
root.addEventListener("show.bs.toast", this.#startTimer, { signal: this.#abortController.signal });
|
|
174
178
|
this.#toast = new BootstrapToast(root);
|
|
175
179
|
if (this.open)
|
|
176
180
|
this.show();
|
|
@@ -179,10 +183,8 @@ export class Toast extends HTMLElement {
|
|
|
179
183
|
* Method invoked when this component is disconnected.
|
|
180
184
|
*/
|
|
181
185
|
disconnectedCallback() {
|
|
182
|
-
const root = this.firstElementChild;
|
|
183
|
-
root.removeEventListener("hide.bs.toast", () => this.#stopTimer);
|
|
184
|
-
root.removeEventListener("show.bs.toast", () => this.#startTimer);
|
|
185
186
|
this.#stopTimer();
|
|
187
|
+
this.#abortController.abort();
|
|
186
188
|
this.#toast.dispose();
|
|
187
189
|
}
|
|
188
190
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/Toaster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,MAAM;IAEtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,gBAAgB,CAAC;IAEvB;;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,OAAO,CAAC;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,WAAW;;IAEvC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAgB;IAOlD;;OAEG;;
|
|
1
|
+
{"version":3,"file":"Toaster.d.ts","sourceRoot":"","sources":["../../../src/Client/UI/Components/Toaster.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,eAAe,CAAC;AACtC,OAAO,EAAC,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,WAAW,MAAM;IAEtB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,IAAI,EAAE,gBAAgB,CAAC;IAEvB;;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,OAAO,CAAC;IAEf;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,qBAAa,OAAQ,SAAQ,WAAW;;IAEvC;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,kBAAkB,WAAgB;IAOlD;;OAEG;;IAaH;;OAEG;IACH,IAAI,QAAQ,IAAI,OAAO,CAEtB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,OAAO,EAE1B;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,IAAI,IAAI,OAAO,CAElB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,OAAO,EAEtB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,GAAC,IAAI,CAGtB;IACD,IAAI,IAAI,CAAC,KAAK,EAAE,MAAM,GAAC,IAAI,EAG1B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,QAAQ,CAGvB;IACD,IAAI,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAE3B;IAED;;;;;OAKG;IACH,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,GAAC,IAAI,GAAG,IAAI;IAO/F;;;;;OAKG;IACH,MAAM,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,GAAG,IAAI;IAI1E;;;OAGG;IACH,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CA4BzB;AAED;;GAEG;AACH,OAAO,CAAC,MAAM,CAAC;IAEd;;OAEG;IACH,UAAU,qBAAqB;QAC9B,mBAAmB,EAAE,OAAO,CAAC;KAC7B;CACD"}
|
package/package.json
CHANGED
|
@@ -7,23 +7,23 @@
|
|
|
7
7
|
"name": "@cedx/base",
|
|
8
8
|
"repository": "cedx/base",
|
|
9
9
|
"type": "module",
|
|
10
|
-
"version": "0.
|
|
10
|
+
"version": "0.32.0",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@playwright/browser-chromium": "^1.55.0",
|
|
13
13
|
"@types/bootstrap": "^5.2.10",
|
|
14
14
|
"@types/chai": "^5.2.2",
|
|
15
15
|
"@types/mocha": "^10.0.10",
|
|
16
|
-
"@types/node": "^24.
|
|
16
|
+
"@types/node": "^24.5.2",
|
|
17
17
|
"@types/serve-handler": "^6.1.4",
|
|
18
18
|
"chai": "^6.0.1",
|
|
19
|
-
"esbuild": "^0.25.
|
|
20
|
-
"globals": "^16.
|
|
19
|
+
"esbuild": "^0.25.10",
|
|
20
|
+
"globals": "^16.4.0",
|
|
21
21
|
"mocha": "^11.7.2",
|
|
22
22
|
"playwright": "^1.55.0",
|
|
23
23
|
"serve-handler": "^6.1.6",
|
|
24
|
-
"typedoc": "^0.28.
|
|
24
|
+
"typedoc": "^0.28.13",
|
|
25
25
|
"typescript": "^5.9.2",
|
|
26
|
-
"typescript-eslint": "^8.
|
|
26
|
+
"typescript-eslint": "^8.44.0"
|
|
27
27
|
},
|
|
28
28
|
"engines": {
|
|
29
29
|
"node": ">=24.0.0"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import {atMidnight, daysInMonth, getQuarter, getWeekOfYear} from "./Date.js";
|
|
2
|
+
import {TimeSpan} from "./TimeSpan.js";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Defines the type of a date range.
|
|
6
|
+
*/
|
|
7
|
+
export const DateRangeType = Object.freeze({
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A custom date range.
|
|
11
|
+
*/
|
|
12
|
+
Custom: "Custom",
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A whole day.
|
|
16
|
+
*/
|
|
17
|
+
Day: "Day",
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* A whole week.
|
|
21
|
+
*/
|
|
22
|
+
Week: "Week",
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* A whole month.
|
|
26
|
+
*/
|
|
27
|
+
Month: "Month",
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* A whole quarter.
|
|
31
|
+
*/
|
|
32
|
+
Quarter: "Quarter",
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* A whole year.
|
|
36
|
+
*/
|
|
37
|
+
Year: "Year"
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Defines the type of a date range.
|
|
42
|
+
*/
|
|
43
|
+
export type DateRangeType = typeof DateRangeType[keyof typeof DateRangeType];
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Defines a date range.
|
|
47
|
+
*/
|
|
48
|
+
export class DateRange {
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The end date.
|
|
52
|
+
*/
|
|
53
|
+
readonly end: Date;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The start date.
|
|
57
|
+
*/
|
|
58
|
+
readonly start: Date;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The range type.
|
|
62
|
+
*/
|
|
63
|
+
readonly type: DateRangeType;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates a new date range.
|
|
67
|
+
* @param start The start date.
|
|
68
|
+
* @param end The end date.
|
|
69
|
+
* @param type The range type.
|
|
70
|
+
*/
|
|
71
|
+
constructor(start: Date, end: Date, type: DateRangeType = DateRangeType.Custom) {
|
|
72
|
+
this.start = start;
|
|
73
|
+
this.end = end;
|
|
74
|
+
this.type = type;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creates a new date range from the specified JSON object.
|
|
79
|
+
* @param json A JSON object representing a date range.
|
|
80
|
+
* @returns The instance corresponding to the specified JSON object.
|
|
81
|
+
*/
|
|
82
|
+
static fromJson(json: Record<string, any>): DateRange {
|
|
83
|
+
return new this(
|
|
84
|
+
new Date(typeof json.start == "string" ? json.start : Date.now()),
|
|
85
|
+
new Date(typeof json.end == "string" ? json.end : Date.now()),
|
|
86
|
+
Object.values(DateRangeType).includes(json.type as DateRangeType) ? json.type as DateRangeType : DateRangeType.Custom
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Creates a date range corresponding to the day including the specified date.
|
|
92
|
+
* @param date The date.
|
|
93
|
+
* @returns The date range corresponding to the day including the specified date.
|
|
94
|
+
*/
|
|
95
|
+
static day(date: Date): DateRange {
|
|
96
|
+
return new this(atMidnight(date), new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59, 999), DateRangeType.Day);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Creates a date range corresponding to the month including the specified date.
|
|
101
|
+
* @param date The date.
|
|
102
|
+
* @returns The date range corresponding to the month including the specified date.
|
|
103
|
+
*/
|
|
104
|
+
static month(date: Date): DateRange {
|
|
105
|
+
return new this(
|
|
106
|
+
new Date(date.getFullYear(), date.getMonth(), 1),
|
|
107
|
+
new Date(date.getFullYear(), date.getMonth(), daysInMonth(date), 23, 59, 59, 999),
|
|
108
|
+
DateRangeType.Month
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Creates a date range corresponding to the quarter including the specified date.
|
|
114
|
+
* @param date The date.
|
|
115
|
+
* @returns The date range corresponding to the quarter including the specified date.
|
|
116
|
+
*/
|
|
117
|
+
static quarter(date: Date): DateRange {
|
|
118
|
+
const firstMonth = (getQuarter(date) * 3) - 3;
|
|
119
|
+
const lastMonth = firstMonth + 2;
|
|
120
|
+
return new this(
|
|
121
|
+
new Date(date.getFullYear(), firstMonth, 1),
|
|
122
|
+
new Date(date.getFullYear(), lastMonth, daysInMonth(new Date(date.getFullYear(), lastMonth, 1)), 23, 59, 59, 999),
|
|
123
|
+
DateRangeType.Quarter
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Creates a date range corresponding to the week including the specified date.
|
|
129
|
+
* @param date The date.
|
|
130
|
+
* @returns The date range corresponding to the week including the specified date.
|
|
131
|
+
*/
|
|
132
|
+
static week(date: Date): DateRange {
|
|
133
|
+
const delta = -((date.getDay() + 6) % 7);
|
|
134
|
+
const sunday = new Date(date.getTime() + ((delta + 6) * TimeSpan.MillisecondsPerDay));
|
|
135
|
+
sunday.setHours(23, 59, 59, 999);
|
|
136
|
+
return new this(atMidnight(new Date(date.getTime() + (delta * TimeSpan.MillisecondsPerDay))), sunday, DateRangeType.Week);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Creates a date range corresponding to the year including the specified date.
|
|
141
|
+
* @param date The date.
|
|
142
|
+
* @returns The date range corresponding to the year including the specified date.
|
|
143
|
+
*/
|
|
144
|
+
static year(date: Date): DateRange {
|
|
145
|
+
return new this(new Date(date.getFullYear(), 0, 1), new Date(date.getFullYear(), 11, 31, 23, 59, 59, 999), DateRangeType.Year);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Returns a value indicating whether this date range is equal to the specified date range.
|
|
150
|
+
* @param other The other date range to compare.
|
|
151
|
+
* @returns `true` if this date range is equal to the specified date range, otherwise `false`.
|
|
152
|
+
*/
|
|
153
|
+
equals(other: DateRange): boolean {
|
|
154
|
+
return this.start.getTime() == other.start.getTime() && this.end.getTime() == other.end.getTime();
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* The label corresponding to this date range.
|
|
159
|
+
* @param culture The current culture.
|
|
160
|
+
* @returns The label corresponding to this date range.
|
|
161
|
+
*/
|
|
162
|
+
getLabel(culture: Intl.Locale|string = navigator.language): string {
|
|
163
|
+
const {start, end, type} = this;
|
|
164
|
+
switch (type) {
|
|
165
|
+
case DateRangeType.Day: return start.toLocaleString(culture, {dateStyle: "medium"});
|
|
166
|
+
case DateRangeType.Week: return `S${getWeekOfYear(start)} ${start.getFullYear()}`;
|
|
167
|
+
case DateRangeType.Month: return start.toLocaleString(culture, {month: "long", year: "numeric"});
|
|
168
|
+
case DateRangeType.Quarter: return `T${getQuarter(start)} ${start.getFullYear()}`;
|
|
169
|
+
case DateRangeType.Year: return start.getFullYear().toString();
|
|
170
|
+
default: return end.toLocaleString(culture, {dateStyle: "medium"});
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
@@ -1,20 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Converts the first character to uppercase.
|
|
2
|
+
* Converts the first character of the specified string to uppercase.
|
|
3
3
|
* @param value The string to process.
|
|
4
|
-
* @param
|
|
4
|
+
* @param culture The current culture.
|
|
5
5
|
* @returns The processed string.
|
|
6
6
|
*/
|
|
7
|
-
export function capitalize(value: string,
|
|
8
|
-
return value.charAt(0).toLocaleUpperCase(
|
|
7
|
+
export function capitalize(value: string, culture: Intl.Locale|string = navigator.language): string {
|
|
8
|
+
return value.length == 0 ? "" : value.charAt(0).toLocaleUpperCase(culture) + value.slice(1);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Replaces all new lines in the specified value by HTML line breaks.
|
|
13
13
|
* @param value The string to format.
|
|
14
|
+
* @param options Value indicating whether to use XHTML compatible line breaks.
|
|
14
15
|
* @returns The formatted string.
|
|
15
16
|
*/
|
|
16
|
-
export function newLineToBr(value: string): string {
|
|
17
|
-
return value.split(/\r?\n/g).join("<br>");
|
|
17
|
+
export function newLineToBr(value: string, options: {xhtml?: boolean} = {}): string {
|
|
18
|
+
return value.split(/\r?\n/g).join(options.xhtml ? "<br />" : "<br>");
|
|
18
19
|
}
|
|
19
20
|
|
|
20
21
|
/**
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"extends": "../../../tsconfig.json",
|
|
3
|
-
"include": ["
|
|
3
|
+
"include": ["**/*.ts"],
|
|
4
4
|
"compilerOptions": {
|
|
5
5
|
"composite": true,
|
|
6
6
|
"declaration": true,
|
|
7
7
|
"declarationMap": true,
|
|
8
8
|
"noEmit": false,
|
|
9
9
|
"outDir": "../../../lib",
|
|
10
|
-
"rootDir": "
|
|
10
|
+
"rootDir": ".",
|
|
11
11
|
"tsBuildInfoFile": "../../../var/Base.tsbuildinfo"
|
|
12
12
|
}
|
|
13
13
|
}
|
|
@@ -8,7 +8,7 @@ export class BackButton extends HTMLElement {
|
|
|
8
8
|
*/
|
|
9
9
|
constructor() {
|
|
10
10
|
super();
|
|
11
|
-
this.addEventListener("click", this.goBack
|
|
11
|
+
this.addEventListener("click", this.goBack, {capture: true});
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/**
|
|
@@ -33,10 +33,10 @@ export class BackButton extends HTMLElement {
|
|
|
33
33
|
* Moves back in the session history.
|
|
34
34
|
* @param event The dispatched event.
|
|
35
35
|
*/
|
|
36
|
-
goBack(event?: Event)
|
|
36
|
+
readonly goBack: (event?: Event) => void = event => {
|
|
37
37
|
event?.stopPropagation();
|
|
38
38
|
history.go(-this.steps);
|
|
39
|
-
}
|
|
39
|
+
};
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
@@ -82,8 +82,8 @@ export class DialogBox extends HTMLElement {
|
|
|
82
82
|
constructor() {
|
|
83
83
|
super();
|
|
84
84
|
this.firstElementChild!.addEventListener("hide.bs.modal", () => this.#resolve(this.#result));
|
|
85
|
-
this.querySelector(".btn-close")!.addEventListener("click", this.#close
|
|
86
|
-
for (const button of this.querySelectorAll(".modal-footer button")) button.addEventListener("click", this.#close
|
|
85
|
+
this.querySelector(".btn-close")!.addEventListener("click", this.#close);
|
|
86
|
+
for (const button of this.querySelectorAll(".modal-footer button")) button.addEventListener("click", this.#close);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
/**
|
|
@@ -267,7 +267,7 @@ export class DialogBox extends HTMLElement {
|
|
|
267
267
|
show(message: IDialogMessage|null = null): Promise<string> {
|
|
268
268
|
if (message) {
|
|
269
269
|
const footer = message.footer ?? document.createDocumentFragment();
|
|
270
|
-
for (const button of footer.querySelectorAll("button")) button.addEventListener("click", this.#close
|
|
270
|
+
for (const button of footer.querySelectorAll("button")) button.addEventListener("click", this.#close);
|
|
271
271
|
this.body = message.body;
|
|
272
272
|
this.caption = message.caption;
|
|
273
273
|
this.footer = footer;
|
|
@@ -284,10 +284,10 @@ export class DialogBox extends HTMLElement {
|
|
|
284
284
|
* Closes this dialog box.
|
|
285
285
|
* @param event The dispatched event.
|
|
286
286
|
*/
|
|
287
|
-
#close(event: Event)
|
|
287
|
+
readonly #close: (event: Event) => void = event => {
|
|
288
288
|
event.preventDefault();
|
|
289
289
|
this.close((event.currentTarget as HTMLButtonElement).value);
|
|
290
|
-
}
|
|
290
|
+
};
|
|
291
291
|
|
|
292
292
|
/**
|
|
293
293
|
* Updates the title displayed in the header.
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export class FullScreenToggler extends HTMLElement {
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* The abort controller used to remove the event listeners.
|
|
8
|
+
*/
|
|
9
|
+
readonly #abortController = new AbortController;
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
12
|
* The target element.
|
|
8
13
|
*/
|
|
@@ -18,7 +23,7 @@ export class FullScreenToggler extends HTMLElement {
|
|
|
18
23
|
*/
|
|
19
24
|
constructor() {
|
|
20
25
|
super();
|
|
21
|
-
this.addEventListener("click", this.toggleFullScreen
|
|
26
|
+
this.addEventListener("click", this.toggleFullScreen, {capture: true}); // eslint-disable-line @typescript-eslint/no-misused-promises
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
/**
|
|
@@ -53,17 +58,16 @@ export class FullScreenToggler extends HTMLElement {
|
|
|
53
58
|
* Method invoked when this component is connected.
|
|
54
59
|
*/
|
|
55
60
|
connectedCallback(): void {
|
|
56
|
-
document.addEventListener("visibilitychange", this.#onVisibilityChanged);
|
|
61
|
+
document.addEventListener("visibilitychange", this.#onVisibilityChanged, {signal: this.#abortController.signal});
|
|
57
62
|
this.#element = document.querySelector(this.target) ?? document.body;
|
|
58
|
-
this.#element.addEventListener("fullscreenchange", this.#onFullScreenChanged);
|
|
63
|
+
this.#element.addEventListener("fullscreenchange", this.#onFullScreenChanged, {signal: this.#abortController.signal});
|
|
59
64
|
}
|
|
60
65
|
|
|
61
66
|
/**
|
|
62
67
|
* Method invoked when this component is disconnected.
|
|
63
68
|
*/
|
|
64
69
|
disconnectedCallback(): void {
|
|
65
|
-
|
|
66
|
-
this.#element.removeEventListener("fullscreenchange", this.#onFullScreenChanged);
|
|
70
|
+
this.#abortController.abort();
|
|
67
71
|
}
|
|
68
72
|
|
|
69
73
|
/**
|
|
@@ -71,11 +75,11 @@ export class FullScreenToggler extends HTMLElement {
|
|
|
71
75
|
* @param event The dispatched event.
|
|
72
76
|
* @returns Completes when the full-screen mode has been toggled.
|
|
73
77
|
*/
|
|
74
|
-
|
|
78
|
+
readonly toggleFullScreen: (event?: Event) => Promise<void> = async event => {
|
|
75
79
|
event?.stopPropagation();
|
|
76
80
|
if (document.fullscreenElement) await document.exitFullscreen();
|
|
77
81
|
else await this.#element.requestFullscreen();
|
|
78
|
-
}
|
|
82
|
+
};
|
|
79
83
|
|
|
80
84
|
/**
|
|
81
85
|
* Acquires a new wake lock.
|
|
@@ -5,6 +5,11 @@ import {KeyboardModifiers} from "../KeyboardModifiers.js";
|
|
|
5
5
|
*/
|
|
6
6
|
export class KeyboardAccelerator extends HTMLElement {
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* The abort controller used to remove the event listeners.
|
|
10
|
+
*/
|
|
11
|
+
readonly #abortController = new AbortController;
|
|
12
|
+
|
|
8
13
|
/**
|
|
9
14
|
* The mapping between the modifier names and their values.
|
|
10
15
|
*/
|
|
@@ -46,14 +51,14 @@ export class KeyboardAccelerator extends HTMLElement {
|
|
|
46
51
|
* Method invoked when this component is connected.
|
|
47
52
|
*/
|
|
48
53
|
connectedCallback(): void {
|
|
49
|
-
addEventListener("keyup", this.#activateChildContent, {capture: true});
|
|
54
|
+
addEventListener("keyup", this.#activateChildContent, {capture: true, signal: this.#abortController.signal});
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
/**
|
|
53
58
|
* Method invoked when this component is disconnected.
|
|
54
59
|
*/
|
|
55
60
|
disconnectedCallback(): void {
|
|
56
|
-
|
|
61
|
+
this.#abortController.abort();
|
|
57
62
|
}
|
|
58
63
|
|
|
59
64
|
/**
|
|
@@ -30,6 +30,13 @@ export class LoadingIndicator extends HTMLElement {
|
|
|
30
30
|
this.toggleAttribute("fade", value);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Value indicating whether this component is shown.
|
|
35
|
+
*/
|
|
36
|
+
get isShown(): boolean {
|
|
37
|
+
return this.classList.contains("show");
|
|
38
|
+
}
|
|
39
|
+
|
|
33
40
|
/**
|
|
34
41
|
* Value indicating whether to initially show this component.
|
|
35
42
|
*/
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export class MenuActivator extends HTMLElement {
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* The abort controller used to remove the event listeners.
|
|
8
|
+
*/
|
|
9
|
+
readonly #abortController = new AbortController;
|
|
10
|
+
|
|
6
11
|
/**
|
|
7
12
|
* Registers the component.
|
|
8
13
|
*/
|
|
@@ -15,16 +20,15 @@ export class MenuActivator extends HTMLElement {
|
|
|
15
20
|
*/
|
|
16
21
|
connectedCallback(): void {
|
|
17
22
|
this.#update();
|
|
18
|
-
addEventListener("popstate", this.#update);
|
|
19
|
-
document.body.addEventListener("htmx:afterRequest", this.#update);
|
|
23
|
+
addEventListener("popstate", this.#update, {signal: this.#abortController.signal});
|
|
24
|
+
document.body.addEventListener("htmx:afterRequest", this.#update, {signal: this.#abortController.signal});
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
/**
|
|
23
28
|
* Method invoked when this component is disconnected.
|
|
24
29
|
*/
|
|
25
30
|
disconnectedCallback(): void {
|
|
26
|
-
|
|
27
|
-
document.body.removeEventListener("htmx:afterRequest", this.#update);
|
|
31
|
+
this.#abortController.abort();
|
|
28
32
|
}
|
|
29
33
|
|
|
30
34
|
/**
|
|
@@ -8,6 +8,11 @@ export class OfflineIndicator extends HTMLElement {
|
|
|
8
8
|
*/
|
|
9
9
|
static readonly observedAttributes = ["fade"];
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* The abort controller used to remove the event listeners.
|
|
13
|
+
*/
|
|
14
|
+
readonly #abortController = new AbortController;
|
|
15
|
+
|
|
11
16
|
/**
|
|
12
17
|
* Registers the component.
|
|
13
18
|
*/
|
|
@@ -25,6 +30,13 @@ export class OfflineIndicator extends HTMLElement {
|
|
|
25
30
|
this.toggleAttribute("fade", value);
|
|
26
31
|
}
|
|
27
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Value indicating whether this component is shown.
|
|
35
|
+
*/
|
|
36
|
+
get isShown(): boolean {
|
|
37
|
+
return this.classList.contains("show");
|
|
38
|
+
}
|
|
39
|
+
|
|
28
40
|
/**
|
|
29
41
|
* Value indicating whether to initially show this component.
|
|
30
42
|
*/
|
|
@@ -52,7 +64,7 @@ export class OfflineIndicator extends HTMLElement {
|
|
|
52
64
|
* Method invoked when this component is connected.
|
|
53
65
|
*/
|
|
54
66
|
connectedCallback(): void {
|
|
55
|
-
for (const event of ["online", "offline"]) addEventListener(event, this.#updateVisibility);
|
|
67
|
+
for (const event of ["online", "offline"]) addEventListener(event, this.#updateVisibility, {signal: this.#abortController.signal});
|
|
56
68
|
if (this.open) this.show();
|
|
57
69
|
else this.#updateVisibility();
|
|
58
70
|
}
|
|
@@ -61,7 +73,7 @@ export class OfflineIndicator extends HTMLElement {
|
|
|
61
73
|
* Method invoked when this component is disconnected.
|
|
62
74
|
*/
|
|
63
75
|
disconnectedCallback(): void {
|
|
64
|
-
|
|
76
|
+
this.#abortController.abort();
|
|
65
77
|
}
|
|
66
78
|
|
|
67
79
|
/**
|
|
@@ -12,6 +12,11 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
12
12
|
*/
|
|
13
13
|
static readonly observedAttributes = ["alignment", "apptheme", "label"];
|
|
14
14
|
|
|
15
|
+
/**
|
|
16
|
+
* The abort controller used to remove the event listeners.
|
|
17
|
+
*/
|
|
18
|
+
readonly #abortController = new AbortController;
|
|
19
|
+
|
|
15
20
|
/**
|
|
16
21
|
* The dropdown menu.
|
|
17
22
|
*/
|
|
@@ -27,8 +32,7 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
27
32
|
*/
|
|
28
33
|
constructor() {
|
|
29
34
|
super();
|
|
30
|
-
for (const button of this.querySelectorAll(".dropdown-menu button"))
|
|
31
|
-
button.addEventListener("click", this.#setAppTheme.bind(this));
|
|
35
|
+
for (const button of this.querySelectorAll(".dropdown-menu button")) button.addEventListener("click", this.#setAppTheme);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
/**
|
|
@@ -130,7 +134,7 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
130
134
|
*/
|
|
131
135
|
async connectedCallback(): Promise<void> {
|
|
132
136
|
this.#dropdown = new Dropdown(this.querySelector(".dropdown-toggle")!);
|
|
133
|
-
this.#mediaQuery.addEventListener("change", this.#applyToDocument);
|
|
137
|
+
this.#mediaQuery.addEventListener("change", this.#applyToDocument, {signal: this.#abortController.signal});
|
|
134
138
|
|
|
135
139
|
const cookie = this.cookie ? await cookieStore.get(this.storageKey) : null;
|
|
136
140
|
if (cookie) this.appTheme = cookie.value as AppTheme;
|
|
@@ -144,8 +148,8 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
144
148
|
* Method invoked when this component is disconnected.
|
|
145
149
|
*/
|
|
146
150
|
disconnectedCallback(): void {
|
|
151
|
+
this.#abortController.abort();
|
|
147
152
|
this.#dropdown.dispose();
|
|
148
|
-
this.#mediaQuery.removeEventListener("change", this.#applyToDocument);
|
|
149
153
|
}
|
|
150
154
|
|
|
151
155
|
/**
|
|
@@ -183,11 +187,11 @@ export class ThemeDropdown extends HTMLElement {
|
|
|
183
187
|
* Changes the current application theme.
|
|
184
188
|
* @param event The dispatched event.
|
|
185
189
|
*/
|
|
186
|
-
#setAppTheme(event: Event)
|
|
190
|
+
readonly #setAppTheme: (event: Event) => void = event => {
|
|
187
191
|
event.preventDefault();
|
|
188
192
|
this.appTheme = (event.currentTarget as HTMLButtonElement).value as AppTheme;
|
|
189
193
|
this.save();
|
|
190
|
-
}
|
|
194
|
+
};
|
|
191
195
|
|
|
192
196
|
/**
|
|
193
197
|
* Updates the alignment of the dropdown menu.
|