@burdenoff/microfe-theculturepost 2026.1014.1 → 2026.1030.1

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 (29) hide show
  1. package/dist/theculturepost/TheCulturePostRoutes.d.ts.map +1 -1
  2. package/dist/theculturepost/TheCulturePostRoutes.js +18 -14
  3. package/dist/theculturepost/TheCulturePostRoutes.js.map +1 -1
  4. package/dist/theculturepost/components/AddCitationDialog.d.ts +12 -2
  5. package/dist/theculturepost/components/AddCitationDialog.d.ts.map +1 -1
  6. package/dist/theculturepost/components/AddCitationDialog.js +114 -92
  7. package/dist/theculturepost/components/AddCitationDialog.js.map +1 -1
  8. package/dist/theculturepost/components/AddClaimDialog.d.ts +14 -0
  9. package/dist/theculturepost/components/AddClaimDialog.d.ts.map +1 -0
  10. package/dist/theculturepost/components/AddClaimDialog.js +108 -0
  11. package/dist/theculturepost/components/AddClaimDialog.js.map +1 -0
  12. package/dist/theculturepost/components/CitationList.d.ts +10 -1
  13. package/dist/theculturepost/components/CitationList.d.ts.map +1 -1
  14. package/dist/theculturepost/components/CitationList.js +89 -85
  15. package/dist/theculturepost/components/CitationList.js.map +1 -1
  16. package/dist/theculturepost/hooks/useTcpApi.d.ts +17 -1
  17. package/dist/theculturepost/hooks/useTcpApi.d.ts.map +1 -1
  18. package/dist/theculturepost/hooks/useTcpApi.js +117 -62
  19. package/dist/theculturepost/hooks/useTcpApi.js.map +1 -1
  20. package/dist/theculturepost/pages/stories/StoryCitationsPage.d.ts +19 -0
  21. package/dist/theculturepost/pages/stories/StoryCitationsPage.d.ts.map +1 -0
  22. package/dist/theculturepost/pages/stories/StoryCitationsPage.js +319 -0
  23. package/dist/theculturepost/pages/stories/StoryCitationsPage.js.map +1 -0
  24. package/dist/theculturepost/pages/stories/StoryDetailPage.d.ts.map +1 -1
  25. package/dist/theculturepost/pages/stories/StoryDetailPage.js +327 -271
  26. package/dist/theculturepost/pages/stories/StoryDetailPage.js.map +1 -1
  27. package/dist/theculturepost/types/index.d.ts +34 -0
  28. package/dist/theculturepost/types/index.d.ts.map +1 -1
  29. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"TheCulturePostRoutes.d.ts","sourceRoot":"","sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAqC,MAAM,OAAO,CAAC;AAgGnE,eAAO,MAAM,oBAAoB,EAAE,EAyDlC,CAAC"}
1
+ {"version":3,"file":"TheCulturePostRoutes.d.ts","sourceRoot":"","sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,KAAK,EAAE,EAAqC,MAAM,OAAO,CAAC;AAmGnE,eAAO,MAAM,oBAAoB,EAAE,EA6DlC,CAAC"}
@@ -37,17 +37,17 @@ function h(e, t) {
37
37
  children: e
38
38
  });
39
39
  }
40
- var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default: e.StoriesPage }))), _ = i(() => import("./pages/stories/StoryDetailPage.js").then((e) => ({ default: e.StoryDetailPage }))), v = i(() => import("./pages/stories/SavedStoriesPage.js").then((e) => ({ default: e.SavedStoriesPage }))), y = i(() => import("./pages/topics/TopicsPage.js").then((e) => ({ default: e.TopicsPage }))), b = i(() => import("./pages/topics/TopicDetailPage.js").then((e) => ({ default: e.TopicDetailPage }))), x = i(() => import("./pages/discussions/DiscussionsPage.js").then((e) => ({ default: e.DiscussionsPage }))), S = i(() => import("./pages/discussions/DiscussionDetailPage.js").then((e) => ({ default: e.DiscussionDetailPage }))), C = i(() => import("./pages/timeline/TimelinePage.js").then((e) => ({ default: e.TimelinePage }))), w = i(() => import("./pages/governance/GovernancePage.js").then((e) => ({ default: e.GovernancePage }))), T = i(() => import("./pages/archive/ArchivePage.js").then((e) => ({ default: e.ArchivePage }))), E = i(() => import("./pages/archive/CollectionDetailPage.js").then((e) => ({ default: e.CollectionDetailPage }))), D = i(() => import("./pages/archive/ArchiveItemDetailPage.js").then((e) => ({ default: e.ArchiveItemDetailPage }))), O = () => /* @__PURE__ */ u("div", {
40
+ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default: e.StoriesPage }))), _ = i(() => import("./pages/stories/StoryDetailPage.js").then((e) => ({ default: e.StoryDetailPage }))), v = i(() => import("./pages/stories/StoryCitationsPage.js").then((e) => ({ default: e.StoryCitationsPage }))), y = i(() => import("./pages/stories/SavedStoriesPage.js").then((e) => ({ default: e.SavedStoriesPage }))), b = i(() => import("./pages/topics/TopicsPage.js").then((e) => ({ default: e.TopicsPage }))), x = i(() => import("./pages/topics/TopicDetailPage.js").then((e) => ({ default: e.TopicDetailPage }))), S = i(() => import("./pages/discussions/DiscussionsPage.js").then((e) => ({ default: e.DiscussionsPage }))), C = i(() => import("./pages/discussions/DiscussionDetailPage.js").then((e) => ({ default: e.DiscussionDetailPage }))), w = i(() => import("./pages/timeline/TimelinePage.js").then((e) => ({ default: e.TimelinePage }))), T = i(() => import("./pages/governance/GovernancePage.js").then((e) => ({ default: e.GovernancePage }))), E = i(() => import("./pages/archive/ArchivePage.js").then((e) => ({ default: e.ArchivePage }))), D = i(() => import("./pages/archive/CollectionDetailPage.js").then((e) => ({ default: e.CollectionDetailPage }))), O = i(() => import("./pages/archive/ArchiveItemDetailPage.js").then((e) => ({ default: e.ArchiveItemDetailPage }))), k = () => /* @__PURE__ */ u("div", {
41
41
  className: "flex min-h-[400px] items-center justify-center",
42
42
  children: /* @__PURE__ */ u(f, { size: "lg" })
43
- }), k = () => {
43
+ }), A = () => {
44
44
  let { basePath: i, isStandalone: a } = e(), f = l();
45
45
  t();
46
46
  let m = i === "/" ? "" : (i ?? "").replace(/\/$/, "");
47
47
  return m && !a && !(f.pathname === m || f.pathname.startsWith(m + "/")) ? null : /* @__PURE__ */ u("div", {
48
48
  className: "flex min-h-full flex-col",
49
49
  children: /* @__PURE__ */ u(r, {
50
- fallback: /* @__PURE__ */ u(O, {}),
50
+ fallback: /* @__PURE__ */ u(k, {}),
51
51
  children: /* @__PURE__ */ d(c, { children: [
52
52
  /* @__PURE__ */ u(s, {
53
53
  index: !0,
@@ -55,7 +55,7 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
55
55
  }),
56
56
  /* @__PURE__ */ u(s, {
57
57
  path: "overview",
58
- element: h(/* @__PURE__ */ u(w, {}), p.overview)
58
+ element: h(/* @__PURE__ */ u(T, {}), p.overview)
59
59
  }),
60
60
  /* @__PURE__ */ u(s, {
61
61
  path: "stories",
@@ -65,41 +65,45 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
65
65
  path: "stories/:id",
66
66
  element: h(/* @__PURE__ */ u(_, {}), p.stories)
67
67
  }),
68
+ /* @__PURE__ */ u(s, {
69
+ path: "stories/:id/citations",
70
+ element: h(/* @__PURE__ */ u(v, {}), p.stories)
71
+ }),
68
72
  /* @__PURE__ */ u(s, {
69
73
  path: "saved",
70
- element: h(/* @__PURE__ */ u(v, {}), p.saved)
74
+ element: h(/* @__PURE__ */ u(y, {}), p.saved)
71
75
  }),
72
76
  /* @__PURE__ */ u(s, {
73
77
  path: "topics",
74
- element: h(/* @__PURE__ */ u(y, {}), p.topics)
78
+ element: h(/* @__PURE__ */ u(b, {}), p.topics)
75
79
  }),
76
80
  /* @__PURE__ */ u(s, {
77
81
  path: "topics/:id",
78
- element: h(/* @__PURE__ */ u(b, {}), p.topics)
82
+ element: h(/* @__PURE__ */ u(x, {}), p.topics)
79
83
  }),
80
84
  /* @__PURE__ */ u(s, {
81
85
  path: "timeline",
82
- element: h(/* @__PURE__ */ u(C, {}), p.timeline)
86
+ element: h(/* @__PURE__ */ u(w, {}), p.timeline)
83
87
  }),
84
88
  /* @__PURE__ */ u(s, {
85
89
  path: "discussions",
86
- element: h(/* @__PURE__ */ u(x, {}), p.discussions)
90
+ element: h(/* @__PURE__ */ u(S, {}), p.discussions)
87
91
  }),
88
92
  /* @__PURE__ */ u(s, {
89
93
  path: "discussions/:id",
90
- element: h(/* @__PURE__ */ u(S, {}), p.discussions)
94
+ element: h(/* @__PURE__ */ u(C, {}), p.discussions)
91
95
  }),
92
96
  /* @__PURE__ */ u(s, {
93
97
  path: "archive",
94
- element: h(/* @__PURE__ */ u(T, {}), p.archive)
98
+ element: h(/* @__PURE__ */ u(E, {}), p.archive)
95
99
  }),
96
100
  /* @__PURE__ */ u(s, {
97
101
  path: "archive/collections/:id",
98
- element: h(/* @__PURE__ */ u(E, {}), p.archive)
102
+ element: h(/* @__PURE__ */ u(D, {}), p.archive)
99
103
  }),
100
104
  /* @__PURE__ */ u(s, {
101
105
  path: "archive/items/:id",
102
- element: h(/* @__PURE__ */ u(D, {}), p.archive)
106
+ element: h(/* @__PURE__ */ u(O, {}), p.archive)
103
107
  }),
104
108
  /* @__PURE__ */ u(s, {
105
109
  path: "*",
@@ -113,6 +117,6 @@ var g = i(() => import("./pages/stories/StoriesPage.js").then((e) => ({ default:
113
117
  });
114
118
  };
115
119
  //#endregion
116
- export { k as TheCulturePostRoutes };
120
+ export { A as TheCulturePostRoutes };
117
121
 
118
122
  //# sourceMappingURL=TheCulturePostRoutes.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TheCulturePostRoutes.js","names":[],"sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"sourcesContent":["/**\n * TheCulturePost Routes\n * @module theculturepost\n *\n * Domain routes. The editorial home page is eager-loaded (primary landing); all\n * other pages are lazy-loaded. Every route maps to a real `tcp*` backend\n * capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactElement } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useTheCulturePost } from './context/TheCulturePostContext';\nimport { usePageAnalytics } from './hooks/usePageAnalytics';\n\nconst FEATURE = {\n home: 'theculturepost.home',\n overview: 'theculturepost.overview',\n stories: 'theculturepost.stories',\n topics: 'theculturepost.topics',\n timeline: 'theculturepost.timeline',\n discussions: 'theculturepost.discussions',\n archive: 'theculturepost.archive',\n saved: 'theculturepost.saved',\n} as const;\n\nfunction FeatureDisabledFallback(): ReactElement {\n return (\n <div className=\"flex min-h-[400px] flex-col items-center justify-center gap-3 text-text-secondary\">\n <span className=\"text-lg font-semibold text-text-primary\">Feature unavailable</span>\n <span className=\"text-sm\">This page is disabled in your workspace.</span>\n </div>\n );\n}\n\nfunction gated(element: ReactElement, flag: string): ReactElement {\n return (\n <FeatureGate flag={flag} defaultValue fallback={<FeatureDisabledFallback />}>\n {element}\n </FeatureGate>\n );\n}\n\n// Eager — primary landing\nimport { HomePage } from './pages/HomePage';\n\n// Stories\nconst StoriesPage = lazy(() =>\n import('./pages/stories/StoriesPage').then((m) => ({ default: m.StoriesPage }))\n);\nconst StoryDetailPage = lazy(() =>\n import('./pages/stories/StoryDetailPage').then((m) => ({ default: m.StoryDetailPage }))\n);\nconst SavedStoriesPage = lazy(() =>\n import('./pages/stories/SavedStoriesPage').then((m) => ({ default: m.SavedStoriesPage }))\n);\n\n// Topics\nconst TopicsPage = lazy(() =>\n import('./pages/topics/TopicsPage').then((m) => ({ default: m.TopicsPage }))\n);\nconst TopicDetailPage = lazy(() =>\n import('./pages/topics/TopicDetailPage').then((m) => ({ default: m.TopicDetailPage }))\n);\n\n// Discussions\nconst DiscussionsPage = lazy(() =>\n import('./pages/discussions/DiscussionsPage').then((m) => ({ default: m.DiscussionsPage }))\n);\nconst DiscussionDetailPage = lazy(() =>\n import('./pages/discussions/DiscussionDetailPage').then((m) => ({\n default: m.DiscussionDetailPage,\n }))\n);\n\n// Timeline\nconst TimelinePage = lazy(() =>\n import('./pages/timeline/TimelinePage').then((m) => ({ default: m.TimelinePage }))\n);\n\n// Governance / Overview\nconst GovernancePage = lazy(() =>\n import('./pages/governance/GovernancePage').then((m) => ({ default: m.GovernancePage }))\n);\n\n// Archive\nconst ArchivePage = lazy(() =>\n import('./pages/archive/ArchivePage').then((m) => ({ default: m.ArchivePage }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/archive/CollectionDetailPage').then((m) => ({ default: m.CollectionDetailPage }))\n);\nconst ArchiveItemDetailPage = lazy(() =>\n import('./pages/archive/ArchiveItemDetailPage').then((m) => ({\n default: m.ArchiveItemDetailPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheCulturePostRoutes: FC = () => {\n const { basePath, isStandalone } = useTheCulturePost();\n const location = useLocation();\n\n usePageAnalytics();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated(<HomePage />, FEATURE.home)} />\n\n <Route path=\"overview\" element={gated(<GovernancePage />, FEATURE.overview)} />\n\n <Route path=\"stories\" element={gated(<StoriesPage />, FEATURE.stories)} />\n <Route path=\"stories/:id\" element={gated(<StoryDetailPage />, FEATURE.stories)} />\n\n <Route path=\"saved\" element={gated(<SavedStoriesPage />, FEATURE.saved)} />\n\n <Route path=\"topics\" element={gated(<TopicsPage />, FEATURE.topics)} />\n <Route path=\"topics/:id\" element={gated(<TopicDetailPage />, FEATURE.topics)} />\n\n <Route path=\"timeline\" element={gated(<TimelinePage />, FEATURE.timeline)} />\n\n <Route path=\"discussions\" element={gated(<DiscussionsPage />, FEATURE.discussions)} />\n <Route\n path=\"discussions/:id\"\n element={gated(<DiscussionDetailPage />, FEATURE.discussions)}\n />\n\n <Route path=\"archive\" element={gated(<ArchivePage />, FEATURE.archive)} />\n <Route\n path=\"archive/collections/:id\"\n element={gated(<CollectionDetailPage />, FEATURE.archive)}\n />\n <Route\n path=\"archive/items/:id\"\n element={gated(<ArchiveItemDetailPage />, FEATURE.archive)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"TheCulturePostRoutes.js","names":[],"sources":["../../src/theculturepost/TheCulturePostRoutes.tsx"],"sourcesContent":["/**\n * TheCulturePost Routes\n * @module theculturepost\n *\n * Domain routes. The editorial home page is eager-loaded (primary landing); all\n * other pages are lazy-loaded. Every route maps to a real `tcp*` backend\n * capability.\n */\n\nimport { type FC, lazy, Suspense, type ReactElement } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { FeatureGate } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useTheCulturePost } from './context/TheCulturePostContext';\nimport { usePageAnalytics } from './hooks/usePageAnalytics';\n\nconst FEATURE = {\n home: 'theculturepost.home',\n overview: 'theculturepost.overview',\n stories: 'theculturepost.stories',\n topics: 'theculturepost.topics',\n timeline: 'theculturepost.timeline',\n discussions: 'theculturepost.discussions',\n archive: 'theculturepost.archive',\n saved: 'theculturepost.saved',\n} as const;\n\nfunction FeatureDisabledFallback(): ReactElement {\n return (\n <div className=\"flex min-h-[400px] flex-col items-center justify-center gap-3 text-text-secondary\">\n <span className=\"text-lg font-semibold text-text-primary\">Feature unavailable</span>\n <span className=\"text-sm\">This page is disabled in your workspace.</span>\n </div>\n );\n}\n\nfunction gated(element: ReactElement, flag: string): ReactElement {\n return (\n <FeatureGate flag={flag} defaultValue fallback={<FeatureDisabledFallback />}>\n {element}\n </FeatureGate>\n );\n}\n\n// Eager — primary landing\nimport { HomePage } from './pages/HomePage';\n\n// Stories\nconst StoriesPage = lazy(() =>\n import('./pages/stories/StoriesPage').then((m) => ({ default: m.StoriesPage }))\n);\nconst StoryDetailPage = lazy(() =>\n import('./pages/stories/StoryDetailPage').then((m) => ({ default: m.StoryDetailPage }))\n);\nconst StoryCitationsPage = lazy(() =>\n import('./pages/stories/StoryCitationsPage').then((m) => ({ default: m.StoryCitationsPage }))\n);\nconst SavedStoriesPage = lazy(() =>\n import('./pages/stories/SavedStoriesPage').then((m) => ({ default: m.SavedStoriesPage }))\n);\n\n// Topics\nconst TopicsPage = lazy(() =>\n import('./pages/topics/TopicsPage').then((m) => ({ default: m.TopicsPage }))\n);\nconst TopicDetailPage = lazy(() =>\n import('./pages/topics/TopicDetailPage').then((m) => ({ default: m.TopicDetailPage }))\n);\n\n// Discussions\nconst DiscussionsPage = lazy(() =>\n import('./pages/discussions/DiscussionsPage').then((m) => ({ default: m.DiscussionsPage }))\n);\nconst DiscussionDetailPage = lazy(() =>\n import('./pages/discussions/DiscussionDetailPage').then((m) => ({\n default: m.DiscussionDetailPage,\n }))\n);\n\n// Timeline\nconst TimelinePage = lazy(() =>\n import('./pages/timeline/TimelinePage').then((m) => ({ default: m.TimelinePage }))\n);\n\n// Governance / Overview\nconst GovernancePage = lazy(() =>\n import('./pages/governance/GovernancePage').then((m) => ({ default: m.GovernancePage }))\n);\n\n// Archive\nconst ArchivePage = lazy(() =>\n import('./pages/archive/ArchivePage').then((m) => ({ default: m.ArchivePage }))\n);\nconst CollectionDetailPage = lazy(() =>\n import('./pages/archive/CollectionDetailPage').then((m) => ({ default: m.CollectionDetailPage }))\n);\nconst ArchiveItemDetailPage = lazy(() =>\n import('./pages/archive/ArchiveItemDetailPage').then((m) => ({\n default: m.ArchiveItemDetailPage,\n }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheCulturePostRoutes: FC = () => {\n const { basePath, isStandalone } = useTheCulturePost();\n const location = useLocation();\n\n usePageAnalytics();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={gated(<HomePage />, FEATURE.home)} />\n\n <Route path=\"overview\" element={gated(<GovernancePage />, FEATURE.overview)} />\n\n <Route path=\"stories\" element={gated(<StoriesPage />, FEATURE.stories)} />\n <Route path=\"stories/:id\" element={gated(<StoryDetailPage />, FEATURE.stories)} />\n <Route\n path=\"stories/:id/citations\"\n element={gated(<StoryCitationsPage />, FEATURE.stories)}\n />\n\n <Route path=\"saved\" element={gated(<SavedStoriesPage />, FEATURE.saved)} />\n\n <Route path=\"topics\" element={gated(<TopicsPage />, FEATURE.topics)} />\n <Route path=\"topics/:id\" element={gated(<TopicDetailPage />, FEATURE.topics)} />\n\n <Route path=\"timeline\" element={gated(<TimelinePage />, FEATURE.timeline)} />\n\n <Route path=\"discussions\" element={gated(<DiscussionsPage />, FEATURE.discussions)} />\n <Route\n path=\"discussions/:id\"\n element={gated(<DiscussionDetailPage />, FEATURE.discussions)}\n />\n\n <Route path=\"archive\" element={gated(<ArchivePage />, FEATURE.archive)} />\n <Route\n path=\"archive/collections/:id\"\n element={gated(<CollectionDetailPage />, FEATURE.archive)}\n />\n <Route\n path=\"archive/items/:id\"\n element={gated(<ArchiveItemDetailPage />, FEATURE.archive)}\n />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
@@ -1,11 +1,21 @@
1
- import { TcpCitation } from '../types';
1
+ import { TcpCitation, TcpStoryClaim } from '../types';
2
2
 
3
3
  interface AddCitationDialogProps {
4
4
  open: boolean;
5
5
  onOpenChange: (open: boolean) => void;
6
6
  storyId: string;
7
7
  onCreated?: (citation: TcpCitation) => void;
8
+ /**
9
+ * The story's evidence-trail claims. When supplied, the dialog offers a
10
+ * "Supports claim" picker so the new source is linked as it is created.
11
+ */
12
+ claims?: TcpStoryClaim[];
13
+ /**
14
+ * Claim preselected in the picker (e.g. "Add citation" on a claim row).
15
+ * Read on mount only — callers re-key the dialog when it changes.
16
+ */
17
+ defaultClaimId?: string | null;
8
18
  }
9
- export declare function AddCitationDialog({ open, onOpenChange, storyId, onCreated, }: AddCitationDialogProps): import("react/jsx-runtime").JSX.Element;
19
+ export declare function AddCitationDialog({ open, onOpenChange, storyId, onCreated, claims, defaultClaimId, }: AddCitationDialogProps): import("react/jsx-runtime").JSX.Element;
10
20
  export {};
11
21
  //# sourceMappingURL=AddCitationDialog.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AddCitationDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,UAAU,CAAC;AAmB3D,UAAU,sBAAsB;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,GACV,EAAE,sBAAsB,2CAmMxB"}
1
+ {"version":3,"file":"AddCitationDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA0BH,OAAO,KAAK,EAAE,WAAW,EAAiB,aAAa,EAAE,MAAM,UAAU,CAAC;AAyB1E,UAAU,sBAAsB;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,CAAC;IAC5C;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,EAAE,CAAC;IACzB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,MAAM,EACN,cAAqB,GACtB,EAAE,sBAAsB,2CAyNxB"}
@@ -1,16 +1,16 @@
1
1
  import { FILE_FOLDERS as e } from "../hooks/useFiles.js";
2
2
  import { formatEnumLabel as t } from "../utils/formatters.js";
3
- import { useTcpAddCitation as n } from "../hooks/useTcpApi.js";
4
- import { describeError as r, notify as i } from "../lib/toast.js";
3
+ import { useTcpAddCitation as ee } from "../hooks/useTcpApi.js";
4
+ import { describeError as n, notify as r } from "../lib/toast.js";
5
5
  import "../hooks/index.js";
6
- import { FileUploadField as a } from "./FileUploadField.js";
7
- import { sourceTypeIcon as o } from "./CitationList.js";
8
- import { createElement as s, useState as c } from "react";
9
- import { ShieldCheck as l } from "lucide-react";
10
- import { jsx as u, jsxs as d } from "react/jsx-runtime";
11
- import { Button as f, Input as p, Label as m, ResponsiveDialog as h, ResponsiveDialogContent as g, ResponsiveDialogDescription as _, ResponsiveDialogFooter as v, ResponsiveDialogHeader as y, ResponsiveDialogTitle as b, Select as x, SelectContent as S, SelectItem as C, SelectTrigger as w, SelectValue as T, Textarea as E } from "@burdenoff/fe-libs/ui";
6
+ import { FileUploadField as te } from "./FileUploadField.js";
7
+ import { sourceTypeIcon as ne } from "./CitationList.js";
8
+ import { createElement as i, useState as a } from "react";
9
+ import { ShieldCheck as o } from "lucide-react";
10
+ import { jsx as s, jsxs as c } from "react/jsx-runtime";
11
+ import { Button as l, Input as u, Label as d, ResponsiveDialog as re, ResponsiveDialogContent as f, ResponsiveDialogDescription as p, ResponsiveDialogFooter as m, ResponsiveDialogHeader as ie, ResponsiveDialogTitle as h, Select as g, SelectContent as _, SelectItem as v, SelectTrigger as y, SelectValue as b, Textarea as x } from "@burdenoff/fe-libs/ui";
12
12
  //#region src/theculturepost/components/AddCitationDialog.tsx
13
- var D = [
13
+ var S = "__none__", ae = [
14
14
  "WEB",
15
15
  "BOOK",
16
16
  "ACADEMIC",
@@ -19,155 +19,176 @@ var D = [
19
19
  "PRIMARY_DOCUMENT",
20
20
  "ARCHIVAL_RECORD",
21
21
  "ARTIFACT"
22
- ], O = (e) => {
22
+ ], C = (e, t) => e.length > t ? `${e.slice(0, t - 1)}…` : e, w = (e) => {
23
23
  if (!e) return null;
24
24
  let t = new Date(e);
25
25
  return Number.isNaN(t.getTime()) ? null : t.toISOString();
26
26
  };
27
- function k({ open: k, onOpenChange: A, storyId: j, onCreated: M }) {
28
- let N = n(), [P, F] = c(""), [I, L] = c(""), [R, z] = c(""), [B, V] = c(""), [H, U] = c(""), [W, G] = c(""), [K, q] = c(""), [J, Y] = c("WEB"), [X, Z] = c(null), [Q, $] = c(null), ee = () => {
29
- F(""), L(""), z(""), V(""), U(""), G(""), q(""), Y("WEB"), Z(null), $(null);
27
+ function T({ open: T, onOpenChange: E, storyId: D, onCreated: O, claims: k, defaultClaimId: A = null }) {
28
+ let j = ee(), [M, N] = a(""), [P, F] = a(""), [I, L] = a(""), [R, z] = a(""), [B, V] = a(""), [H, U] = a(""), [W, G] = a(""), [K, q] = a("WEB"), [J, Y] = a(null), [X, Z] = a(A ?? S), [Q, $] = a(null), oe = () => {
29
+ N(""), F(""), L(""), z(""), V(""), U(""), G(""), q("WEB"), Y(null), Z(A ?? S), $(null);
30
30
  };
31
- return /* @__PURE__ */ u(h, {
32
- open: k,
33
- onOpenChange: A,
34
- children: /* @__PURE__ */ d(g, {
31
+ return /* @__PURE__ */ s(re, {
32
+ open: T,
33
+ onOpenChange: E,
34
+ children: /* @__PURE__ */ c(f, {
35
35
  className: "sm:max-w-lg",
36
36
  children: [
37
- /* @__PURE__ */ d(y, { children: [/* @__PURE__ */ u(b, { children: "Add a citation" }), /* @__PURE__ */ u(_, { children: "Ground this story in the record with a verifiable source." })] }),
38
- /* @__PURE__ */ d("div", {
37
+ /* @__PURE__ */ c(ie, { children: [/* @__PURE__ */ s(h, { children: "Add a citation" }), /* @__PURE__ */ s(p, { children: "Ground this story in the record with a verifiable source." })] }),
38
+ /* @__PURE__ */ c("div", {
39
39
  className: "flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2",
40
40
  children: [
41
- /* @__PURE__ */ d("div", {
41
+ /* @__PURE__ */ c("div", {
42
42
  className: "grid gap-1.5",
43
- children: [/* @__PURE__ */ d(m, {
43
+ children: [/* @__PURE__ */ c(d, {
44
44
  htmlFor: "cite-title",
45
- children: ["Title ", /* @__PURE__ */ u("span", {
45
+ children: ["Title ", /* @__PURE__ */ s("span", {
46
46
  className: "text-status-error-text",
47
47
  children: "*"
48
48
  })]
49
- }), /* @__PURE__ */ u(p, {
49
+ }), /* @__PURE__ */ s(u, {
50
50
  id: "cite-title",
51
- value: P,
52
- onChange: (e) => F(e.target.value),
51
+ value: M,
52
+ onChange: (e) => N(e.target.value),
53
53
  placeholder: "e.g. The Penguin History of Early India"
54
54
  })]
55
55
  }),
56
- /* @__PURE__ */ d("div", {
56
+ /* @__PURE__ */ c("div", {
57
57
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
58
- children: [/* @__PURE__ */ d("div", {
58
+ children: [/* @__PURE__ */ c("div", {
59
59
  className: "grid gap-1.5",
60
- children: [/* @__PURE__ */ u(m, { children: "Source type" }), /* @__PURE__ */ d(x, {
61
- value: J,
62
- onValueChange: (e) => Y(e),
63
- children: [/* @__PURE__ */ u(w, { children: /* @__PURE__ */ u(T, {}) }), /* @__PURE__ */ u(S, { children: D.map((e) => /* @__PURE__ */ u(C, {
60
+ children: [/* @__PURE__ */ s(d, { children: "Source type" }), /* @__PURE__ */ c(g, {
61
+ value: K,
62
+ onValueChange: (e) => q(e),
63
+ children: [/* @__PURE__ */ s(y, { children: /* @__PURE__ */ s(b, {}) }), /* @__PURE__ */ s(_, { children: ae.map((e) => /* @__PURE__ */ s(v, {
64
64
  value: e,
65
- children: /* @__PURE__ */ d("span", {
65
+ children: /* @__PURE__ */ c("span", {
66
66
  className: "inline-flex items-center gap-2",
67
- children: [s(o(e), { className: "h-3.5 w-3.5 text-text-tertiary" }), t(e)]
67
+ children: [i(ne(e), { className: "h-3.5 w-3.5 text-text-tertiary" }), t(e)]
68
68
  })
69
69
  }, e)) })]
70
70
  })]
71
- }), /* @__PURE__ */ d("div", {
71
+ }), /* @__PURE__ */ c("div", {
72
72
  className: "grid gap-1.5",
73
- children: [/* @__PURE__ */ u(m, {
73
+ children: [/* @__PURE__ */ s(d, {
74
74
  htmlFor: "cite-published",
75
75
  children: "Published on"
76
- }), /* @__PURE__ */ u(p, {
76
+ }), /* @__PURE__ */ s(u, {
77
77
  id: "cite-published",
78
78
  type: "date",
79
- value: B,
80
- onChange: (e) => V(e.target.value)
79
+ value: R,
80
+ onChange: (e) => z(e.target.value)
81
81
  })]
82
82
  })]
83
83
  }),
84
- /* @__PURE__ */ d("div", {
84
+ /* @__PURE__ */ c("div", {
85
85
  className: "grid grid-cols-1 gap-3 sm:grid-cols-2",
86
- children: [/* @__PURE__ */ d("div", {
86
+ children: [/* @__PURE__ */ c("div", {
87
87
  className: "grid gap-1.5",
88
- children: [/* @__PURE__ */ u(m, {
88
+ children: [/* @__PURE__ */ s(d, {
89
89
  htmlFor: "cite-author",
90
90
  children: "Author"
91
- }), /* @__PURE__ */ u(p, {
91
+ }), /* @__PURE__ */ s(u, {
92
92
  id: "cite-author",
93
- value: I,
94
- onChange: (e) => L(e.target.value),
93
+ value: P,
94
+ onChange: (e) => F(e.target.value),
95
95
  placeholder: "e.g. Romila Thapar"
96
96
  })]
97
- }), /* @__PURE__ */ d("div", {
97
+ }), /* @__PURE__ */ c("div", {
98
98
  className: "grid gap-1.5",
99
- children: [/* @__PURE__ */ u(m, {
99
+ children: [/* @__PURE__ */ s(d, {
100
100
  htmlFor: "cite-publisher",
101
101
  children: "Publisher"
102
- }), /* @__PURE__ */ u(p, {
102
+ }), /* @__PURE__ */ s(u, {
103
103
  id: "cite-publisher",
104
- value: R,
105
- onChange: (e) => z(e.target.value),
104
+ value: I,
105
+ onChange: (e) => L(e.target.value),
106
106
  placeholder: "e.g. Penguin Books"
107
107
  })]
108
108
  })]
109
109
  }),
110
- /* @__PURE__ */ d("div", {
110
+ /* @__PURE__ */ c("div", {
111
111
  className: "grid gap-1.5",
112
- children: [/* @__PURE__ */ u(m, {
112
+ children: [/* @__PURE__ */ s(d, {
113
113
  htmlFor: "cite-url",
114
114
  children: "URL"
115
- }), /* @__PURE__ */ u(p, {
115
+ }), /* @__PURE__ */ s(u, {
116
116
  id: "cite-url",
117
117
  type: "url",
118
118
  inputMode: "url",
119
- value: H,
120
- onChange: (e) => U(e.target.value),
119
+ value: B,
120
+ onChange: (e) => V(e.target.value),
121
121
  placeholder: "https://…"
122
122
  })]
123
123
  }),
124
- /* @__PURE__ */ d("div", {
124
+ k && k.length > 0 && /* @__PURE__ */ c("div", {
125
125
  className: "grid gap-1.5",
126
- children: [/* @__PURE__ */ u(m, {
126
+ children: [/* @__PURE__ */ s(d, { children: "Supports claim" }), /* @__PURE__ */ c(g, {
127
+ value: X,
128
+ onValueChange: Z,
129
+ children: [/* @__PURE__ */ s(y, {
130
+ "aria-label": "Supports claim",
131
+ children: /* @__PURE__ */ s(b, {})
132
+ }), /* @__PURE__ */ c(_, { children: [/* @__PURE__ */ s(v, {
133
+ value: S,
134
+ children: "General source (no specific claim)"
135
+ }), k.map((e) => /* @__PURE__ */ c(v, {
136
+ value: e.id,
137
+ children: [
138
+ e.position,
139
+ ". ",
140
+ C(e.text, 70)
141
+ ]
142
+ }, e.id))] })]
143
+ })]
144
+ }),
145
+ /* @__PURE__ */ c("div", {
146
+ className: "grid gap-1.5",
147
+ children: [/* @__PURE__ */ s(d, {
127
148
  htmlFor: "cite-excerpt",
128
149
  children: "Excerpt"
129
- }), /* @__PURE__ */ u(E, {
150
+ }), /* @__PURE__ */ s(x, {
130
151
  id: "cite-excerpt",
131
- value: W,
132
- onChange: (e) => G(e.target.value),
152
+ value: H,
153
+ onChange: (e) => U(e.target.value),
133
154
  placeholder: "A short quoted passage that supports the story.",
134
155
  rows: 2
135
156
  })]
136
157
  }),
137
- /* @__PURE__ */ d("div", {
158
+ /* @__PURE__ */ c("div", {
138
159
  className: "grid gap-1.5",
139
- children: [/* @__PURE__ */ u(m, {
160
+ children: [/* @__PURE__ */ s(d, {
140
161
  htmlFor: "cite-provenance",
141
162
  children: "Provenance"
142
- }), /* @__PURE__ */ u(E, {
163
+ }), /* @__PURE__ */ s(x, {
143
164
  id: "cite-provenance",
144
- value: K,
145
- onChange: (e) => q(e.target.value),
165
+ value: W,
166
+ onChange: (e) => G(e.target.value),
146
167
  placeholder: "Where the source is held, reference numbers, chain of custody…",
147
168
  rows: 2
148
169
  })]
149
170
  }),
150
- /* @__PURE__ */ d("div", {
171
+ /* @__PURE__ */ c("div", {
151
172
  className: "grid gap-1.5",
152
- children: [/* @__PURE__ */ u(m, { children: "Source scan" }), /* @__PURE__ */ u(a, {
173
+ children: [/* @__PURE__ */ s(d, { children: "Source scan" }), /* @__PURE__ */ s(te, {
153
174
  folder: e.artifacts,
154
175
  accept: "image/*,application/pdf",
155
176
  label: "Upload source scan",
156
177
  hint: "A scan of the primary source (optional).",
157
- fileId: X,
158
- onUploaded: Z,
159
- onCleared: () => Z(null)
178
+ fileId: J,
179
+ onUploaded: Y,
180
+ onCleared: () => Y(null)
160
181
  })]
161
182
  }),
162
- /* @__PURE__ */ d("p", {
183
+ /* @__PURE__ */ c("p", {
163
184
  className: "flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary",
164
185
  children: [
165
- /* @__PURE__ */ u(l, {
186
+ /* @__PURE__ */ s(o, {
166
187
  className: "mt-0.5 h-3.5 w-3.5 shrink-0",
167
188
  "aria-hidden": "true"
168
189
  }),
169
190
  "New sources start as ",
170
- /* @__PURE__ */ u("span", {
191
+ /* @__PURE__ */ s("span", {
171
192
  className: "font-medium text-text-secondary",
172
193
  children: "Unverified"
173
194
  }),
@@ -175,41 +196,42 @@ function k({ open: k, onOpenChange: A, storyId: j, onCreated: M }) {
175
196
  "and are reviewed for accuracy, relevance, and cultural sensitivity before verification."
176
197
  ]
177
198
  }),
178
- Q && /* @__PURE__ */ u("p", {
199
+ Q && /* @__PURE__ */ s("p", {
179
200
  className: "text-sm text-status-error-text",
180
201
  children: Q
181
202
  })
182
203
  ]
183
204
  }),
184
- /* @__PURE__ */ d(v, { children: [/* @__PURE__ */ u(f, {
205
+ /* @__PURE__ */ c(m, { children: [/* @__PURE__ */ s(l, {
185
206
  variant: "outline",
186
- onClick: () => A(!1),
207
+ onClick: () => E(!1),
187
208
  children: "Cancel"
188
- }), /* @__PURE__ */ u(f, {
209
+ }), /* @__PURE__ */ s(l, {
189
210
  onClick: async () => {
190
- if (!P.trim()) {
211
+ if (!M.trim()) {
191
212
  $("A citation title is required.");
192
213
  return;
193
214
  }
194
215
  try {
195
- let e = await N.mutateAsync({
196
- storyId: j,
197
- title: P.trim(),
198
- author: I.trim() || null,
199
- publisher: R.trim() || null,
200
- publishedOn: O(B),
201
- url: H.trim() || null,
202
- excerpt: W.trim() || null,
203
- provenance: K.trim() || null,
204
- sourceType: J,
205
- sourceFileId: X
216
+ let e = await j.mutateAsync({
217
+ storyId: D,
218
+ title: M.trim(),
219
+ author: P.trim() || null,
220
+ publisher: I.trim() || null,
221
+ publishedOn: w(R),
222
+ url: B.trim() || null,
223
+ excerpt: H.trim() || null,
224
+ provenance: W.trim() || null,
225
+ sourceType: K,
226
+ sourceFileId: J,
227
+ ...X === S ? {} : { claimId: X }
206
228
  });
207
- i.success("Citation added", e.title), A(!1), ee(), M?.(e);
229
+ r.success("Citation added", e.title), E(!1), oe(), O?.(e);
208
230
  } catch (e) {
209
- $(r(e));
231
+ $(n(e));
210
232
  }
211
233
  },
212
- disabled: N.isPending,
234
+ disabled: j.isPending,
213
235
  children: "Add citation"
214
236
  })] })
215
237
  ]
@@ -217,6 +239,6 @@ function k({ open: k, onOpenChange: A, storyId: j, onCreated: M }) {
217
239
  });
218
240
  }
219
241
  //#endregion
220
- export { k as AddCitationDialog };
242
+ export { T as AddCitationDialog };
221
243
 
222
244
  //# sourceMappingURL=AddCitationDialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AddCitationDialog.js","names":[],"sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"sourcesContent":["/**\n * AddCitationDialog — attach a verifiable source to a story.\n * @module theculturepost/components\n *\n * Writes `tcpAddCitation`. An optional source scan is uploaded to\n * wspace-files-svc (only the id is stored).\n */\n\nimport { createElement, useState } from 'react';\nimport { ShieldCheck } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { FileUploadField } from './FileUploadField';\nimport { sourceTypeIcon } from './CitationList';\nimport { useTcpAddCitation, FILE_FOLDERS } from '../hooks';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpCitation, TcpSourceType } from '../types';\n\nconst SOURCE_TYPES: TcpSourceType[] = [\n 'WEB',\n 'BOOK',\n 'ACADEMIC',\n 'PERIODICAL',\n 'INTERVIEW',\n 'PRIMARY_DOCUMENT',\n 'ARCHIVAL_RECORD',\n 'ARTIFACT',\n];\n\nconst dateToIso = (value: string): string | null => {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n};\n\ninterface AddCitationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n storyId: string;\n onCreated?: (citation: TcpCitation) => void;\n}\n\nexport function AddCitationDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n}: AddCitationDialogProps) {\n const addCitation = useTcpAddCitation();\n const [title, setTitle] = useState('');\n const [author, setAuthor] = useState('');\n const [publisher, setPublisher] = useState('');\n const [publishedOn, setPublishedOn] = useState('');\n const [url, setUrl] = useState('');\n const [excerpt, setExcerpt] = useState('');\n const [provenance, setProvenance] = useState('');\n const [sourceType, setSourceType] = useState<TcpSourceType>('WEB');\n const [sourceFileId, setSourceFileId] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setAuthor('');\n setPublisher('');\n setPublishedOn('');\n setUrl('');\n setExcerpt('');\n setProvenance('');\n setSourceType('WEB');\n setSourceFileId(null);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A citation title is required.');\n return;\n }\n try {\n const created = await addCitation.mutateAsync({\n storyId,\n title: title.trim(),\n author: author.trim() || null,\n publisher: publisher.trim() || null,\n publishedOn: dateToIso(publishedOn),\n url: url.trim() || null,\n excerpt: excerpt.trim() || null,\n provenance: provenance.trim() || null,\n sourceType,\n sourceFileId,\n });\n notify.success('Citation added', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add a citation</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Ground this story in the record with a verifiable source.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Source identity */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-title\">\n Title <span className=\"text-status-error-text\">*</span>\n </Label>\n <Input\n id=\"cite-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Penguin History of Early India\"\n />\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Source type</Label>\n <Select value={sourceType} onValueChange={(v) => setSourceType(v as TcpSourceType)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SOURCE_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n <span className=\"inline-flex items-center gap-2\">\n {createElement(sourceTypeIcon(s), {\n className: 'h-3.5 w-3.5 text-text-tertiary',\n })}\n {formatEnumLabel(s)}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-published\">Published on</Label>\n <Input\n id=\"cite-published\"\n type=\"date\"\n value={publishedOn}\n onChange={(e) => setPublishedOn(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-author\">Author</Label>\n <Input\n id=\"cite-author\"\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder=\"e.g. Romila Thapar\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-publisher\">Publisher</Label>\n <Input\n id=\"cite-publisher\"\n value={publisher}\n onChange={(e) => setPublisher(e.target.value)}\n placeholder=\"e.g. Penguin Books\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-url\">URL</Label>\n <Input\n id=\"cite-url\"\n type=\"url\"\n inputMode=\"url\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n\n {/* Grounding detail */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-excerpt\">Excerpt</Label>\n <Textarea\n id=\"cite-excerpt\"\n value={excerpt}\n onChange={(e) => setExcerpt(e.target.value)}\n placeholder=\"A short quoted passage that supports the story.\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-provenance\">Provenance</Label>\n <Textarea\n id=\"cite-provenance\"\n value={provenance}\n onChange={(e) => setProvenance(e.target.value)}\n placeholder=\"Where the source is held, reference numbers, chain of custody…\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label>Source scan</Label>\n <FileUploadField\n folder={FILE_FOLDERS.artifacts}\n accept=\"image/*,application/pdf\"\n label=\"Upload source scan\"\n hint=\"A scan of the primary source (optional).\"\n fileId={sourceFileId}\n onUploaded={setSourceFileId}\n onCleared={() => setSourceFileId(null)}\n />\n </div>\n\n <p className=\"flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary\">\n <ShieldCheck className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n New sources start as <span className=\"font-medium text-text-secondary\">\n Unverified\n </span>{' '}\n and are reviewed for accuracy, relevance, and cultural sensitivity before verification.\n </p>\n\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 Cancel\n </Button>\n <Button onClick={submit} disabled={addCitation.isPending}>\n Add citation\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AddCitationDialog.js","names":[],"sources":["../../../src/theculturepost/components/AddCitationDialog.tsx"],"sourcesContent":["/**\n * AddCitationDialog — attach a verifiable source to a story.\n * @module theculturepost/components\n *\n * Writes `tcpAddCitation`. An optional source scan is uploaded to\n * wspace-files-svc (only the id is stored).\n */\n\nimport { createElement, useState } from 'react';\nimport { ShieldCheck } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n ResponsiveDialog,\n ResponsiveDialogContent,\n ResponsiveDialogHeader,\n ResponsiveDialogTitle,\n ResponsiveDialogDescription,\n ResponsiveDialogFooter,\n} from '@burdenoff/fe-libs/ui';\nimport { FileUploadField } from './FileUploadField';\nimport { sourceTypeIcon } from './CitationList';\nimport { useTcpAddCitation, FILE_FOLDERS } from '../hooks';\nimport { formatEnumLabel } from '../utils/formatters';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpCitation, TcpSourceType, TcpStoryClaim } from '../types';\n\n/** Sentinel Select value for \"not tied to a specific claim\". */\nconst NO_CLAIM = '__none__';\n\nconst SOURCE_TYPES: TcpSourceType[] = [\n 'WEB',\n 'BOOK',\n 'ACADEMIC',\n 'PERIODICAL',\n 'INTERVIEW',\n 'PRIMARY_DOCUMENT',\n 'ARCHIVAL_RECORD',\n 'ARTIFACT',\n];\n\nconst truncate = (text: string, max: number): string =>\n text.length > max ? `${text.slice(0, max - 1)}…` : text;\n\nconst dateToIso = (value: string): string | null => {\n if (!value) return null;\n const d = new Date(value);\n return Number.isNaN(d.getTime()) ? null : d.toISOString();\n};\n\ninterface AddCitationDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n storyId: string;\n onCreated?: (citation: TcpCitation) => void;\n /**\n * The story's evidence-trail claims. When supplied, the dialog offers a\n * \"Supports claim\" picker so the new source is linked as it is created.\n */\n claims?: TcpStoryClaim[];\n /**\n * Claim preselected in the picker (e.g. \"Add citation\" on a claim row).\n * Read on mount only — callers re-key the dialog when it changes.\n */\n defaultClaimId?: string | null;\n}\n\nexport function AddCitationDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n claims,\n defaultClaimId = null,\n}: AddCitationDialogProps) {\n const addCitation = useTcpAddCitation();\n const [title, setTitle] = useState('');\n const [author, setAuthor] = useState('');\n const [publisher, setPublisher] = useState('');\n const [publishedOn, setPublishedOn] = useState('');\n const [url, setUrl] = useState('');\n const [excerpt, setExcerpt] = useState('');\n const [provenance, setProvenance] = useState('');\n const [sourceType, setSourceType] = useState<TcpSourceType>('WEB');\n const [sourceFileId, setSourceFileId] = useState<string | null>(null);\n const [claimId, setClaimId] = useState<string>(defaultClaimId ?? NO_CLAIM);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setAuthor('');\n setPublisher('');\n setPublishedOn('');\n setUrl('');\n setExcerpt('');\n setProvenance('');\n setSourceType('WEB');\n setSourceFileId(null);\n setClaimId(defaultClaimId ?? NO_CLAIM);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A citation title is required.');\n return;\n }\n try {\n const created = await addCitation.mutateAsync({\n storyId,\n title: title.trim(),\n author: author.trim() || null,\n publisher: publisher.trim() || null,\n publishedOn: dateToIso(publishedOn),\n url: url.trim() || null,\n excerpt: excerpt.trim() || null,\n provenance: provenance.trim() || null,\n sourceType,\n sourceFileId,\n ...(claimId !== NO_CLAIM ? { claimId } : {}),\n });\n notify.success('Citation added', created.title);\n onOpenChange(false);\n reset();\n onCreated?.(created);\n } catch (err) {\n setError(describeError(err));\n }\n };\n\n return (\n <ResponsiveDialog open={open} onOpenChange={onOpenChange}>\n <ResponsiveDialogContent className=\"sm:max-w-lg\">\n <ResponsiveDialogHeader>\n <ResponsiveDialogTitle>Add a citation</ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Ground this story in the record with a verifiable source.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[62vh] flex-col gap-5 overflow-y-auto py-2\">\n {/* Source identity */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-title\">\n Title <span className=\"text-status-error-text\">*</span>\n </Label>\n <Input\n id=\"cite-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. The Penguin History of Early India\"\n />\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label>Source type</Label>\n <Select value={sourceType} onValueChange={(v) => setSourceType(v as TcpSourceType)}>\n <SelectTrigger>\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {SOURCE_TYPES.map((s) => (\n <SelectItem key={s} value={s}>\n <span className=\"inline-flex items-center gap-2\">\n {createElement(sourceTypeIcon(s), {\n className: 'h-3.5 w-3.5 text-text-tertiary',\n })}\n {formatEnumLabel(s)}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-published\">Published on</Label>\n <Input\n id=\"cite-published\"\n type=\"date\"\n value={publishedOn}\n onChange={(e) => setPublishedOn(e.target.value)}\n />\n </div>\n </div>\n <div className=\"grid grid-cols-1 gap-3 sm:grid-cols-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-author\">Author</Label>\n <Input\n id=\"cite-author\"\n value={author}\n onChange={(e) => setAuthor(e.target.value)}\n placeholder=\"e.g. Romila Thapar\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-publisher\">Publisher</Label>\n <Input\n id=\"cite-publisher\"\n value={publisher}\n onChange={(e) => setPublisher(e.target.value)}\n placeholder=\"e.g. Penguin Books\"\n />\n </div>\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-url\">URL</Label>\n <Input\n id=\"cite-url\"\n type=\"url\"\n inputMode=\"url\"\n value={url}\n onChange={(e) => setUrl(e.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n\n {claims && claims.length > 0 && (\n <div className=\"grid gap-1.5\">\n <Label>Supports claim</Label>\n <Select value={claimId} onValueChange={setClaimId}>\n <SelectTrigger aria-label=\"Supports claim\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value={NO_CLAIM}>General source (no specific claim)</SelectItem>\n {claims.map((claim) => (\n <SelectItem key={claim.id} value={claim.id}>\n {claim.position}. {truncate(claim.text, 70)}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n\n {/* Grounding detail */}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-excerpt\">Excerpt</Label>\n <Textarea\n id=\"cite-excerpt\"\n value={excerpt}\n onChange={(e) => setExcerpt(e.target.value)}\n placeholder=\"A short quoted passage that supports the story.\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"cite-provenance\">Provenance</Label>\n <Textarea\n id=\"cite-provenance\"\n value={provenance}\n onChange={(e) => setProvenance(e.target.value)}\n placeholder=\"Where the source is held, reference numbers, chain of custody…\"\n rows={2}\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label>Source scan</Label>\n <FileUploadField\n folder={FILE_FOLDERS.artifacts}\n accept=\"image/*,application/pdf\"\n label=\"Upload source scan\"\n hint=\"A scan of the primary source (optional).\"\n fileId={sourceFileId}\n onUploaded={setSourceFileId}\n onCleared={() => setSourceFileId(null)}\n />\n </div>\n\n <p className=\"flex items-start gap-2 rounded-lg bg-bg-sunken/60 px-3 py-2 text-xs text-text-tertiary\">\n <ShieldCheck className=\"mt-0.5 h-3.5 w-3.5 shrink-0\" aria-hidden=\"true\" />\n New sources start as <span className=\"font-medium text-text-secondary\">\n Unverified\n </span>{' '}\n and are reviewed for accuracy, relevance, and cultural sensitivity before verification.\n </p>\n\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 Cancel\n </Button>\n <Button onClick={submit} disabled={addCitation.isPending}>\n Add citation\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { TcpStoryClaim } from '../types';
2
+
3
+ /** Split a story body into its sentences (trimmed, de-duplicated, bounded). */
4
+ export declare function bodySentences(body: string | null | undefined): string[];
5
+ interface AddClaimDialogProps {
6
+ open: boolean;
7
+ onOpenChange: (open: boolean) => void;
8
+ storyId: string;
9
+ storyBody?: string | null;
10
+ onCreated?: (claim: TcpStoryClaim) => void;
11
+ }
12
+ export declare function AddClaimDialog({ open, onOpenChange, storyId, storyBody, onCreated, }: AddClaimDialogProps): import("react/jsx-runtime").JSX.Element;
13
+ export {};
14
+ //# sourceMappingURL=AddClaimDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AddClaimDialog.d.ts","sourceRoot":"","sources":["../../../src/theculturepost/components/AddClaimDialog.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAsBH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAM9C,+EAA+E;AAC/E,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,EAAE,CAWvE;AAKD,UAAU,mBAAmB;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC5C;AAED,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,SAAS,EACT,SAAS,GACV,EAAE,mBAAmB,2CAgGrB"}