This document summarizes how ?knighted-css&combined behaves for different module export shapes and how to structure your imports accordingly, plus how the double-extension proxy import replaces most combined-query use cases.
Note
TypeScript reads literal selector tokens from the generated .knighted-css.ts modules (emitted by knighted-css-generate-types). The double-extension modules also re-export the original module exports and knightedCss, so a single import can provide component exports, typed selectors, and the compiled stylesheet string without helper casts.
Tip
Prefer the double-extension import when you run knighted-css-generate-types—it removes the need for asKnightedCssCombinedModule. Use the helper only for ?knighted-css&combined queries or when you cannot rely on generated proxy modules.
| Module exports | Recommended query | Import pattern | Notes |
|---|---|---|---|
| Named only | ?knighted-css&combined&named-only |
Snippet | &named-only disables the synthetic default export so you only destructure the original named members plus knightedCss. |
| Default only | ?knighted-css&combined |
Snippet | Loader mirrors the default export and adds knightedCss, so default-import code keeps working. |
| Default + named | ?knighted-css&combined (append &named-only when you never consume the default) |
Snippet | Without the flag you get both default + named exports; adding it drops the synthetic default for stricter codebases. |
| Named + stable selectors | ?knighted-css&combined&named-only&types |
Snippet | Adds a stableSelectors named export; configure namespaces via the loader option or CLI flag. |
| Default only + stable selectors | ?knighted-css&combined&types |
Snippet | Keep your default-import flow and add stableSelectors; namespaces come from loader/CLI configuration. |
| Default + named + stable selectors | ?knighted-css&combined&types (append &named-only if you skip the default) |
Snippet | Best of both worlds—stableSelectors is exported alongside knightedCss; add &named-only if you don’t use the default. |
- Named exports only – drop the synthetic default and keep namespace imports tidy.
- Default export only – keep your default-import flow with
knightedCssalongside. - Default and named exports – destructure everything without extra loader flags.
- Named exports with stable selectors – add
stableSelectorswhile staying default-free. - Default export with stable selectors – default import plus runtime selector map.
- Default and named exports with stable selectors – grab every export plus
stableSelectors.
Use when your module only exposes named exports and you never rely on a synthetic default.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import * as combinedModule from './module.js?knighted-css&combined&named-only'
const { Component, knightedCss } =
asKnightedCssCombinedModule<typeof import('./module.js')>(combinedModule)Note
Namespace imports (import * as combined …) are the most reliable pattern for &named-only queries because you intentionally drop the default export. Keep using the helper type to narrow the namespace.
If you run knighted-css-generate-types, use the unified proxy import instead:
import { Component, knightedCss, stableSelectors } from './module.knighted-css.js'Use when your component only exposes a default export and you want knightedCss beside it.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import * as combinedModule from './module.js?knighted-css&combined'
const { default: Component, knightedCss } =
asKnightedCssCombinedModule<typeof import('./module.js')>(combinedModule)With generated proxies, use a single import instead:
import Component, { knightedCss, stableSelectors } from './module.knighted-css.js'Use when you consume both the default export and its named helpers from the same module.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import * as combinedModule from './module.js?knighted-css&combined'
const {
default: Component,
helper,
knightedCss,
} = asKnightedCssCombinedModule<typeof import('./module.js')>(combinedModule)With generated proxies, a single import covers everything:
import Component, { helper, knightedCss, stableSelectors } from './module.knighted-css.js'Prefer ?knighted-css&combined&named-only plus the named exports only snippet when you intentionally avoid default exports but still need the named members and knightedCss.
Append &types whenever you need the runtime stableSelectors map in addition to knightedCss. Configure the loader’s stableNamespace option (or pass --stable-namespace to the CLI) so runtime exports and generated .knighted-css.ts modules stay aligned.
If you run knighted-css-generate-types, the double-extension proxy already exports stableSelectors and keeps the literal types in sync—no &types query or helper required.
Use when you only consume named exports (no default) but still want typed stableSelectors.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import type { KnightedCssStableSelectors as ModuleStableSelectors } from './module.css.knighted-css.js'
import * as combinedModule from './module.js?knighted-css&combined&named-only&types'
const { Component, knightedCss, stableSelectors } = asKnightedCssCombinedModule<
typeof import('./module.js'),
{ stableSelectors: Readonly<Record<keyof ModuleStableSelectors, string>> }
>(combinedModule)
stableSelectors.card // "knighted-card"With generated proxies, use a single import instead:
import { Component, knightedCss, stableSelectors } from './module.knighted-css.js'Tip
Add &named-only before &types to drop the synthetic default export while still receiving stableSelectors.
Use when you stick with default imports but also need access to the selector map.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import type { KnightedCssStableSelectors as ModuleStableSelectors } from './module.css.knighted-css.js'
import * as combinedModule from './module.js?knighted-css&combined&types'
const {
default: Component,
knightedCss,
stableSelectors,
} = asKnightedCssCombinedModule<
typeof import('./module.js'),
{ stableSelectors: Readonly<Record<keyof ModuleStableSelectors, string>> }
>(combinedModule)
stableSelectors.badge // "knighted-badge"With generated proxies, use a single import instead:
import Component, { knightedCss, stableSelectors } from './module.knighted-css.js'Use when you consume every export from the module and still want the selector map.
import { asKnightedCssCombinedModule } from '@knighted/css/loader-helpers'
import type { KnightedCssStableSelectors as ModuleStableSelectors } from './module.css.knighted-css.js'
import * as combinedModule from './module.js?knighted-css&combined&types'
const {
default: Component,
helper,
knightedCss,
stableSelectors,
} = asKnightedCssCombinedModule<
typeof import('./module.js'),
{ stableSelectors: Readonly<Record<keyof ModuleStableSelectors, string>> }
>(combinedModule)
stableSelectors.card // "knighted-card" (or your configured namespace)With generated proxies, a single import covers everything:
import Component, { helper, knightedCss, stableSelectors } from './module.knighted-css.js'- The loader always injects
knightedCssalongside the module’s exports. - When you run
knighted-css-generate-types, prefer the double-extension proxy import to get component exports,knightedCss, andstableSelectorsin one place. - Use
?knighted-css&combined(plusasKnightedCssCombinedModule) when you need runtime combined imports without generated proxy modules. - Add
&typesonly when you need a runtime selector map and cannot rely on the generated proxy files.
The helper type still earns its keep when you need to narrow combined results without asKnightedCssCombinedModule (for example, in test doubles, custom wrappers, or when you skip generated proxies):
import type { KnightedCssCombinedModule } from '@knighted/css/loader'
import * as moduleWithCss from './component.js?knighted-css&combined&types'
type CombinedComponent = KnightedCssCombinedModule<
typeof import('./component.js'),
{ stableSelectors: Readonly<Record<string, string>> }
>
const combined = moduleWithCss as CombinedComponent
combined.knightedCss // string
combined.stableSelectors.card // typed selector tokenReach for the type whenever you need to annotate combined modules manually—otherwise, the runtime helper keeps the snippets leaner.