From ce78188072fbdd35d4b8e9f481b8c777401f9738 Mon Sep 17 00:00:00 2001 From: Juergen Kunz Date: Wed, 11 Mar 2026 08:30:00 +0000 Subject: [PATCH] fix(dees-element): rename cssForCustom to cssForConstraint, remove DeesElement static cssFor* helpers, and add optional elementClass parameter to cssManager breakpoint helpers --- changelog.md | 9 ++++++++ package.json | 2 +- pnpm-lock.yaml | 12 +++++------ readme.md | 34 +++++++++++++++--------------- ts/00_commitinfo_data.ts | 2 +- ts/classes.cssmanager.ts | 43 +++++++++++++++++++++++++++++++------- ts/classes.dees-element.ts | 36 +++---------------------------- 7 files changed, 73 insertions(+), 65 deletions(-) diff --git a/changelog.md b/changelog.md index bc2fd38..7d3797c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2026-03-11 - 2.2.1 - fix(dees-element) +rename cssForCustom to cssForConstraint, remove DeesElement static cssFor* helpers, and add optional elementClass parameter to cssManager breakpoint helpers + +- Rename: cssManager.cssForCustom -> cssManager.cssForConstraint and DeesElement.cssForCustom -> DeesElement.cssForConstraint; underlying domtools calls updated to cssForConstraint/cssForConstraintContainer. +- Breaking: Removed static helpers DeesElement.cssForDesktop, cssForNotebook, cssForTablet, cssForPhablet, cssForPhone — consumers must now use cssManager.cssFor*(css, this) or pass an element class to get component-scoped container rules. +- API change: cssManager.cssForDesktop|cssForNotebook|cssForTablet|cssForPhablet|cssForPhone now accept an optional elementClass (or pass this) and a helper getContainerNameFromClass was added to generate container names. +- Docs: readme.md updated to show new signatures, guidance to pass this for component-scoped constraints, and renaming of "custom" to "constraint". +- Dependency: bumped @design.estate/dees-domtools from ^2.4.0 to ^2.5.1. + ## 2026-03-11 - 2.2.0 - feat(dees-element) add container-responsive APIs (containerResponsive decorator, DeesElement static cssFor* container helpers, and cssManager cssForCustom) and update docs diff --git a/package.json b/package.json index d1bb760..e08953b 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@types/node": "^25.0.10" }, "dependencies": { - "@design.estate/dees-domtools": "^2.4.0", + "@design.estate/dees-domtools": "^2.5.1", "@push.rocks/isounique": "^1.0.5", "@push.rocks/smartrx": "^3.0.10", "lit": "^3.3.2" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d0d9d67..d500eea 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: dependencies: '@design.estate/dees-domtools': - specifier: ^2.4.0 - version: 2.4.0 + specifier: ^2.5.1 + version: 2.5.1 '@push.rocks/isounique': specifier: ^1.0.5 version: 1.0.5 @@ -246,8 +246,8 @@ packages: '@design.estate/dees-comms@1.0.30': resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==} - '@design.estate/dees-domtools@2.4.0': - resolution: {integrity: sha512-CbleS20q5R8EXMtN0SMGenckrRtcLmCR+e7aslbcd0XMWwN+SWyuRqCg1p6Fr9spW+cVOCo/bhpvrwSVubTuAA==} + '@design.estate/dees-domtools@2.5.1': + resolution: {integrity: sha512-ojzRSkOpQvxpd4drCNF1wadvPwthI6xIJpYjBbOwlgxkFCrlgxlOxHzRKEVnj5wWeUPqykKhddKp33LKW9mydw==} '@design.estate/dees-element@2.1.3': resolution: {integrity: sha512-TjXWxVcdSPaT1IOk31ckfxvAZnJLuTxhFGsNCKoh63/UE2FVf6slp8//UFvN+ADigiA9ZsY0azkY99XbJCwDDA==} @@ -4063,7 +4063,7 @@ snapshots: '@push.rocks/smartdelay': 3.0.5 broadcast-channel: 7.2.0 - '@design.estate/dees-domtools@2.4.0': + '@design.estate/dees-domtools@2.5.1': dependencies: '@api.global/typedrequest': 3.3.0 '@design.estate/dees-comms': 1.0.30 @@ -4091,7 +4091,7 @@ snapshots: '@design.estate/dees-element@2.1.3': dependencies: - '@design.estate/dees-domtools': 2.4.0 + '@design.estate/dees-domtools': 2.5.1 '@push.rocks/isounique': 1.0.5 '@push.rocks/smartrx': 3.0.10 lit: 3.3.2 diff --git a/readme.md b/readme.md index 80e7d34..43337b5 100644 --- a/readme.md +++ b/readme.md @@ -72,12 +72,12 @@ The singleton `cssManager` is the central hub for theming and responsive layout: |---|---| | `cssManager.defaultStyles` | Base styles for consistent element rendering | | `cssManager.bdTheme(bright, dark)` | Returns a `CSSResult` that auto-switches between bright/dark values | -| `cssManager.cssForDesktop(css)` | Media-query wrapper for desktop breakpoints | -| `cssManager.cssForNotebook(css)` | Media-query wrapper for notebook breakpoints | -| `cssManager.cssForTablet(css)` | Media-query wrapper for tablet breakpoints | -| `cssManager.cssForPhablet(css)` | Media-query wrapper for phablet breakpoints | -| `cssManager.cssForPhone(css)` | Media-query wrapper for phone breakpoints | -| `cssManager.cssForCustom({ maxWidth, minWidth })` | Custom viewport-level breakpoint (curried) | +| `cssManager.cssForDesktop(css, this?)` | Breakpoint for desktop; pass `this` for component-scoped | +| `cssManager.cssForNotebook(css, this?)` | Breakpoint for notebook; pass `this` for component-scoped | +| `cssManager.cssForTablet(css, this?)` | Breakpoint for tablet; pass `this` for component-scoped | +| `cssManager.cssForPhablet(css, this?)` | Breakpoint for phablet; pass `this` for component-scoped | +| `cssManager.cssForPhone(css, this?)` | Breakpoint for phone; pass `this` for component-scoped | +| `cssManager.cssForConstraint({ maxWidth, minWidth })` | Custom viewport-level constraint (curried) | | `cssManager.cssGridColumns(cols, gap)` | Generates CSS grid column widths | Example — responsive + themed styles: @@ -109,7 +109,7 @@ class MyCard extends DeesElement { ### 📦 Container-Responsive Components -For components that need to respond to their **own width** (not the viewport), use the `@containerResponsive()` decorator together with `DeesElement`'s static `cssFor*` methods: +For components that need to respond to their **own width** (not the viewport), use the `@containerResponsive()` decorator and pass `this` as the second argument to `cssManager.cssFor*`: ```typescript import { @@ -124,18 +124,18 @@ class MyStatsGrid extends DeesElement { cssManager.defaultStyles, css`.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; }`, - // Component-level: when THIS element is narrow - this.cssForTablet(css` + // Component-level: when THIS element is narrower than tablet width + cssManager.cssForTablet(css` .grid { grid-template-columns: repeat(2, 1fr); } - `), + `, this), - // Viewport-level: when the browser window is narrow + // Viewport-level: when the browser window is phone-sized cssManager.cssForPhone(css` .grid { grid-template-columns: 1fr; } `), - // Component-level with custom constraint - this.cssForCustom({ maxWidth: 500 })(css` + // Component-level with custom width constraint + this.cssForConstraint({ maxWidth: 500 })(css` .grid { gap: 8px; } `), ]; @@ -151,12 +151,12 @@ class MyStatsGrid extends DeesElement { | API | Scope | Generated CSS | |-----|-------|---------------| | `cssManager.cssForPhablet(css)` | Viewport | `@media` + `@container wccToolsViewport` | -| `cssManager.cssForCustom({maxWidth:800})(css)` | Viewport | `@media` + `@container wccToolsViewport` | -| `this.cssForPhablet(css)` | Component | `@container ` only | -| `this.cssForCustom({maxWidth:800})(css)` | Component | `@container ` only | +| `cssManager.cssForPhablet(css, this)` | Component | `@container ` only | +| `cssManager.cssForConstraint({maxWidth:800})(css)` | Viewport | `@media` + `@container wccToolsViewport` | +| `this.cssForConstraint({maxWidth:500})(css)` | Component | `@container ` only | | `@containerResponsive()` | Decorator | Sets `container-type: inline-size` + `container-name` on `:host` | -The `@containerResponsive()` decorator is required for the component-level `this.cssFor*` methods to take effect — it establishes the CSS containment context on `:host`. +The `@containerResponsive()` decorator is required for component-scoped queries — it establishes the CSS containment context on `:host`. ### ⚡ Reactive Properties & State diff --git a/ts/00_commitinfo_data.ts b/ts/00_commitinfo_data.ts index 2299dae..a9381c4 100644 --- a/ts/00_commitinfo_data.ts +++ b/ts/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-element', - version: '2.2.0', + version: '2.2.1', description: 'A library for creating custom elements extending the lit element class with additional functionalities.' } diff --git a/ts/classes.cssmanager.ts b/ts/classes.cssmanager.ts index c18d411..0afdf12 100644 --- a/ts/classes.cssmanager.ts +++ b/ts/classes.cssmanager.ts @@ -47,29 +47,58 @@ export class CssManager { return domtools.elementBasic.staticStyles; } - public cssForDesktop(contentArg: CSSResult) { + private getContainerNameFromClass(elementClass: { is?: string; name: string }): string { + return elementClass.is || elementClass.name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); + } + + public cssForDesktop(contentArg: CSSResult, elementClass?: { is?: string; name: string }) { + if (elementClass) { + return unsafeCSS(domtools.breakpoints.cssForContainer( + contentArg, `(min-width: ${domtools.breakpoints.desktop}px)`, this.getContainerNameFromClass(elementClass), + )); + } return unsafeCSS(domtools.breakpoints.cssForDesktop(contentArg)); } - public cssForNotebook(contentArg: CSSResult) { + public cssForNotebook(contentArg: CSSResult, elementClass?: { is?: string; name: string }) { + if (elementClass) { + return unsafeCSS(domtools.breakpoints.cssForContainer( + contentArg, `(max-width: ${domtools.breakpoints.notebook}px)`, this.getContainerNameFromClass(elementClass), + )); + } return unsafeCSS(domtools.breakpoints.cssForNotebook(contentArg)); } - public cssForTablet(contentArg: CSSResult) { + public cssForTablet(contentArg: CSSResult, elementClass?: { is?: string; name: string }) { + if (elementClass) { + return unsafeCSS(domtools.breakpoints.cssForContainer( + contentArg, `(max-width: ${domtools.breakpoints.tablet}px)`, this.getContainerNameFromClass(elementClass), + )); + } return unsafeCSS(domtools.breakpoints.cssForTablet(contentArg)); } - public cssForPhablet(contentArg: CSSResult) { + public cssForPhablet(contentArg: CSSResult, elementClass?: { is?: string; name: string }) { + if (elementClass) { + return unsafeCSS(domtools.breakpoints.cssForContainer( + contentArg, `(max-width: ${domtools.breakpoints.phablet}px)`, this.getContainerNameFromClass(elementClass), + )); + } return unsafeCSS(domtools.breakpoints.cssForPhablet(contentArg)); } - public cssForPhone(contentArg: CSSResult) { + public cssForPhone(contentArg: CSSResult, elementClass?: { is?: string; name: string }) { + if (elementClass) { + return unsafeCSS(domtools.breakpoints.cssForContainer( + contentArg, `(max-width: ${domtools.breakpoints.phone}px)`, this.getContainerNameFromClass(elementClass), + )); + } return unsafeCSS(domtools.breakpoints.cssForPhone(contentArg)); } - public cssForCustom(constraints: { maxWidth?: number; minWidth?: number }) { + public cssForConstraint(constraints: { maxWidth?: number; minWidth?: number }) { return (contentArg: CSSResult) => - unsafeCSS(domtools.breakpoints.cssForCustom(constraints)(contentArg)); + unsafeCSS(domtools.breakpoints.cssForConstraint(constraints)(contentArg)); } public bdTheme(brightValueArg: string, darkValueArg: string): CSSResult { diff --git a/ts/classes.dees-element.ts b/ts/classes.dees-element.ts index 1081f9a..d20b776 100644 --- a/ts/classes.dees-element.ts +++ b/ts/classes.dees-element.ts @@ -2,45 +2,15 @@ import * as plugins from './plugins.js'; import { type CSSResult } from 'lit'; export class DeesElement extends plugins.lit.LitElement { - // STATIC — component-level responsive helpers (use in `static styles = [...]`) + // STATIC — component-level constraint helper (use in `static styles = [...]`) private static getContainerName(): string { return (this as any).is || this.name.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); } - static cssForDesktop(cssArg: CSSResult) { - return plugins.domtools.breakpoints.cssForContainer( - cssArg, `(min-width: ${plugins.domtools.breakpoints.desktop}px)`, this.getContainerName(), - ); - } - - static cssForNotebook(cssArg: CSSResult) { - return plugins.domtools.breakpoints.cssForContainer( - cssArg, `(max-width: ${plugins.domtools.breakpoints.notebook}px)`, this.getContainerName(), - ); - } - - static cssForTablet(cssArg: CSSResult) { - return plugins.domtools.breakpoints.cssForContainer( - cssArg, `(max-width: ${plugins.domtools.breakpoints.tablet}px)`, this.getContainerName(), - ); - } - - static cssForPhablet(cssArg: CSSResult) { - return plugins.domtools.breakpoints.cssForContainer( - cssArg, `(max-width: ${plugins.domtools.breakpoints.phablet}px)`, this.getContainerName(), - ); - } - - static cssForPhone(cssArg: CSSResult) { - return plugins.domtools.breakpoints.cssForContainer( - cssArg, `(max-width: ${plugins.domtools.breakpoints.phone}px)`, this.getContainerName(), - ); - } - - static cssForCustom(constraints: { maxWidth?: number; minWidth?: number }) { + static cssForConstraint(constraints: { maxWidth?: number; minWidth?: number }) { return (cssArg: CSSResult) => - plugins.domtools.breakpoints.cssForCustomContainer(constraints, this.getContainerName())(cssArg); + plugins.domtools.breakpoints.cssForConstraintContainer(constraints, this.getContainerName())(cssArg); } // INSTANCE