@gmono/scoped-css-core
v0.2.0
Published
Framework-agnostic CSS scoping core — pure logic, CssAdapter interface, createCssHooks factory. Zero framework dependencies.
Readme
@gmono/scoped-css-core
Framework-agnostic CSS scoping core. Zero framework dependencies.
This package contains the pure scoping logic, the CssAdapter interface, and
the createCssHooks factory. It does not import React or server-reactor —
adapter packages bind it to a concrete rendering environment:
@gmono/scoped-css-react— regular React adapter@gmono/scoped-css-reactor— server-reactor adapter
Install
npm install @gmono/scoped-css-coreWhat it does
useCSS() scopes a CSS string to the current component instance. Every
.className selector is rewritten to .scopeId-className, and the returned
classes proxy maps the original name to the scoped name. The style node
renders the scoped <style> tag once in the component tree.
const { classes, style } = useCSS(`.btn { padding: 0.5rem; }`)
// classes = { btn: 'c3-btn' }API
createCssHooks(adapter)
Creates a set of CSS hooks bound to the given CssAdapter.
Adapter packages call this once at module-eval time and re-export the hooks.
The generic node type N flows from the adapter (e.g. WriterNode for
server-reactor, ReactNode for React).
Returns:
| Hook | Description |
| --- | --- |
| useCSS(css, opts?) | Scope a CSS string; returns { classes, style, scopeId } |
| useCSSFile(path, opts?) | Same as useCSS but reads the CSS from a file synchronously (server environments only) |
| CSSMappingProvider | Provides { scopeId, classes } to the subtree so child components can reuse the scope |
| useCSSClasses() | Returns the nearest ancestor CSSMappingProvider's classes map (or undefined) |
scopeCss(css, scopeId, global)
Pure function — parses .className selectors and rewrites them with the scope
prefix. With global: true no scoping is applied and class names stay as-is.
extractClassNames(css)
Returns the list of class names found in a CSS string.
nextScopeId()
Returns the next sequential scope id (e.g. c3). Exposed for custom adapters.
CssAdapter<N>
The "trait" every adapter must implement:
| Member | Purpose |
| --- | --- |
| useRef<T>(initial) | Persistent mutable ref across renders |
| useMemo<T>(factory, deps) | Memoize across renders, recompute on dep change |
| useMapping() | Read the nearest CSSMapping from the provider tree |
| provideMapping(mapping, id, children) | Create a provider node that supplies a CSSMapping to its subtree |
| renderStyle(css) | Render a <style> element with the given CSS |
| readCssFileSync?(path) | (optional) Synchronously read a CSS file — required by useCSSFile |
Options
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| global | boolean | false | Skip scoping — class names are emitted as-is |
| scoped | boolean | false | Inherit the scope prefix from the nearest CSSMappingProvider instead of allocating a new scope id |
Writing a custom adapter
import { createCssHooks, type CssAdapter } from '@gmono/scoped-css-core'
const myAdapter: CssAdapter<MyNode> = {
useRef: /* ... */,
useMemo: /* ... */,
useMapping: /* ... */,
provideMapping: /* ... */,
renderStyle: (css) => createStyleNode(css),
}
export const useCSS = createCssHooks<MyNode>(myAdapter).useCSSLicense
MIT
