@@ -25,6 +25,7 @@ const orgName = computed(() => {
2525// ─── Mock data ────────────────────────────────────────────────────────────────
2626// TODO: Replace distTags with pkg['dist-tags'] from usePackage()
2727// TODO: Replace versionHistory with data from useAllPackageVersions()
28+ // TODO: Replace mockChangelogs with real changelog data (e.g. GitHub releases or CHANGELOG.md)
2829
2930const distTags: Record <string , string > = {
3031 ' latest' : ' 7.26.3' ,
@@ -82,14 +83,51 @@ const versionHistory: PackageVersionInfo[] = [
8283 },
8384]
8485
86+ // Changelog entries keyed by version. In production this would come from GitHub
87+ // releases or a CHANGELOG.md parsed from the package files.
88+ const mockChangelogs: Record <string , string []> = {
89+ ' 8.0.0-alpha.16' : [
90+ ' Added support for TypeScript 5.x type imports in builder helpers' ,
91+ ' Improved error messages for invalid AST node transformations' ,
92+ ' Fixed incorrect location tracking for template literals inside tagged expressions' ,
93+ ' Resolved memory leak in recursive type visitor traversal' ,
94+ ],
95+ ' 7.26.3' : [
96+ ' Fixed edge case in identifier validation for private class fields (#16421)' ,
97+ ' Corrected span calculation for async generator function expressions' ,
98+ ],
99+ ' 7.26.0' : [
100+ ' Added assert keyword support for import assertions (Stage 3 proposal)' ,
101+ ' New createTypeAnnotation builder helper for programmatic AST construction' ,
102+ ' Fixed inconsistent behavior in optional chaining type narrowing' ,
103+ ' Corrected position data for JSX fragment children with whitespace' ,
104+ ],
105+ ' 7.25.0' : [
106+ ' Introduced satisfies operator support (TypeScript 4.9)' ,
107+ ' Added experimental decorator metadata helpers behind a flag' ,
108+ ' Removed deprecated isType aliases — use isTSType instead' ,
109+ ' Improved clone performance for large ASTs by ~18%' ,
110+ ],
111+ ' 7.0.0' : [
112+ ' Package renamed from babel-types to @babel/types' ,
113+ ' All APIs now use ES module syntax' ,
114+ ' Dropped support for Node.js < 6' ,
115+ ' Removed all deprecated v5 builder aliases' ,
116+ ],
117+ }
118+
85119// ─── Derived data ─────────────────────────────────────────────────────────────
86120
87121const versionToTagsMap = computed (() => buildVersionToTagsMap (distTags ))
88122
89123const sortedVersions = computed (() =>
90124 [... versionHistory ]
91125 .sort ((a , b ) => compare (b .version , a .version ))
92- .map (v => ({ ... v , tags: versionToTagsMap .value .get (v .version ) })),
126+ .map (v => ({
127+ ... v ,
128+ tags: versionToTagsMap .value .get (v .version ),
129+ changelog: mockChangelogs [v .version ] ?? null ,
130+ })),
93131)
94132
95133const tagRows = computed (() => buildTaggedVersionRows (distTags ))
@@ -98,6 +136,19 @@ function getVersionTime(version: string): string | undefined {
98136 return versionHistory .find (v => v .version === version )?.time
99137}
100138
139+ // ─── Changelog expand/collapse ────────────────────────────────────────────────
140+
141+ const expandedChangelogs = ref <Set <string >>(new Set ())
142+
143+ function toggleChangelog(version : string ) {
144+ if (expandedChangelogs .value .has (version )) {
145+ expandedChangelogs .value .delete (version )
146+ } else {
147+ expandedChangelogs .value .add (version )
148+ }
149+ expandedChangelogs .value = new Set (expandedChangelogs .value )
150+ }
151+
101152// ─── Jump to version ──────────────────────────────────────────────────────────
102153
103154const jumpVersion = ref (' ' )
@@ -137,26 +188,26 @@ function navigateToVersion() {
137188 </header >
138189
139190 <!-- Content -->
140- <div class =" container max-w-3xl py-8 " >
191+ <div class =" container py-8 flex flex-col lg:flex-row gap-8 items-start " >
141192 <!-- ── Current Tags ─────────────────────────────────────────────────── -->
142- <section class =" mb-10 " >
193+ <section class =" w-full lg:w-72 shrink-0 " >
143194 <h2 class =" text-xs text-fg-subtle uppercase tracking-wider mb-3 ps-1" >Current Tags</h2 >
144195 <div class =" rounded-lg border border-border overflow-hidden" >
145196 <table class =" w-full" >
146197 <thead >
147198 <tr class =" border-b border-border bg-bg-subtle" >
148199 <th
149- class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider w-1/3 "
200+ class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider"
150201 >
151202 Tag
152203 </th >
153204 <th
154- class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider w-1/3 "
205+ class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider"
155206 >
156207 Version
157208 </th >
158209 <th
159- class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider hidden sm:table-cell"
210+ class =" text-start px-4 py-2.5 text-xs text-fg-subtle font-medium uppercase tracking-wider hidden sm:table-cell lg:hidden xl:table-cell "
160211 >
161212 Published
162213 </th >
@@ -189,7 +240,7 @@ function navigateToVersion() {
189240 {{ row.version }}
190241 </LinkBase >
191242 </td >
192- <td class =" px-4 py-3 hidden sm:table-cell" >
243+ <td class =" px-4 py-3 hidden sm:table-cell lg:hidden xl:table-cell " >
193244 <DateTime
194245 v-if =" getVersionTime(row.version)"
195246 :datetime =" getVersionTime(row.version)!"
@@ -207,7 +258,7 @@ function navigateToVersion() {
207258 </section >
208259
209260 <!-- ── Version History ──────────────────────────────────────────────── -->
210- <section >
261+ <section class = " flex-1 min-w-0 " >
211262 <!-- Header + jump-to-version -->
212263 <div class =" flex flex-wrap items-center justify-between gap-3 mb-4 ps-1" >
213264 <h2 class =" text-xs text-fg-subtle uppercase tracking-wider" >
@@ -246,59 +297,104 @@ function navigateToVersion() {
246297 <div
247298 v-for =" v in sortedVersions"
248299 :key =" v.version"
249- class =" flex items-center gap-3 px-4 py-2.5 border-b border-border last:border-0 hover:bg-bg-subtle transition-colors group relative "
300+ class =" border-b border-border last:border-0"
250301 >
251- <!-- Version + badges -->
252- <div class =" flex-1 min-w-0 flex items-center gap-2 flex-wrap" >
253- <LinkBase
254- :to =" packageRoute(packageName, v.version)"
255- class =" font-mono text-sm after:absolute after:inset-0 after:content-['']"
256- :class =" v.deprecated ? 'text-red-700 dark:text-red-400' : ''"
257- :classicon =" v.deprecated ? 'i-lucide:octagon-alert' : undefined"
258- dir =" ltr"
259- >
260- {{ v.version }}
261- </LinkBase >
302+ <!-- Version row -->
303+ <div
304+ class =" flex items-center gap-3 px-4 py-2.5 hover:bg-bg-subtle transition-colors group relative"
305+ >
306+ <!-- Version + badges -->
307+ <div class =" flex-1 min-w-0 flex items-center gap-2 flex-wrap" >
308+ <LinkBase
309+ :to =" packageRoute(packageName, v.version)"
310+ class =" font-mono text-sm after:absolute after:inset-0 after:content-['']"
311+ :class =" v.deprecated ? 'text-red-700 dark:text-red-400' : ''"
312+ :classicon =" v.deprecated ? 'i-lucide:octagon-alert' : undefined"
313+ dir =" ltr"
314+ >
315+ {{ v.version }}
316+ </LinkBase >
262317
263- <!-- Dist-tags -->
264- <div v-if =" v.tags?.length" class =" flex items-center gap-1 flex-wrap relative z-10" >
318+ <!-- Dist-tags -->
319+ <div v-if =" v.tags?.length" class =" flex items-center gap-1 flex-wrap relative z-10" >
320+ <span
321+ v-for =" tag in v.tags"
322+ :key =" tag"
323+ class =" text-4xs font-semibold uppercase tracking-wide"
324+ :class =" tag === 'latest' ? 'text-accent' : 'text-fg-subtle'"
325+ >
326+ {{ tag }}
327+ </span >
328+ </div >
329+
330+ <!-- Deprecated label -->
265331 <span
266- v-for =" tag in v.tags"
267- :key =" tag"
268- class =" text-4xs font-semibold uppercase tracking-wide"
269- :class =" tag === 'latest' ? 'text-accent' : 'text-fg-subtle'"
332+ v-if =" v.deprecated"
333+ class =" text-3xs font-medium text-red-700 dark:text-red-400 bg-red-100 dark:bg-red-900/30 px-1.5 py-0.5 rounded relative z-10"
334+ :title =" v.deprecated"
270335 >
271- {{ tag }}
336+ deprecated
272337 </span >
273338 </div >
274339
275- <!-- Deprecated label -->
276- <span
277- v-if =" v.deprecated"
278- class =" text-3xs font-medium text-red-700 dark:text-red-400 bg-red-100 dark:bg-red-900/30 px-1.5 py-0.5 rounded relative z-10"
279- :title =" v.deprecated"
280- >
281- deprecated
282- </span >
340+ <!-- Right side: date + provenance + changelog toggle -->
341+ <div class =" flex items-center gap-3 shrink-0 relative z-10" >
342+ <DateTime
343+ v-if =" v.time"
344+ :datetime =" v.time"
345+ class =" text-xs text-fg-subtle hidden sm:block"
346+ year =" numeric"
347+ month =" short"
348+ day =" numeric"
349+ />
350+ <ProvenanceBadge
351+ v-if =" v.hasProvenance"
352+ :package-name =" packageName"
353+ :version =" v.version"
354+ compact
355+ :linked =" false"
356+ />
357+ <!-- Changelog toggle button -->
358+ <button
359+ v-if =" v.changelog"
360+ type =" button"
361+ class =" flex items-center gap-1 text-xs text-fg-subtle hover:text-fg transition-colors rounded focus-visible:outline-accent/70"
362+ :aria-expanded =" expandedChangelogs.has(v.version)"
363+ @click.stop =" toggleChangelog(v.version)"
364+ >
365+ <span
366+ class =" i-lucide:chevron-right w-3 h-3 transition-transform duration-200 motion-reduce:transition-none"
367+ :class =" { 'rotate-90': expandedChangelogs.has(v.version) }"
368+ aria-hidden =" true"
369+ />
370+ <span class =" hidden sm:inline" >Changelog</span >
371+ </button >
372+ </div >
283373 </div >
284374
285- <!-- Right side: date + provenance -->
286- <div class =" flex items-center gap-3 shrink-0 relative z-10" >
287- <DateTime
288- v-if =" v.time"
289- :datetime =" v.time"
290- class =" text-xs text-fg-subtle hidden sm:block"
291- year =" numeric"
292- month =" short"
293- day =" numeric"
294- />
295- <ProvenanceBadge
296- v-if =" v.hasProvenance"
297- :package-name =" packageName"
298- :version =" v.version"
299- compact
300- :linked =" false"
301- />
375+ <!-- Changelog expansion -->
376+ <div
377+ v-if =" v.changelog"
378+ class =" grid transition-[grid-template-rows] duration-200 ease-out motion-reduce:transition-none"
379+ :class =" expandedChangelogs.has(v.version) ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'"
380+ >
381+ <div class =" overflow-hidden min-h-0" >
382+ <div class =" px-4 pb-4 pt-3 border-t border-border bg-bg-subtle" >
383+ <ul class =" space-y-1.5 list-none m-0 p-0" >
384+ <li
385+ v-for =" (entry, i) in v.changelog"
386+ :key =" i"
387+ class =" flex items-start gap-2 text-sm text-fg-muted"
388+ >
389+ <span
390+ class =" i-lucide:minus w-3.5 h-3.5 mt-0.5 text-fg-subtle shrink-0"
391+ aria-hidden =" true"
392+ />
393+ {{ entry }}
394+ </li >
395+ </ul >
396+ </div >
397+ </div >
302398 </div >
303399 </div >
304400 </div >
0 commit comments