@burdenoff/microfe-theculturepost 2026.704.2 → 2026.705.2

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.
Files changed (91) hide show
  1. package/dist/theculturepost/TheCulturePostRoot.js +63 -45
  2. package/dist/theculturepost/TheCulturePostRoot.js.map +1 -1
  3. package/dist/theculturepost/TheCulturePostRoutes.js +17 -9
  4. package/dist/theculturepost/TheCulturePostRoutes.js.map +1 -1
  5. package/dist/theculturepost/components/AddCitationDialog.js +131 -102
  6. package/dist/theculturepost/components/AddCitationDialog.js.map +1 -1
  7. package/dist/theculturepost/components/ArchiveItemCard.js +56 -43
  8. package/dist/theculturepost/components/ArchiveItemCard.js.map +1 -1
  9. package/dist/theculturepost/components/AudioPlayer.js +74 -0
  10. package/dist/theculturepost/components/AudioPlayer.js.map +1 -0
  11. package/dist/theculturepost/components/CitationList.js +215 -105
  12. package/dist/theculturepost/components/CitationList.js.map +1 -1
  13. package/dist/theculturepost/components/CollectionCard.js +32 -32
  14. package/dist/theculturepost/components/CollectionCard.js.map +1 -1
  15. package/dist/theculturepost/components/CreateArchiveItemDialog.js +133 -93
  16. package/dist/theculturepost/components/CreateArchiveItemDialog.js.map +1 -1
  17. package/dist/theculturepost/components/CreateCollectionDialog.js +91 -70
  18. package/dist/theculturepost/components/CreateCollectionDialog.js.map +1 -1
  19. package/dist/theculturepost/components/CreateStoryDialog.js +311 -132
  20. package/dist/theculturepost/components/CreateStoryDialog.js.map +1 -1
  21. package/dist/theculturepost/components/DecorativeCover.js +78 -0
  22. package/dist/theculturepost/components/DecorativeCover.js.map +1 -0
  23. package/dist/theculturepost/components/DecorativeDivider.js +45 -0
  24. package/dist/theculturepost/components/DecorativeDivider.js.map +1 -0
  25. package/dist/theculturepost/components/DiscussionCard.js +75 -60
  26. package/dist/theculturepost/components/DiscussionCard.js.map +1 -1
  27. package/dist/theculturepost/components/HistoryTimeline.js +115 -0
  28. package/dist/theculturepost/components/HistoryTimeline.js.map +1 -0
  29. package/dist/theculturepost/components/LifecycleStepper.js +33 -0
  30. package/dist/theculturepost/components/LifecycleStepper.js.map +1 -0
  31. package/dist/theculturepost/components/OpenDiscussionDialog.js +66 -56
  32. package/dist/theculturepost/components/OpenDiscussionDialog.js.map +1 -1
  33. package/dist/theculturepost/components/OralHistoryCard.js +6 -73
  34. package/dist/theculturepost/components/OverlayBadge.js +22 -0
  35. package/dist/theculturepost/components/OverlayBadge.js.map +1 -0
  36. package/dist/theculturepost/components/PageHero.js +62 -0
  37. package/dist/theculturepost/components/PageHero.js.map +1 -0
  38. package/dist/theculturepost/components/RecordOralHistoryDialog.js +306 -131
  39. package/dist/theculturepost/components/RecordOralHistoryDialog.js.map +1 -1
  40. package/dist/theculturepost/components/ReplyThread.js +268 -139
  41. package/dist/theculturepost/components/ReplyThread.js.map +1 -1
  42. package/dist/theculturepost/components/StatusBadge.js +9 -9
  43. package/dist/theculturepost/components/StatusBadge.js.map +1 -1
  44. package/dist/theculturepost/components/StoryCard.js +54 -49
  45. package/dist/theculturepost/components/StoryCard.js.map +1 -1
  46. package/dist/theculturepost/components/TopicCard.js +60 -41
  47. package/dist/theculturepost/components/TopicCard.js.map +1 -1
  48. package/dist/theculturepost/components/Waveform.js +31 -0
  49. package/dist/theculturepost/components/Waveform.js.map +1 -0
  50. package/dist/theculturepost/components/categoryMeta.js +20 -0
  51. package/dist/theculturepost/components/categoryMeta.js.map +1 -0
  52. package/dist/theculturepost/components/index.js +41 -0
  53. package/dist/theculturepost/components/viz/BarChart.js +53 -0
  54. package/dist/theculturepost/components/viz/BarChart.js.map +1 -0
  55. package/dist/theculturepost/components/viz/Donut.js +58 -0
  56. package/dist/theculturepost/components/viz/Donut.js.map +1 -0
  57. package/dist/theculturepost/components/viz/StatTile.js +35 -0
  58. package/dist/theculturepost/components/viz/StatTile.js.map +1 -0
  59. package/dist/theculturepost/components/viz/index.js +3 -0
  60. package/dist/theculturepost/hooks/useFiles.js +1 -1
  61. package/dist/theculturepost/hooks/useFiles.js.map +1 -1
  62. package/dist/theculturepost/pages/HomePage.js +247 -124
  63. package/dist/theculturepost/pages/HomePage.js.map +1 -1
  64. package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.js +319 -127
  65. package/dist/theculturepost/pages/archive/ArchiveItemDetailPage.js.map +1 -1
  66. package/dist/theculturepost/pages/archive/ArchivePage.js +265 -180
  67. package/dist/theculturepost/pages/archive/ArchivePage.js.map +1 -1
  68. package/dist/theculturepost/pages/archive/CollectionDetailPage.js +158 -143
  69. package/dist/theculturepost/pages/archive/CollectionDetailPage.js.map +1 -1
  70. package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js +155 -93
  71. package/dist/theculturepost/pages/discussions/DiscussionDetailPage.js.map +1 -1
  72. package/dist/theculturepost/pages/discussions/DiscussionsPage.js +16 -16
  73. package/dist/theculturepost/pages/discussions/DiscussionsPage.js.map +1 -1
  74. package/dist/theculturepost/pages/governance/GovernancePage.js +293 -0
  75. package/dist/theculturepost/pages/governance/GovernancePage.js.map +1 -0
  76. package/dist/theculturepost/pages/stories/StoriesPage.js +18 -18
  77. package/dist/theculturepost/pages/stories/StoriesPage.js.map +1 -1
  78. package/dist/theculturepost/pages/stories/StoryDetailPage.js +603 -285
  79. package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
  80. package/dist/theculturepost/pages/timeline/TimelinePage.js +162 -0
  81. package/dist/theculturepost/pages/timeline/TimelinePage.js.map +1 -0
  82. package/dist/theculturepost/pages/topics/TopicDetailPage.js +239 -163
  83. package/dist/theculturepost/pages/topics/TopicDetailPage.js.map +1 -1
  84. package/dist/theculturepost/pages/topics/TopicsPage.js +76 -74
  85. package/dist/theculturepost/pages/topics/TopicsPage.js.map +1 -1
  86. package/dist/theculturepost/styles/injectDisplayFont.js +11 -0
  87. package/dist/theculturepost/styles/injectDisplayFont.js.map +1 -0
  88. package/dist/theculturepost/utils/formatters.js +6 -1
  89. package/dist/theculturepost/utils/formatters.js.map +1 -1
  90. package/package.json +1 -1
  91. package/dist/theculturepost/components/OralHistoryCard.js.map +0 -1
@@ -1,163 +1,355 @@
1
1
  import { useTheCulturePost as e } from "../../context/TheCulturePostContext.js";
2
- import { PageLayout as t } from "../../components/PageLayout.js";
3
- import { ErrorView as n, LoadingView as r } from "../../components/StateViews.js";
2
+ import { cn as t } from "../../utils/cn.js";
4
3
  import "../../context/index.js";
5
- import { useFileUrl as i } from "../../hooks/useFiles.js";
6
- import { CoverImage as a } from "../../components/CoverImage.js";
7
- import { formatDate as o, formatEnumLabel as s } from "../../utils/formatters.js";
8
- import { StatusBadge as c } from "../../components/StatusBadge.js";
9
- import { useTcpArchiveItem as l } from "../../hooks/useTcpApi.js";
4
+ import { useFileUrl as n } from "../../hooks/useFiles.js";
5
+ import { ErrorView as r, LoadingView as i } from "../../components/StateViews.js";
6
+ import { formatDate as a, formatEnumLabel as o } from "../../utils/formatters.js";
7
+ import { StatusBadge as s } from "../../components/StatusBadge.js";
8
+ import { useTcpAddCitation as c, useTcpArchiveItem as l, useTcpStories as u } from "../../hooks/useTcpApi.js";
10
9
  import "../../hooks/index.js";
11
- import { IMAGE_KINDS as u, KIND_ICON as d } from "../../components/kindIcon.js";
12
- import { ArrowLeft as f, CalendarClock as p, Download as m, Languages as h, Library as g, MapPin as _, Tag as v } from "lucide-react";
13
- import { useParams as y } from "react-router-dom";
14
- import { jsx as b, jsxs as x } from "react/jsx-runtime";
15
- import { Button as S, GlassCard as C } from "@burdenoff/fe-libs/ui";
10
+ import { DecorativeDivider as d } from "../../components/DecorativeDivider.js";
11
+ import { IMAGE_KINDS as f, KIND_ICON as p } from "../../components/kindIcon.js";
12
+ import { describeError as m, notify as h } from "../../lib/toast.js";
13
+ import { createElement as g, useEffect as _, useState as v } from "react";
14
+ import { ArrowLeft as y, CalendarClock as b, Clock as x, Download as S, Globe as C, Landmark as w, Languages as T, Library as E, Loader2 as D, Lock as O, Maximize2 as k, Minus as A, Plus as j, Quote as M, Tag as N, Users as P, X as F } from "lucide-react";
15
+ import { useParams as I } from "react-router-dom";
16
+ import { Fragment as L, jsx as R, jsxs as z } from "react/jsx-runtime";
17
+ import { Button as B, GlassCard as V, Input as H, ResponsiveDialog as U, ResponsiveDialogContent as W, ResponsiveDialogDescription as G, ResponsiveDialogFooter as K, ResponsiveDialogHeader as q, ResponsiveDialogTitle as J } from "@burdenoff/fe-libs/ui";
16
18
  //#region src/theculturepost/pages/archive/ArchiveItemDetailPage.tsx
17
- function w({ fileId: e }) {
18
- let { data: t } = i(e);
19
- return t ? /* @__PURE__ */ x("a", {
20
- href: t,
21
- target: "_blank",
22
- rel: "noreferrer noopener",
23
- className: "inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
24
- children: [/* @__PURE__ */ b(m, { className: "h-4 w-4" }), " Download / open file"]
25
- }) : null;
26
- }
27
- function T() {
28
- let { id: i } = y(), { navigateTo: m } = e(), { data: T, isLoading: E, isError: D, refetch: O } = l(i), k = /* @__PURE__ */ x(S, {
29
- variant: "ghost",
30
- size: "sm",
31
- onClick: () => m("archive"),
32
- children: [/* @__PURE__ */ b(f, { className: "mr-1.5 h-4 w-4" }), " Back"]
19
+ var Y = {
20
+ PUBLIC: C,
21
+ COMMUNITY: P,
22
+ RESTRICTED: O,
23
+ EMBARGOED: x
24
+ };
25
+ function X({ onBack: e, children: t }) {
26
+ return /* @__PURE__ */ R("div", {
27
+ className: "flex h-full flex-col",
28
+ children: /* @__PURE__ */ R("div", {
29
+ className: "flex-1 overflow-auto",
30
+ children: /* @__PURE__ */ z("div", {
31
+ className: "mx-auto w-full max-w-6xl p-4 sm:p-6",
32
+ children: [/* @__PURE__ */ z("button", {
33
+ type: "button",
34
+ onClick: e,
35
+ className: "inline-flex items-center gap-1.5 text-sm font-medium text-text-secondary hover:text-text-primary",
36
+ children: [/* @__PURE__ */ R(y, {
37
+ className: "h-4 w-4",
38
+ "aria-hidden": "true"
39
+ }), " Archive"]
40
+ }), /* @__PURE__ */ R("div", {
41
+ className: "mt-4",
42
+ children: t
43
+ })]
44
+ })
45
+ })
33
46
  });
34
- if (E) return /* @__PURE__ */ b(t, {
35
- title: "Artifact",
36
- actions: k,
37
- children: /* @__PURE__ */ b(r, { label: "Loading artifact…" })
47
+ }
48
+ function Z() {
49
+ let { id: t } = I(), { navigateTo: n } = e(), { data: c, isLoading: u, isError: f, refetch: m } = l(t), [h, _] = v(!1), y = () => n("archive");
50
+ if (u) return /* @__PURE__ */ R(X, {
51
+ onBack: y,
52
+ children: /* @__PURE__ */ R(i, { label: "Loading artifact…" })
38
53
  });
39
- if (D || !T) return /* @__PURE__ */ b(t, {
40
- title: "Artifact",
41
- actions: k,
42
- children: /* @__PURE__ */ b(n, {
54
+ if (f || !c) return /* @__PURE__ */ R(X, {
55
+ onBack: y,
56
+ children: /* @__PURE__ */ R(r, {
43
57
  title: "Artifact not found",
44
58
  message: "This artifact may have been archived, or you may not have access.",
45
- onRetry: () => O()
59
+ onRetry: () => m()
46
60
  })
47
61
  });
48
- let A = d[T.kind], j = u.has(T.kind);
49
- return /* @__PURE__ */ b(t, {
50
- title: T.title,
51
- actions: k,
52
- children: /* @__PURE__ */ x("div", {
53
- className: "mx-auto grid max-w-5xl gap-6 lg:grid-cols-[1.4fr_1fr]",
54
- children: [/* @__PURE__ */ x("div", {
55
- className: "flex flex-col gap-4",
56
- children: [j ? /* @__PURE__ */ b(a, {
57
- fileId: T.file?.id,
58
- alt: T.title,
59
- className: "aspect-[4/3] w-full",
60
- icon: /* @__PURE__ */ b(A, { className: "h-12 w-12" })
61
- }) : /* @__PURE__ */ x(C, {
62
- treatment: "plain",
63
- className: "flex aspect-[4/3] w-full flex-col items-center justify-center gap-3 text-text-tertiary",
64
- children: [/* @__PURE__ */ b(A, { className: "h-14 w-14" }), /* @__PURE__ */ b("span", {
65
- className: "text-sm font-medium",
66
- children: s(T.kind)
67
- })]
68
- }), T.file?.id && /* @__PURE__ */ b(w, { fileId: T.file.id })]
69
- }), /* @__PURE__ */ x("div", {
70
- className: "flex flex-col gap-5",
62
+ let x = c.collection, S = Y[c.accessLevel], D = p[c.kind];
63
+ return /* @__PURE__ */ z(X, {
64
+ onBack: y,
65
+ children: [/* @__PURE__ */ z("div", {
66
+ className: "grid gap-6 lg:grid-cols-[1.3fr_1fr]",
67
+ children: [/* @__PURE__ */ R($, { item: c }), /* @__PURE__ */ z("div", {
68
+ className: "flex min-w-0 flex-col gap-5",
71
69
  children: [
72
- /* @__PURE__ */ x("div", {
70
+ /* @__PURE__ */ R("h1", {
71
+ className: "font-display text-3xl font-semibold leading-tight text-text-primary",
72
+ children: c.title
73
+ }),
74
+ /* @__PURE__ */ z("div", {
73
75
  className: "flex flex-wrap items-center gap-1.5",
74
- children: [/* @__PURE__ */ b(c, { status: T.kind }), /* @__PURE__ */ b(c, { status: T.accessLevel })]
76
+ children: [/* @__PURE__ */ R(s, {
77
+ status: c.kind,
78
+ icon: g(D, { className: "h-3 w-3" })
79
+ }), /* @__PURE__ */ R(s, {
80
+ status: c.accessLevel,
81
+ icon: g(S, { className: "h-3 w-3" })
82
+ })]
75
83
  }),
76
- T.description && /* @__PURE__ */ b("p", {
84
+ c.description && /* @__PURE__ */ R("p", {
77
85
  className: "whitespace-pre-wrap text-sm leading-relaxed text-text-secondary",
78
- children: T.description
86
+ children: c.description
79
87
  }),
80
- /* @__PURE__ */ x("dl", {
81
- className: "flex flex-col gap-3 text-sm",
88
+ /* @__PURE__ */ R(d, { className: "py-2" }),
89
+ /* @__PURE__ */ z("dl", {
90
+ className: "flex flex-col gap-4",
82
91
  children: [
83
- T.origin && /* @__PURE__ */ x("div", {
84
- className: "flex items-start gap-2.5",
85
- children: [/* @__PURE__ */ b(_, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
86
- className: "text-text-tertiary",
87
- children: "Origin"
88
- }), /* @__PURE__ */ b("dd", {
89
- className: "mt-0.5 text-text-primary",
90
- children: T.origin
91
- })] })]
92
+ c.provenance && /* @__PURE__ */ R(Q, {
93
+ icon: w,
94
+ label: "Provenance",
95
+ children: c.provenance
96
+ }),
97
+ c.origin && /* @__PURE__ */ R(Q, {
98
+ icon: C,
99
+ label: "Origin",
100
+ children: c.origin
92
101
  }),
93
- T.datedAt && /* @__PURE__ */ x("div", {
94
- className: "flex items-start gap-2.5",
95
- children: [/* @__PURE__ */ b(p, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
96
- className: "text-text-tertiary",
97
- children: "Dated"
98
- }), /* @__PURE__ */ b("dd", {
99
- className: "mt-0.5 text-text-primary",
100
- children: o(T.datedAt)
101
- })] })]
102
+ c.datedAt && /* @__PURE__ */ R(Q, {
103
+ icon: b,
104
+ label: "Date",
105
+ children: a(c.datedAt)
102
106
  }),
103
- T.languages.length > 0 && /* @__PURE__ */ x("div", {
104
- className: "flex items-start gap-2.5",
105
- children: [/* @__PURE__ */ b(h, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
106
- className: "text-text-tertiary",
107
- children: "Languages"
108
- }), /* @__PURE__ */ b("dd", {
109
- className: "mt-0.5 text-text-primary",
110
- children: T.languages.map(s).join(", ")
111
- })] })]
107
+ c.languages.length > 0 && /* @__PURE__ */ R(Q, {
108
+ icon: T,
109
+ label: "Languages",
110
+ children: c.languages.map(o).join(", ")
112
111
  }),
113
- /* @__PURE__ */ x("div", {
114
- className: "flex items-start gap-2.5",
115
- children: [/* @__PURE__ */ b(p, { className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("dt", {
116
- className: "text-text-tertiary",
117
- children: "Catalogued"
118
- }), /* @__PURE__ */ b("dd", {
119
- className: "mt-0.5 text-text-primary",
120
- children: o(T.createdAt)
121
- })] })]
112
+ c.tags.length > 0 && /* @__PURE__ */ R(Q, {
113
+ icon: N,
114
+ label: "Tags",
115
+ children: /* @__PURE__ */ R("div", {
116
+ className: "flex flex-wrap gap-1.5",
117
+ children: c.tags.map((e) => /* @__PURE__ */ R("span", {
118
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
119
+ children: e
120
+ }, e))
121
+ })
122
122
  })
123
123
  ]
124
124
  }),
125
- T.provenance && /* @__PURE__ */ x("div", {
126
- className: "rounded-xl border border-border-seam bg-bg-surface p-4",
127
- children: [/* @__PURE__ */ b("p", {
128
- className: "text-xs font-semibold uppercase tracking-wide text-text-tertiary",
129
- children: "Provenance"
130
- }), /* @__PURE__ */ b("p", {
131
- className: "mt-1.5 whitespace-pre-wrap text-sm text-text-secondary",
132
- children: T.provenance
133
- })]
134
- }),
135
- T.tags.length > 0 && /* @__PURE__ */ x("div", {
136
- className: "flex flex-wrap items-center gap-1.5",
137
- children: [/* @__PURE__ */ b(v, {
138
- className: "h-3.5 w-3.5 text-text-tertiary",
139
- "aria-hidden": "true"
140
- }), T.tags.map((e) => /* @__PURE__ */ x("span", {
141
- className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
142
- children: ["#", e]
143
- }, e))]
144
- }),
145
- T.collection && /* @__PURE__ */ x("button", {
125
+ x && /* @__PURE__ */ z("button", {
146
126
  type: "button",
147
- onClick: () => m(`archive/collections/${T.collection.id}`),
127
+ onClick: () => n(`archive/collections/${x.id}`),
148
128
  className: "inline-flex items-center gap-2 self-start rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
149
129
  children: [
150
- /* @__PURE__ */ b(g, { className: "h-4 w-4 text-text-tertiary" }),
130
+ /* @__PURE__ */ R(E, {
131
+ className: "h-4 w-4 text-text-tertiary",
132
+ "aria-hidden": "true"
133
+ }),
151
134
  " ",
152
- T.collection.name
135
+ x.name
153
136
  ]
137
+ }),
138
+ /* @__PURE__ */ z(B, {
139
+ className: "w-full sm:w-auto",
140
+ onClick: () => _(!0),
141
+ children: [/* @__PURE__ */ R(M, { className: "mr-1.5 h-4 w-4" }), " Cite in a story"]
154
142
  })
155
143
  ]
156
144
  })]
145
+ }), /* @__PURE__ */ R(ee, {
146
+ open: h,
147
+ onOpenChange: _,
148
+ item: c
149
+ })]
150
+ });
151
+ }
152
+ function Q({ icon: e, label: t, children: n }) {
153
+ return /* @__PURE__ */ z("div", {
154
+ className: "flex items-start gap-3",
155
+ children: [
156
+ /* @__PURE__ */ R(e, {
157
+ className: "mt-0.5 h-4 w-4 shrink-0 text-accent",
158
+ "aria-hidden": "true"
159
+ }),
160
+ /* @__PURE__ */ R("dt", {
161
+ className: "w-24 shrink-0 text-sm text-text-tertiary",
162
+ children: t
163
+ }),
164
+ /* @__PURE__ */ R("dd", {
165
+ className: "min-w-0 flex-1 text-sm text-text-primary",
166
+ children: n
167
+ })
168
+ ]
169
+ });
170
+ }
171
+ function $({ item: e }) {
172
+ let { data: r } = n(e.file?.id), i = p[e.kind], [a, s] = v(1), [c, l] = v(!1), [u, d] = v(!1), m = f.has(e.kind) && !!r && !u;
173
+ return _(() => {
174
+ if (!c) return;
175
+ let e = (e) => {
176
+ e.key === "Escape" && l(!1);
177
+ };
178
+ return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
179
+ }, [c]), /* @__PURE__ */ z("div", {
180
+ className: "flex flex-col gap-4",
181
+ children: [
182
+ /* @__PURE__ */ R(V, {
183
+ treatment: "plain",
184
+ className: "p-3 sm:p-4",
185
+ children: /* @__PURE__ */ z("div", {
186
+ className: t("relative aspect-[4/3] w-full rounded-xl bg-bg-sunken", a > 1 ? "overflow-auto" : "overflow-hidden"),
187
+ children: [m && r ? /* @__PURE__ */ R("img", {
188
+ src: r,
189
+ alt: e.title,
190
+ onError: () => d(!0),
191
+ style: {
192
+ transform: `scale(${a})`,
193
+ transformOrigin: "center center"
194
+ },
195
+ className: "h-full w-full object-contain transition-transform duration-200"
196
+ }) : /* @__PURE__ */ z("div", {
197
+ className: "flex h-full w-full flex-col items-center justify-center gap-3 text-text-tertiary",
198
+ children: [/* @__PURE__ */ R(i, {
199
+ className: "h-16 w-16",
200
+ "aria-hidden": "true"
201
+ }), /* @__PURE__ */ R("span", {
202
+ className: "text-sm font-medium",
203
+ children: o(e.kind)
204
+ })]
205
+ }), m && r && /* @__PURE__ */ z(L, { children: [/* @__PURE__ */ R("button", {
206
+ type: "button",
207
+ onClick: () => l(!0),
208
+ "aria-label": "View full screen",
209
+ className: "absolute right-3 top-3 z-10 flex h-9 w-9 items-center justify-center rounded-lg bg-bg-canvas/85 text-text-primary shadow-sm backdrop-blur-sm hover:bg-bg-canvas",
210
+ children: /* @__PURE__ */ R(k, { className: "h-4 w-4" })
211
+ }), /* @__PURE__ */ z("div", {
212
+ className: "absolute bottom-3 left-3 z-10 flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-canvas/85 text-text-primary shadow-sm backdrop-blur-sm",
213
+ children: [
214
+ /* @__PURE__ */ R("button", {
215
+ type: "button",
216
+ onClick: () => s((e) => Math.min(4, Math.round((e + .5) * 10) / 10)),
217
+ disabled: a >= 4,
218
+ "aria-label": "Zoom in",
219
+ className: "flex h-8 w-9 items-center justify-center hover:bg-bg-sunken disabled:opacity-40",
220
+ children: /* @__PURE__ */ R(j, { className: "h-4 w-4" })
221
+ }),
222
+ /* @__PURE__ */ z("button", {
223
+ type: "button",
224
+ onClick: () => s(1),
225
+ "aria-label": "Reset zoom",
226
+ className: "border-y border-border-seam px-1 py-1 text-[10px] font-medium tabular-nums hover:bg-bg-sunken",
227
+ children: [Math.round(a * 100), "%"]
228
+ }),
229
+ /* @__PURE__ */ R("button", {
230
+ type: "button",
231
+ onClick: () => s((e) => Math.max(1, Math.round((e - .5) * 10) / 10)),
232
+ disabled: a <= 1,
233
+ "aria-label": "Zoom out",
234
+ className: "flex h-8 w-9 items-center justify-center hover:bg-bg-sunken disabled:opacity-40",
235
+ children: /* @__PURE__ */ R(A, { className: "h-4 w-4" })
236
+ })
237
+ ]
238
+ })] })]
239
+ })
240
+ }),
241
+ r && /* @__PURE__ */ z("a", {
242
+ href: r,
243
+ target: "_blank",
244
+ rel: "noreferrer noopener",
245
+ download: !0,
246
+ className: "inline-flex items-center justify-center gap-2 self-start rounded-lg border border-border-seam bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken",
247
+ children: [/* @__PURE__ */ R(S, { className: "h-4 w-4" }), " Download"]
248
+ }),
249
+ c && r && /* @__PURE__ */ z("div", {
250
+ role: "dialog",
251
+ "aria-modal": "true",
252
+ "aria-label": `${e.title} — full view`,
253
+ onClick: () => l(!1),
254
+ className: "fixed inset-0 z-50 flex items-center justify-center bg-bg-canvas/95 p-4 backdrop-blur-sm",
255
+ children: [/* @__PURE__ */ R("button", {
256
+ type: "button",
257
+ onClick: () => l(!1),
258
+ "aria-label": "Close full view",
259
+ className: "absolute right-4 top-4 flex h-10 w-10 items-center justify-center rounded-full bg-bg-surface text-text-primary shadow-sm hover:bg-bg-sunken",
260
+ children: /* @__PURE__ */ R(F, { className: "h-5 w-5" })
261
+ }), /* @__PURE__ */ R("img", {
262
+ src: r,
263
+ alt: e.title,
264
+ onClick: (e) => e.stopPropagation(),
265
+ className: "max-h-full max-w-full rounded-lg object-contain"
266
+ })]
267
+ })
268
+ ]
269
+ });
270
+ }
271
+ function ee({ open: e, onOpenChange: t, item: n }) {
272
+ let r = u({ pagination: { limit: 50 } }), a = c(), [s, l] = v(""), [d, f] = v(null), [p, g] = v(null), _ = r.data?.items ?? [], y = s.trim().toLowerCase(), b = y ? _.filter((e) => e.title.toLowerCase().includes(y)) : _, x = async (e) => {
273
+ f(e.id), g(null);
274
+ try {
275
+ await a.mutateAsync({
276
+ storyId: e.id,
277
+ title: n.title,
278
+ sourceType: "ARCHIVAL_RECORD",
279
+ provenance: n.provenance ?? null,
280
+ excerpt: n.description ?? null,
281
+ sourceFileId: n.file?.id ?? null
282
+ }), h.success("Cited in a story", e.title), t(!1);
283
+ } catch (e) {
284
+ g(m(e));
285
+ } finally {
286
+ f(null);
287
+ }
288
+ };
289
+ return /* @__PURE__ */ R(U, {
290
+ open: e,
291
+ onOpenChange: t,
292
+ children: /* @__PURE__ */ z(W, {
293
+ className: "sm:max-w-lg",
294
+ children: [
295
+ /* @__PURE__ */ z(q, { children: [/* @__PURE__ */ R(J, { children: "Cite in a story" }), /* @__PURE__ */ z(G, { children: [
296
+ "Attach “",
297
+ n.title,
298
+ "” to a story as an archival-record citation."
299
+ ] })] }),
300
+ /* @__PURE__ */ z("div", {
301
+ className: "flex flex-col gap-3 py-2",
302
+ children: [
303
+ /* @__PURE__ */ R(H, {
304
+ value: s,
305
+ onChange: (e) => l(e.target.value),
306
+ placeholder: "Search stories…",
307
+ "aria-label": "Search stories"
308
+ }),
309
+ /* @__PURE__ */ R("div", {
310
+ className: "flex max-h-[50vh] flex-col gap-1.5 overflow-y-auto",
311
+ children: r.isLoading ? /* @__PURE__ */ R(i, {
312
+ label: "Loading stories…",
313
+ className: "min-h-[8rem]"
314
+ }) : b.length === 0 ? /* @__PURE__ */ R("p", {
315
+ className: "py-8 text-center text-sm text-text-tertiary",
316
+ children: _.length === 0 ? "No stories yet — draft a story first." : "No stories match your search."
317
+ }) : b.map((e) => /* @__PURE__ */ z("button", {
318
+ type: "button",
319
+ onClick: () => x(e),
320
+ disabled: a.isPending,
321
+ className: "flex items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-surface px-3 py-2.5 text-left transition-colors hover:bg-bg-sunken disabled:opacity-60",
322
+ children: [/* @__PURE__ */ z("span", {
323
+ className: "min-w-0",
324
+ children: [/* @__PURE__ */ R("span", {
325
+ className: "block truncate text-sm font-medium text-text-primary",
326
+ children: e.title
327
+ }), /* @__PURE__ */ R("span", {
328
+ className: "mt-0.5 block truncate text-xs text-text-tertiary",
329
+ children: e.topic?.name ?? o(e.status)
330
+ })]
331
+ }), d === e.id ? /* @__PURE__ */ R(D, { className: "h-4 w-4 shrink-0 animate-spin text-text-tertiary" }) : /* @__PURE__ */ R(M, {
332
+ className: "h-4 w-4 shrink-0 text-text-tertiary",
333
+ "aria-hidden": "true"
334
+ })]
335
+ }, e.id))
336
+ }),
337
+ p && /* @__PURE__ */ R("p", {
338
+ className: "text-sm text-status-error-text",
339
+ children: p
340
+ })
341
+ ]
342
+ }),
343
+ /* @__PURE__ */ R(K, { children: /* @__PURE__ */ R(B, {
344
+ variant: "outline",
345
+ onClick: () => t(!1),
346
+ children: "Close"
347
+ }) })
348
+ ]
157
349
  })
158
350
  });
159
351
  }
160
352
  //#endregion
161
- export { T as ArchiveItemDetailPage };
353
+ export { Z as ArchiveItemDetailPage };
162
354
 
163
355
  //# sourceMappingURL=ArchiveItemDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ArchiveItemDetailPage.js","names":[],"sources":["../../../../src/theculturepost/pages/archive/ArchiveItemDetailPage.tsx"],"sourcesContent":["/**\n * ArchiveItemDetailPage — a single archived artifact.\n * @module theculturepost/pages/archive\n *\n * Reads `tcpArchiveItem` (with its parent collection). Image kinds render the\n * file inline; other kinds expose a download link resolved from the file id.\n */\n\nimport { ArrowLeft, MapPin, CalendarClock, Languages, Download, Library, Tag } from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { CoverImage } from '../../components/CoverImage';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { KIND_ICON, IMAGE_KINDS } from '../../components/kindIcon';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpArchiveItem, useFileUrl } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\nimport { useParams } from 'react-router-dom';\n\nfunction DownloadLink({ fileId }: { fileId: string }) {\n const { data: url } = useFileUrl(fileId);\n if (!url) return null;\n return (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"inline-flex items-center gap-1.5 rounded-lg bg-action-primary-bg px-3 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n <Download className=\"h-4 w-4\" /> Download / open file\n </a>\n );\n}\n\nexport function ArchiveItemDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: item, isLoading, isError, refetch } = useTcpArchiveItem(id);\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('archive')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Artifact\" actions={backButton}>\n <LoadingView label=\"Loading artifact…\" />\n </PageLayout>\n );\n }\n\n if (isError || !item) {\n return (\n <PageLayout title=\"Artifact\" actions={backButton}>\n <ErrorView\n title=\"Artifact not found\"\n message=\"This artifact may have been archived, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const Icon = KIND_ICON[item.kind];\n const isImage = IMAGE_KINDS.has(item.kind);\n\n return (\n <PageLayout title={item.title} actions={backButton}>\n <div className=\"mx-auto grid max-w-5xl gap-6 lg:grid-cols-[1.4fr_1fr]\">\n {/* Media */}\n <div className=\"flex flex-col gap-4\">\n {isImage ? (\n <CoverImage\n fileId={item.file?.id}\n alt={item.title}\n className=\"aspect-[4/3] w-full\"\n icon={<Icon className=\"h-12 w-12\" />}\n />\n ) : (\n <GlassCard\n treatment=\"plain\"\n className=\"flex aspect-[4/3] w-full flex-col items-center justify-center gap-3 text-text-tertiary\"\n >\n <Icon className=\"h-14 w-14\" />\n <span className=\"text-sm font-medium\">{formatEnumLabel(item.kind)}</span>\n </GlassCard>\n )}\n {item.file?.id && <DownloadLink fileId={item.file.id} />}\n </div>\n\n {/* Details */}\n <div className=\"flex flex-col gap-5\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={item.kind} />\n <StatusBadge status={item.accessLevel} />\n </div>\n\n {item.description && (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {item.description}\n </p>\n )}\n\n <dl className=\"flex flex-col gap-3 text-sm\">\n {item.origin && (\n <div className=\"flex items-start gap-2.5\">\n <MapPin className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Origin</dt>\n <dd className=\"mt-0.5 text-text-primary\">{item.origin}</dd>\n </div>\n </div>\n )}\n {item.datedAt && (\n <div className=\"flex items-start gap-2.5\">\n <CalendarClock className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Dated</dt>\n <dd className=\"mt-0.5 text-text-primary\">{formatDate(item.datedAt)}</dd>\n </div>\n </div>\n )}\n {item.languages.length > 0 && (\n <div className=\"flex items-start gap-2.5\">\n <Languages className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Languages</dt>\n <dd className=\"mt-0.5 text-text-primary\">\n {item.languages.map(formatEnumLabel).join(', ')}\n </dd>\n </div>\n </div>\n )}\n <div className=\"flex items-start gap-2.5\">\n <CalendarClock className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\" />\n <div>\n <dt className=\"text-text-tertiary\">Catalogued</dt>\n <dd className=\"mt-0.5 text-text-primary\">{formatDate(item.createdAt)}</dd>\n </div>\n </div>\n </dl>\n\n {item.provenance && (\n <div className=\"rounded-xl border border-border-seam bg-bg-surface p-4\">\n <p className=\"text-xs font-semibold uppercase tracking-wide text-text-tertiary\">\n Provenance\n </p>\n <p className=\"mt-1.5 whitespace-pre-wrap text-sm text-text-secondary\">\n {item.provenance}\n </p>\n </div>\n )}\n\n {item.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <Tag className=\"h-3.5 w-3.5 text-text-tertiary\" aria-hidden=\"true\" />\n {item.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n #{tag}\n </span>\n ))}\n </div>\n )}\n\n {item.collection && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`archive/collections/${item.collection!.id}`)}\n className=\"inline-flex items-center gap-2 self-start rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Library className=\"h-4 w-4 text-text-tertiary\" /> {item.collection.name}\n </button>\n )}\n </div>\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ArchiveItemDetailPage.js","names":[],"sources":["../../../../src/theculturepost/pages/archive/ArchiveItemDetailPage.tsx"],"sourcesContent":["/**\n * ArchiveItemDetailPage — a single archived artifact.\n * @module theculturepost/pages/archive\n *\n * Reads `tcpArchiveItem` (with its parent collection). Two columns: a media\n * viewer with CSS zoom + a full-screen lightbox (the schema exposes a SINGLE\n * `file` — never a thumbnail-strip gallery) and a details panel. \"Cite in a\n * story\" opens a story picker and writes an `ARCHIVAL_RECORD` citation via\n * `tcpAddCitation`. There is no bookmark/share (the schema has neither).\n */\n\nimport { createElement, useEffect, useState } from 'react';\nimport {\n ArrowLeft,\n Landmark,\n Globe,\n CalendarClock,\n Languages,\n Download,\n Library,\n Tag,\n Quote,\n Maximize2,\n Plus,\n Minus,\n X,\n Loader2,\n Users,\n Lock,\n Clock,\n type LucideIcon,\n} from 'lucide-react';\nimport {\n Button,\n GlassCard,\n Input,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { useParams } from 'react-router-dom';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { DecorativeDivider } from '../../components/DecorativeDivider';\nimport { KIND_ICON, IMAGE_KINDS } from '../../components/kindIcon';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpArchiveItem, useFileUrl, useTcpStories, useTcpAddCitation } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport { formatDate, formatEnumLabel } from '../../utils/formatters';\nimport { notify, describeError } from '../../lib/toast';\nimport type { TcpArchiveItem, TcpStory, TcpAccessLevel } from '../../types';\n\nconst ACCESS_ICON: Record<TcpAccessLevel, LucideIcon> = {\n PUBLIC: Globe,\n COMMUNITY: Users,\n RESTRICTED: Lock,\n EMBARGOED: Clock,\n};\n\nfunction Shell({ onBack, children }: { onBack: () => void; children: React.ReactNode }) {\n return (\n <div className=\"flex h-full flex-col\">\n <div className=\"flex-1 overflow-auto\">\n <div className=\"mx-auto w-full max-w-6xl p-4 sm:p-6\">\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center gap-1.5 text-sm font-medium text-text-secondary hover:text-text-primary\"\n >\n <ArrowLeft className=\"h-4 w-4\" aria-hidden=\"true\" /> Archive\n </button>\n <div className=\"mt-4\">{children}</div>\n </div>\n </div>\n </div>\n );\n}\n\nexport function ArchiveItemDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: item, isLoading, isError, refetch } = useTcpArchiveItem(id);\n const [citeOpen, setCiteOpen] = useState(false);\n\n const goBack = () => navigateTo('archive');\n\n if (isLoading) {\n return (\n <Shell onBack={goBack}>\n <LoadingView label=\"Loading artifact…\" />\n </Shell>\n );\n }\n\n if (isError || !item) {\n return (\n <Shell onBack={goBack}>\n <ErrorView\n title=\"Artifact not found\"\n message=\"This artifact may have been archived, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </Shell>\n );\n }\n\n const collection = item.collection;\n const AccessIcon = ACCESS_ICON[item.accessLevel];\n const KindIcon = KIND_ICON[item.kind];\n\n return (\n <Shell onBack={goBack}>\n <div className=\"grid gap-6 lg:grid-cols-[1.3fr_1fr]\">\n <MediaViewer item={item} />\n\n <div className=\"flex min-w-0 flex-col gap-5\">\n <h1 className=\"font-display text-3xl font-semibold leading-tight text-text-primary\">\n {item.title}\n </h1>\n\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge\n status={item.kind}\n icon={createElement(KindIcon, { className: 'h-3 w-3' })}\n />\n <StatusBadge\n status={item.accessLevel}\n icon={createElement(AccessIcon, { className: 'h-3 w-3' })}\n />\n </div>\n\n {item.description && (\n <p className=\"whitespace-pre-wrap text-sm leading-relaxed text-text-secondary\">\n {item.description}\n </p>\n )}\n\n <DecorativeDivider className=\"py-2\" />\n\n <dl className=\"flex flex-col gap-4\">\n {item.provenance && (\n <DetailRow icon={Landmark} label=\"Provenance\">\n {item.provenance}\n </DetailRow>\n )}\n {item.origin && (\n <DetailRow icon={Globe} label=\"Origin\">\n {item.origin}\n </DetailRow>\n )}\n {item.datedAt && (\n <DetailRow icon={CalendarClock} label=\"Date\">\n {formatDate(item.datedAt)}\n </DetailRow>\n )}\n {item.languages.length > 0 && (\n <DetailRow icon={Languages} label=\"Languages\">\n {item.languages.map(formatEnumLabel).join(', ')}\n </DetailRow>\n )}\n {item.tags.length > 0 && (\n <DetailRow icon={Tag} label=\"Tags\">\n <div className=\"flex flex-wrap gap-1.5\">\n {item.tags.map((tag) => (\n <span\n key={tag}\n className=\"rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\"\n >\n {tag}\n </span>\n ))}\n </div>\n </DetailRow>\n )}\n </dl>\n\n {collection && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`archive/collections/${collection.id}`)}\n className=\"inline-flex items-center gap-2 self-start rounded-lg border border-border-seam bg-bg-surface px-3 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Library className=\"h-4 w-4 text-text-tertiary\" aria-hidden=\"true\" />{' '}\n {collection.name}\n </button>\n )}\n\n <Button className=\"w-full sm:w-auto\" onClick={() => setCiteOpen(true)}>\n <Quote className=\"mr-1.5 h-4 w-4\" /> Cite in a story\n </Button>\n </div>\n </div>\n\n <CiteInStoryDialog open={citeOpen} onOpenChange={setCiteOpen} item={item} />\n </Shell>\n );\n}\n\n// ---------------------------------------------------------------------------\n// DetailRow\n// ---------------------------------------------------------------------------\n\nfunction DetailRow({\n icon: Icon,\n label,\n children,\n}: {\n icon: LucideIcon;\n label: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"flex items-start gap-3\">\n <Icon className=\"mt-0.5 h-4 w-4 shrink-0 text-accent\" aria-hidden=\"true\" />\n <dt className=\"w-24 shrink-0 text-sm text-text-tertiary\">{label}</dt>\n <dd className=\"min-w-0 flex-1 text-sm text-text-primary\">{children}</dd>\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// MediaViewer — single file only (no gallery), CSS zoom + a full-screen lightbox.\n// ---------------------------------------------------------------------------\n\nfunction MediaViewer({ item }: { item: TcpArchiveItem }) {\n const { data: url } = useFileUrl(item.file?.id);\n const Icon = KIND_ICON[item.kind];\n const [zoom, setZoom] = useState(1);\n const [lightbox, setLightbox] = useState(false);\n const [imgFailed, setImgFailed] = useState(false);\n const showImage = IMAGE_KINDS.has(item.kind) && Boolean(url) && !imgFailed;\n\n useEffect(() => {\n if (!lightbox) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setLightbox(false);\n };\n window.addEventListener('keydown', onKey);\n return () => window.removeEventListener('keydown', onKey);\n }, [lightbox]);\n\n const zoomIn = () => setZoom((z) => Math.min(4, Math.round((z + 0.5) * 10) / 10));\n const zoomOut = () => setZoom((z) => Math.max(1, Math.round((z - 0.5) * 10) / 10));\n\n return (\n <div className=\"flex flex-col gap-4\">\n <GlassCard treatment=\"plain\" className=\"p-3 sm:p-4\">\n <div\n className={cn(\n 'relative aspect-[4/3] w-full rounded-xl bg-bg-sunken',\n zoom > 1 ? 'overflow-auto' : 'overflow-hidden'\n )}\n >\n {showImage && url ? (\n <img\n src={url}\n alt={item.title}\n onError={() => setImgFailed(true)}\n style={{ transform: `scale(${zoom})`, transformOrigin: 'center center' }}\n className=\"h-full w-full object-contain transition-transform duration-200\"\n />\n ) : (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-3 text-text-tertiary\">\n <Icon className=\"h-16 w-16\" aria-hidden=\"true\" />\n <span className=\"text-sm font-medium\">{formatEnumLabel(item.kind)}</span>\n </div>\n )}\n\n {showImage && url && (\n <>\n <button\n type=\"button\"\n onClick={() => setLightbox(true)}\n aria-label=\"View full screen\"\n className=\"absolute right-3 top-3 z-10 flex h-9 w-9 items-center justify-center rounded-lg bg-bg-canvas/85 text-text-primary shadow-sm backdrop-blur-sm hover:bg-bg-canvas\"\n >\n <Maximize2 className=\"h-4 w-4\" />\n </button>\n <div className=\"absolute bottom-3 left-3 z-10 flex flex-col overflow-hidden rounded-lg border border-border-seam bg-bg-canvas/85 text-text-primary shadow-sm backdrop-blur-sm\">\n <button\n type=\"button\"\n onClick={zoomIn}\n disabled={zoom >= 4}\n aria-label=\"Zoom in\"\n className=\"flex h-8 w-9 items-center justify-center hover:bg-bg-sunken disabled:opacity-40\"\n >\n <Plus className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={() => setZoom(1)}\n aria-label=\"Reset zoom\"\n className=\"border-y border-border-seam px-1 py-1 text-[10px] font-medium tabular-nums hover:bg-bg-sunken\"\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n onClick={zoomOut}\n disabled={zoom <= 1}\n aria-label=\"Zoom out\"\n className=\"flex h-8 w-9 items-center justify-center hover:bg-bg-sunken disabled:opacity-40\"\n >\n <Minus className=\"h-4 w-4\" />\n </button>\n </div>\n </>\n )}\n </div>\n </GlassCard>\n\n {url && (\n <a\n href={url}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n download\n className=\"inline-flex items-center justify-center gap-2 self-start rounded-lg border border-border-seam bg-bg-surface px-4 py-2 text-sm font-medium text-text-primary transition-colors hover:bg-bg-sunken\"\n >\n <Download className=\"h-4 w-4\" /> Download\n </a>\n )}\n\n {lightbox && url && (\n <div\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={`${item.title} — full view`}\n onClick={() => setLightbox(false)}\n className=\"fixed inset-0 z-50 flex items-center justify-center bg-bg-canvas/95 p-4 backdrop-blur-sm\"\n >\n <button\n type=\"button\"\n onClick={() => setLightbox(false)}\n aria-label=\"Close full view\"\n className=\"absolute right-4 top-4 flex h-10 w-10 items-center justify-center rounded-full bg-bg-surface text-text-primary shadow-sm hover:bg-bg-sunken\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n <img\n src={url}\n alt={item.title}\n onClick={(e) => e.stopPropagation()}\n className=\"max-h-full max-w-full rounded-lg object-contain\"\n />\n </div>\n )}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// CiteInStoryDialog — pick a story and attach this artifact as a citation.\n// ---------------------------------------------------------------------------\n\nfunction CiteInStoryDialog({\n open,\n onOpenChange,\n item,\n}: {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n item: TcpArchiveItem;\n}) {\n const storiesQuery = useTcpStories({ pagination: { limit: 50 } });\n const addCitation = useTcpAddCitation();\n const [query, setQuery] = useState('');\n const [pendingId, setPendingId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const stories = storiesQuery.data?.items ?? [];\n const q = query.trim().toLowerCase();\n const filtered = q ? stories.filter((s) => s.title.toLowerCase().includes(q)) : stories;\n\n const cite = async (story: TcpStory) => {\n setPendingId(story.id);\n setError(null);\n try {\n await addCitation.mutateAsync({\n storyId: story.id,\n title: item.title,\n sourceType: 'ARCHIVAL_RECORD',\n provenance: item.provenance ?? null,\n excerpt: item.description ?? null,\n sourceFileId: item.file?.id ?? null,\n });\n notify.success('Cited in a story', story.title);\n onOpenChange(false);\n } catch (err) {\n setError(describeError(err));\n } finally {\n setPendingId(null);\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Cite in a story</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Attach “{item.title}” to a story as an archival-record citation.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex flex-col gap-3 py-2\">\n <Input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search stories…\"\n aria-label=\"Search stories\"\n />\n <div className=\"flex max-h-[50vh] flex-col gap-1.5 overflow-y-auto\">\n {storiesQuery.isLoading ? (\n <LoadingView label=\"Loading stories…\" className=\"min-h-[8rem]\" />\n ) : filtered.length === 0 ? (\n <p className=\"py-8 text-center text-sm text-text-tertiary\">\n {stories.length === 0\n ? 'No stories yet — draft a story first.'\n : 'No stories match your search.'}\n </p>\n ) : (\n filtered.map((story) => (\n <button\n key={story.id}\n type=\"button\"\n onClick={() => cite(story)}\n disabled={addCitation.isPending}\n className=\"flex items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-surface px-3 py-2.5 text-left transition-colors hover:bg-bg-sunken disabled:opacity-60\"\n >\n <span className=\"min-w-0\">\n <span className=\"block truncate text-sm font-medium text-text-primary\">\n {story.title}\n </span>\n <span className=\"mt-0.5 block truncate text-xs text-text-tertiary\">\n {story.topic?.name ?? formatEnumLabel(story.status)}\n </span>\n </span>\n {pendingId === story.id ? (\n <Loader2 className=\"h-4 w-4 shrink-0 animate-spin text-text-tertiary\" />\n ) : (\n <Quote className=\"h-4 w-4 shrink-0 text-text-tertiary\" aria-hidden=\"true\" />\n )}\n </button>\n ))\n )}\n </div>\n {error && <p className=\"text-sm text-status-error-text\">{error}</p>}\n </div>\n\n <ResponsiveDialogFooter>\n <Button variant=\"outline\" onClick={() => onOpenChange(false)}>\n Close\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}