Files
tools/configs/tsconfig
robonen 1d2130f279
Publish to NPM / Check version changes and publish (push) Successful in 11m33s
fix(primitives): make v-model, native attributes and panel styling usable under strict TS
Consuming the package under `verbatimModuleSyntax` + `strictTemplates` surfaced
four defects that forced workarounds downstream.

- Drop the deprecated `SelectValue` string alias. It collided with the
  `SelectValue` component exported from the same barrel, so the component
  resolved to the type meaning and could not be imported (TS1484).

- Narrow the select's model to `SelectModelValue<T, Multiple>` and make
  `TabsRoot` generic over its value, so a plain `v-model` on a `Ref<string>`
  type-checks. Both roots declare the value prop and emit explicitly instead of
  via `defineModel`, which would widen the payload with `| undefined` even
  though neither control ever clears its value.

- Stop declaring `defineModel` keys in `defineEmits` as well. The duplicate
  erased the payload type from the generated declarations, shipping
  `(...args: unknown[]) => any` for eleven components' model events.

- Let every part accept global DOM attributes (`id`, `role`, `aria-*`,
  `data-*`, ...) through `PrimitiveAttributes`. The heritage clause is marked
  `@vue-ignore`, so they stay out of the runtime props and keep falling through
  via `$attrs` exactly as before.

- Give `SelectContent` and `SelectViewport` a single styleable root: the
  content forwards `$attrs` onto the panel, and the viewport's scrollbar CSS
  moves to a reference-counted `<head>` style tag. A forwarded `class` was
  previously dropped, leaving the panel unstyled.

The tsconfig vue preset gains `htmlAttributes: ["aria-*", "data-*"]` so
hyphenated data attributes are not camelized before they reach those types.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-10 00:14:44 +07:00
..

@robonen/tsconfig

Shared TypeScript configurations.

Install

pnpm install -D @robonen/tsconfig

Presets

Preset Extends Use for
tsconfig.base.json Node / isomorphic libraries (lib: ESNext, no DOM)
tsconfig.dom.json base Browser libraries (adds DOM, DOM.Iterable)
tsconfig.vue.json dom Vue SFC libraries / apps (adds jsx, vueCompilerOptions)
tsconfig.node.json base Build/test tooling files (*.config.ts) — adds types: ["node"], no DOM
tsconfig.json base Default alias for base (bare @robonen/tsconfig import)

Usage

Pick the preset that matches the package and extend it:

// Node / isomorphic library
{ "extends": "@robonen/tsconfig/tsconfig.base.json" }
// Browser library
{ "extends": "@robonen/tsconfig/tsconfig.dom.json" }
// Vue package, with path aliases
{
  "extends": "@robonen/tsconfig/tsconfig.vue.json",
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Path aliases resolve relative to the tsconfig.json location — baseUrl is intentionally omitted (deprecated, removed in TypeScript 7.0).

Project references (DOM + Node split)

Most packages contain two environments: browser/library src (DOM) and Node tooling files (vite.config.ts, vitest.config.ts, tsdown.config.ts). They are split into separate projects wired with references, so src never sees Node globals and config files never see DOM:

// tsconfig.json — solution root, tools (tsdown/vitest/editor) target src below
{
  "files": [],
  "references": [
    { "path": "./tsconfig.src.json" },
    { "path": "./tsconfig.node.json" }
  ]
}
// tsconfig.src.json — the library code
{
  "extends": "@robonen/tsconfig/tsconfig.dom.json",
  "compilerOptions": {
    "composite": true,
    "types": [],
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.src.tsbuildinfo"
  },
  "include": ["src/**/*.ts"]
}
// tsconfig.node.json — build/test tooling files
{
  "extends": "@robonen/tsconfig/tsconfig.node.json",
  "compilerOptions": {
    "composite": true,
    "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo"
  },
  "include": ["*.config.ts"]
}

Type-check the whole package (both projects) with tsc -b / vue-tsc -b. Point tsdown at the src project (tsconfig: './tsconfig.src.json') since the root has no compilerOptions.

What's included (base)

  • Target / Module: ESNext with module: Preserve + Bundler resolution
  • Strict mode: strict, noUncheckedIndexedAccess, noImplicitOverride, noImplicitReturns, noFallthroughCasesInSwitch, noUncheckedSideEffectImports
  • Module safety: verbatimModuleSyntax, isolatedModules, moduleDetection: force
  • Type-check only: noEmit (declarations/output are produced by tsdown)
  • Interop: esModuleInterop, resolveJsonModule