@olwiba/ui 0.0.37 → 0.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@olwiba/ui",
3
- "version": "0.0.37",
3
+ "version": "0.0.38",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -0,0 +1,73 @@
1
+ 'use client';
2
+
3
+ import * as React from 'react';
4
+ import { Badge, cn } from '@olwiba/cn';
5
+ import type { AppShellRenderLink } from '../app/AppShell';
6
+
7
+ export interface ChangelogCardProps {
8
+ title: string;
9
+ summary: string;
10
+ date: string;
11
+ slug: string;
12
+ version?: string;
13
+ hrefPrefix?: string;
14
+ renderLink?: AppShellRenderLink;
15
+ }
16
+
17
+ function formatDate(dateStr: string) {
18
+ return new Date(dateStr).toLocaleDateString('en-US', {
19
+ year: 'numeric',
20
+ month: 'long',
21
+ day: 'numeric',
22
+ });
23
+ }
24
+
25
+ export function ChangelogCard({
26
+ title,
27
+ summary,
28
+ date,
29
+ slug,
30
+ version,
31
+ hrefPrefix = '/changelog',
32
+ renderLink,
33
+ }: ChangelogCardProps) {
34
+ const href = `${hrefPrefix}/${slug}`;
35
+
36
+ const LinkWrapper = ({
37
+ children,
38
+ className,
39
+ }: {
40
+ children: React.ReactNode;
41
+ className?: string;
42
+ }) =>
43
+ renderLink ? (
44
+ renderLink({ href, children, className })
45
+ ) : (
46
+ <a href={href} className={className}>
47
+ {children}
48
+ </a>
49
+ );
50
+
51
+ return (
52
+ <article className="group flex flex-col gap-3 border-b border-border/60 pb-8 last:border-0 last:pb-0">
53
+ <div className="flex flex-wrap items-center gap-2 text-sm text-muted-foreground">
54
+ <time dateTime={date}>{formatDate(date)}</time>
55
+ {version && (
56
+ <>
57
+ <span>·</span>
58
+ <Badge variant="secondary" className="font-mono text-xs">
59
+ {version}
60
+ </Badge>
61
+ </>
62
+ )}
63
+ </div>
64
+ <h2 className="text-lg font-semibold leading-snug tracking-tight">
65
+ <LinkWrapper className="transition-colors hover:text-primary">{title}</LinkWrapper>
66
+ </h2>
67
+ <p className={cn('line-clamp-3 text-sm text-muted-foreground')}>{summary}</p>
68
+ <LinkWrapper className="text-sm font-medium text-primary hover:underline">
69
+ Read release notes →
70
+ </LinkWrapper>
71
+ </article>
72
+ );
73
+ }
@@ -0,0 +1,35 @@
1
+ 'use client';
2
+
3
+ import type { AppShellRenderLink } from '../app/AppShell';
4
+ import { ChangelogCard, type ChangelogCardProps } from './ChangelogCard';
5
+
6
+ export interface ChangelogListProps {
7
+ entries: ChangelogCardProps[];
8
+ renderLink?: AppShellRenderLink;
9
+ emptyMessage?: string;
10
+ hrefPrefix?: string;
11
+ }
12
+
13
+ export function ChangelogList({
14
+ entries,
15
+ renderLink,
16
+ emptyMessage = 'No changelog entries yet.',
17
+ hrefPrefix,
18
+ }: ChangelogListProps) {
19
+ if (entries.length === 0) {
20
+ return <p className="text-sm italic text-muted-foreground">{emptyMessage}</p>;
21
+ }
22
+
23
+ return (
24
+ <div className="flex flex-col gap-8">
25
+ {entries.map((entry) => (
26
+ <ChangelogCard
27
+ key={entry.slug}
28
+ {...entry}
29
+ hrefPrefix={hrefPrefix}
30
+ renderLink={renderLink}
31
+ />
32
+ ))}
33
+ </div>
34
+ );
35
+ }
package/src/index.ts CHANGED
@@ -107,6 +107,8 @@ export { RootErrorFallback } from './components/RootErrorFallback';
107
107
  // ─── Blog ────────────────────────────────────────────────────────────────────
108
108
  export { PostCard, type PostCardProps } from './blog/PostCard';
109
109
  export { PostList, type PostListProps } from './blog/PostList';
110
+ export { ChangelogList, type ChangelogListProps } from './blog/ChangelogList';
111
+ export { ChangelogCard, type ChangelogCardProps } from './blog/ChangelogCard';
110
112
  export { MdxContent, type MdxContentProps } from './blog/MdxContent';
111
113
 
112
114
  // ─── Hooks ────────────────────────────────────────────────────────────────────