@crossworks/share-ui 0.230.62 → 0.230.67

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": "@crossworks/share-ui",
3
- "version": "0.230.62",
3
+ "version": "0.230.67",
4
4
  "description": "The server-rendered share surface — the /s/<token> presenters, view-payload contract, mini-app sandbox, and the few primitives they need. Lives in MANTLE (the server renders these), published for jackdaw to consume; may depend only on @mantle/{client-types,content-core} (the jackdaw-repo-split boundary).",
5
5
  "exports": {
6
6
  "./app-presenter": "./src/app-presenter.tsx",
@@ -31,8 +31,8 @@
31
31
  "./styles/app.css": "./styles/app.css"
32
32
  },
33
33
  "dependencies": {
34
- "@mantle/client-types": "npm:@crossworks/client-types@0.230.62",
35
- "@mantle/content-core": "npm:@crossworks/content-core@0.230.62",
34
+ "@mantle/client-types": "npm:@crossworks/client-types@0.230.67",
35
+ "@mantle/content-core": "npm:@crossworks/content-core@0.230.67",
36
36
  "@radix-ui/react-label": "^2.1.12",
37
37
  "@radix-ui/react-slot": "^1.3.0",
38
38
  "class-variance-authority": "^0.7.1",
@@ -3,13 +3,30 @@ import remarkGfm from 'remark-gfm';
3
3
  import { Check, Circle } from 'lucide-react';
4
4
  import { formatDateTime } from '@mantle/client-types/lib/format-datetime';
5
5
 
6
+ /** Human label per lifecycle status (raw value falls through for forward
7
+ * compatibility — never render a snake_case token to a reader). */
8
+ const STATUS_LABEL: Record<string, string> = {
9
+ open: 'To do',
10
+ in_progress: 'In progress',
11
+ blocked: 'Blocked',
12
+ done: 'Done',
13
+ };
14
+
6
15
  /** Public task render — a clean status card. */
7
16
  export function TaskPresenter({
8
17
  view,
9
18
  }: {
10
- view: { title: string; body: string; status: string; priority: string; dueAt: string | null };
19
+ view: {
20
+ title: string;
21
+ body: string;
22
+ status: string;
23
+ priority: string;
24
+ dueAt: string | null;
25
+ todos?: { text: string; done: boolean }[];
26
+ };
11
27
  }) {
12
28
  const done = view.status === 'done';
29
+ const todos = view.todos ?? [];
13
30
  return (
14
31
  <div className="mx-auto max-w-2xl px-6 py-12 md:py-16">
15
32
  <div className="rounded-xl border border-border bg-card p-6">
@@ -35,8 +52,8 @@ export function TaskPresenter({
35
52
  {view.title}
36
53
  </h1>
37
54
  <div className="mt-3 flex flex-wrap items-center gap-2 text-xs">
38
- <span className="rounded-full border border-border px-2 py-0.5 capitalize text-muted-foreground">
39
- {view.status}
55
+ <span className="rounded-full border border-border px-2 py-0.5 text-muted-foreground">
56
+ {STATUS_LABEL[view.status] ?? view.status.replace(/_/g, ' ')}
40
57
  </span>
41
58
  <span className="rounded-full border border-border px-2 py-0.5 capitalize text-muted-foreground">
42
59
  {view.priority} priority
@@ -54,6 +71,33 @@ export function TaskPresenter({
54
71
  <ReactMarkdown remarkPlugins={[remarkGfm]}>{view.body}</ReactMarkdown>
55
72
  </div>
56
73
  )}
74
+ {todos.length > 0 && (
75
+ <div className="mt-5 border-t border-border pt-5">
76
+ <p className="mb-2 text-xs font-semibold uppercase tracking-wider text-muted-foreground">
77
+ Checklist · {todos.filter((t) => t.done).length}/{todos.length} done
78
+ </p>
79
+ <ul className="space-y-1">
80
+ {todos.map((t, i) => (
81
+ <li key={i} className="flex items-start gap-2 text-sm">
82
+ <span
83
+ className={
84
+ 'mt-0.5 flex size-4 shrink-0 items-center justify-center rounded border ' +
85
+ (t.done
86
+ ? 'border-primary bg-primary text-primary-foreground'
87
+ : 'border-border text-transparent')
88
+ }
89
+ aria-hidden
90
+ >
91
+ {t.done && <Check className="size-3" />}
92
+ </span>
93
+ <span className={t.done ? 'text-muted-foreground line-through' : ''}>
94
+ {t.text}
95
+ </span>
96
+ </li>
97
+ ))}
98
+ </ul>
99
+ </div>
100
+ )}
57
101
  </div>
58
102
  </div>
59
103
  );
@@ -43,6 +43,8 @@ export type ShareViewPayload =
43
43
  status: string;
44
44
  priority: string;
45
45
  dueAt: string | null;
46
+ /** Read-only checklist snapshot (absent on pre-upgrade payloads). */
47
+ todos?: { text: string; done: boolean }[];
46
48
  }
47
49
  | {
48
50
  kind: 'event';