Skip to content

Latest commit

 

History

History
205 lines (145 loc) · 10.5 KB

File metadata and controls

205 lines (145 loc) · 10.5 KB

Knighted CSS Combined Loader Reference

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.

Decision Matrix

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.

Jump to a scenario

Named exports only

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'

Default export only

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'

Default and named exports

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.

Adding stable selectors (&types)

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.

Named exports with stable selectors

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.

Default export with stable selectors

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'

Default and named exports with stable selectors

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'

Key Takeaways

  • The loader always injects knightedCss alongside the module’s exports.
  • When you run knighted-css-generate-types, prefer the double-extension proxy import to get component exports, knightedCss, and stableSelectors in one place.
  • Use ?knighted-css&combined (plus asKnightedCssCombinedModule) when you need runtime combined imports without generated proxy modules.
  • Add &types only when you need a runtime selector map and cannot rely on the generated proxy files.

When to use KnightedCssCombinedModule

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 token

Reach for the type whenever you need to annotate combined modules manually—otherwise, the runtime helper keeps the snippets leaner.