@design.estate/dees-domtools 2.5.4 → 2.5.6
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 +83 -83
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/domtools.classes.domtools.d.ts +14 -4
- package/dist_ts/domtools.classes.domtools.js +115 -80
- package/dist_ts/domtools.classes.keyboard.d.ts +9 -0
- package/dist_ts/domtools.classes.keyboard.js +349 -14
- package/dist_ts/domtools.classes.scroller.d.ts +6 -1
- package/dist_ts/domtools.classes.scroller.js +70 -29
- package/dist_ts/domtools.classes.thememanager.d.ts +3 -0
- package/dist_ts/domtools.classes.thememanager.js +21 -9
- package/dist_ts/domtools.elementbasic.js +7 -4
- package/dist_ts/domtools.pluginexports.d.ts +1 -11
- package/dist_ts/domtools.pluginexports.js +2 -12
- package/license +2 -2
- package/package.json +3 -4
- package/readme.md +187 -371
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/domtools.classes.domtools.ts +136 -81
- package/ts/domtools.classes.keyboard.ts +374 -15
- package/ts/domtools.classes.scroller.ts +80 -29
- package/ts/domtools.classes.thememanager.ts +21 -8
- package/ts/domtools.elementbasic.ts +6 -3
- package/ts/domtools.pluginexports.ts +11 -22
package/readme.md
CHANGED
|
@@ -1,521 +1,337 @@
|
|
|
1
1
|
# @design.estate/dees-domtools
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Browser-side TypeScript utilities for bootstrapping DOM work, responsive styling, theme handling, scrolling, metadata setup, and Lit-based web components.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It gives you a singleton-style `DomTools` runtime plus a few focused exports for CSS breakpoints, base element styling, and low-level integrations with the underlying `design.estate` and `push.rocks` packages.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Issue Reporting and Security
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- 📱 **Responsive Breakpoints** - Built-in support for desktop, tablet, phablet, and phone viewports with container queries
|
|
11
|
-
- 🎭 **Theme Management** - Automatic dark/light mode detection and switching with RxJS observables
|
|
12
|
-
- ⌨️ **Keyboard Shortcuts** - Elegant keyboard event handling with combo support
|
|
13
|
-
- 📜 **Smooth Scrolling** - Native and Lenis-powered smooth scrolling with automatic detection
|
|
14
|
-
- 🎯 **State Management** - Integrated state management with smartstate
|
|
15
|
-
- 🧭 **Routing** - Client-side routing with smartrouter
|
|
16
|
-
- 🌐 **WebSetup** - Easy management of website metadata, favicons, and SEO tags
|
|
17
|
-
- 💅 **CSS Utilities** - Grid helpers, breakpoint utilities, and base styles for web components
|
|
9
|
+
For reporting bugs, issues, or security vulnerabilities, please visit [community.foss.global/](https://community.foss.global/). This is the central community hub for all issue reporting. Developers who sign and comply with our contribution agreement and go through identification can also get a [code.foss.global/](https://code.foss.global/) account to submit Pull Requests directly.
|
|
18
10
|
|
|
19
11
|
## Installation
|
|
20
12
|
|
|
21
13
|
```bash
|
|
22
|
-
npm install @design.estate/dees-domtools
|
|
23
|
-
# or
|
|
24
14
|
pnpm add @design.estate/dees-domtools
|
|
25
15
|
```
|
|
26
16
|
|
|
17
|
+
## What It Includes
|
|
18
|
+
|
|
19
|
+
- `DomTools` for one-time app bootstrap and shared browser services
|
|
20
|
+
- `breakpoints` helpers for viewport and container-query driven Lit CSS
|
|
21
|
+
- `css.cssGridColumns()` for simple grid-template generation
|
|
22
|
+
- `elementBasic` helpers for Lit base styles and one-time global CSS setup
|
|
23
|
+
- `TypedRequest` re-exported from `@api.global/typedrequest`
|
|
24
|
+
- `plugins` for direct access to the package ecosystem used internally
|
|
25
|
+
|
|
26
|
+
The `plugins` export keeps the commonly used downstream namespaces available, including `plugins.smartdelay`, `plugins.smartstate`, `plugins.smartpromise`, `plugins.smartrouter`, `plugins.smartrx`, `plugins.smarturl`, and `plugins.typedrequest`.
|
|
27
|
+
|
|
27
28
|
## Quick Start
|
|
28
29
|
|
|
29
|
-
```
|
|
30
|
+
```ts
|
|
30
31
|
import { DomTools } from '@design.estate/dees-domtools';
|
|
31
32
|
|
|
32
|
-
// Initialize DomTools (singleton pattern - safe to call multiple times)
|
|
33
33
|
const domtools = await DomTools.setupDomTools();
|
|
34
|
-
|
|
35
|
-
// Wait for DOM to be ready
|
|
36
34
|
await domtools.domReady.promise;
|
|
37
35
|
|
|
38
|
-
|
|
39
|
-
console.log(
|
|
36
|
+
console.log(domtools.elements.headElement);
|
|
37
|
+
console.log(domtools.elements.bodyElement);
|
|
40
38
|
```
|
|
41
39
|
|
|
42
|
-
|
|
40
|
+
`setupDomTools()` is safe to call repeatedly. By default it returns a shared global instance and avoids duplicate initialization work.
|
|
43
41
|
|
|
44
|
-
|
|
42
|
+
If you need an isolated instance for testing or short-lived usage, pass `ignoreGlobal: true`. Isolated instances follow the same `domToolsReady` and `domReady` lifecycle as the shared singleton.
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
## DomTools Lifecycle
|
|
47
45
|
|
|
48
|
-
```
|
|
46
|
+
```ts
|
|
49
47
|
import { DomTools } from '@design.estate/dees-domtools';
|
|
50
48
|
|
|
51
|
-
// Setup with options
|
|
52
49
|
const domtools = await DomTools.setupDomTools({
|
|
53
|
-
ignoreGlobal: false
|
|
50
|
+
ignoreGlobal: false,
|
|
54
51
|
});
|
|
55
52
|
|
|
56
|
-
|
|
53
|
+
await domtools.domToolsReady.promise;
|
|
57
54
|
await domtools.domReady.promise;
|
|
58
|
-
const head = domtools.elements.headElement;
|
|
59
|
-
const body = domtools.elements.bodyElement;
|
|
60
55
|
```
|
|
61
56
|
|
|
62
|
-
|
|
57
|
+
`setupDomTools()` resolves once the instance is initialized and its readiness listeners are installed. `domReady` resolves later, once `document.head` and `document.body` are available.
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
- `domtools.themeManager` - Theme management (dark/light mode)
|
|
66
|
-
- `domtools.scroller` - Smooth scrolling utilities
|
|
67
|
-
- `domtools.keyboard` - Keyboard event handling
|
|
68
|
-
- `domtools.websetup` - Website metadata management
|
|
69
|
-
- `domtools.smartstate` - State management
|
|
70
|
-
- `domtools.deesComms` - Communication utilities
|
|
59
|
+
Main instance properties:
|
|
71
60
|
|
|
72
|
-
|
|
61
|
+
- `elements.headElement` and `elements.bodyElement`
|
|
62
|
+
- `router` from `@push.rocks/smartrouter`
|
|
63
|
+
- `websetup` from `@push.rocks/websetup`
|
|
64
|
+
- `smartstate` and `domToolsStatePart`
|
|
65
|
+
- `themeManager`
|
|
66
|
+
- `scroller`
|
|
67
|
+
- `keyboard` after `domReady`
|
|
68
|
+
- `deesComms`
|
|
69
|
+
- `convenience.typedrequest`, `convenience.smartdelay`, `convenience.smartjson`, `convenience.smarturl`
|
|
73
70
|
|
|
74
|
-
- `
|
|
75
|
-
- `domtools.domReady.promise` - Resolves when DOM is interactive/complete
|
|
76
|
-
- `domtools.globalStylesReady.promise` - Resolves when global styles are set
|
|
71
|
+
If you need the already-created global instance synchronously, use `DomTools.getGlobalDomToolsSync()` after startup has completed.
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
## Cleanup
|
|
79
74
|
|
|
80
|
-
|
|
75
|
+
```ts
|
|
76
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
81
77
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
const domtools = await DomTools.setupDomTools({
|
|
79
|
+
ignoreGlobal: true,
|
|
80
|
+
});
|
|
85
81
|
|
|
86
|
-
//
|
|
87
|
-
breakpoints.desktop // 1600px
|
|
88
|
-
breakpoints.notebook // 1240px
|
|
89
|
-
breakpoints.tablet // 1024px
|
|
90
|
-
breakpoints.phablet // 600px
|
|
91
|
-
breakpoints.phone // 400px
|
|
82
|
+
// ...use the instance
|
|
92
83
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
.container {
|
|
96
|
-
padding: 20px;
|
|
97
|
-
}
|
|
84
|
+
domtools.dispose();
|
|
85
|
+
```
|
|
98
86
|
|
|
99
|
-
|
|
100
|
-
.container {
|
|
101
|
-
padding: 10px;
|
|
102
|
-
}
|
|
103
|
-
`)}
|
|
87
|
+
`dispose()` removes the listeners and DOM resources owned by that `DomTools` instance. For shared global usage you usually keep the singleton alive for the lifetime of the page, but disposal is useful for tests and intentionally short-lived isolated instances.
|
|
104
88
|
|
|
105
|
-
|
|
106
|
-
.container {
|
|
107
|
-
padding: 5px;
|
|
108
|
-
}
|
|
109
|
-
`)}
|
|
110
|
-
`;
|
|
111
|
-
```
|
|
89
|
+
## DOM, CSS, and External Resources
|
|
112
90
|
|
|
113
|
-
|
|
91
|
+
```ts
|
|
92
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
114
93
|
|
|
115
|
-
|
|
116
|
-
- `cssForNotebook(css)` - Styles for 1240px and below
|
|
117
|
-
- `cssForTablet(css)` - Styles for 1024px and below
|
|
118
|
-
- `cssForPhablet(css)` - Styles for 600px and below
|
|
119
|
-
- `cssForPhone(css)` - Styles for 400px and below
|
|
94
|
+
const domtools = await DomTools.setupDomTools();
|
|
120
95
|
|
|
121
|
-
|
|
96
|
+
await domtools.setGlobalStyles(`
|
|
97
|
+
body {
|
|
98
|
+
margin: 0;
|
|
99
|
+
font-family: Inter, sans-serif;
|
|
100
|
+
}
|
|
101
|
+
`);
|
|
122
102
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
breakpoints.cssForConstraint({ maxWidth: 800 })(litCss`.box { padding: 8px; }`)
|
|
129
|
-
|
|
130
|
-
// Component-level — targets a named container (no @media fallback)
|
|
131
|
-
breakpoints.cssForContainer(
|
|
132
|
-
litCss`.grid { columns: 1; }`,
|
|
133
|
-
'(max-width: 600px)',
|
|
134
|
-
'my-component' // CSS container-name
|
|
135
|
-
)
|
|
136
|
-
|
|
137
|
-
// Component-level with custom constraints (curried)
|
|
138
|
-
breakpoints.cssForConstraintContainer({ maxWidth: 500 }, 'my-component')(litCss`
|
|
139
|
-
.grid { gap: 8px; }
|
|
140
|
-
`)
|
|
141
|
-
|
|
142
|
-
// Generate containment styles for :host (used by @containerResponsive decorator)
|
|
143
|
-
breakpoints.containerContextStyles('my-component')
|
|
144
|
-
// → :host { container-type: inline-size; container-name: my-component; }
|
|
103
|
+
await domtools.setExternalCss(
|
|
104
|
+
'https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap'
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
await domtools.setExternalScript('https://cdn.example.com/some-script.js');
|
|
145
108
|
```
|
|
146
109
|
|
|
147
|
-
|
|
110
|
+
For page metadata and favicons:
|
|
148
111
|
|
|
149
|
-
|
|
150
|
-
|
|
112
|
+
```ts
|
|
113
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
151
114
|
|
|
152
|
-
|
|
115
|
+
const domtools = await DomTools.setupDomTools();
|
|
153
116
|
|
|
154
|
-
|
|
117
|
+
await domtools.setWebsiteInfo({
|
|
118
|
+
metaObject: {
|
|
119
|
+
title: 'Example App',
|
|
120
|
+
description: 'A browser app bootstrapped with DomTools',
|
|
121
|
+
},
|
|
122
|
+
faviconUrl: '/favicon.ico',
|
|
123
|
+
});
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Theme Management
|
|
127
|
+
|
|
128
|
+
```ts
|
|
129
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
155
130
|
|
|
156
|
-
```typescript
|
|
157
131
|
const domtools = await DomTools.setupDomTools();
|
|
158
132
|
const { themeManager } = domtools;
|
|
159
133
|
|
|
160
|
-
|
|
161
|
-
|
|
134
|
+
themeManager.themeObservable.subscribe((isBright) => {
|
|
135
|
+
console.log('bright mode?', isBright);
|
|
136
|
+
});
|
|
162
137
|
|
|
163
|
-
// Set specific theme
|
|
164
138
|
themeManager.goDark();
|
|
165
139
|
themeManager.goBright();
|
|
140
|
+
themeManager.toggleDarkBright();
|
|
166
141
|
|
|
167
|
-
// Enable automatic global background changes
|
|
168
142
|
await themeManager.enableAutomaticGlobalThemeChange();
|
|
143
|
+
```
|
|
169
144
|
|
|
170
|
-
|
|
171
|
-
themeManager.themeObservable.subscribe((isBright) => {
|
|
172
|
-
console.log(`Theme is now: ${isBright ? 'light' : 'dark'}`);
|
|
173
|
-
});
|
|
145
|
+
The theme manager starts from `prefers-color-scheme` and publishes updates through an RxJS `ReplaySubject<boolean>`.
|
|
174
146
|
|
|
175
|
-
|
|
176
|
-
if (themeManager.goBrightBoolean) {
|
|
177
|
-
console.log('Light mode active');
|
|
178
|
-
}
|
|
179
|
-
```
|
|
147
|
+
`enableAutomaticGlobalThemeChange()` waits for `domReady`, so it is safe to call before `document.body` exists.
|
|
180
148
|
|
|
181
|
-
|
|
149
|
+
## Keyboard Shortcuts
|
|
182
150
|
|
|
183
|
-
|
|
151
|
+
The keyboard helper is created after `document.body` exists, so wait for `domReady` before using it.
|
|
184
152
|
|
|
185
|
-
```
|
|
186
|
-
import {
|
|
153
|
+
```ts
|
|
154
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
187
155
|
|
|
188
156
|
const domtools = await DomTools.setupDomTools();
|
|
189
157
|
await domtools.domReady.promise;
|
|
190
158
|
|
|
191
|
-
|
|
192
|
-
const {
|
|
193
|
-
|
|
194
|
-
// Listen for Ctrl+S
|
|
195
|
-
keyboard.on([Key.Ctrl, Key.S]).subscribe((event) => {
|
|
196
|
-
event.preventDefault();
|
|
197
|
-
console.log('Save triggered!');
|
|
198
|
-
});
|
|
159
|
+
const keyboard = domtools.keyboard!;
|
|
160
|
+
const { keyEnum } = keyboard;
|
|
199
161
|
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
console.log('Command palette opened!');
|
|
162
|
+
keyboard.on([keyEnum.Ctrl, keyEnum.S]).subscribe(() => {
|
|
163
|
+
console.log('save triggered');
|
|
203
164
|
});
|
|
204
165
|
|
|
205
|
-
|
|
206
|
-
keyboard.triggerKeyPress([Key.Ctrl, Key.S]);
|
|
207
|
-
|
|
208
|
-
// Clean up when done
|
|
209
|
-
keyboard.stopListening();
|
|
166
|
+
keyboard.triggerKeyPress([keyEnum.Ctrl, keyEnum.S]);
|
|
210
167
|
```
|
|
211
168
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
All standard keyboard keys are available in the `Key` enum, including:
|
|
215
|
-
|
|
216
|
-
- Modifiers: `Ctrl`, `Shift`, `Alt`
|
|
217
|
-
- Letters: `A` through `Z`
|
|
218
|
-
- Numbers: `Zero` through `Nine`
|
|
219
|
-
- Function keys: `F1` through `F12`
|
|
220
|
-
- Navigation: `Home`, `End`, `PageUp`, `PageDown`, arrows
|
|
221
|
-
- And many more...
|
|
222
|
-
|
|
223
|
-
### Smooth Scrolling
|
|
169
|
+
## Scrolling
|
|
224
170
|
|
|
225
|
-
|
|
171
|
+
```ts
|
|
172
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
226
173
|
|
|
227
|
-
```typescript
|
|
228
174
|
const domtools = await DomTools.setupDomTools();
|
|
229
175
|
const { scroller } = domtools;
|
|
230
176
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
await scroller.toElement(targetElement, {
|
|
234
|
-
duration: 1000,
|
|
235
|
-
easing: 'easeInOutQuad'
|
|
177
|
+
scroller.onScroll(() => {
|
|
178
|
+
console.log('scroll event');
|
|
236
179
|
});
|
|
237
180
|
|
|
238
|
-
// Enable Lenis smooth scrolling
|
|
239
181
|
await scroller.enableLenisScroll({
|
|
240
|
-
disableOnNativeSmoothScroll: true
|
|
182
|
+
disableOnNativeSmoothScroll: true,
|
|
241
183
|
});
|
|
242
184
|
|
|
243
|
-
|
|
244
|
-
scroller.
|
|
245
|
-
console.log('Page scrolled!');
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Detect if native smooth scrolling is enabled
|
|
249
|
-
const hasNativeSmooth = await scroller.detectNativeSmoothScroll();
|
|
185
|
+
const section = document.querySelector('#details') as HTMLElement;
|
|
186
|
+
await scroller.toElement(section, { duration: 600 });
|
|
250
187
|
```
|
|
251
188
|
|
|
252
|
-
|
|
189
|
+
The scroller uses native scroll listeners by default and switches to Lenis when enabled.
|
|
253
190
|
|
|
254
|
-
|
|
191
|
+
## Responsive CSS Helpers
|
|
255
192
|
|
|
256
|
-
|
|
257
|
-
import { css } from '@design.estate/dees-domtools';
|
|
193
|
+
`breakpoints` is designed for Lit CSS and ships both preset breakpoints and lower-level helpers.
|
|
258
194
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
195
|
+
```ts
|
|
196
|
+
import { breakpoints } from '@design.estate/dees-domtools';
|
|
197
|
+
import { css } from 'lit';
|
|
262
198
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
grid-template-columns: ${gridTemplate};
|
|
268
|
-
gap: 16px;
|
|
199
|
+
const styles = css`
|
|
200
|
+
:host {
|
|
201
|
+
display: block;
|
|
202
|
+
padding: 24px;
|
|
269
203
|
}
|
|
204
|
+
|
|
205
|
+
${breakpoints.cssForTablet(css`
|
|
206
|
+
:host {
|
|
207
|
+
padding: 16px;
|
|
208
|
+
}
|
|
209
|
+
`)}
|
|
210
|
+
|
|
211
|
+
${breakpoints.cssForPhone(css`
|
|
212
|
+
:host {
|
|
213
|
+
padding: 10px;
|
|
214
|
+
}
|
|
215
|
+
`)}
|
|
270
216
|
`;
|
|
271
217
|
```
|
|
272
218
|
|
|
273
|
-
|
|
219
|
+
Available values:
|
|
274
220
|
|
|
275
|
-
|
|
276
|
-
|
|
221
|
+
- `breakpoints.desktop` => `1600`
|
|
222
|
+
- `breakpoints.notebook` => `1240`
|
|
223
|
+
- `breakpoints.tablet` => `1024`
|
|
224
|
+
- `breakpoints.phablet` => `600`
|
|
225
|
+
- `breakpoints.phone` => `400`
|
|
277
226
|
|
|
278
|
-
|
|
279
|
-
await domtools.setGlobalStyles(`
|
|
280
|
-
body {
|
|
281
|
-
margin: 0;
|
|
282
|
-
font-family: 'Inter', sans-serif;
|
|
283
|
-
}
|
|
284
|
-
`);
|
|
227
|
+
Available helpers:
|
|
285
228
|
|
|
286
|
-
|
|
287
|
-
|
|
229
|
+
- `cssForDesktop()`
|
|
230
|
+
- `cssForNotebook()`
|
|
231
|
+
- `cssForTablet()`
|
|
232
|
+
- `cssForPhablet()`
|
|
233
|
+
- `cssForPhone()`
|
|
234
|
+
- `cssForViewport()`
|
|
235
|
+
- `cssForContainer()`
|
|
236
|
+
- `cssForConstraint()`
|
|
237
|
+
- `cssForConstraintContainer()`
|
|
238
|
+
- `containerContextStyles()`
|
|
288
239
|
|
|
289
|
-
|
|
290
|
-
await domtools.setExternalScript('https://cdn.example.com/analytics.js');
|
|
291
|
-
```
|
|
240
|
+
Viewport helpers emit both `@media` and `@container wccToolsViewport` rules. Container helpers target a named CSS container only.
|
|
292
241
|
|
|
293
|
-
|
|
242
|
+
## CSS Utility
|
|
294
243
|
|
|
295
|
-
|
|
244
|
+
```ts
|
|
245
|
+
import { css } from '@design.estate/dees-domtools';
|
|
296
246
|
|
|
297
|
-
|
|
298
|
-
const domtools = await DomTools.setupDomTools();
|
|
247
|
+
const columns = css.cssGridColumns(3, 24);
|
|
299
248
|
|
|
300
|
-
|
|
301
|
-
metaObject: {
|
|
302
|
-
title: 'My Awesome App',
|
|
303
|
-
description: 'The best app ever created',
|
|
304
|
-
keywords: ['awesome', 'app', 'web'],
|
|
305
|
-
author: 'Your Name'
|
|
306
|
-
},
|
|
307
|
-
faviconUrl: '/favicon.ico',
|
|
308
|
-
appleTouchIconUrl: '/apple-touch-icon.png'
|
|
309
|
-
});
|
|
249
|
+
console.log(columns);
|
|
310
250
|
```
|
|
311
251
|
|
|
312
|
-
|
|
252
|
+
This returns a ready-to-insert `grid-template-columns` string.
|
|
313
253
|
|
|
314
|
-
|
|
254
|
+
## Lit Element Setup
|
|
315
255
|
|
|
316
|
-
```
|
|
317
|
-
import { LitElement } from 'lit';
|
|
256
|
+
```ts
|
|
318
257
|
import { elementBasic } from '@design.estate/dees-domtools';
|
|
258
|
+
import { LitElement, html } from 'lit';
|
|
319
259
|
|
|
320
|
-
class
|
|
260
|
+
class DemoElement extends LitElement {
|
|
321
261
|
static styles = [elementBasic.staticStyles];
|
|
322
262
|
|
|
323
263
|
async connectedCallback() {
|
|
324
264
|
super.connectedCallback();
|
|
325
265
|
await elementBasic.setup(this);
|
|
326
266
|
}
|
|
267
|
+
|
|
268
|
+
render() {
|
|
269
|
+
return html`<p>Hello DOM tools</p>`;
|
|
270
|
+
}
|
|
327
271
|
}
|
|
328
272
|
```
|
|
329
273
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
- Box-sizing reset
|
|
333
|
-
- Smooth transitions for background and color
|
|
334
|
-
- Custom scrollbar styles
|
|
335
|
-
- Default font family (Geist Sans, Inter fallback)
|
|
336
|
-
|
|
337
|
-
### State Management
|
|
338
|
-
|
|
339
|
-
Integrated state management with smartstate:
|
|
340
|
-
|
|
341
|
-
```typescript
|
|
342
|
-
const domtools = await DomTools.setupDomTools();
|
|
274
|
+
`elementBasic.setup()` performs the shared `DomTools` setup and injects the package's global base styles once.
|
|
343
275
|
|
|
344
|
-
|
|
345
|
-
const state = domtools.domToolsStatePart;
|
|
276
|
+
The returned promise resolves after the shared base styles have been injected, and `domtools.globalStylesReady` resolves at the same point.
|
|
346
277
|
|
|
347
|
-
|
|
348
|
-
const currentState = state.getState();
|
|
349
|
-
console.log(currentState.virtualViewport); // 'native'
|
|
350
|
-
console.log(currentState.jwt); // ''
|
|
278
|
+
## State and One-Time Work
|
|
351
279
|
|
|
352
|
-
|
|
353
|
-
state.setState({
|
|
354
|
-
virtualViewport: 'tablet',
|
|
355
|
-
jwt: 'your-token-here'
|
|
356
|
-
});
|
|
280
|
+
`domToolsStatePart` starts with this shape:
|
|
357
281
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
282
|
+
```ts
|
|
283
|
+
{
|
|
284
|
+
virtualViewport: 'native',
|
|
285
|
+
jwt: '',
|
|
286
|
+
}
|
|
362
287
|
```
|
|
363
288
|
|
|
364
|
-
|
|
289
|
+
You can also guard expensive async work with `runOnce()`:
|
|
365
290
|
|
|
366
|
-
|
|
291
|
+
```ts
|
|
292
|
+
import { DomTools } from '@design.estate/dees-domtools';
|
|
367
293
|
|
|
368
|
-
```typescript
|
|
369
294
|
const domtools = await DomTools.setupDomTools();
|
|
370
295
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
console.log('Running expensive operation...');
|
|
374
|
-
await someExpensiveAsyncOperation();
|
|
375
|
-
return 'result';
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
// Subsequent calls return the same result without re-executing
|
|
379
|
-
const sameResult = await domtools.runOnce('myExpensiveOperation', async () => {
|
|
380
|
-
console.log('This will never run!');
|
|
381
|
-
return 'different result';
|
|
296
|
+
const result = await domtools.runOnce('load-config', async () => {
|
|
297
|
+
return { ok: true };
|
|
382
298
|
});
|
|
383
|
-
|
|
384
|
-
console.log(result === sameResult); // true
|
|
385
299
|
```
|
|
386
300
|
|
|
387
|
-
|
|
301
|
+
Repeated callers receive the first result, and repeated failures re-throw the stored error.
|
|
388
302
|
|
|
389
|
-
##
|
|
303
|
+
## Extra Exports
|
|
390
304
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
Here's a real-world example combining multiple features:
|
|
394
|
-
|
|
395
|
-
```typescript
|
|
396
|
-
import { DomTools, breakpoints, elementBasic, Key } from '@design.estate/dees-domtools';
|
|
397
|
-
import { LitElement, html, css as litCss } from 'lit';
|
|
398
|
-
import { customElement } from 'lit/decorators.js';
|
|
399
|
-
|
|
400
|
-
@customElement('my-app')
|
|
401
|
-
class MyApp extends LitElement {
|
|
402
|
-
static styles = [
|
|
403
|
-
elementBasic.staticStyles,
|
|
404
|
-
litCss`
|
|
405
|
-
:host {
|
|
406
|
-
display: block;
|
|
407
|
-
padding: 2rem;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
${breakpoints.cssForTablet(litCss`
|
|
411
|
-
:host {
|
|
412
|
-
padding: 1rem;
|
|
413
|
-
}
|
|
414
|
-
`)}
|
|
415
|
-
`
|
|
416
|
-
];
|
|
417
|
-
|
|
418
|
-
private domtools?: DomTools;
|
|
419
|
-
|
|
420
|
-
async connectedCallback() {
|
|
421
|
-
super.connectedCallback();
|
|
422
|
-
|
|
423
|
-
// Setup DomTools
|
|
424
|
-
this.domtools = await elementBasic.setup(this);
|
|
425
|
-
await this.domtools.domReady.promise;
|
|
426
|
-
|
|
427
|
-
// Setup keyboard shortcuts
|
|
428
|
-
this.domtools.keyboard.on([Key.Ctrl, Key.K]).subscribe(() => {
|
|
429
|
-
this.openCommandPalette();
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
// Subscribe to theme changes
|
|
433
|
-
this.domtools.themeManager.themeObservable.subscribe((isBright) => {
|
|
434
|
-
this.requestUpdate();
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
// Enable smooth scrolling
|
|
438
|
-
await this.domtools.scroller.enableLenisScroll({
|
|
439
|
-
disableOnNativeSmoothScroll: true
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
private openCommandPalette() {
|
|
444
|
-
console.log('Command palette opened!');
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
render() {
|
|
448
|
-
const isDark = !this.domtools?.themeManager.goBrightBoolean;
|
|
449
|
-
|
|
450
|
-
return html`
|
|
451
|
-
<div class="app" style="background: ${isDark ? '#1a1a1a' : '#ffffff'}">
|
|
452
|
-
<h1>My Awesome App</h1>
|
|
453
|
-
<button @click=${() => this.domtools?.themeManager.toggleDarkBright()}>
|
|
454
|
-
Toggle Theme
|
|
455
|
-
</button>
|
|
456
|
-
</div>
|
|
457
|
-
`;
|
|
458
|
-
}
|
|
459
|
-
}
|
|
305
|
+
```ts
|
|
306
|
+
import { TypedRequest, plugins } from '@design.estate/dees-domtools';
|
|
460
307
|
```
|
|
461
308
|
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
This package is written in TypeScript and provides full type definitions:
|
|
309
|
+
- `TypedRequest` is re-exported for typed request flows
|
|
310
|
+
- `plugins` exposes the underlying modules used by the package, including `smartrouter`, `smartstate`, `smartrx`, `smartpromise`, `typedrequest`, and `deesComms`
|
|
465
311
|
|
|
466
|
-
|
|
467
|
-
import type {
|
|
468
|
-
IDomToolsState,
|
|
469
|
-
IDomToolsContructorOptions,
|
|
470
|
-
TViewport
|
|
471
|
-
} from '@design.estate/dees-domtools';
|
|
472
|
-
|
|
473
|
-
// Custom state interface
|
|
474
|
-
interface MyState extends IDomToolsState {
|
|
475
|
-
customProperty: string;
|
|
476
|
-
}
|
|
477
|
-
|
|
478
|
-
// Type-safe viewport handling
|
|
479
|
-
const viewport: TViewport = 'tablet';
|
|
480
|
-
```
|
|
312
|
+
## Runtime Notes
|
|
481
313
|
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
## Why @design.estate/dees-domtools?
|
|
487
|
-
|
|
488
|
-
- ✅ **Race-condition free** - Carefully designed initialization prevents common timing issues
|
|
489
|
-
- ✅ **TypeScript first** - Full type safety and IntelliSense support
|
|
490
|
-
- ✅ **Modern APIs** - Built on Lit, RxJS, and other modern web standards
|
|
491
|
-
- ✅ **Batteries included** - Everything you need for sophisticated web apps
|
|
492
|
-
- ✅ **Production ready** - Used in real-world applications at design.estate
|
|
493
|
-
- ✅ **Well maintained** - Active development and support
|
|
494
|
-
|
|
495
|
-
## Related Packages
|
|
496
|
-
|
|
497
|
-
This library integrates with the design.estate ecosystem:
|
|
498
|
-
|
|
499
|
-
- `@design.estate/dees-comms` - Communication utilities
|
|
500
|
-
- `@push.rocks/websetup` - Website setup and meta management
|
|
501
|
-
- `@push.rocks/smartrouter` - Client-side routing
|
|
502
|
-
- `@push.rocks/smartstate` - State management
|
|
314
|
+
- This package is browser-oriented and touches `window`, `document`, `navigator`, and `matchMedia`
|
|
315
|
+
- `keyboard` is `null` until `domReady` resolves
|
|
316
|
+
- The published package targets the latest Chrome via `browserslist`
|
|
503
317
|
|
|
504
318
|
## License and Legal Information
|
|
505
319
|
|
|
506
|
-
This repository contains open-source code
|
|
320
|
+
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
|
|
507
321
|
|
|
508
322
|
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.
|
|
509
323
|
|
|
510
324
|
### Trademarks
|
|
511
325
|
|
|
512
|
-
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH and are not included within the scope of the MIT license granted herein.
|
|
326
|
+
This project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.
|
|
327
|
+
|
|
328
|
+
Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.
|
|
513
329
|
|
|
514
330
|
### Company Information
|
|
515
331
|
|
|
516
|
-
Task Venture Capital GmbH
|
|
517
|
-
Registered at District
|
|
332
|
+
Task Venture Capital GmbH
|
|
333
|
+
Registered at District Court Bremen HRB 35230 HB, Germany
|
|
518
334
|
|
|
519
|
-
For any legal inquiries or
|
|
335
|
+
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
|
520
336
|
|
|
521
337
|
By using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.
|