diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index decd758..2378f74 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,12 +14,23 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + with: + # Full history so the tags are present: the version check below needs + # to know which numbers are already spent. + fetch-depth: 0 - uses: actions/setup-node@v6 with: node-version: 24 cache: npm + # Before the build, and before a tag exists — the only moment a version + # mistake is still cheap. Once a tag is pushed it is installable as a git + # dependency forever, whether or not its Release run went green, so the + # Release workflow's own tag/manifest guard fires too late to help. + - name: Version is ahead of every existing tag + run: npm run verify:version + - run: npm ci - name: Lint diff --git a/CHANGELOG.md b/CHANGELOG.md index eb72cae..9ae7f08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,146 @@ All notable changes to `@codebar-ag/storybook`. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## v1.18.0 + +A types-only release, prompted by a consuming app that stood up a `vue-tsc` +lane over 152 components for the first time and found out what this package +does and does not let it say. **No component changes behaviour.** Not one +template, class, token, prop default or emitted value differs; every call site +that renders correctly today renders byte-identically after this. Everything +below happens at the type boundary. + +There is no v1.17.0 — see the note at the end. + +### Added + +- **Every component now exports a named `Props` type.** 73 of them, one + per component, re-exported from the barrel. + + The supporting types were all exported already — `Tone`, `Category`, + `SelectOption`, `DataTableColumn`, `BreadcrumbItem`, `TabItem`, `RowKey`, + `SortState`, `IconName` — which is what made the gap conspicuous rather than + merely absent. The props themselves reached `dist/index.d.ts` as **71 + anonymous `__VLS_Props` interfaces**, the names `vue-tsc` generates for a + type literal passed inline to `defineProps`. Nothing can import those. A + consuming app wrapping an atom therefore re-declared the unions by hand, and + they drifted the moment either side moved: a `ConfirmDialog` over `Modal` + declaring `variant: String` compiles in the app and fails against + `'danger' | 'primary' | …` at the boundary. + + So a wrapper can now say what it means: + + ```ts + import type { ButtonProps, ModalProps } from '@codebar-ag/storybook'; + + defineProps<{ + size?: ModalProps['size']; + variant?: ButtonProps['variant']; + }>(); + ``` + + …or take the whole surface, which `@vue/compiler-sfc` resolves out of the + published `.d.ts` well enough to emit runtime props from: + + ```ts + defineProps(); + ``` + + `dist/index.d.ts` now carries 73 named prop interfaces and zero + `__VLS_Props`. A new `verify:props` build step keeps the three parts in + step — the SFC declares the interface, the barrel re-exports it, and + api-extractor carries it into the bundled declarations. Only the last is + observable to a consumer, and a type exported from source but dropped from + the rollup is invisible until an app tries to import it. + +- **`SelectOption` takes its value type as a parameter**, and the two controls + that hand an option's value back to the caller — `SearchableSelect` via + `update:modelValue`, `Combobox` via `@select` — are generic over it. A caller + whose values are all strings says so once, on the options, and stops + coercing with `String()` at every call site that writes into a string-typed + form field. + + Both infer the parameter from `options` and `modelValue` together, so binding + a plain `string` model widens it rather than pinning it to the literal union + of an inline options array. + + `Select` is deliberately **not** generic, and the source says why: it is a + native `