fix(build): align test imports with tstest tapbundle and simplify the build script
This commit is contained in:
Vendored
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["/npmextra.json"],
|
||||
"fileMatch": ["/.smartconfig.json"],
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-04-23 - 2.5.5 - fix(build)
|
||||
align test imports with tstest tapbundle and simplify the build script
|
||||
|
||||
- switches the Chromium test from @push.rocks/tapbundle to @git.zone/tstest/tapbundle
|
||||
- removes the unused @push.rocks/tapbundle devDependency
|
||||
- drops the web-specific and allowimplicitany flags from the build command
|
||||
- refreshes the README to match the current package API and usage
|
||||
|
||||
## 2026-03-27 - 2.5.4 - fix(build)
|
||||
remove npm bundling from build script and align documented jwt default state
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2020 Lossless GmbH (hello@lossless.com)
|
||||
Copyright (c) 2020 Task Venture Capital GmbH (hello@task.vc)
|
||||
Copyright (c) 2017 Nathan Friend (ts-keycode-enum)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
@@ -17,4 +17,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
||||
+2
-3
@@ -10,7 +10,7 @@
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "(tstest test/ --verbose --logfile)",
|
||||
"build": "(tsbuild --web --allowimplicitany && tsbundle)",
|
||||
"build": "(tsbuild && tsbundle)",
|
||||
"format": "(gitzone format)",
|
||||
"buildDocs": "tsdoc"
|
||||
},
|
||||
@@ -18,8 +18,7 @@
|
||||
"@git.zone/tsbuild": "^4.4.0",
|
||||
"@git.zone/tsbundle": "^2.10.0",
|
||||
"@git.zone/tstest": "^3.6.3",
|
||||
"@push.rocks/tapbundle": "^6.0.3",
|
||||
"@types/node": "^25.5.0"
|
||||
"@types/node": "^25.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@api.global/typedrequest": "^3.3.0",
|
||||
|
||||
Generated
+18
-2120
File diff suppressed because it is too large
Load Diff
@@ -1,521 +1,311 @@
|
||||
# @design.estate/dees-domtools
|
||||
|
||||
> 🎨 A comprehensive TypeScript toolkit for simplifying DOM manipulation, CSS management, and web component development
|
||||
Browser-side TypeScript utilities for bootstrapping DOM work, responsive styling, theme handling, scrolling, metadata setup, and Lit-based web components.
|
||||
|
||||
Modern web development made elegant. `@design.estate/dees-domtools` provides a powerful suite of utilities for managing complex CSS structures, handling browser events, implementing smooth scrolling, and building responsive web applications with ease.
|
||||
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.
|
||||
|
||||
## Features
|
||||
## Issue Reporting and Security
|
||||
|
||||
- 🚀 **Smart DOM Management** - Singleton-based DomTools instance with race-condition-free initialization
|
||||
- 📱 **Responsive Breakpoints** - Built-in support for desktop, tablet, phablet, and phone viewports with container queries
|
||||
- 🎭 **Theme Management** - Automatic dark/light mode detection and switching with RxJS observables
|
||||
- ⌨️ **Keyboard Shortcuts** - Elegant keyboard event handling with combo support
|
||||
- 📜 **Smooth Scrolling** - Native and Lenis-powered smooth scrolling with automatic detection
|
||||
- 🎯 **State Management** - Integrated state management with smartstate
|
||||
- 🧭 **Routing** - Client-side routing with smartrouter
|
||||
- 🌐 **WebSetup** - Easy management of website metadata, favicons, and SEO tags
|
||||
- 💅 **CSS Utilities** - Grid helpers, breakpoint utilities, and base styles for web components
|
||||
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.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @design.estate/dees-domtools
|
||||
# or
|
||||
pnpm add @design.estate/dees-domtools
|
||||
```
|
||||
|
||||
## What It Includes
|
||||
|
||||
- `DomTools` for one-time app bootstrap and shared browser services
|
||||
- `breakpoints` helpers for viewport and container-query driven Lit CSS
|
||||
- `css.cssGridColumns()` for simple grid-template generation
|
||||
- `elementBasic` helpers for Lit base styles and one-time global CSS setup
|
||||
- `TypedRequest` re-exported from `@api.global/typedrequest`
|
||||
- `plugins` for direct access to the package ecosystem used internally
|
||||
|
||||
## Quick Start
|
||||
|
||||
```typescript
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
// Initialize DomTools (singleton pattern - safe to call multiple times)
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
// Wait for DOM to be ready
|
||||
await domtools.domReady.promise;
|
||||
|
||||
// Now you're ready to rock! 🎸
|
||||
console.log('DOM is ready, head and body elements are available');
|
||||
console.log(domtools.elements.headElement);
|
||||
console.log(domtools.elements.bodyElement);
|
||||
```
|
||||
|
||||
## Core API
|
||||
`setupDomTools()` is safe to call repeatedly. By default it returns a shared global instance and avoids duplicate initialization work.
|
||||
|
||||
### DomTools Instance
|
||||
## DomTools Lifecycle
|
||||
|
||||
The `DomTools` class is the heart of the library. It provides a singleton instance that manages all the utilities.
|
||||
|
||||
```typescript
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
// Setup with options
|
||||
const domtools = await DomTools.setupDomTools({
|
||||
ignoreGlobal: false // Set to true to create isolated instance
|
||||
ignoreGlobal: false,
|
||||
});
|
||||
|
||||
// Access DOM elements (available after domReady)
|
||||
await domtools.domToolsReady.promise;
|
||||
await domtools.domReady.promise;
|
||||
const head = domtools.elements.headElement;
|
||||
const body = domtools.elements.bodyElement;
|
||||
```
|
||||
|
||||
**Key Properties:**
|
||||
Main instance properties:
|
||||
|
||||
- `domtools.router` - SmartRouter instance for client-side routing
|
||||
- `domtools.themeManager` - Theme management (dark/light mode)
|
||||
- `domtools.scroller` - Smooth scrolling utilities
|
||||
- `domtools.keyboard` - Keyboard event handling
|
||||
- `domtools.websetup` - Website metadata management
|
||||
- `domtools.smartstate` - State management
|
||||
- `domtools.deesComms` - Communication utilities
|
||||
- `elements.headElement` and `elements.bodyElement`
|
||||
- `router` from `@push.rocks/smartrouter`
|
||||
- `websetup` from `@push.rocks/websetup`
|
||||
- `smartstate` and `domToolsStatePart`
|
||||
- `themeManager`
|
||||
- `scroller`
|
||||
- `keyboard` after `domReady`
|
||||
- `deesComms`
|
||||
- `convenience.typedrequest`, `convenience.smartdelay`, `convenience.smartjson`, `convenience.smarturl`
|
||||
|
||||
**Lifecycle Promises:**
|
||||
If you need the already-created global instance synchronously, use `DomTools.getGlobalDomToolsSync()` after startup has completed.
|
||||
|
||||
- `domtools.domToolsReady.promise` - Resolves when DomTools is initialized
|
||||
- `domtools.domReady.promise` - Resolves when DOM is interactive/complete
|
||||
- `domtools.globalStylesReady.promise` - Resolves when global styles are set
|
||||
## DOM, CSS, and External Resources
|
||||
|
||||
### Responsive Breakpoints
|
||||
|
||||
Built-in breakpoint system with both media queries and container queries:
|
||||
|
||||
```typescript
|
||||
import { breakpoints, css } from '@design.estate/dees-domtools';
|
||||
import { css as litCss } from 'lit';
|
||||
|
||||
// Breakpoint values (in pixels)
|
||||
breakpoints.desktop // 1600px
|
||||
breakpoints.notebook // 1240px
|
||||
breakpoints.tablet // 1024px
|
||||
breakpoints.phablet // 600px
|
||||
breakpoints.phone // 400px
|
||||
|
||||
// Use with Lit components
|
||||
const myStyles = litCss`
|
||||
.container {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
${breakpoints.cssForTablet(litCss`
|
||||
.container {
|
||||
padding: 10px;
|
||||
}
|
||||
`)}
|
||||
|
||||
${breakpoints.cssForPhone(litCss`
|
||||
.container {
|
||||
padding: 5px;
|
||||
}
|
||||
`)}
|
||||
`;
|
||||
```
|
||||
|
||||
**Preset viewport helpers** (emit both `@media` and `@container wccToolsViewport`):
|
||||
|
||||
- `cssForDesktop(css)` - Styles for 1600px and above
|
||||
- `cssForNotebook(css)` - Styles for 1240px and below
|
||||
- `cssForTablet(css)` - Styles for 1024px and below
|
||||
- `cssForPhablet(css)` - Styles for 600px and below
|
||||
- `cssForPhone(css)` - Styles for 400px and below
|
||||
|
||||
**Low-level helpers** for custom constraints and component-scoped containers:
|
||||
|
||||
```typescript
|
||||
import { breakpoints } from '@design.estate/dees-domtools';
|
||||
import { css as litCss } from 'lit';
|
||||
|
||||
// Viewport-level with custom constraints (emits @media + @container wccToolsViewport)
|
||||
breakpoints.cssForConstraint({ maxWidth: 800 })(litCss`.box { padding: 8px; }`)
|
||||
|
||||
// Component-level — targets a named container (no @media fallback)
|
||||
breakpoints.cssForContainer(
|
||||
litCss`.grid { columns: 1; }`,
|
||||
'(max-width: 600px)',
|
||||
'my-component' // CSS container-name
|
||||
)
|
||||
|
||||
// Component-level with custom constraints (curried)
|
||||
breakpoints.cssForConstraintContainer({ maxWidth: 500 }, 'my-component')(litCss`
|
||||
.grid { gap: 8px; }
|
||||
`)
|
||||
|
||||
// Generate containment styles for :host (used by @containerResponsive decorator)
|
||||
breakpoints.containerContextStyles('my-component')
|
||||
// → :host { container-type: inline-size; container-name: my-component; }
|
||||
```
|
||||
|
||||
**Exported types:**
|
||||
|
||||
- `ICssForConstraints` — `{ maxWidth?: number; minWidth?: number }`
|
||||
- `TViewport` — `'native' | 'desktop' | 'tablet' | 'phablet' | 'phone'`
|
||||
|
||||
### Theme Management
|
||||
|
||||
Automatic theme detection with system preference support:
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
const { themeManager } = domtools;
|
||||
|
||||
// Toggle between dark and light
|
||||
themeManager.toggleDarkBright();
|
||||
|
||||
// Set specific theme
|
||||
themeManager.goDark();
|
||||
themeManager.goBright();
|
||||
|
||||
// Enable automatic global background changes
|
||||
await themeManager.enableAutomaticGlobalThemeChange();
|
||||
|
||||
// Subscribe to theme changes
|
||||
themeManager.themeObservable.subscribe((isBright) => {
|
||||
console.log(`Theme is now: ${isBright ? 'light' : 'dark'}`);
|
||||
});
|
||||
|
||||
// Check current theme
|
||||
if (themeManager.goBrightBoolean) {
|
||||
console.log('Light mode active');
|
||||
}
|
||||
```
|
||||
|
||||
### Keyboard Shortcuts
|
||||
|
||||
Handle keyboard events with ease, including complex combinations:
|
||||
|
||||
```typescript
|
||||
import { Keyboard, Key } from '@design.estate/dees-domtools';
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
await domtools.domReady.promise;
|
||||
|
||||
// Access the keyboard instance
|
||||
const { keyboard } = domtools;
|
||||
|
||||
// Listen for Ctrl+S
|
||||
keyboard.on([Key.Ctrl, Key.S]).subscribe((event) => {
|
||||
event.preventDefault();
|
||||
console.log('Save triggered!');
|
||||
});
|
||||
|
||||
// Listen for Ctrl+Shift+P
|
||||
keyboard.on([Key.Ctrl, Key.Shift, Key.P]).subscribe(() => {
|
||||
console.log('Command palette opened!');
|
||||
});
|
||||
|
||||
// Programmatically trigger key presses
|
||||
keyboard.triggerKeyPress([Key.Ctrl, Key.S]);
|
||||
|
||||
// Clean up when done
|
||||
keyboard.stopListening();
|
||||
```
|
||||
|
||||
**Available Keys:**
|
||||
|
||||
All standard keyboard keys are available in the `Key` enum, including:
|
||||
|
||||
- Modifiers: `Ctrl`, `Shift`, `Alt`
|
||||
- Letters: `A` through `Z`
|
||||
- Numbers: `Zero` through `Nine`
|
||||
- Function keys: `F1` through `F12`
|
||||
- Navigation: `Home`, `End`, `PageUp`, `PageDown`, arrows
|
||||
- And many more...
|
||||
|
||||
### Smooth Scrolling
|
||||
|
||||
Powerful scrolling utilities with Lenis integration:
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
const { scroller } = domtools;
|
||||
|
||||
// Scroll to an element smoothly
|
||||
const targetElement = document.querySelector('#section-2');
|
||||
await scroller.toElement(targetElement, {
|
||||
duration: 1000,
|
||||
easing: 'easeInOutQuad'
|
||||
});
|
||||
|
||||
// Enable Lenis smooth scrolling
|
||||
await scroller.enableLenisScroll({
|
||||
disableOnNativeSmoothScroll: true // Auto-disable if browser has native smooth scroll
|
||||
});
|
||||
|
||||
// Register scroll callbacks
|
||||
scroller.onScroll(() => {
|
||||
console.log('Page scrolled!');
|
||||
});
|
||||
|
||||
// Detect if native smooth scrolling is enabled
|
||||
const hasNativeSmooth = await scroller.detectNativeSmoothScroll();
|
||||
```
|
||||
|
||||
### CSS Utilities
|
||||
|
||||
Helper functions for common CSS patterns:
|
||||
|
||||
```typescript
|
||||
import { css } from '@design.estate/dees-domtools';
|
||||
|
||||
// Create responsive grid columns
|
||||
const gridTemplate = css.cssGridColumns(4, 16);
|
||||
// Returns: calc((100%/4) - (48px/4)) calc((100%/4) - (48px/4)) ...
|
||||
|
||||
// Use in your styles
|
||||
const styles = `
|
||||
.grid {
|
||||
display: grid;
|
||||
grid-template-columns: ${gridTemplate};
|
||||
gap: 16px;
|
||||
}
|
||||
`;
|
||||
```
|
||||
|
||||
### Global Styles & External Resources
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
// Add global CSS
|
||||
await domtools.setGlobalStyles(`
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: 'Inter', sans-serif;
|
||||
font-family: Inter, sans-serif;
|
||||
}
|
||||
`);
|
||||
|
||||
// Load external CSS
|
||||
await domtools.setExternalCss('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
|
||||
await domtools.setExternalCss(
|
||||
'https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap'
|
||||
);
|
||||
|
||||
// Load external JavaScript
|
||||
await domtools.setExternalScript('https://cdn.example.com/analytics.js');
|
||||
await domtools.setExternalScript('https://cdn.example.com/some-script.js');
|
||||
```
|
||||
|
||||
### Website Metadata
|
||||
For page metadata and favicons:
|
||||
|
||||
Manage your website's metadata easily:
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
await domtools.setWebsiteInfo({
|
||||
metaObject: {
|
||||
title: 'My Awesome App',
|
||||
description: 'The best app ever created',
|
||||
keywords: ['awesome', 'app', 'web'],
|
||||
author: 'Your Name'
|
||||
title: 'Example App',
|
||||
description: 'A browser app bootstrapped with DomTools',
|
||||
},
|
||||
faviconUrl: '/favicon.ico',
|
||||
appleTouchIconUrl: '/apple-touch-icon.png'
|
||||
});
|
||||
```
|
||||
|
||||
### Web Component Base Styles
|
||||
## Theme Management
|
||||
|
||||
Kickstart your Lit elements with pre-configured styles:
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
```typescript
|
||||
import { LitElement } from 'lit';
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
const { themeManager } = domtools;
|
||||
|
||||
themeManager.themeObservable.subscribe((isBright) => {
|
||||
console.log('bright mode?', isBright);
|
||||
});
|
||||
|
||||
themeManager.goDark();
|
||||
themeManager.goBright();
|
||||
themeManager.toggleDarkBright();
|
||||
|
||||
await themeManager.enableAutomaticGlobalThemeChange();
|
||||
```
|
||||
|
||||
The theme manager starts from `prefers-color-scheme` and publishes updates through an RxJS `ReplaySubject<boolean>`.
|
||||
|
||||
## Keyboard Shortcuts
|
||||
|
||||
The keyboard helper is created after `document.body` exists, so wait for `domReady` before using it.
|
||||
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
await domtools.domReady.promise;
|
||||
|
||||
const keyboard = domtools.keyboard!;
|
||||
const { keyEnum } = keyboard;
|
||||
|
||||
keyboard.on([keyEnum.Ctrl, keyEnum.S]).subscribe(() => {
|
||||
console.log('save triggered');
|
||||
});
|
||||
|
||||
keyboard.triggerKeyPress([keyEnum.Ctrl, keyEnum.S]);
|
||||
```
|
||||
|
||||
## Scrolling
|
||||
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
const { scroller } = domtools;
|
||||
|
||||
scroller.onScroll(() => {
|
||||
console.log('scroll event');
|
||||
});
|
||||
|
||||
await scroller.enableLenisScroll({
|
||||
disableOnNativeSmoothScroll: true,
|
||||
});
|
||||
|
||||
const section = document.querySelector('#details') as HTMLElement;
|
||||
await scroller.toElement(section, { duration: 600 });
|
||||
```
|
||||
|
||||
The scroller uses native scroll listeners by default and switches to Lenis when enabled.
|
||||
|
||||
## Responsive CSS Helpers
|
||||
|
||||
`breakpoints` is designed for Lit CSS and ships both preset breakpoints and lower-level helpers.
|
||||
|
||||
```ts
|
||||
import { breakpoints } from '@design.estate/dees-domtools';
|
||||
import { css } from 'lit';
|
||||
|
||||
const styles = css`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
${breakpoints.cssForTablet(css`
|
||||
:host {
|
||||
padding: 16px;
|
||||
}
|
||||
`)}
|
||||
|
||||
${breakpoints.cssForPhone(css`
|
||||
:host {
|
||||
padding: 10px;
|
||||
}
|
||||
`)}
|
||||
`;
|
||||
```
|
||||
|
||||
Available values:
|
||||
|
||||
- `breakpoints.desktop` => `1600`
|
||||
- `breakpoints.notebook` => `1240`
|
||||
- `breakpoints.tablet` => `1024`
|
||||
- `breakpoints.phablet` => `600`
|
||||
- `breakpoints.phone` => `400`
|
||||
|
||||
Available helpers:
|
||||
|
||||
- `cssForDesktop()`
|
||||
- `cssForNotebook()`
|
||||
- `cssForTablet()`
|
||||
- `cssForPhablet()`
|
||||
- `cssForPhone()`
|
||||
- `cssForViewport()`
|
||||
- `cssForContainer()`
|
||||
- `cssForConstraint()`
|
||||
- `cssForConstraintContainer()`
|
||||
- `containerContextStyles()`
|
||||
|
||||
Viewport helpers emit both `@media` and `@container wccToolsViewport` rules. Container helpers target a named CSS container only.
|
||||
|
||||
## CSS Utility
|
||||
|
||||
```ts
|
||||
import { css } from '@design.estate/dees-domtools';
|
||||
|
||||
const columns = css.cssGridColumns(3, 24);
|
||||
|
||||
console.log(columns);
|
||||
```
|
||||
|
||||
This returns a ready-to-insert `grid-template-columns` string.
|
||||
|
||||
## Lit Element Setup
|
||||
|
||||
```ts
|
||||
import { elementBasic } from '@design.estate/dees-domtools';
|
||||
import { LitElement, html } from 'lit';
|
||||
|
||||
class MyElement extends LitElement {
|
||||
class DemoElement extends LitElement {
|
||||
static styles = [elementBasic.staticStyles];
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
await elementBasic.setup(this);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**The `elementBasic.staticStyles` includes:**
|
||||
|
||||
- Box-sizing reset
|
||||
- Smooth transitions for background and color
|
||||
- Custom scrollbar styles
|
||||
- Default font family (Geist Sans, Inter fallback)
|
||||
|
||||
### State Management
|
||||
|
||||
Integrated state management with smartstate:
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
// Access the state part
|
||||
const state = domtools.domToolsStatePart;
|
||||
|
||||
// Get current state
|
||||
const currentState = state.getState();
|
||||
console.log(currentState.virtualViewport); // 'native'
|
||||
console.log(currentState.jwt); // ''
|
||||
|
||||
// Update state
|
||||
state.setState({
|
||||
virtualViewport: 'tablet',
|
||||
jwt: 'your-token-here'
|
||||
});
|
||||
|
||||
// Subscribe to state changes
|
||||
state.subscribe((newState) => {
|
||||
console.log('State updated:', newState);
|
||||
});
|
||||
```
|
||||
|
||||
### Run Once Pattern
|
||||
|
||||
Execute expensive operations only once, even if called multiple times:
|
||||
|
||||
```typescript
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
// This will only execute once, even if called multiple times
|
||||
const result = await domtools.runOnce('myExpensiveOperation', async () => {
|
||||
console.log('Running expensive operation...');
|
||||
await someExpensiveAsyncOperation();
|
||||
return 'result';
|
||||
});
|
||||
|
||||
// Subsequent calls return the same result without re-executing
|
||||
const sameResult = await domtools.runOnce('myExpensiveOperation', async () => {
|
||||
console.log('This will never run!');
|
||||
return 'different result';
|
||||
});
|
||||
|
||||
console.log(result === sameResult); // true
|
||||
```
|
||||
|
||||
Error handling is built-in - if the function throws, all waiting callers receive the same error.
|
||||
|
||||
## Advanced Usage
|
||||
|
||||
### Combining Features
|
||||
|
||||
Here's a real-world example combining multiple features:
|
||||
|
||||
```typescript
|
||||
import { DomTools, breakpoints, elementBasic, Key } from '@design.estate/dees-domtools';
|
||||
import { LitElement, html, css as litCss } from 'lit';
|
||||
import { customElement } from 'lit/decorators.js';
|
||||
|
||||
@customElement('my-app')
|
||||
class MyApp extends LitElement {
|
||||
static styles = [
|
||||
elementBasic.staticStyles,
|
||||
litCss`
|
||||
:host {
|
||||
display: block;
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
${breakpoints.cssForTablet(litCss`
|
||||
:host {
|
||||
padding: 1rem;
|
||||
}
|
||||
`)}
|
||||
`
|
||||
];
|
||||
|
||||
private domtools?: DomTools;
|
||||
|
||||
async connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
// Setup DomTools
|
||||
this.domtools = await elementBasic.setup(this);
|
||||
await this.domtools.domReady.promise;
|
||||
|
||||
// Setup keyboard shortcuts
|
||||
this.domtools.keyboard.on([Key.Ctrl, Key.K]).subscribe(() => {
|
||||
this.openCommandPalette();
|
||||
});
|
||||
|
||||
// Subscribe to theme changes
|
||||
this.domtools.themeManager.themeObservable.subscribe((isBright) => {
|
||||
this.requestUpdate();
|
||||
});
|
||||
|
||||
// Enable smooth scrolling
|
||||
await this.domtools.scroller.enableLenisScroll({
|
||||
disableOnNativeSmoothScroll: true
|
||||
});
|
||||
}
|
||||
|
||||
private openCommandPalette() {
|
||||
console.log('Command palette opened!');
|
||||
}
|
||||
|
||||
render() {
|
||||
const isDark = !this.domtools?.themeManager.goBrightBoolean;
|
||||
|
||||
return html`
|
||||
<div class="app" style="background: ${isDark ? '#1a1a1a' : '#ffffff'}">
|
||||
<h1>My Awesome App</h1>
|
||||
<button @click=${() => this.domtools?.themeManager.toggleDarkBright()}>
|
||||
Toggle Theme
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
return html`<p>Hello DOM tools</p>`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## TypeScript Support
|
||||
`elementBasic.setup()` performs the shared `DomTools` setup and injects the package's global base styles once.
|
||||
|
||||
This package is written in TypeScript and provides full type definitions:
|
||||
## State and One-Time Work
|
||||
|
||||
```typescript
|
||||
import type {
|
||||
IDomToolsState,
|
||||
IDomToolsContructorOptions,
|
||||
TViewport
|
||||
} from '@design.estate/dees-domtools';
|
||||
`domToolsStatePart` starts with this shape:
|
||||
|
||||
// Custom state interface
|
||||
interface MyState extends IDomToolsState {
|
||||
customProperty: string;
|
||||
```ts
|
||||
{
|
||||
virtualViewport: 'native',
|
||||
jwt: '',
|
||||
}
|
||||
|
||||
// Type-safe viewport handling
|
||||
const viewport: TViewport = 'tablet';
|
||||
```
|
||||
|
||||
## Browser Support
|
||||
You can also guard expensive async work with `runOnce()`:
|
||||
|
||||
Targets the latest version of Chrome. For other browsers, you may need to include polyfills.
|
||||
```ts
|
||||
import { DomTools } from '@design.estate/dees-domtools';
|
||||
|
||||
## Why @design.estate/dees-domtools?
|
||||
const domtools = await DomTools.setupDomTools();
|
||||
|
||||
- ✅ **Race-condition free** - Carefully designed initialization prevents common timing issues
|
||||
- ✅ **TypeScript first** - Full type safety and IntelliSense support
|
||||
- ✅ **Modern APIs** - Built on Lit, RxJS, and other modern web standards
|
||||
- ✅ **Batteries included** - Everything you need for sophisticated web apps
|
||||
- ✅ **Production ready** - Used in real-world applications at design.estate
|
||||
- ✅ **Well maintained** - Active development and support
|
||||
const result = await domtools.runOnce('load-config', async () => {
|
||||
return { ok: true };
|
||||
});
|
||||
```
|
||||
|
||||
## Related Packages
|
||||
Repeated callers receive the first result, and repeated failures re-throw the stored error.
|
||||
|
||||
This library integrates with the design.estate ecosystem:
|
||||
## Extra Exports
|
||||
|
||||
- `@design.estate/dees-comms` - Communication utilities
|
||||
- `@push.rocks/websetup` - Website setup and meta management
|
||||
- `@push.rocks/smartrouter` - Client-side routing
|
||||
- `@push.rocks/smartstate` - State management
|
||||
```ts
|
||||
import { TypedRequest, plugins } from '@design.estate/dees-domtools';
|
||||
```
|
||||
|
||||
- `TypedRequest` is re-exported for typed request flows
|
||||
- `plugins` exposes the underlying modules used by the package, including `smartrouter`, `smartstate`, `smartrx`, `smartpromise`, `typedrequest`, and `deesComms`
|
||||
|
||||
## Runtime Notes
|
||||
|
||||
- This package is browser-oriented and touches `window`, `document`, `navigator`, and `matchMedia`
|
||||
- `keyboard` is `null` until `domReady` resolves
|
||||
- The published package targets the latest Chrome via `browserslist`
|
||||
|
||||
## License and Legal Information
|
||||
|
||||
This repository contains open-source code that is licensed under the MIT License. A copy of the MIT License can be found in the [license](license) file within this repository.
|
||||
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
|
||||
|
||||
**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.
|
||||
|
||||
### Trademarks
|
||||
|
||||
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. Use of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines, and any usage must be approved in writing by Task Venture Capital GmbH.
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
### Company Information
|
||||
|
||||
Task Venture Capital GmbH
|
||||
Registered at District court Bremen HRB 35230 HB, Germany
|
||||
Task Venture Capital GmbH
|
||||
Registered at District Court Bremen HRB 35230 HB, Germany
|
||||
|
||||
For any legal inquiries or if you require further information, please contact us via email at hello@task.vc.
|
||||
For any legal inquiries or further information, please contact us via email at hello@task.vc.
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { expect, tap } from '@push.rocks/tapbundle';
|
||||
import { expect, tap } from '@git.zone/tstest/tapbundle';
|
||||
import * as domtools from '../ts/index.js';
|
||||
|
||||
tap.test('first test', async () => {
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
*/
|
||||
export const commitinfo = {
|
||||
name: '@design.estate/dees-domtools',
|
||||
version: '2.5.4',
|
||||
version: '2.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.'
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user