@design.estate/dees-domtools 5.1.0 → 5.2.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/dist_bundle/bundle.js +6 -6
- package/dist_bundle/bundle.js.map +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/domtools.classes.thememanager.d.ts +16 -0
- package/dist_ts/domtools.classes.thememanager.js +29 -9
- package/dist_ts/index.d.ts +1 -1
- package/dist_ts/index.js +1 -1
- package/package.json +1 -1
- package/readme.md +11 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/domtools.classes.thememanager.ts +38 -7
- package/ts/index.ts +1 -1
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-domtools',
|
|
6
|
-
version: '5.
|
|
6
|
+
version: '5.2.0',
|
|
7
7
|
description: 'A package providing tools to simplify complex CSS structures and web development tasks, featuring TypeScript support and integration with various web technologies.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSw4QkFBOEI7SUFDcEMsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHFLQUFxSztDQUNuTCxDQUFBIn0=
|
|
@@ -5,6 +5,14 @@ import * as plugins from './domtools.plugins.js';
|
|
|
5
5
|
* `'dark'` hold that theme whatever the system does.
|
|
6
6
|
*/
|
|
7
7
|
export type TThemePreference = 'system' | 'bright' | 'dark';
|
|
8
|
+
/** What a theme toggle shows: the reader's preference, the system's colour scheme and the theme they resolve to. */
|
|
9
|
+
export interface IThemeState {
|
|
10
|
+
preference: TThemePreference;
|
|
11
|
+
/** The system's colour scheme is light. */
|
|
12
|
+
systemBright: boolean;
|
|
13
|
+
/** The page shows the bright theme. */
|
|
14
|
+
goBright: boolean;
|
|
15
|
+
}
|
|
8
16
|
export declare class ThemeManager {
|
|
9
17
|
/**
|
|
10
18
|
* The `localStorage` key a picked preference is kept under, per browser and origin. `'system'` is
|
|
@@ -16,7 +24,14 @@ export declare class ThemeManager {
|
|
|
16
24
|
/** The reader's preference; the theme follows the system only while it is `'system'`. */
|
|
17
25
|
preference: TThemePreference;
|
|
18
26
|
preferredColorSchemeMediaMatch: MediaQueryList;
|
|
27
|
+
/** The system's colour scheme is light, as `prefers-color-scheme` last reported it. */
|
|
28
|
+
systemBright: boolean;
|
|
19
29
|
themeObservable: plugins.smartrx.rxjs.ReplaySubject<boolean>;
|
|
30
|
+
/**
|
|
31
|
+
* The preference, the system's colour scheme and the theme, on every change of any of them, also
|
|
32
|
+
* when the theme stays; replays the current state to a new subscriber.
|
|
33
|
+
*/
|
|
34
|
+
stateObservable: plugins.smartrx.rxjs.ReplaySubject<IThemeState>;
|
|
20
35
|
private automaticGlobalThemeChangeSubscription;
|
|
21
36
|
private readonly preferredColorSchemeChangeHandler;
|
|
22
37
|
/** Another tab of this origin picked a preference; this page follows it. */
|
|
@@ -29,6 +44,7 @@ export declare class ThemeManager {
|
|
|
29
44
|
private static storedPreference;
|
|
30
45
|
enableAutomaticGlobalThemeChange(): Promise<void>;
|
|
31
46
|
private updateAllConnectedElements;
|
|
47
|
+
private publishState;
|
|
32
48
|
private resolveBright;
|
|
33
49
|
private applyPreference;
|
|
34
50
|
/**
|
|
@@ -13,11 +13,21 @@ export class ThemeManager {
|
|
|
13
13
|
/** The reader's preference; the theme follows the system only while it is `'system'`. */
|
|
14
14
|
preference = 'system';
|
|
15
15
|
preferredColorSchemeMediaMatch = window.matchMedia('(prefers-color-scheme: light)');
|
|
16
|
+
/** The system's colour scheme is light, as `prefers-color-scheme` last reported it. */
|
|
17
|
+
systemBright = this.preferredColorSchemeMediaMatch.matches;
|
|
16
18
|
themeObservable = new plugins.smartrx.rxjs.ReplaySubject(1);
|
|
19
|
+
/**
|
|
20
|
+
* The preference, the system's colour scheme and the theme, on every change of any of them, also
|
|
21
|
+
* when the theme stays; replays the current state to a new subscriber.
|
|
22
|
+
*/
|
|
23
|
+
stateObservable = new plugins.smartrx.rxjs.ReplaySubject(1);
|
|
17
24
|
automaticGlobalThemeChangeSubscription = null;
|
|
18
25
|
preferredColorSchemeChangeHandler = (eventArg) => {
|
|
19
|
-
|
|
26
|
+
this.systemBright = eventArg.matches;
|
|
27
|
+
if (this.preference !== 'system') {
|
|
28
|
+
this.publishState();
|
|
20
29
|
return;
|
|
30
|
+
}
|
|
21
31
|
this.goBrightBoolean = eventArg.matches;
|
|
22
32
|
this.updateAllConnectedElements();
|
|
23
33
|
};
|
|
@@ -69,19 +79,28 @@ export class ThemeManager {
|
|
|
69
79
|
return;
|
|
70
80
|
}
|
|
71
81
|
this.themeObservable.next(this.goBrightBoolean);
|
|
82
|
+
this.publishState();
|
|
83
|
+
}
|
|
84
|
+
publishState() {
|
|
85
|
+
if (this.domtoolsRef.disposed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.stateObservable.next({ preference: this.preference, systemBright: this.systemBright, goBright: this.goBrightBoolean });
|
|
72
89
|
}
|
|
73
90
|
resolveBright() {
|
|
74
|
-
return this.preference === 'system'
|
|
75
|
-
? this.preferredColorSchemeMediaMatch.matches
|
|
76
|
-
: this.preference === 'bright';
|
|
91
|
+
return this.preference === 'system' ? this.systemBright : this.preference === 'bright';
|
|
77
92
|
}
|
|
78
93
|
applyPreference(preferenceArg) {
|
|
94
|
+
const preferenceChanged = preferenceArg !== this.preference;
|
|
79
95
|
this.preference = preferenceArg;
|
|
80
96
|
const goBright = this.resolveBright();
|
|
81
|
-
if (goBright
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
97
|
+
if (goBright !== this.goBrightBoolean) {
|
|
98
|
+
this.goBrightBoolean = goBright;
|
|
99
|
+
this.updateAllConnectedElements();
|
|
100
|
+
}
|
|
101
|
+
else if (preferenceChanged) {
|
|
102
|
+
this.publishState();
|
|
103
|
+
}
|
|
85
104
|
}
|
|
86
105
|
/**
|
|
87
106
|
* Picks the theme and keeps the pick in this browser (`'system'` forgets it), so the next page
|
|
@@ -133,6 +152,7 @@ export class ThemeManager {
|
|
|
133
152
|
this.automaticGlobalThemeChangeSubscription?.unsubscribe();
|
|
134
153
|
this.automaticGlobalThemeChangeSubscription = null;
|
|
135
154
|
this.themeObservable.complete();
|
|
155
|
+
this.stateObservable.complete();
|
|
136
156
|
}
|
|
137
157
|
}
|
|
138
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
158
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tdG9vbHMuY2xhc3Nlcy50aGVtZW1hbmFnZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9kb210b29scy5jbGFzc2VzLnRoZW1lbWFuYWdlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDMUQsT0FBTyxLQUFLLE9BQU8sTUFBTSx1QkFBdUIsQ0FBQztBQVFqRCxNQUFNLGdCQUFnQixHQUFnQyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFFbkYsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLFFBQWlCLEVBQWdDLEVBQUUsQ0FBQyxDQUM3RSxnQkFBZ0IsQ0FBQyxRQUFRLENBQUMsUUFBNEIsQ0FBQyxDQUN4RCxDQUFDO0FBV0YsTUFBTSxPQUFPLFlBQVk7SUFDdkI7OztPQUdHO0lBQ0ksTUFBTSxDQUFVLG9CQUFvQixHQUFHLGdDQUFnQyxDQUFDO0lBRXhFLFdBQVcsQ0FBVztJQUV0QixlQUFlLEdBQUcsS0FBSyxDQUFDO0lBQy9CLHlGQUF5RjtJQUNsRixVQUFVLEdBQXFCLFFBQVEsQ0FBQztJQUN4Qyw4QkFBOEIsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDM0YsdUZBQXVGO0lBQ2hGLFlBQVksR0FBRyxJQUFJLENBQUMsOEJBQThCLENBQUMsT0FBTyxDQUFDO0lBRTNELGVBQWUsR0FBRyxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBVSxDQUFDLENBQUMsQ0FBQztJQUM1RTs7O09BR0c7SUFDSSxlQUFlLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQWMsQ0FBQyxDQUFDLENBQUM7SUFDeEUsc0NBQXNDLEdBQTZDLElBQUksQ0FBQztJQUMvRSxpQ0FBaUMsR0FBRyxDQUFDLFFBQTZCLEVBQUUsRUFBRTtRQUNyRixJ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
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import * as breakpoints from './domtools.css.breakpoints.js';
|
|
|
4
4
|
import * as css from './domtools.css.js';
|
|
5
5
|
export { css, breakpoints, elementBasic };
|
|
6
6
|
export { DomTools, type IDomToolsConstructorOptions } from './domtools.classes.domtools.js';
|
|
7
|
-
export { ThemeManager, type TThemePreference } from './domtools.classes.thememanager.js';
|
|
7
|
+
export { ThemeManager, type IThemeState, type TThemePreference } from './domtools.classes.thememanager.js';
|
|
8
8
|
export { TypedRequest } from '@api.global/typedrequest';
|
|
9
9
|
export { type IWebSetupConstructorOptions } from '@push.rocks/websetup';
|
|
10
10
|
import * as plugins from './domtools.pluginexports.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -9,4 +9,4 @@ export { TypedRequest } from '@api.global/typedrequest';
|
|
|
9
9
|
export {} from '@push.rocks/websetup';
|
|
10
10
|
import * as plugins from './domtools.pluginexports.js';
|
|
11
11
|
export { plugins };
|
|
12
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
12
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHNCQUFzQixDQUFDO0FBRXJDLE9BQU8sS0FBSyxZQUFZLE1BQU0sNEJBQTRCLENBQUM7QUFDM0QsT0FBTyxLQUFLLFdBQVcsTUFBTSwrQkFBK0IsQ0FBQztBQUM3RCxPQUFPLEtBQUssR0FBRyxNQUFNLG1CQUFtQixDQUFDO0FBRXpDLE9BQU8sRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLFlBQVksRUFBRSxDQUFDO0FBQzFDLE9BQU8sRUFBRSxRQUFRLEVBQW9DLE1BQU0sZ0NBQWdDLENBQUM7QUFDNUYsT0FBTyxFQUFFLFlBQVksRUFBMkMsTUFBTSxvQ0FBb0MsQ0FBQztBQUMzRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDeEQsT0FBTyxFQUFvQyxNQUFNLHNCQUFzQixDQUFDO0FBRXhFLE9BQU8sS0FBSyxPQUFPLE1BQU0sNkJBQTZCLENBQUM7QUFDdkQsT0FBTyxFQUFFLE9BQU8sRUFBRSxDQUFDIn0=
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@design.estate/dees-domtools",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A package providing tools to simplify complex CSS structures and web development tasks, featuring TypeScript support and integration with various web technologies.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
package/readme.md
CHANGED
|
@@ -157,6 +157,15 @@ themeManager.setPreference('system'); // follow prefers-color-scheme again
|
|
|
157
157
|
|
|
158
158
|
`'system'` follows `prefers-color-scheme`; `'bright'` and `'dark'` hold that theme while the system's scheme changes. A picked preference is kept in `localStorage` under `ThemeManager.preferenceStorageKey` (`dees-domtools:theme-preference`, per browser and origin; `'system'` removes the key) and is read before the theme manager's first emission, so a reload starts in it without showing the system theme first. Another tab's pick reaches every open page of the origin through the `storage` event. `setPreference()` returns `false` when the browser refuses the page its storage: the pick then holds for this page only, and it throws on a value that is no `TThemePreference`. An unknown stored value counts as no pick. `goBright()`, `goDark()` and `toggleDarkBright()` set the theme for now and leave the preference alone.
|
|
159
159
|
|
|
160
|
+
A toggle that shows the preference, not only the theme, subscribes to `stateObservable`, a `ReplaySubject<IThemeState>` that replays the current state and emits on every change of the preference, the system's colour scheme or the theme, also when the theme stays (a pick of the theme the system already shows, the system changing while a pick holds, another tab's pick):
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
themeManager.stateObservable.subscribe(({ preference, systemBright, goBright }) => {
|
|
164
|
+
// e.g. offer "follow the system" while a pick holds the theme the system shows
|
|
165
|
+
});
|
|
166
|
+
themeManager.systemBright; // the system's colour scheme is light, as prefers-color-scheme last reported it
|
|
167
|
+
```
|
|
168
|
+
|
|
160
169
|
The page's `DomTools` is one instance on `globalThis` shared by every copy of this package, so it is the copy that creates it whose `ThemeManager` serves the page: every copy in a bundle must be a version with `setPreference()` for a toggle to rely on it.
|
|
161
170
|
|
|
162
171
|
`enableAutomaticGlobalThemeChange()` waits for `domReady`, so it is safe to call before `document.body` exists.
|
|
@@ -320,10 +329,10 @@ Repeated callers receive the first result, and repeated failures re-throw the st
|
|
|
320
329
|
## Extra Exports
|
|
321
330
|
|
|
322
331
|
```ts
|
|
323
|
-
import { TypedRequest, ThemeManager, type TThemePreference, plugins } from '@design.estate/dees-domtools';
|
|
332
|
+
import { TypedRequest, ThemeManager, type IThemeState, type TThemePreference, plugins } from '@design.estate/dees-domtools';
|
|
324
333
|
```
|
|
325
334
|
|
|
326
|
-
- `ThemeManager` is the class of `domtools.themeManager`, exported for `ThemeManager.preferenceStorageKey` and for typing; use the page's instance rather than constructing one,
|
|
335
|
+
- `ThemeManager` is the class of `domtools.themeManager`, exported for `ThemeManager.preferenceStorageKey` and for typing; use the page's instance rather than constructing one, `TThemePreference` (`'system' | 'bright' | 'dark'`) for a preference, and `IThemeState` for what `stateObservable` emits (see Theme preference)
|
|
327
336
|
- `TypedRequest` is re-exported from `@api.global/typedrequest` 9 for typed request flows
|
|
328
337
|
- `plugins` exposes the underlying modules used by the package, including `smartrouter`, `smartstate`, `smartrx`, `smartpromise`, and `typedrequest`
|
|
329
338
|
|
package/ts/00_commitinfo_data.ts
CHANGED
|
@@ -3,6 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@design.estate/dees-domtools',
|
|
6
|
-
version: '5.
|
|
6
|
+
version: '5.2.0',
|
|
7
7
|
description: 'A package providing tools to simplify complex CSS structures and web development tasks, featuring TypeScript support and integration with various web technologies.'
|
|
8
8
|
}
|
|
@@ -13,6 +13,15 @@ const isThemePreference = (valueArg: unknown): valueArg is TThemePreference => (
|
|
|
13
13
|
themePreferences.includes(valueArg as TThemePreference)
|
|
14
14
|
);
|
|
15
15
|
|
|
16
|
+
/** What a theme toggle shows: the reader's preference, the system's colour scheme and the theme they resolve to. */
|
|
17
|
+
export interface IThemeState {
|
|
18
|
+
preference: TThemePreference;
|
|
19
|
+
/** The system's colour scheme is light. */
|
|
20
|
+
systemBright: boolean;
|
|
21
|
+
/** The page shows the bright theme. */
|
|
22
|
+
goBright: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
16
25
|
export class ThemeManager {
|
|
17
26
|
/**
|
|
18
27
|
* The `localStorage` key a picked preference is kept under, per browser and origin. `'system'` is
|
|
@@ -26,11 +35,22 @@ export class ThemeManager {
|
|
|
26
35
|
/** The reader's preference; the theme follows the system only while it is `'system'`. */
|
|
27
36
|
public preference: TThemePreference = 'system';
|
|
28
37
|
public preferredColorSchemeMediaMatch = window.matchMedia('(prefers-color-scheme: light)');
|
|
38
|
+
/** The system's colour scheme is light, as `prefers-color-scheme` last reported it. */
|
|
39
|
+
public systemBright = this.preferredColorSchemeMediaMatch.matches;
|
|
29
40
|
|
|
30
41
|
public themeObservable = new plugins.smartrx.rxjs.ReplaySubject<boolean>(1);
|
|
42
|
+
/**
|
|
43
|
+
* The preference, the system's colour scheme and the theme, on every change of any of them, also
|
|
44
|
+
* when the theme stays; replays the current state to a new subscriber.
|
|
45
|
+
*/
|
|
46
|
+
public stateObservable = new plugins.smartrx.rxjs.ReplaySubject<IThemeState>(1);
|
|
31
47
|
private automaticGlobalThemeChangeSubscription: plugins.smartrx.rxjs.Subscription | null = null;
|
|
32
48
|
private readonly preferredColorSchemeChangeHandler = (eventArg: MediaQueryListEvent) => {
|
|
33
|
-
|
|
49
|
+
this.systemBright = eventArg.matches;
|
|
50
|
+
if (this.preference !== 'system') {
|
|
51
|
+
this.publishState();
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
34
54
|
this.goBrightBoolean = eventArg.matches;
|
|
35
55
|
this.updateAllConnectedElements();
|
|
36
56
|
};
|
|
@@ -84,20 +104,30 @@ export class ThemeManager {
|
|
|
84
104
|
return;
|
|
85
105
|
}
|
|
86
106
|
this.themeObservable.next(this.goBrightBoolean);
|
|
107
|
+
this.publishState();
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
private publishState(): void {
|
|
111
|
+
if (this.domtoolsRef.disposed) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
this.stateObservable.next({ preference: this.preference, systemBright: this.systemBright, goBright: this.goBrightBoolean });
|
|
87
115
|
}
|
|
88
116
|
|
|
89
117
|
private resolveBright(): boolean {
|
|
90
|
-
return this.preference === 'system'
|
|
91
|
-
? this.preferredColorSchemeMediaMatch.matches
|
|
92
|
-
: this.preference === 'bright';
|
|
118
|
+
return this.preference === 'system' ? this.systemBright : this.preference === 'bright';
|
|
93
119
|
}
|
|
94
120
|
|
|
95
121
|
private applyPreference(preferenceArg: TThemePreference): void {
|
|
122
|
+
const preferenceChanged = preferenceArg !== this.preference;
|
|
96
123
|
this.preference = preferenceArg;
|
|
97
124
|
const goBright = this.resolveBright();
|
|
98
|
-
if (goBright
|
|
99
|
-
|
|
100
|
-
|
|
125
|
+
if (goBright !== this.goBrightBoolean) {
|
|
126
|
+
this.goBrightBoolean = goBright;
|
|
127
|
+
this.updateAllConnectedElements();
|
|
128
|
+
} else if (preferenceChanged) {
|
|
129
|
+
this.publishState();
|
|
130
|
+
}
|
|
101
131
|
}
|
|
102
132
|
|
|
103
133
|
/**
|
|
@@ -151,5 +181,6 @@ export class ThemeManager {
|
|
|
151
181
|
this.automaticGlobalThemeChangeSubscription?.unsubscribe();
|
|
152
182
|
this.automaticGlobalThemeChangeSubscription = null;
|
|
153
183
|
this.themeObservable.complete();
|
|
184
|
+
this.stateObservable.complete();
|
|
154
185
|
}
|
|
155
186
|
}
|
package/ts/index.ts
CHANGED
|
@@ -6,7 +6,7 @@ import * as css from './domtools.css.js';
|
|
|
6
6
|
|
|
7
7
|
export { css, breakpoints, elementBasic };
|
|
8
8
|
export { DomTools, type IDomToolsConstructorOptions } from './domtools.classes.domtools.js';
|
|
9
|
-
export { ThemeManager, type TThemePreference } from './domtools.classes.thememanager.js';
|
|
9
|
+
export { ThemeManager, type IThemeState, type TThemePreference } from './domtools.classes.thememanager.js';
|
|
10
10
|
export { TypedRequest } from '@api.global/typedrequest';
|
|
11
11
|
export { type IWebSetupConstructorOptions } from '@push.rocks/websetup';
|
|
12
12
|
|