@burdenoff/microfe-theculturepost 2026.1113.1 → 2026.1113.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.
@@ -0,0 +1,22 @@
1
+ /**
2
+ * CommunityNorms — the community norms, shown up front wherever people
3
+ * start or join a conversation (discussions list, discussion detail, and the
4
+ * open-discussion dialog).
5
+ * @module theculturepost/components
6
+ *
7
+ * Product-wide norms from i18n keys (`norms.*`); workspace-editable norms are
8
+ * a post-launch enhancement. Semantic tokens only.
9
+ */
10
+ export interface CommunityNorm {
11
+ key: string;
12
+ fallback: string;
13
+ }
14
+ /** The norms, in display order. Exported so tests can pin the i18n keys. */
15
+ export declare const COMMUNITY_NORMS: readonly CommunityNorm[];
16
+ interface CommunityNormsProps {
17
+ className?: string;
18
+ /** Tighter spacing for dialogs and list headers. */
19
+ compact?: boolean;
20
+ }
21
+ export declare function CommunityNorms({ className, compact }: CommunityNormsProps): import('react').JSX.Element;
22
+ export {};
@@ -0,0 +1,42 @@
1
+ import "../hooks/index.js";
2
+ import { useTr as e } from "../hooks/useTr.js";
3
+ import { cn as t } from "../utils/cn.js";
4
+ import { useId as n } from "react";
5
+ import { HeartHandshake as r } from "lucide-react";
6
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
7
+ // src/theculturepost/components/CommunityNorms.tsx
8
+ var o = [
9
+ {
10
+ key: "norms.respect",
11
+ fallback: "Treat every tradition, faith and community with respect."
12
+ },
13
+ {
14
+ key: "norms.ownVoice",
15
+ fallback: "Speak from your own experience; do not speak for others."
16
+ },
17
+ {
18
+ key: "norms.ideas",
19
+ fallback: "Challenge ideas, never people, and cite sources where you can."
20
+ }
21
+ ];
22
+ function s({ className: s, compact: c = !1 }) {
23
+ let l = e(), u = n();
24
+ return /* @__PURE__ */ a("section", {
25
+ "aria-labelledby": u,
26
+ className: t("rounded-xl border border-border-seam bg-[var(--color-accent-soft)]", c ? "p-3" : "p-4", s),
27
+ children: [/* @__PURE__ */ a("h2", {
28
+ id: u,
29
+ className: "flex items-center gap-2 text-sm font-semibold text-text-primary",
30
+ children: [/* @__PURE__ */ i(r, {
31
+ className: "h-4 w-4 text-accent",
32
+ "aria-hidden": "true"
33
+ }), l("norms.title", "Community norms")]
34
+ }), /* @__PURE__ */ i("ul", {
35
+ className: "mt-2 flex list-disc flex-col gap-1 pl-5 text-sm text-text-secondary",
36
+ children: o.map((e) => /* @__PURE__ */ i("li", { children: l(e.key, e.fallback) }, e.key))
37
+ })]
38
+ });
39
+ }
40
+ export { o as COMMUNITY_NORMS, s as CommunityNorms };
41
+
42
+ //# sourceMappingURL=CommunityNorms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CommunityNorms.js","names":["COMMUNITY_NORMS","CommunityNorms","tr","useTr","titleId","useId","cn","compact","className","HeartHandshake","norm"],"sources":["../../../src/theculturepost/components/CommunityNorms.tsx"],"sourcesContent":["/**\n * CommunityNorms — the community norms, shown up front wherever people\n * start or join a conversation (discussions list, discussion detail, and the\n * open-discussion dialog).\n * @module theculturepost/components\n *\n * Product-wide norms from i18n keys (`norms.*`); workspace-editable norms are\n * a post-launch enhancement. Semantic tokens only.\n */\n\nimport { useId } from 'react';\nimport { HeartHandshake } from 'lucide-react';\nimport { useTr } from '../hooks';\nimport { cn } from '../utils/cn';\n\nexport interface CommunityNorm {\n key: string;\n fallback: string;\n}\n\n/** The norms, in display order. Exported so tests can pin the i18n keys. */\nexport const COMMUNITY_NORMS: readonly CommunityNorm[] = [\n {\n key: 'norms.respect',\n fallback: 'Treat every tradition, faith and community with respect.',\n },\n {\n key: 'norms.ownVoice',\n fallback: 'Speak from your own experience; do not speak for others.',\n },\n {\n key: 'norms.ideas',\n fallback: 'Challenge ideas, never people, and cite sources where you can.',\n },\n];\n\ninterface CommunityNormsProps {\n className?: string;\n /** Tighter spacing for dialogs and list headers. */\n compact?: boolean;\n}\n\nexport function CommunityNorms({ className, compact = false }: CommunityNormsProps) {\n const tr = useTr();\n const titleId = useId();\n return (\n <section\n aria-labelledby={titleId}\n className={cn(\n 'rounded-xl border border-border-seam bg-[var(--color-accent-soft)]',\n compact ? 'p-3' : 'p-4',\n className\n )}\n >\n <h2 id={titleId} className=\"flex items-center gap-2 text-sm font-semibold text-text-primary\">\n <HeartHandshake className=\"h-4 w-4 text-accent\" aria-hidden=\"true\" />\n {tr('norms.title', 'Community norms')}\n </h2>\n <ul className=\"mt-2 flex list-disc flex-col gap-1 pl-5 text-sm text-text-secondary\">\n {COMMUNITY_NORMS.map((norm) => (\n <li key={norm.key}>{tr(norm.key, norm.fallback)}</li>\n ))}\n </ul>\n </section>\n );\n}\n"],"mappings":";;;;;;;AAqBA,IAAaA,IAA4C;CACvD;EACE,KAAK;EACL,UAAU;CACZ;CACA;EACE,KAAK;EACL,UAAU;CACZ;CACA;EACE,KAAK;EACL,UAAU;CACZ;AACF;AAQA,SAAgBC,EAAe,EAAE,cAAW,aAAU,MAA8B;CAClF,IAAMC,IAAKC,EAAM,GACXC,IAAUC,EAAM;CACtB,OACE,kBAAC,WAAD;EACE,mBAAiBD;EACjB,WAAWE,EACT,sEACAC,IAAU,QAAQ,OAClBC,CACF;EANF,UAAA,CAQE,kBAAC,MAAD;GAAI,IAAIJ;GAAS,WAAU;GAA3B,UAAA,CACE,kBAACK,GAAD;IAAgB,WAAU;IAAsB,eAAY;GAAQ,CAAA,GACnEP,EAAG,eAAe,iBAAiB,CAClC;EACJ,CAAA,GAAA,kBAAC,MAAD;GAAI,WAAU;GACX,UAAAF,EAAgB,KAAK,MACpB,kBAAC,MAAD,EAAA,UAAoBE,EAAGQ,EAAK,KAAKA,EAAK,QAAQ,EAAM,GAA3CA,EAAK,GAAsC,CACrD;EACC,CAAA,CACG;;AAEb"}
@@ -1,125 +1,127 @@
1
1
  import { useTcpOpenDiscussion as e, useTcpStories as t } from "../hooks/useTcpApi.js";
2
- import { TagInput as n } from "./TagInput.js";
2
+ import { CommunityNorms as n } from "./CommunityNorms.js";
3
+ import { TagInput as r } from "./TagInput.js";
3
4
  import "../hooks/index.js";
4
- import { describeError as r, notify as i } from "../lib/toast.js";
5
- import { useState as a } from "react";
6
- import { MessagesSquare as o, Plus as s } from "lucide-react";
7
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
8
- import { Button as u, Input as d, Label as f, ResponsiveDialog as p, ResponsiveDialogContent as m, ResponsiveDialogDescription as h, ResponsiveDialogFooter as g, ResponsiveDialogHeader as _, ResponsiveDialogTitle as v, Select as y, SelectContent as b, SelectItem as x, SelectTrigger as S, SelectValue as C, Switch as w, Textarea as T } from "@burdenoff/fe-libs/ui";
5
+ import { describeError as i, notify as a } from "../lib/toast.js";
6
+ import { useState as o } from "react";
7
+ import { MessagesSquare as s, Plus as c } from "lucide-react";
8
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
9
+ import { Button as d, Input as f, Label as p, ResponsiveDialog as m, ResponsiveDialogContent as h, ResponsiveDialogDescription as g, ResponsiveDialogFooter as _, ResponsiveDialogHeader as v, ResponsiveDialogTitle as y, Select as b, SelectContent as x, SelectItem as S, SelectTrigger as C, SelectValue as w, Switch as T, Textarea as E } from "@burdenoff/fe-libs/ui";
9
10
  // src/theculturepost/components/OpenDiscussionDialog.tsx
10
- function E({ open: E, onOpenChange: D, storyId: O, onCreated: k }) {
11
- let A = e(), j = t({
11
+ function D({ open: D, onOpenChange: O, storyId: k, onCreated: A }) {
12
+ let j = e(), M = t({
12
13
  status: "PUBLISHED",
13
14
  pagination: { limit: 100 }
14
- }), [M, N] = a(""), [P, F] = a(""), [I, L] = a(O ?? ""), [R, z] = a(!1), [B, V] = a([]), [H, U] = a(null), W = () => {
15
- N(""), F(""), L(O ?? ""), z(!1), V([]), U(null);
15
+ }), [N, P] = o(""), [F, I] = o(""), [L, R] = o(k ?? ""), [z, B] = o(!1), [V, H] = o([]), [U, W] = o(null), G = () => {
16
+ P(""), I(""), R(k ?? ""), B(!1), H([]), W(null);
16
17
  };
17
- return /* @__PURE__ */ c(p, {
18
- open: E,
19
- onOpenChange: D,
20
- children: /* @__PURE__ */ l(m, {
18
+ return /* @__PURE__ */ l(m, {
19
+ open: D,
20
+ onOpenChange: O,
21
+ children: /* @__PURE__ */ u(h, {
21
22
  className: "sm:max-w-lg",
22
23
  children: [
23
- /* @__PURE__ */ l(_, { children: [/* @__PURE__ */ l(v, {
24
+ /* @__PURE__ */ u(v, { children: [/* @__PURE__ */ u(y, {
24
25
  className: "flex items-center gap-2",
25
- children: [/* @__PURE__ */ c(o, {
26
+ children: [/* @__PURE__ */ l(s, {
26
27
  className: "h-5 w-5 text-accent",
27
28
  "aria-hidden": "true"
28
29
  }), " Open a discussion"]
29
- }), /* @__PURE__ */ c(h, { children: "Start a respectful conversation. Replies are moderated to keep the space welcoming." })] }),
30
- /* @__PURE__ */ l("div", {
30
+ }), /* @__PURE__ */ l(g, { children: "Start a respectful conversation. Replies are moderated to keep the space welcoming." })] }),
31
+ /* @__PURE__ */ u("div", {
31
32
  className: "flex max-h-[60vh] flex-col gap-4 overflow-y-auto py-2",
32
33
  children: [
33
- /* @__PURE__ */ l("div", {
34
+ /* @__PURE__ */ l(n, { compact: !0 }),
35
+ /* @__PURE__ */ u("div", {
34
36
  className: "grid gap-1.5",
35
- children: [/* @__PURE__ */ c(f, {
37
+ children: [/* @__PURE__ */ l(p, {
36
38
  htmlFor: "discussion-title",
37
39
  children: "Title"
38
- }), /* @__PURE__ */ c(d, {
40
+ }), /* @__PURE__ */ l(f, {
39
41
  id: "discussion-title",
40
- value: M,
41
- onChange: (e) => N(e.target.value),
42
+ value: N,
43
+ onChange: (e) => P(e.target.value),
42
44
  placeholder: "e.g. How do communities keep oral traditions alive?"
43
45
  })]
44
46
  }),
45
- /* @__PURE__ */ l("div", {
47
+ /* @__PURE__ */ u("div", {
46
48
  className: "grid gap-1.5",
47
- children: [/* @__PURE__ */ c(f, {
49
+ children: [/* @__PURE__ */ l(p, {
48
50
  htmlFor: "discussion-prompt",
49
51
  children: "Prompt"
50
- }), /* @__PURE__ */ c(T, {
52
+ }), /* @__PURE__ */ l(E, {
51
53
  id: "discussion-prompt",
52
- value: P,
53
- onChange: (e) => F(e.target.value),
54
+ value: F,
55
+ onChange: (e) => I(e.target.value),
54
56
  placeholder: "Set the context and invite perspectives.",
55
57
  rows: 3
56
58
  })]
57
59
  }),
58
- !O && /* @__PURE__ */ l("div", {
60
+ !k && /* @__PURE__ */ u("div", {
59
61
  className: "grid gap-1.5",
60
- children: [/* @__PURE__ */ c(f, { children: "Linked story" }), /* @__PURE__ */ l(y, {
61
- value: I,
62
- onValueChange: L,
63
- children: [/* @__PURE__ */ c(S, { children: /* @__PURE__ */ c(C, { placeholder: "Anchor to a story (optional)" }) }), /* @__PURE__ */ c(b, { children: (j.data?.items ?? []).map((e) => /* @__PURE__ */ c(x, {
62
+ children: [/* @__PURE__ */ l(p, { children: "Linked story" }), /* @__PURE__ */ u(b, {
63
+ value: L,
64
+ onValueChange: R,
65
+ children: [/* @__PURE__ */ l(C, { children: /* @__PURE__ */ l(w, { placeholder: "Anchor to a story (optional)" }) }), /* @__PURE__ */ l(x, { children: (M.data?.items ?? []).map((e) => /* @__PURE__ */ l(S, {
64
66
  value: e.id,
65
67
  children: e.title
66
68
  }, e.id)) })]
67
69
  })]
68
70
  }),
69
- /* @__PURE__ */ l("div", {
71
+ /* @__PURE__ */ u("div", {
70
72
  className: "grid gap-1.5",
71
- children: [/* @__PURE__ */ c(f, {
73
+ children: [/* @__PURE__ */ l(p, {
72
74
  htmlFor: "discussion-tags",
73
75
  children: "Tags"
74
- }), /* @__PURE__ */ c(n, {
76
+ }), /* @__PURE__ */ l(r, {
75
77
  id: "discussion-tags",
76
- value: B,
77
- onChange: V,
78
+ value: V,
79
+ onChange: H,
78
80
  placeholder: "Add tags…"
79
81
  })]
80
82
  }),
81
- /* @__PURE__ */ l("label", {
83
+ /* @__PURE__ */ u("label", {
82
84
  className: "flex items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-surface px-4 py-3",
83
- children: [/* @__PURE__ */ l("span", { children: [/* @__PURE__ */ c("span", {
85
+ children: [/* @__PURE__ */ u("span", { children: [/* @__PURE__ */ l("span", {
84
86
  className: "block text-sm font-medium text-text-primary",
85
87
  children: "Interfaith space"
86
- }), /* @__PURE__ */ c("span", {
88
+ }), /* @__PURE__ */ l("span", {
87
89
  className: "block text-xs text-text-secondary",
88
90
  children: "Signals that perspectives from many traditions are welcome."
89
- })] }), /* @__PURE__ */ c(w, {
90
- checked: R,
91
- onCheckedChange: z,
91
+ })] }), /* @__PURE__ */ l(T, {
92
+ checked: z,
93
+ onCheckedChange: B,
92
94
  "aria-label": "Interfaith discussion"
93
95
  })]
94
96
  }),
95
- H && /* @__PURE__ */ c("p", {
97
+ U && /* @__PURE__ */ l("p", {
96
98
  className: "text-sm text-status-error-text",
97
- children: H
99
+ children: U
98
100
  })
99
101
  ]
100
102
  }),
101
- /* @__PURE__ */ l(g, { children: [/* @__PURE__ */ c(u, {
103
+ /* @__PURE__ */ u(_, { children: [/* @__PURE__ */ l(d, {
102
104
  variant: "outline",
103
- onClick: () => D(!1),
105
+ onClick: () => O(!1),
104
106
  children: "Cancel"
105
- }), /* @__PURE__ */ l(u, {
107
+ }), /* @__PURE__ */ u(d, {
106
108
  onClick: async () => {
107
- if (!M.trim()) U("A title is required.");
109
+ if (!N.trim()) W("A title is required.");
108
110
  else try {
109
- let e = await A.mutateAsync({
110
- title: M.trim(),
111
- prompt: P.trim() || null,
112
- storyId: I || null,
113
- isInterfaith: R,
114
- tags: B.length ? B : null
111
+ let e = await j.mutateAsync({
112
+ title: N.trim(),
113
+ prompt: F.trim() || null,
114
+ storyId: L || null,
115
+ isInterfaith: z,
116
+ tags: V.length ? V : null
115
117
  });
116
- i.success("Discussion opened", e.title), D(!1), W(), k?.(e);
118
+ a.success("Discussion opened", e.title), O(!1), G(), A?.(e);
117
119
  } catch (e) {
118
- U(r(e));
120
+ W(i(e));
119
121
  }
120
122
  },
121
- disabled: A.isPending,
122
- children: [/* @__PURE__ */ c(s, {
123
+ disabled: j.isPending,
124
+ children: [/* @__PURE__ */ l(c, {
123
125
  className: "mr-1.5 h-4 w-4",
124
126
  "aria-hidden": "true"
125
127
  }), " Open discussion"]
@@ -128,6 +130,6 @@ function E({ open: E, onOpenChange: D, storyId: O, onCreated: k }) {
128
130
  })
129
131
  });
130
132
  }
131
- export { E as OpenDiscussionDialog };
133
+ export { D as OpenDiscussionDialog };
132
134
 
133
135
  //# sourceMappingURL=OpenDiscussionDialog.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OpenDiscussionDialog.js","names":["OpenDiscussionDialog","openDiscussion","useTcpOpenDiscussion","storiesQuery","useTcpStories","title","setTitle","useState","prompt","setPrompt","pickedStory","setPickedStory","storyId","isInterfaith","setIsInterfaith","tags","setTags","error","setError","reset","ResponsiveDialog","ResponsiveDialogContent","ResponsiveDialogHeader","ResponsiveDialogTitle","MessagesSquare","ResponsiveDialogDescription","Label","Input","Textarea","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","story","TagInput","Switch","ResponsiveDialogFooter","Button","onOpenChange","created","notify","onCreated","err","describeError","Plus"],"sources":["../../../src/theculturepost/components/OpenDiscussionDialog.tsx"],"sourcesContent":["/**\n * OpenDiscussionDialog — open a new community discussion.\n * @module theculturepost/components\n *\n * Writes `tcpOpenDiscussion`. An optional interfaith flag marks the space as one\n * that welcomes multiple traditions; an optional story link anchors the thread.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Switch,\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 { TagInput } from './TagInput';\nimport { useTcpOpenDiscussion, useTcpStories } from '../hooks';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpDiscussion } from '../types';\n\ninterface OpenDiscussionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Anchor the discussion to a story (e.g. from a story detail page). */\n storyId?: string;\n onCreated?: (discussion: TcpDiscussion) => void;\n}\n\nexport function OpenDiscussionDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n}: OpenDiscussionDialogProps) {\n const openDiscussion = useTcpOpenDiscussion();\n const storiesQuery = useTcpStories({ status: 'PUBLISHED', pagination: { limit: 100 } });\n\n const [title, setTitle] = useState('');\n const [prompt, setPrompt] = useState('');\n const [pickedStory, setPickedStory] = useState(storyId ?? '');\n const [isInterfaith, setIsInterfaith] = useState(false);\n const [tags, setTags] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setPrompt('');\n setPickedStory(storyId ?? '');\n setIsInterfaith(false);\n setTags([]);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A title is required.');\n return;\n }\n try {\n const created = await openDiscussion.mutateAsync({\n title: title.trim(),\n prompt: prompt.trim() || null,\n storyId: pickedStory || null,\n isInterfaith,\n tags: tags.length ? tags : null,\n });\n notify.success('Discussion opened', 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 className=\"flex items-center gap-2\">\n <MessagesSquare className=\"h-5 w-5 text-accent\" aria-hidden=\"true\" /> Open a discussion\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Start a respectful conversation. Replies are moderated to keep the space welcoming.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[60vh] flex-col gap-4 overflow-y-auto py-2\">\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-title\">Title</Label>\n <Input\n id=\"discussion-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. How do communities keep oral traditions alive?\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-prompt\">Prompt</Label>\n <Textarea\n id=\"discussion-prompt\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder=\"Set the context and invite perspectives.\"\n rows={3}\n />\n </div>\n {!storyId && (\n <div className=\"grid gap-1.5\">\n <Label>Linked story</Label>\n <Select value={pickedStory} onValueChange={setPickedStory}>\n <SelectTrigger>\n <SelectValue placeholder=\"Anchor to a story (optional)\" />\n </SelectTrigger>\n <SelectContent>\n {(storiesQuery.data?.items ?? []).map((story) => (\n <SelectItem key={story.id} value={story.id}>\n {story.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-tags\">Tags</Label>\n <TagInput\n id=\"discussion-tags\"\n value={tags}\n onChange={setTags}\n placeholder=\"Add tags…\"\n />\n </div>\n <label className=\"flex items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-surface px-4 py-3\">\n <span>\n <span className=\"block text-sm font-medium text-text-primary\">Interfaith space</span>\n <span className=\"block text-xs text-text-secondary\">\n Signals that perspectives from many traditions are welcome.\n </span>\n </span>\n <Switch\n checked={isInterfaith}\n onCheckedChange={setIsInterfaith}\n aria-label=\"Interfaith discussion\"\n />\n </label>\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={openDiscussion.isPending}>\n <Plus className=\"mr-1.5 h-4 w-4\" aria-hidden=\"true\" /> Open discussion\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"OpenDiscussionDialog.js","names":["OpenDiscussionDialog","openDiscussion","useTcpOpenDiscussion","storiesQuery","useTcpStories","title","setTitle","useState","prompt","setPrompt","pickedStory","setPickedStory","storyId","isInterfaith","setIsInterfaith","tags","setTags","error","setError","reset","ResponsiveDialog","ResponsiveDialogContent","ResponsiveDialogHeader","ResponsiveDialogTitle","MessagesSquare","ResponsiveDialogDescription","CommunityNorms","Label","Input","Textarea","Select","SelectTrigger","SelectValue","SelectContent","SelectItem","story","TagInput","Switch","ResponsiveDialogFooter","Button","onOpenChange","created","notify","onCreated","err","describeError","Plus"],"sources":["../../../src/theculturepost/components/OpenDiscussionDialog.tsx"],"sourcesContent":["/**\n * OpenDiscussionDialog — open a new community discussion.\n * @module theculturepost/components\n *\n * Writes `tcpOpenDiscussion`. An optional interfaith flag marks the space as one\n * that welcomes multiple traditions; an optional story link anchors the thread.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus } from 'lucide-react';\nimport {\n Button,\n Input,\n Label,\n Textarea,\n Switch,\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 { CommunityNorms } from './CommunityNorms';\nimport { TagInput } from './TagInput';\nimport { useTcpOpenDiscussion, useTcpStories } from '../hooks';\nimport { notify, describeError } from '../lib/toast';\nimport type { TcpDiscussion } from '../types';\n\ninterface OpenDiscussionDialogProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Anchor the discussion to a story (e.g. from a story detail page). */\n storyId?: string;\n onCreated?: (discussion: TcpDiscussion) => void;\n}\n\nexport function OpenDiscussionDialog({\n open,\n onOpenChange,\n storyId,\n onCreated,\n}: OpenDiscussionDialogProps) {\n const openDiscussion = useTcpOpenDiscussion();\n const storiesQuery = useTcpStories({ status: 'PUBLISHED', pagination: { limit: 100 } });\n\n const [title, setTitle] = useState('');\n const [prompt, setPrompt] = useState('');\n const [pickedStory, setPickedStory] = useState(storyId ?? '');\n const [isInterfaith, setIsInterfaith] = useState(false);\n const [tags, setTags] = useState<string[]>([]);\n const [error, setError] = useState<string | null>(null);\n\n const reset = () => {\n setTitle('');\n setPrompt('');\n setPickedStory(storyId ?? '');\n setIsInterfaith(false);\n setTags([]);\n setError(null);\n };\n\n const submit = async () => {\n if (!title.trim()) {\n setError('A title is required.');\n return;\n }\n try {\n const created = await openDiscussion.mutateAsync({\n title: title.trim(),\n prompt: prompt.trim() || null,\n storyId: pickedStory || null,\n isInterfaith,\n tags: tags.length ? tags : null,\n });\n notify.success('Discussion opened', 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 className=\"flex items-center gap-2\">\n <MessagesSquare className=\"h-5 w-5 text-accent\" aria-hidden=\"true\" /> Open a discussion\n </ResponsiveDialogTitle>\n <ResponsiveDialogDescription>\n Start a respectful conversation. Replies are moderated to keep the space welcoming.\n </ResponsiveDialogDescription>\n </ResponsiveDialogHeader>\n\n <div className=\"flex max-h-[60vh] flex-col gap-4 overflow-y-auto py-2\">\n <CommunityNorms compact />\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-title\">Title</Label>\n <Input\n id=\"discussion-title\"\n value={title}\n onChange={(e) => setTitle(e.target.value)}\n placeholder=\"e.g. How do communities keep oral traditions alive?\"\n />\n </div>\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-prompt\">Prompt</Label>\n <Textarea\n id=\"discussion-prompt\"\n value={prompt}\n onChange={(e) => setPrompt(e.target.value)}\n placeholder=\"Set the context and invite perspectives.\"\n rows={3}\n />\n </div>\n {!storyId && (\n <div className=\"grid gap-1.5\">\n <Label>Linked story</Label>\n <Select value={pickedStory} onValueChange={setPickedStory}>\n <SelectTrigger>\n <SelectValue placeholder=\"Anchor to a story (optional)\" />\n </SelectTrigger>\n <SelectContent>\n {(storiesQuery.data?.items ?? []).map((story) => (\n <SelectItem key={story.id} value={story.id}>\n {story.title}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n )}\n <div className=\"grid gap-1.5\">\n <Label htmlFor=\"discussion-tags\">Tags</Label>\n <TagInput\n id=\"discussion-tags\"\n value={tags}\n onChange={setTags}\n placeholder=\"Add tags…\"\n />\n </div>\n <label className=\"flex items-center justify-between gap-3 rounded-xl border border-border-seam bg-bg-surface px-4 py-3\">\n <span>\n <span className=\"block text-sm font-medium text-text-primary\">Interfaith space</span>\n <span className=\"block text-xs text-text-secondary\">\n Signals that perspectives from many traditions are welcome.\n </span>\n </span>\n <Switch\n checked={isInterfaith}\n onCheckedChange={setIsInterfaith}\n aria-label=\"Interfaith discussion\"\n />\n </label>\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={openDiscussion.isPending}>\n <Plus className=\"mr-1.5 h-4 w-4\" aria-hidden=\"true\" /> Open discussion\n </Button>\n </ResponsiveDialogFooter>\n </ResponsiveDialogContent>\n </ResponsiveDialog>\n );\n}\n"],"mappings":"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"}
@@ -9,190 +9,195 @@ import "../../hooks/index.js";
9
9
  import "../../context/index.js";
10
10
  import { formatNumber as l, formatRelativeTime as u } from "../../utils/formatters.js";
11
11
  import { describeError as d, notify as f } from "../../lib/toast.js";
12
- import { impact as p, nativeConfirm as m } from "../../utils/nativeBridge.js";
13
- import { ArrowLeft as h, BookOpen as g, CheckCircle2 as _, Clock as v, ExternalLink as y, Flag as b, HeartHandshake as x, Lock as S, MessagesSquare as C, Quote as w, Trash2 as T, Unlock as E } from "lucide-react";
14
- import { useParams as D } from "react-router";
15
- import { Fragment as O, jsx as k, jsxs as A } from "react/jsx-runtime";
16
- import { Button as j, GlassCard as M } from "@burdenoff/fe-libs/ui";
12
+ import { CommunityNorms as p } from "../../components/CommunityNorms.js";
13
+ import { impact as m, nativeConfirm as h } from "../../utils/nativeBridge.js";
14
+ import { ArrowLeft as g, BookOpen as _, CheckCircle2 as v, Clock as y, ExternalLink as b, Flag as x, HeartHandshake as S, Lock as C, MessagesSquare as w, Quote as T, Trash2 as E, Unlock as D } from "lucide-react";
15
+ import { useParams as O } from "react-router";
16
+ import { Fragment as k, jsx as A, jsxs as j } from "react/jsx-runtime";
17
+ import { Button as M, GlassCard as N } from "@burdenoff/fe-libs/ui";
17
18
  // src/theculturepost/pages/discussions/DiscussionDetailPage.tsx
18
- function N(e) {
19
+ function P(e) {
19
20
  let t = "h-3 w-3";
20
21
  switch (e) {
21
- case "APPROVED": return /* @__PURE__ */ k(_, {
22
+ case "APPROVED": return /* @__PURE__ */ A(v, {
22
23
  className: t,
23
24
  "aria-hidden": "true"
24
25
  });
25
- case "PENDING": return /* @__PURE__ */ k(v, {
26
+ case "PENDING": return /* @__PURE__ */ A(y, {
26
27
  className: t,
27
28
  "aria-hidden": "true"
28
29
  });
29
- case "FLAGGED": return /* @__PURE__ */ k(b, {
30
+ case "FLAGGED": return /* @__PURE__ */ A(x, {
30
31
  className: t,
31
32
  "aria-hidden": "true"
32
33
  });
33
- case "REMOVED": return /* @__PURE__ */ k(T, {
34
+ case "REMOVED": return /* @__PURE__ */ A(E, {
34
35
  className: t,
35
36
  "aria-hidden": "true"
36
37
  });
37
38
  }
38
39
  }
39
- function P() {
40
- let { id: _ } = D(), { navigateTo: v } = e(), { data: b, isLoading: T, isError: P, refetch: F } = s(_), I = c(), L = /* @__PURE__ */ A(j, {
40
+ function F() {
41
+ let { id: v } = O(), { navigateTo: y } = e(), { data: x, isLoading: E, isError: F, refetch: I } = s(v), L = c(), R = /* @__PURE__ */ j(M, {
41
42
  variant: "ghost",
42
43
  size: "sm",
43
- onClick: () => v("discussions"),
44
- children: [/* @__PURE__ */ k(h, { className: "mr-1.5 h-4 w-4" }), " Back"]
44
+ onClick: () => y("discussions"),
45
+ children: [/* @__PURE__ */ A(g, { className: "mr-1.5 h-4 w-4" }), " Back"]
45
46
  });
46
- return T ? /* @__PURE__ */ k(t, {
47
+ return E ? /* @__PURE__ */ A(t, {
47
48
  title: "Discussion",
48
- actions: L,
49
- children: /* @__PURE__ */ k(o, { label: "Loading discussion…" })
50
- }) : P || !b ? /* @__PURE__ */ k(t, {
49
+ actions: R,
50
+ children: /* @__PURE__ */ A(o, { label: "Loading discussion…" })
51
+ }) : F || !x ? /* @__PURE__ */ A(t, {
51
52
  title: "Discussion",
52
- actions: L,
53
- children: /* @__PURE__ */ k(a, {
53
+ actions: R,
54
+ children: /* @__PURE__ */ A(a, {
54
55
  title: "Discussion not found",
55
56
  message: "This discussion may have been removed, or you may not have access.",
56
- onRetry: () => F()
57
+ onRetry: () => I()
57
58
  })
58
- }) : /* @__PURE__ */ k(t, {
59
+ }) : /* @__PURE__ */ A(t, {
59
60
  title: "Discussion",
60
- actions: L,
61
- children: /* @__PURE__ */ A("div", {
61
+ actions: R,
62
+ children: /* @__PURE__ */ j("div", {
62
63
  className: "mx-auto flex max-w-3xl flex-col gap-6",
63
- children: [/* @__PURE__ */ A(M, {
64
- treatment: "plain",
65
- className: "flex flex-col gap-4 p-5 sm:p-6",
66
- children: [
67
- /* @__PURE__ */ A("div", {
68
- className: "flex items-start justify-between gap-3",
69
- children: [/* @__PURE__ */ k("h1", {
70
- className: "font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl",
71
- children: b.title
72
- }), /* @__PURE__ */ k(j, {
73
- variant: "outline",
74
- size: "sm",
75
- onClick: async () => {
76
- await p("light");
77
- let e = b.isLocked ? "unlock" : "lock";
78
- if (await m({
79
- title: `${e === "lock" ? "Lock" : "Unlock"} discussion`,
80
- message: `Are you sure you want to ${e} this discussion?`,
81
- okButtonTitle: e === "lock" ? "Lock" : "Unlock",
82
- cancelButtonTitle: "Cancel"
83
- })) try {
84
- await I.mutateAsync(b.id), f.success(b.isLocked ? "Discussion unlocked" : "Discussion locked");
85
- } catch (e) {
86
- f.error("Could not update the discussion", d(e));
87
- }
88
- },
89
- disabled: I.isPending,
90
- className: "shrink-0",
91
- children: b.isLocked ? /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(E, { className: "mr-1.5 h-4 w-4" }), " Unlock"] }) : /* @__PURE__ */ A(O, { children: [/* @__PURE__ */ k(S, { className: "mr-1.5 h-4 w-4" }), " Lock"] })
92
- })]
93
- }),
94
- /* @__PURE__ */ A("div", {
95
- className: "flex flex-wrap items-center gap-x-4 gap-y-2",
96
- children: [/* @__PURE__ */ A("div", {
97
- className: "flex flex-wrap items-center gap-1.5",
64
+ children: [
65
+ /* @__PURE__ */ j(N, {
66
+ treatment: "plain",
67
+ className: "flex flex-col gap-4 p-5 sm:p-6",
68
+ children: [
69
+ /* @__PURE__ */ j("div", {
70
+ className: "flex items-start justify-between gap-3",
71
+ children: [/* @__PURE__ */ A("h1", {
72
+ className: "font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl",
73
+ children: x.title
74
+ }), /* @__PURE__ */ A(M, {
75
+ variant: "outline",
76
+ size: "sm",
77
+ onClick: async () => {
78
+ await m("light");
79
+ let e = x.isLocked ? "unlock" : "lock";
80
+ if (await h({
81
+ title: `${e === "lock" ? "Lock" : "Unlock"} discussion`,
82
+ message: `Are you sure you want to ${e} this discussion?`,
83
+ okButtonTitle: e === "lock" ? "Lock" : "Unlock",
84
+ cancelButtonTitle: "Cancel"
85
+ })) try {
86
+ await L.mutateAsync(x.id), f.success(x.isLocked ? "Discussion unlocked" : "Discussion locked");
87
+ } catch (e) {
88
+ f.error("Could not update the discussion", d(e));
89
+ }
90
+ },
91
+ disabled: L.isPending,
92
+ className: "shrink-0",
93
+ children: x.isLocked ? /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(D, { className: "mr-1.5 h-4 w-4" }), " Unlock"] }) : /* @__PURE__ */ j(k, { children: [/* @__PURE__ */ A(C, { className: "mr-1.5 h-4 w-4" }), " Lock"] })
94
+ })]
95
+ }),
96
+ /* @__PURE__ */ j("div", {
97
+ className: "flex flex-wrap items-center gap-x-4 gap-y-2",
98
+ children: [/* @__PURE__ */ j("div", {
99
+ className: "flex flex-wrap items-center gap-1.5",
100
+ children: [
101
+ /* @__PURE__ */ A(n, {
102
+ status: x.status,
103
+ icon: P(x.status)
104
+ }),
105
+ x.isInterfaith && /* @__PURE__ */ j("span", {
106
+ className: "inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary",
107
+ children: [/* @__PURE__ */ A(S, {
108
+ className: "h-3 w-3",
109
+ "aria-hidden": "true"
110
+ }), " Interfaith"]
111
+ }),
112
+ x.isLocked && /* @__PURE__ */ j("span", {
113
+ className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
114
+ children: [/* @__PURE__ */ A(C, {
115
+ className: "h-3 w-3",
116
+ "aria-hidden": "true"
117
+ }), " Locked"]
118
+ })
119
+ ]
120
+ }), x.tags.length > 0 && /* @__PURE__ */ A("div", {
121
+ className: "flex flex-wrap items-center gap-1.5 sm:ml-auto",
122
+ children: x.tags.map((e) => /* @__PURE__ */ j("span", {
123
+ className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
124
+ children: ["#", e]
125
+ }, e))
126
+ })]
127
+ }),
128
+ /* @__PURE__ */ j("div", {
129
+ className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary",
98
130
  children: [
99
- /* @__PURE__ */ k(n, {
100
- status: b.status,
101
- icon: N(b.status)
131
+ /* @__PURE__ */ A(r, {
132
+ actorId: x.openedById,
133
+ prefix: "Opened by"
102
134
  }),
103
- b.isInterfaith && /* @__PURE__ */ A("span", {
104
- className: "inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary",
105
- children: [/* @__PURE__ */ k(x, {
106
- className: "h-3 w-3",
107
- "aria-hidden": "true"
108
- }), " Interfaith"]
135
+ /* @__PURE__ */ A("span", {
136
+ "aria-hidden": "true",
137
+ children: "·"
109
138
  }),
110
- b.isLocked && /* @__PURE__ */ A("span", {
111
- className: "inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
112
- children: [/* @__PURE__ */ k(S, {
113
- className: "h-3 w-3",
114
- "aria-hidden": "true"
115
- }), " Locked"]
116
- })
139
+ /* @__PURE__ */ j("span", {
140
+ className: "inline-flex items-center gap-1",
141
+ children: [
142
+ /* @__PURE__ */ A(w, {
143
+ className: "h-3.5 w-3.5",
144
+ "aria-hidden": "true"
145
+ }),
146
+ l(x.replyCount),
147
+ " ",
148
+ x.replyCount === 1 ? "reply" : "replies"
149
+ ]
150
+ }),
151
+ /* @__PURE__ */ A("span", {
152
+ "aria-hidden": "true",
153
+ children: "·"
154
+ }),
155
+ /* @__PURE__ */ j("span", { children: ["Started ", u(x.createdAt)] })
117
156
  ]
118
- }), b.tags.length > 0 && /* @__PURE__ */ k("div", {
119
- className: "flex flex-wrap items-center gap-1.5 sm:ml-auto",
120
- children: b.tags.map((e) => /* @__PURE__ */ A("span", {
121
- className: "rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary",
122
- children: ["#", e]
123
- }, e))
124
- })]
125
- }),
126
- /* @__PURE__ */ A("div", {
127
- className: "flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary",
128
- children: [
129
- /* @__PURE__ */ k(r, {
130
- actorId: b.openedById,
131
- prefix: "Opened by"
132
- }),
133
- /* @__PURE__ */ k("span", {
134
- "aria-hidden": "true",
135
- children: "·"
136
- }),
137
- /* @__PURE__ */ A("span", {
138
- className: "inline-flex items-center gap-1",
157
+ }),
158
+ (x.prompt || x.storyId) && /* @__PURE__ */ j("div", {
159
+ className: "flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between",
160
+ children: [x.prompt ? /* @__PURE__ */ j("div", {
161
+ className: "flex min-w-0 items-start gap-3",
162
+ children: [/* @__PURE__ */ A("span", {
163
+ className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent",
164
+ "aria-hidden": "true",
165
+ children: /* @__PURE__ */ A(T, { className: "h-4 w-4" })
166
+ }), /* @__PURE__ */ A("p", {
167
+ className: "min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary",
168
+ children: x.prompt
169
+ })]
170
+ }) : /* @__PURE__ */ A("span", {
171
+ className: "text-sm text-text-secondary",
172
+ children: "Anchored to a story."
173
+ }), x.storyId && /* @__PURE__ */ j("button", {
174
+ type: "button",
175
+ onClick: () => y(`stories/${x.storyId}`),
176
+ className: "inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline",
139
177
  children: [
140
- /* @__PURE__ */ k(C, {
141
- className: "h-3.5 w-3.5",
178
+ /* @__PURE__ */ A(_, {
179
+ className: "h-4 w-4",
142
180
  "aria-hidden": "true"
143
181
  }),
144
- l(b.replyCount),
145
- " ",
146
- b.replyCount === 1 ? "reply" : "replies"
182
+ " View linked story",
183
+ /* @__PURE__ */ A(b, {
184
+ className: "h-3.5 w-3.5",
185
+ "aria-hidden": "true"
186
+ })
147
187
  ]
148
- }),
149
- /* @__PURE__ */ k("span", {
150
- "aria-hidden": "true",
151
- children: "·"
152
- }),
153
- /* @__PURE__ */ A("span", { children: ["Started ", u(b.createdAt)] })
154
- ]
155
- }),
156
- (b.prompt || b.storyId) && /* @__PURE__ */ A("div", {
157
- className: "flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between",
158
- children: [b.prompt ? /* @__PURE__ */ A("div", {
159
- className: "flex min-w-0 items-start gap-3",
160
- children: [/* @__PURE__ */ k("span", {
161
- className: "mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent",
162
- "aria-hidden": "true",
163
- children: /* @__PURE__ */ k(w, { className: "h-4 w-4" })
164
- }), /* @__PURE__ */ k("p", {
165
- className: "min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary",
166
- children: b.prompt
167
188
  })]
168
- }) : /* @__PURE__ */ k("span", {
169
- className: "text-sm text-text-secondary",
170
- children: "Anchored to a story."
171
- }), b.storyId && /* @__PURE__ */ A("button", {
172
- type: "button",
173
- onClick: () => v(`stories/${b.storyId}`),
174
- className: "inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline",
175
- children: [
176
- /* @__PURE__ */ k(g, {
177
- className: "h-4 w-4",
178
- "aria-hidden": "true"
179
- }),
180
- " View linked story",
181
- /* @__PURE__ */ k(y, {
182
- className: "h-3.5 w-3.5",
183
- "aria-hidden": "true"
184
- })
185
- ]
186
- })]
187
- })
188
- ]
189
- }), /* @__PURE__ */ k(i, {
190
- discussionId: b.id,
191
- isLocked: b.isLocked
192
- })]
189
+ })
190
+ ]
191
+ }),
192
+ /* @__PURE__ */ A(p, {}),
193
+ /* @__PURE__ */ A(i, {
194
+ discussionId: x.id,
195
+ isLocked: x.isLocked
196
+ })
197
+ ]
193
198
  })
194
199
  });
195
200
  }
196
- export { P as DiscussionDetailPage };
201
+ export { F as DiscussionDetailPage };
197
202
 
198
203
  //# sourceMappingURL=DiscussionDetailPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionDetailPage.js","names":["_Fragment","statusIcon","className","status","CheckCircle2","Clock","Flag","Trash2","DiscussionDetailPage","useParams","useTheCulturePost","discussion","useTcpDiscussion","id","lock","useTcpLockDiscussion","backButton","Button","navigateTo","ArrowLeft","isLoading","PageLayout","LoadingView","isError","ErrorView","refetch","GlassCard","impact","action","nativeConfirm","notify","err","describeError","Fragment","Unlock","Lock","StatusBadge","HeartHandshake","tag","AuthorLabel","MessagesSquare","formatNumber","formatRelativeTime","Quote","BookOpen","ExternalLink","ReplyThread"],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionDetailPage.tsx"],"sourcesContent":["/**\n * DiscussionDetailPage — a single discussion and its moderated replies.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpDiscussion`. Writes `tcpLockDiscussion` and, via {@link ReplyThread},\n * `tcpPostReply` / `tcpModerateReply`. When anchored to a story, a link back to\n * the story is shown. The header is an editorial card: display-serif title, a\n * moderation-status + interfaith badge row, tag chips, an \"opened by\" byline and\n * a framed prompt callout.\n */\n\nimport type { ReactNode } from 'react';\nimport { useParams } from 'react-router';\nimport {\n ArrowLeft,\n Lock,\n Unlock,\n HeartHandshake,\n BookOpen,\n MessagesSquare,\n Quote,\n CheckCircle2,\n Clock,\n Flag,\n Trash2,\n ExternalLink,\n} from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { AuthorLabel } from '../../components/AuthorLabel';\nimport { ReplyThread } from '../../components/ReplyThread';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpDiscussion, useTcpLockDiscussion } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport { notify, describeError } from '../../lib/toast';\nimport { impact, nativeConfirm } from '../../utils/nativeBridge';\nimport type { TcpModerationStatus } from '../../types';\n\n/** Leading icon for a moderation-status badge (token colours come from StatusBadge). */\nfunction statusIcon(status: TcpModerationStatus): ReactNode {\n const className = 'h-3 w-3';\n switch (status) {\n case 'APPROVED':\n return <CheckCircle2 className={className} aria-hidden=\"true\" />;\n case 'PENDING':\n return <Clock className={className} aria-hidden=\"true\" />;\n case 'FLAGGED':\n return <Flag className={className} aria-hidden=\"true\" />;\n case 'REMOVED':\n return <Trash2 className={className} aria-hidden=\"true\" />;\n }\n}\n\nexport function DiscussionDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: discussion, isLoading, isError, refetch } = useTcpDiscussion(id);\n const lock = useTcpLockDiscussion();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('discussions')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <LoadingView label=\"Loading discussion…\" />\n </PageLayout>\n );\n }\n\n if (isError || !discussion) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <ErrorView\n title=\"Discussion not found\"\n message=\"This discussion may have been removed, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const doLock = async () => {\n await impact('light');\n const action = discussion.isLocked ? 'unlock' : 'lock';\n const confirmed = await nativeConfirm({\n title: `${action === 'lock' ? 'Lock' : 'Unlock'} discussion`,\n message: `Are you sure you want to ${action} this discussion?`,\n okButtonTitle: action === 'lock' ? 'Lock' : 'Unlock',\n cancelButtonTitle: 'Cancel',\n });\n if (!confirmed) return;\n try {\n await lock.mutateAsync(discussion.id);\n notify.success(discussion.isLocked ? 'Discussion unlocked' : 'Discussion locked');\n } catch (err) {\n notify.error('Could not update the discussion', describeError(err));\n }\n };\n\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-4 p-5 sm:p-6\">\n {/* Title + lock/unlock */}\n <div className=\"flex items-start justify-between gap-3\">\n <h1 className=\"font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl\">\n {discussion.title}\n </h1>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={doLock}\n disabled={lock.isPending}\n className=\"shrink-0\"\n >\n {discussion.isLocked ? (\n <>\n <Unlock className=\"mr-1.5 h-4 w-4\" /> Unlock\n </>\n ) : (\n <>\n <Lock className=\"mr-1.5 h-4 w-4\" /> Lock\n </>\n )}\n </Button>\n </div>\n\n {/* Moderation status + interfaith / locked signals, with tags to the right */}\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={discussion.status} icon={statusIcon(discussion.status)} />\n {discussion.isInterfaith && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <HeartHandshake className=\"h-3 w-3\" aria-hidden=\"true\" /> Interfaith\n </span>\n )}\n {discussion.isLocked && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n <Lock className=\"h-3 w-3\" aria-hidden=\"true\" /> Locked\n </span>\n )}\n </div>\n {discussion.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5 sm:ml-auto\">\n {discussion.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 </div>\n\n {/* Byline */}\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary\">\n <AuthorLabel actorId={discussion.openedById} prefix=\"Opened by\" />\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <MessagesSquare className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {formatNumber(discussion.replyCount)}{' '}\n {discussion.replyCount === 1 ? 'reply' : 'replies'}\n </span>\n <span aria-hidden=\"true\">·</span>\n <span>Started {formatRelativeTime(discussion.createdAt)}</span>\n </div>\n\n {/* Prompt callout + linked story */}\n {(discussion.prompt || discussion.storyId) && (\n <div className=\"flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between\">\n {discussion.prompt ? (\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent\"\n aria-hidden=\"true\"\n >\n <Quote className=\"h-4 w-4\" />\n </span>\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary\">\n {discussion.prompt}\n </p>\n </div>\n ) : (\n <span className=\"text-sm text-text-secondary\">Anchored to a story.</span>\n )}\n {discussion.storyId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`stories/${discussion.storyId}`)}\n className=\"inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline\"\n >\n <BookOpen className=\"h-4 w-4\" aria-hidden=\"true\" /> View linked story\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n </GlassCard>\n\n <ReplyThread discussionId={discussion.id} isLocked={discussion.isLocked} />\n </div>\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DiscussionDetailPage.js","names":["_Fragment","statusIcon","className","status","CheckCircle2","Clock","Flag","Trash2","DiscussionDetailPage","useParams","useTheCulturePost","discussion","useTcpDiscussion","id","lock","useTcpLockDiscussion","backButton","Button","navigateTo","ArrowLeft","isLoading","PageLayout","LoadingView","isError","ErrorView","refetch","GlassCard","impact","action","nativeConfirm","notify","err","describeError","Fragment","Unlock","Lock","StatusBadge","HeartHandshake","tag","AuthorLabel","MessagesSquare","formatNumber","formatRelativeTime","Quote","BookOpen","ExternalLink","CommunityNorms","ReplyThread"],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionDetailPage.tsx"],"sourcesContent":["/**\n * DiscussionDetailPage — a single discussion and its moderated replies.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpDiscussion`. Writes `tcpLockDiscussion` and, via {@link ReplyThread},\n * `tcpPostReply` / `tcpModerateReply`. When anchored to a story, a link back to\n * the story is shown. The header is an editorial card: display-serif title, a\n * moderation-status + interfaith badge row, tag chips, an \"opened by\" byline and\n * a framed prompt callout.\n */\n\nimport type { ReactNode } from 'react';\nimport { useParams } from 'react-router';\nimport {\n ArrowLeft,\n Lock,\n Unlock,\n HeartHandshake,\n BookOpen,\n MessagesSquare,\n Quote,\n CheckCircle2,\n Clock,\n Flag,\n Trash2,\n ExternalLink,\n} from 'lucide-react';\nimport { Button, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { StatusBadge } from '../../components/StatusBadge';\nimport { AuthorLabel } from '../../components/AuthorLabel';\nimport { ReplyThread } from '../../components/ReplyThread';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { useTcpDiscussion, useTcpLockDiscussion } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { formatNumber, formatRelativeTime } from '../../utils/formatters';\nimport { notify, describeError } from '../../lib/toast';\nimport { CommunityNorms } from '../../components/CommunityNorms';\nimport { impact, nativeConfirm } from '../../utils/nativeBridge';\nimport type { TcpModerationStatus } from '../../types';\n\n/** Leading icon for a moderation-status badge (token colours come from StatusBadge). */\nfunction statusIcon(status: TcpModerationStatus): ReactNode {\n const className = 'h-3 w-3';\n switch (status) {\n case 'APPROVED':\n return <CheckCircle2 className={className} aria-hidden=\"true\" />;\n case 'PENDING':\n return <Clock className={className} aria-hidden=\"true\" />;\n case 'FLAGGED':\n return <Flag className={className} aria-hidden=\"true\" />;\n case 'REMOVED':\n return <Trash2 className={className} aria-hidden=\"true\" />;\n }\n}\n\nexport function DiscussionDetailPage() {\n const { id } = useParams<{ id: string }>();\n const { navigateTo } = useTheCulturePost();\n const { data: discussion, isLoading, isError, refetch } = useTcpDiscussion(id);\n const lock = useTcpLockDiscussion();\n\n const backButton = (\n <Button variant=\"ghost\" size=\"sm\" onClick={() => navigateTo('discussions')}>\n <ArrowLeft className=\"mr-1.5 h-4 w-4\" /> Back\n </Button>\n );\n\n if (isLoading) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <LoadingView label=\"Loading discussion…\" />\n </PageLayout>\n );\n }\n\n if (isError || !discussion) {\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <ErrorView\n title=\"Discussion not found\"\n message=\"This discussion may have been removed, or you may not have access.\"\n onRetry={() => refetch()}\n />\n </PageLayout>\n );\n }\n\n const doLock = async () => {\n await impact('light');\n const action = discussion.isLocked ? 'unlock' : 'lock';\n const confirmed = await nativeConfirm({\n title: `${action === 'lock' ? 'Lock' : 'Unlock'} discussion`,\n message: `Are you sure you want to ${action} this discussion?`,\n okButtonTitle: action === 'lock' ? 'Lock' : 'Unlock',\n cancelButtonTitle: 'Cancel',\n });\n if (!confirmed) return;\n try {\n await lock.mutateAsync(discussion.id);\n notify.success(discussion.isLocked ? 'Discussion unlocked' : 'Discussion locked');\n } catch (err) {\n notify.error('Could not update the discussion', describeError(err));\n }\n };\n\n return (\n <PageLayout title=\"Discussion\" actions={backButton}>\n <div className=\"mx-auto flex max-w-3xl flex-col gap-6\">\n <GlassCard treatment=\"plain\" className=\"flex flex-col gap-4 p-5 sm:p-6\">\n {/* Title + lock/unlock */}\n <div className=\"flex items-start justify-between gap-3\">\n <h1 className=\"font-display text-2xl font-semibold leading-tight text-text-primary sm:text-3xl\">\n {discussion.title}\n </h1>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={doLock}\n disabled={lock.isPending}\n className=\"shrink-0\"\n >\n {discussion.isLocked ? (\n <>\n <Unlock className=\"mr-1.5 h-4 w-4\" /> Unlock\n </>\n ) : (\n <>\n <Lock className=\"mr-1.5 h-4 w-4\" /> Lock\n </>\n )}\n </Button>\n </div>\n\n {/* Moderation status + interfaith / locked signals, with tags to the right */}\n <div className=\"flex flex-wrap items-center gap-x-4 gap-y-2\">\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <StatusBadge status={discussion.status} icon={statusIcon(discussion.status)} />\n {discussion.isInterfaith && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-[var(--color-accent-soft)] px-2.5 py-0.5 text-xs font-medium text-text-primary\">\n <HeartHandshake className=\"h-3 w-3\" aria-hidden=\"true\" /> Interfaith\n </span>\n )}\n {discussion.isLocked && (\n <span className=\"inline-flex items-center gap-1 rounded-full bg-bg-sunken px-2.5 py-0.5 text-xs font-medium text-text-secondary\">\n <Lock className=\"h-3 w-3\" aria-hidden=\"true\" /> Locked\n </span>\n )}\n </div>\n {discussion.tags.length > 0 && (\n <div className=\"flex flex-wrap items-center gap-1.5 sm:ml-auto\">\n {discussion.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 </div>\n\n {/* Byline */}\n <div className=\"flex flex-wrap items-center gap-x-2 gap-y-1 text-xs text-text-tertiary\">\n <AuthorLabel actorId={discussion.openedById} prefix=\"Opened by\" />\n <span aria-hidden=\"true\">·</span>\n <span className=\"inline-flex items-center gap-1\">\n <MessagesSquare className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n {formatNumber(discussion.replyCount)}{' '}\n {discussion.replyCount === 1 ? 'reply' : 'replies'}\n </span>\n <span aria-hidden=\"true\">·</span>\n <span>Started {formatRelativeTime(discussion.createdAt)}</span>\n </div>\n\n {/* Prompt callout + linked story */}\n {(discussion.prompt || discussion.storyId) && (\n <div className=\"flex flex-col gap-3 rounded-xl border border-border-seam bg-[var(--color-accent-soft)] p-4 sm:flex-row sm:items-start sm:justify-between\">\n {discussion.prompt ? (\n <div className=\"flex min-w-0 items-start gap-3\">\n <span\n className=\"mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-bg-canvas/70 text-accent\"\n aria-hidden=\"true\"\n >\n <Quote className=\"h-4 w-4\" />\n </span>\n <p className=\"min-w-0 whitespace-pre-wrap text-sm leading-relaxed text-text-primary\">\n {discussion.prompt}\n </p>\n </div>\n ) : (\n <span className=\"text-sm text-text-secondary\">Anchored to a story.</span>\n )}\n {discussion.storyId && (\n <button\n type=\"button\"\n onClick={() => navigateTo(`stories/${discussion.storyId}`)}\n className=\"inline-flex shrink-0 items-center gap-1.5 self-start rounded-lg px-1 text-sm font-medium text-accent hover:underline\"\n >\n <BookOpen className=\"h-4 w-4\" aria-hidden=\"true\" /> View linked story\n <ExternalLink className=\"h-3.5 w-3.5\" aria-hidden=\"true\" />\n </button>\n )}\n </div>\n )}\n </GlassCard>\n\n <CommunityNorms />\n\n <ReplyThread discussionId={discussion.id} isLocked={discussion.isLocked} />\n </div>\n </PageLayout>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA0CA,SAASC,EAAW,GAAwC;CAC1D,IAAMC,IAAY;CAClB,QAAQC,GAAR;EACE,KAAK,YACH,OAAO,kBAACC,GAAD;GAAyB;GAAW,eAAY;EAAQ,CAAA;EACjE,KAAK,WACH,OAAO,kBAACC,GAAD;GAAkB;GAAW,eAAY;EAAQ,CAAA;EAC1D,KAAK,WACH,OAAO,kBAACC,GAAD;GAAiB;GAAW,eAAY;EAAQ,CAAA;EACzD,KAAK,WACH,OAAO,kBAACC,GAAD;GAAmB;GAAW,eAAY;EAAQ,CAAA;CAC7D;AACF;AAEA,SAAgBC,IAAuB;CACrC,IAAM,EAAE,UAAOC,EAA0B,GACnC,EAAE,kBAAeC,EAAkB,GACnC,EAAE,MAAMC,GAAY,cAAW,YAAS,eAAYC,EAAiBC,CAAE,GACvEC,IAAOC,EAAqB,GAE5BC,IACJ,kBAACC,GAAD;EAAQ,SAAQ;EAAQ,MAAK;EAAK,eAAeC,EAAW,aAAa;EAAzE,UAAA,CACE,kBAACC,GAAD,EAAW,WAAU,iBAAkB,CAAA,GAAC,OAClC;;CAyCV,OAtCIC,IAEA,kBAACC,GAAD;EAAY,OAAM;EAAa,SAASL;EACtC,UAAA,kBAACM,GAAD,EAAa,OAAM,sBAAuB,CAAA;CAChC,CAAA,IAIZC,KAAW,CAACZ,IAEZ,kBAACU,GAAD;EAAY,OAAM;EAAa,SAASL;EACtC,UAAA,kBAACQ,GAAD;GACE,OAAM;GACN,SAAQ;GACR,eAAeC,EAAQ;EACxB,CAAA;CACS,CAAA,IAuBd,kBAACJ,GAAD;EAAY,OAAM;EAAa,SAASL;EACtC,UAAA,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IACE,kBAACU,GAAD;KAAW,WAAU;KAAQ,WAAU;KAAvC,UAAA;MAEE,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,MAAD;QAAI,WAAU;QACX,UAAAf,EAAW;OACV,CAAA,GACJ,kBAACM,GAAD;QACE,SAAQ;QACR,MAAK;QACL,SAAS,YA9BM;SACzB,MAAMU,EAAO,OAAO;SACpB,IAAMC,IAASjB,EAAW,WAAW,WAAW;SAOhD,IAAK,MANmBkB,EAAc;UACpC,OAAO,GAAGD,MAAW,SAAS,SAAS,SAAS;UAChD,SAAS,4BAA4BA,EAAO;UAC5C,eAAeA,MAAW,SAAS,SAAS;UAC5C,mBAAmB;SACrB,CAAC,GAED,IAAI;UAEF,AADA,MAAMd,EAAK,YAAYH,EAAW,EAAE,GACpCmB,EAAO,QAAQnB,EAAW,WAAW,wBAAwB,mBAAmB;SAClF,SAASoB,GAAK;UACZ,EAAO,MAAM,mCAAmCC,EAAcD,CAAG,CAAC;SACpE;QACF;QAeY,UAAUjB,EAAK;QACf,WAAU;QAET,UAAAH,EAAW,WACV,kBAAAX,GAAA,EAAA,UAAA,CACE,kBAACkC,GAAD,EAAQ,WAAU,iBAAkB,CAAA,GAAC,SACrC,EAAA,CAAA,IAEF,kBAAAlC,GAAA,EAAA,UAAA,CACE,kBAACmC,GAAD,EAAM,WAAU,iBAAkB,CAAA,GAAC,OACnC,EAAA,CAAA;OAEE,CAAA,CACL;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA;SACE,kBAACC,GAAD;UAAa,QAAQzB,EAAW;UAAQ,MAAMV,EAAWU,EAAW,MAAM;SAAI,CAAA;SAC7EA,EAAW,gBACV,kBAAC,QAAD;UAAM,WAAU;UAAhB,UAAA,CACE,kBAAC0B,GAAD;WAAgB,WAAU;WAAU,eAAY;UAAQ,CAAA,GAAC,aACrD;;SAEP1B,EAAW,YACV,kBAAC,QAAD;UAAM,WAAU;UAAhB,UAAA,CACE,kBAACwB,GAAD;WAAM,WAAU;WAAU,eAAY;UAAQ,CAAA,GAAC,SAC3C;;QAEL;OACJ,CAAA,GAAAxB,EAAW,KAAK,SAAS,KACxB,kBAAC,OAAD;QAAK,WAAU;QACZ,UAAAA,EAAW,KAAK,KAAK,MACpB,kBAAC,QAAD;SAEE,WAAU;SAFZ,UAAA,CAGC,KACG2B,CACE;QAJC,GAAAA,CAID,CACP;OACE,CAAA,CAEJ;;MAGL,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA;QACE,kBAACC,GAAD;SAAa,SAAS5B,EAAW;SAAY,QAAO;QAAa,CAAA;QACjE,kBAAC,QAAD;SAAM,eAAY;SAAO,UAAA;QAAO,CAAA;QAChC,kBAAC,QAAD;SAAM,WAAU;SAAhB,UAAA;UACE,kBAAC6B,GAAD;WAAgB,WAAU;WAAc,eAAY;UAAQ,CAAA;UAC3DC,EAAa9B,EAAW,UAAU;UAAG;UACrCA,EAAW,eAAe,IAAI,UAAU;SACrC;;QACN,kBAAC,QAAD;SAAM,eAAY;SAAO,UAAA;QAAO,CAAA;QAChC,kBAAC,QAAD,EAAA,UAAA,CAAM,YAAS+B,EAAmB/B,EAAW,SAAS,CAAQ,EAAA,CAAA;OAC3D;;OAGHA,EAAW,UAAUA,EAAW,YAChC,kBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACGA,EAAW,SACV,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAAC,QAAD;SACE,WAAU;SACV,eAAY;SAEZ,UAAA,kBAACgC,GAAD,EAAO,WAAU,UAAW,CAAA;QACxB,CAAA,GACN,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAhC,EAAW;QACX,CAAA,CACA;OAEL,CAAA,IAAA,kBAAC,QAAD;QAAM,WAAU;QAA8B,UAAA;OAA0B,CAAA,GAEzEA,EAAW,WACV,kBAAC,UAAD;QACE,MAAK;QACL,eAAeO,EAAW,WAAWP,EAAW,SAAS;QACzD,WAAU;QAHZ,UAAA;SAKE,kBAACiC,GAAD;UAAU,WAAU;UAAU,eAAY;SAAQ,CAAA;SAAC;SACnD,kBAACC,GAAD;UAAc,WAAU;UAAc,eAAY;SAAQ,CAAA;QACpD;OAEP,CAAA,CAAA;;KAEE;;IAEX,kBAACC,GAAD,CAAiB,CAAA;IAEjB,kBAACC,GAAD;KAAa,cAAcpC,EAAW;KAAI,UAAUA,EAAW;IAAW,CAAA;GACvE;;CACK,CAAA;AAEhB"}
@@ -1,23 +1,24 @@
1
1
  import { useTheCulturePost as e } from "../../context/TheCulturePostContext.js";
2
2
  import { PageLayout as t } from "../../components/PageLayout.js";
3
3
  import { FilterTabs as n } from "../../components/FilterTabs.js";
4
- import { DiscussionCard as r } from "../../components/DiscussionCard.js";
4
+ import { CommunityNorms as r } from "../../components/CommunityNorms.js";
5
5
  import { useTcpDiscussions as i } from "../../hooks/useTcpApi.js";
6
6
  import { useCursorPager as a } from "../../hooks/useCursorPager.js";
7
7
  import { useTr as o } from "../../hooks/useTr.js";
8
- import { OpenDiscussionDialog as s } from "../../components/OpenDiscussionDialog.js";
9
- import { EmptyState as c } from "../../components/EmptyState.js";
10
- import { ErrorView as l, LoadingView as u } from "../../components/StateViews.js";
11
- import { Pagination as d } from "../../components/Pagination.js";
8
+ import { DiscussionCard as s } from "../../components/DiscussionCard.js";
9
+ import { OpenDiscussionDialog as c } from "../../components/OpenDiscussionDialog.js";
10
+ import { EmptyState as l } from "../../components/EmptyState.js";
11
+ import { ErrorView as u, LoadingView as d } from "../../components/StateViews.js";
12
+ import { Pagination as f } from "../../components/Pagination.js";
12
13
  import "../../hooks/index.js";
13
14
  import "../../context/index.js";
14
- import { cn as f } from "../../utils/cn.js";
15
- import { useState as p } from "react";
16
- import { HeartHandshake as m, MessagesSquare as h, Plus as g } from "lucide-react";
17
- import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
18
- import { Button as b } from "@burdenoff/fe-libs/ui";
15
+ import { cn as p } from "../../utils/cn.js";
16
+ import { useState as m } from "react";
17
+ import { HeartHandshake as h, MessagesSquare as g, Plus as _ } from "lucide-react";
18
+ import { Fragment as v, jsx as y, jsxs as b } from "react/jsx-runtime";
19
+ import { Button as x } from "@burdenoff/fe-libs/ui";
19
20
  // src/theculturepost/pages/discussions/DiscussionsPage.tsx
20
- var x = 12, S = [
21
+ var S = 12, C = [
21
22
  {
22
23
  value: "ALL",
23
24
  label: "All"
@@ -39,77 +40,81 @@ var x = 12, S = [
39
40
  label: "Removed"
40
41
  }
41
42
  ];
42
- function C() {
43
- let { navigateTo: C } = e(), w = o(), T = a(), [E, D] = p("ALL"), [O, k] = p(!1), [A, j] = p(!1), { data: M, isLoading: N, isError: P, refetch: F } = i({
44
- status: E === "ALL" ? void 0 : E,
43
+ function w() {
44
+ let { navigateTo: w } = e(), T = o(), E = a(), [D, O] = m("ALL"), [k, A] = m(!1), [j, M] = m(!1), { data: N, isLoading: P, isError: F, refetch: I } = i({
45
+ status: D === "ALL" ? void 0 : D,
45
46
  pagination: {
46
- limit: x,
47
- cursor: T.cursor
47
+ limit: S,
48
+ cursor: E.cursor
48
49
  }
49
- }), I = M?.items ?? [], L = O ? I.filter((e) => e.isInterfaith) : I;
50
- return /* @__PURE__ */ y(t, {
51
- title: w("discussions.title", "Discussions"),
52
- description: w("discussions.description", "Respectful, moderated conversations — including interfaith spaces that welcome many traditions."),
53
- actions: /* @__PURE__ */ y(b, {
54
- onClick: () => j(!0),
50
+ }), L = N?.items ?? [], R = k ? L.filter((e) => e.isInterfaith) : L;
51
+ return /* @__PURE__ */ b(t, {
52
+ title: T("discussions.title", "Discussions"),
53
+ description: T("discussions.description", "Respectful, moderated conversations — including interfaith spaces that welcome many traditions."),
54
+ actions: /* @__PURE__ */ b(x, {
55
+ onClick: () => M(!0),
55
56
  "data-tour": "theculturepost-discussions-create",
56
57
  children: [
57
- /* @__PURE__ */ v(g, { className: "mr-1.5 h-4 w-4" }),
58
+ /* @__PURE__ */ y(_, { className: "mr-1.5 h-4 w-4" }),
58
59
  " ",
59
- w("discussions.openDiscussion", "Open discussion")
60
+ T("discussions.openDiscussion", "Open discussion")
60
61
  ]
61
62
  }),
62
63
  children: [
63
- /* @__PURE__ */ y("div", {
64
+ /* @__PURE__ */ y(r, {
65
+ compact: !0,
66
+ className: "mb-5"
67
+ }),
68
+ /* @__PURE__ */ b("div", {
64
69
  className: "mb-5 flex flex-wrap items-center gap-3",
65
70
  "data-tour": "theculturepost-discussions-filters",
66
- children: [/* @__PURE__ */ v(n, {
67
- options: S,
68
- value: E,
71
+ children: [/* @__PURE__ */ y(n, {
72
+ options: C,
73
+ value: D,
69
74
  onChange: (e) => {
70
- D(e), T.reset();
75
+ O(e), E.reset();
71
76
  }
72
- }), /* @__PURE__ */ y("button", {
77
+ }), /* @__PURE__ */ b("button", {
73
78
  type: "button",
74
- "aria-pressed": O,
75
- onClick: () => k((e) => !e),
76
- className: f("inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors", O ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary"),
77
- children: [/* @__PURE__ */ v(m, { className: "h-4 w-4" }), " Interfaith"]
79
+ "aria-pressed": k,
80
+ onClick: () => A((e) => !e),
81
+ className: p("inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors", k ? "border-transparent bg-action-primary-bg text-action-primary-text" : "border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary"),
82
+ children: [/* @__PURE__ */ y(h, { className: "h-4 w-4" }), " Interfaith"]
78
83
  })]
79
84
  }),
80
- N ? /* @__PURE__ */ v(u, { label: "Loading discussions…" }) : P ? /* @__PURE__ */ v(l, {
85
+ P ? /* @__PURE__ */ y(d, { label: "Loading discussions…" }) : F ? /* @__PURE__ */ y(u, {
81
86
  message: "We couldn't load discussions.",
82
- onRetry: () => F()
83
- }) : L.length === 0 && T.page === 0 ? /* @__PURE__ */ v(c, {
87
+ onRetry: () => I()
88
+ }) : R.length === 0 && E.page === 0 ? /* @__PURE__ */ y(l, {
84
89
  illustration: "empty-notifications",
85
- icon: /* @__PURE__ */ v(h, { className: "h-10 w-10" }),
86
- title: O ? "No interfaith discussions here" : E === "ALL" ? "No discussions yet" : "No discussions match this filter",
87
- description: E === "ALL" && !O ? "Open a discussion to invite thoughtful, respectful perspectives." : "Try a different filter, or open a new discussion.",
88
- action: /* @__PURE__ */ y(b, {
89
- onClick: () => j(!0),
90
- children: [/* @__PURE__ */ v(g, { className: "mr-1.5 h-4 w-4" }), " Open discussion"]
90
+ icon: /* @__PURE__ */ y(g, { className: "h-10 w-10" }),
91
+ title: k ? "No interfaith discussions here" : D === "ALL" ? "No discussions yet" : "No discussions match this filter",
92
+ description: D === "ALL" && !k ? "Open a discussion to invite thoughtful, respectful perspectives." : "Try a different filter, or open a new discussion.",
93
+ action: /* @__PURE__ */ b(x, {
94
+ onClick: () => M(!0),
95
+ children: [/* @__PURE__ */ y(_, { className: "mr-1.5 h-4 w-4" }), " Open discussion"]
91
96
  })
92
- }) : /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ v("ul", {
97
+ }) : /* @__PURE__ */ b(v, { children: [/* @__PURE__ */ y("ul", {
93
98
  className: "flex flex-col gap-3",
94
- children: L.map((e) => /* @__PURE__ */ v("li", { children: /* @__PURE__ */ v(r, {
99
+ children: R.map((e) => /* @__PURE__ */ y("li", { children: /* @__PURE__ */ y(s, {
95
100
  discussion: e,
96
- onOpen: () => C(`discussions/${e.id}`)
101
+ onOpen: () => w(`discussions/${e.id}`)
97
102
  }) }, e.id))
98
- }), /* @__PURE__ */ v(d, {
99
- page: T.page,
100
- pageSize: x,
101
- itemCount: I.length,
102
- hasMore: M?.pageInfo.hasMore ?? !1,
103
- onPageChange: (e) => T.onPageChange(e, M?.pageInfo.cursor)
103
+ }), /* @__PURE__ */ y(f, {
104
+ page: E.page,
105
+ pageSize: S,
106
+ itemCount: L.length,
107
+ hasMore: N?.pageInfo.hasMore ?? !1,
108
+ onPageChange: (e) => E.onPageChange(e, N?.pageInfo.cursor)
104
109
  })] }),
105
- /* @__PURE__ */ v(s, {
106
- open: A,
107
- onOpenChange: j,
108
- onCreated: (e) => C(`discussions/${e.id}`)
110
+ /* @__PURE__ */ y(c, {
111
+ open: j,
112
+ onOpenChange: M,
113
+ onCreated: (e) => w(`discussions/${e.id}`)
109
114
  })
110
115
  ]
111
116
  });
112
117
  }
113
- export { C as DiscussionsPage };
118
+ export { w as DiscussionsPage };
114
119
 
115
120
  //# sourceMappingURL=DiscussionsPage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionsPage.js","names":["_Fragment","Fragment$1","PAGE_SIZE","STATUS_FILTERS","DiscussionsPage","useTheCulturePost","tr","useTr","pager","useCursorPager","status","setStatus","useState","interfaithOnly","setInterfaithOnly","createOpen","setCreateOpen","useTcpDiscussions","allItems","data","discussions","d","PageLayout","Button","Plus","FilterTabs","next","v","cn","HeartHandshake","isLoading","LoadingView","isError","ErrorView","refetch","EmptyState","MessagesSquare","DiscussionCard","navigateTo","discussion","Pagination","target","OpenDiscussionDialog"],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionsPage.tsx"],"sourcesContent":["/**\n * DiscussionsPage — browse moderated community discussions.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpListDiscussions` (filtered by moderation status). The interfaith\n * toggle is a client-side filter over the loaded page (the svc list field does\n * not filter by interfaith). \"Open Discussion\" opens {@link OpenDiscussionDialog}.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus, HeartHandshake } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { DiscussionCard } from '../../components/DiscussionCard';\nimport { OpenDiscussionDialog } from '../../components/OpenDiscussionDialog';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useTcpDiscussions, useCursorPager, useTr } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport type { TcpModerationStatus } from '../../types';\n\nconst PAGE_SIZE = 12;\n\ntype StatusFilter = 'ALL' | TcpModerationStatus;\n\nconst STATUS_FILTERS: FilterOption<StatusFilter>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'APPROVED', label: 'Approved' },\n { value: 'PENDING', label: 'Pending' },\n { value: 'FLAGGED', label: 'Flagged' },\n { value: 'REMOVED', label: 'Removed' },\n];\n\nexport function DiscussionsPage() {\n const { navigateTo } = useTheCulturePost();\n const tr = useTr();\n const pager = useCursorPager();\n const [status, setStatus] = useState<StatusFilter>('ALL');\n const [interfaithOnly, setInterfaithOnly] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const { data, isLoading, isError, refetch } = useTcpDiscussions({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const allItems = data?.items ?? [];\n const discussions = interfaithOnly ? allItems.filter((d) => d.isInterfaith) : allItems;\n\n const changeStatus = (next: StatusFilter) => {\n setStatus(next);\n pager.reset();\n };\n\n return (\n <PageLayout\n title={tr('discussions.title', 'Discussions')}\n description={tr(\n 'discussions.description',\n 'Respectful, moderated conversations — including interfaith spaces that welcome many traditions.'\n )}\n actions={\n <Button onClick={() => setCreateOpen(true)} data-tour=\"theculturepost-discussions-create\">\n <Plus className=\"mr-1.5 h-4 w-4\" /> {tr('discussions.openDiscussion', 'Open discussion')}\n </Button>\n }\n >\n <div\n className=\"mb-5 flex flex-wrap items-center gap-3\"\n data-tour=\"theculturepost-discussions-filters\"\n >\n <FilterTabs options={STATUS_FILTERS} value={status} onChange={changeStatus} />\n <button\n type=\"button\"\n aria-pressed={interfaithOnly}\n onClick={() => setInterfaithOnly((v) => !v)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors',\n interfaithOnly\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary'\n )}\n >\n <HeartHandshake className=\"h-4 w-4\" /> Interfaith\n </button>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading discussions…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load discussions.\" onRetry={() => refetch()} />\n ) : discussions.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<MessagesSquare className=\"h-10 w-10\" />}\n title={\n interfaithOnly\n ? 'No interfaith discussions here'\n : status === 'ALL'\n ? 'No discussions yet'\n : 'No discussions match this filter'\n }\n description={\n status === 'ALL' && !interfaithOnly\n ? 'Open a discussion to invite thoughtful, respectful perspectives.'\n : 'Try a different filter, or open a new discussion.'\n }\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Open discussion\n </Button>\n }\n />\n ) : (\n <>\n <ul className=\"flex flex-col gap-3\">\n {discussions.map((discussion) => (\n <li key={discussion.id}>\n <DiscussionCard\n discussion={discussion}\n onOpen={() => navigateTo(`discussions/${discussion.id}`)}\n />\n </li>\n ))}\n </ul>\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={allItems.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </>\n )}\n\n <OpenDiscussionDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreated={(discussion) => navigateTo(`discussions/${discussion.id}`)}\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DiscussionsPage.js","names":["_Fragment","Fragment$1","PAGE_SIZE","STATUS_FILTERS","DiscussionsPage","useTheCulturePost","tr","useTr","pager","useCursorPager","status","setStatus","useState","interfaithOnly","setInterfaithOnly","createOpen","setCreateOpen","useTcpDiscussions","allItems","data","discussions","d","PageLayout","Button","Plus","CommunityNorms","FilterTabs","next","v","cn","HeartHandshake","isLoading","LoadingView","isError","ErrorView","refetch","EmptyState","MessagesSquare","DiscussionCard","navigateTo","discussion","Pagination","target","OpenDiscussionDialog"],"sources":["../../../../src/theculturepost/pages/discussions/DiscussionsPage.tsx"],"sourcesContent":["/**\n * DiscussionsPage — browse moderated community discussions.\n * @module theculturepost/pages/discussions\n *\n * Reads `tcpListDiscussions` (filtered by moderation status). The interfaith\n * toggle is a client-side filter over the loaded page (the svc list field does\n * not filter by interfaith). \"Open Discussion\" opens {@link OpenDiscussionDialog}.\n */\n\nimport { useState } from 'react';\nimport { MessagesSquare, Plus, HeartHandshake } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { PageLayout } from '../../components/PageLayout';\nimport { FilterTabs, type FilterOption } from '../../components/FilterTabs';\nimport { CommunityNorms } from '../../components/CommunityNorms';\nimport { DiscussionCard } from '../../components/DiscussionCard';\nimport { OpenDiscussionDialog } from '../../components/OpenDiscussionDialog';\nimport { EmptyState } from '../../components/EmptyState';\nimport { LoadingView, ErrorView } from '../../components/StateViews';\nimport { Pagination } from '../../components/Pagination';\nimport { useTcpDiscussions, useCursorPager, useTr } from '../../hooks';\nimport { useTheCulturePost } from '../../context';\nimport { cn } from '../../utils/cn';\nimport type { TcpModerationStatus } from '../../types';\n\nconst PAGE_SIZE = 12;\n\ntype StatusFilter = 'ALL' | TcpModerationStatus;\n\nconst STATUS_FILTERS: FilterOption<StatusFilter>[] = [\n { value: 'ALL', label: 'All' },\n { value: 'APPROVED', label: 'Approved' },\n { value: 'PENDING', label: 'Pending' },\n { value: 'FLAGGED', label: 'Flagged' },\n { value: 'REMOVED', label: 'Removed' },\n];\n\nexport function DiscussionsPage() {\n const { navigateTo } = useTheCulturePost();\n const tr = useTr();\n const pager = useCursorPager();\n const [status, setStatus] = useState<StatusFilter>('ALL');\n const [interfaithOnly, setInterfaithOnly] = useState(false);\n const [createOpen, setCreateOpen] = useState(false);\n\n const { data, isLoading, isError, refetch } = useTcpDiscussions({\n status: status === 'ALL' ? undefined : status,\n pagination: { limit: PAGE_SIZE, cursor: pager.cursor },\n });\n\n const allItems = data?.items ?? [];\n const discussions = interfaithOnly ? allItems.filter((d) => d.isInterfaith) : allItems;\n\n const changeStatus = (next: StatusFilter) => {\n setStatus(next);\n pager.reset();\n };\n\n return (\n <PageLayout\n title={tr('discussions.title', 'Discussions')}\n description={tr(\n 'discussions.description',\n 'Respectful, moderated conversations — including interfaith spaces that welcome many traditions.'\n )}\n actions={\n <Button onClick={() => setCreateOpen(true)} data-tour=\"theculturepost-discussions-create\">\n <Plus className=\"mr-1.5 h-4 w-4\" /> {tr('discussions.openDiscussion', 'Open discussion')}\n </Button>\n }\n >\n <CommunityNorms compact className=\"mb-5\" />\n <div\n className=\"mb-5 flex flex-wrap items-center gap-3\"\n data-tour=\"theculturepost-discussions-filters\"\n >\n <FilterTabs options={STATUS_FILTERS} value={status} onChange={changeStatus} />\n <button\n type=\"button\"\n aria-pressed={interfaithOnly}\n onClick={() => setInterfaithOnly((v) => !v)}\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-xl border px-3 py-1.5 text-sm font-medium transition-colors',\n interfaithOnly\n ? 'border-transparent bg-action-primary-bg text-action-primary-text'\n : 'border-border-seam bg-bg-surface text-text-secondary hover:bg-bg-sunken hover:text-text-primary'\n )}\n >\n <HeartHandshake className=\"h-4 w-4\" /> Interfaith\n </button>\n </div>\n\n {isLoading ? (\n <LoadingView label=\"Loading discussions…\" />\n ) : isError ? (\n <ErrorView message=\"We couldn't load discussions.\" onRetry={() => refetch()} />\n ) : discussions.length === 0 && pager.page === 0 ? (\n <EmptyState\n illustration=\"empty-notifications\"\n icon={<MessagesSquare className=\"h-10 w-10\" />}\n title={\n interfaithOnly\n ? 'No interfaith discussions here'\n : status === 'ALL'\n ? 'No discussions yet'\n : 'No discussions match this filter'\n }\n description={\n status === 'ALL' && !interfaithOnly\n ? 'Open a discussion to invite thoughtful, respectful perspectives.'\n : 'Try a different filter, or open a new discussion.'\n }\n action={\n <Button onClick={() => setCreateOpen(true)}>\n <Plus className=\"mr-1.5 h-4 w-4\" /> Open discussion\n </Button>\n }\n />\n ) : (\n <>\n <ul className=\"flex flex-col gap-3\">\n {discussions.map((discussion) => (\n <li key={discussion.id}>\n <DiscussionCard\n discussion={discussion}\n onOpen={() => navigateTo(`discussions/${discussion.id}`)}\n />\n </li>\n ))}\n </ul>\n <Pagination\n page={pager.page}\n pageSize={PAGE_SIZE}\n itemCount={allItems.length}\n hasMore={data?.pageInfo.hasMore ?? false}\n onPageChange={(target) => pager.onPageChange(target, data?.pageInfo.cursor)}\n />\n </>\n )}\n\n <OpenDiscussionDialog\n open={createOpen}\n onOpenChange={setCreateOpen}\n onCreated={(discussion) => navigateTo(`discussions/${discussion.id}`)}\n />\n </PageLayout>\n );\n}\n"],"mappings":"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"}
@@ -64,6 +64,12 @@ export declare const enTranslations: {
64
64
  newTopic: string;
65
65
  noTopics: string;
66
66
  };
67
+ norms: {
68
+ title: string;
69
+ respect: string;
70
+ ownVoice: string;
71
+ ideas: string;
72
+ };
67
73
  discussions: {
68
74
  title: string;
69
75
  description: string;
@@ -65,6 +65,12 @@ var e = {
65
65
  newTopic: "New topic",
66
66
  noTopics: "No topics yet"
67
67
  },
68
+ norms: {
69
+ title: "Community norms",
70
+ respect: "Treat every tradition, faith and community with respect.",
71
+ ownVoice: "Speak from your own experience; do not speak for others.",
72
+ ideas: "Challenge ideas, never people, and cite sources where you can."
73
+ },
68
74
  discussions: {
69
75
  title: "Discussions",
70
76
  description: "Respectful, moderated conversations — including interfaith spaces that welcome many traditions.",
@@ -1 +1 @@
1
- {"version":3,"file":"en.js","names":["enTranslations"],"sources":["../../../src/theculturepost/translations/en.ts"],"sourcesContent":["export const enTranslations = {\n nav: {\n home: 'Home',\n overview: 'Overview',\n stories: 'Stories',\n topics: 'Topics',\n timeline: 'Timeline',\n discussions: 'Discussions',\n archive: 'Archive',\n },\n home: {\n hero: {\n eyebrow: 'TheCulturePost',\n title: 'Culture, religion, values & history — told with care',\n description:\n 'A space for respectful stories and thoughtful conversations that connect us across traditions and time — grounded in the record.',\n readStories: 'Read stories',\n },\n loading: 'Loading the latest…',\n welcome: {\n title: 'Welcome to TheCulturePost',\n description:\n 'This publication is just getting started. Curate a topic, draft a story, or begin building the archive.',\n draftStory: 'Draft a story',\n curateTopic: 'Curate a topic',\n },\n topics: {\n title: 'Featured topics',\n description: 'Curated subjects across culture, faith, history and heritage.',\n allTopics: 'All topics',\n emptyTitle: 'No topics yet',\n emptyDescription: 'Curate the first topic to organise the publication.',\n },\n stories: {\n title: 'Latest published stories',\n description: 'Freshly published pieces from the newsroom.',\n allStories: 'All stories',\n emptyTitle: 'No published stories yet',\n emptyDescription: 'Draft a story and move it through the editorial lifecycle to publish.',\n },\n discussions: {\n title: 'Active discussions',\n viewAll: 'View all',\n emptyTitle: 'No open discussions',\n emptyDescription: 'Open a discussion to invite thoughtful perspectives.',\n },\n archive: {\n title: 'From the archive',\n viewAll: 'View all',\n emptyTitle: 'The archive is empty',\n emptyDescription: 'Create a collection to begin preserving heritage.',\n },\n interfaith: 'Interfaith',\n },\n stories: {\n title: 'Stories',\n description:\n 'Articles, essays, explainers, photo stories and timelines — across the full editorial lifecycle.',\n newStory: 'New story',\n noStories: 'No stories yet',\n filterStatus: 'Filter by status',\n filterTopic: 'Filter by topic',\n },\n topics: {\n title: 'Topics',\n description: 'Curated subjects spanning culture, faith, history, heritage and thought.',\n newTopic: 'New topic',\n noTopics: 'No topics yet',\n },\n discussions: {\n title: 'Discussions',\n description:\n 'Respectful, moderated conversations — including interfaith spaces that welcome many traditions.',\n openDiscussion: 'Open discussion',\n noDiscussions: 'No open discussions',\n },\n archive: {\n title: 'Archive',\n description:\n 'A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.',\n newCollection: 'New collection',\n newArtifact: 'Add artifact',\n newRecording: 'Record',\n openCollection: 'Open {{name}}',\n noCollections: 'No collections yet',\n },\n common: {\n loading: 'Loading…',\n error: 'An error occurred',\n retry: 'Retry',\n save: 'Save',\n cancel: 'Cancel',\n edit: 'Edit',\n share: 'Share',\n back: 'Back',\n },\n};\n"],"mappings":";AAAA,IAAaA,IAAiB;CAC5B,KAAK;EACH,MAAM;EACN,UAAU;EACV,SAAS;EACT,QAAQ;EACR,UAAU;EACV,aAAa;EACb,SAAS;CACX;CACA,MAAM;EACJ,MAAM;GACJ,SAAS;GACT,OAAO;GACP,aACE;GACF,aAAa;EACf;EACA,SAAS;EACT,SAAS;GACP,OAAO;GACP,aACE;GACF,YAAY;GACZ,aAAa;EACf;EACA,QAAQ;GACN,OAAO;GACP,aAAa;GACb,WAAW;GACX,YAAY;GACZ,kBAAkB;EACpB;EACA,SAAS;GACP,OAAO;GACP,aAAa;GACb,YAAY;GACZ,YAAY;GACZ,kBAAkB;EACpB;EACA,aAAa;GACX,OAAO;GACP,SAAS;GACT,YAAY;GACZ,kBAAkB;EACpB;EACA,SAAS;GACP,OAAO;GACP,SAAS;GACT,YAAY;GACZ,kBAAkB;EACpB;EACA,YAAY;CACd;CACA,SAAS;EACP,OAAO;EACP,aACE;EACF,UAAU;EACV,WAAW;EACX,cAAc;EACd,aAAa;CACf;CACA,QAAQ;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,UAAU;CACZ;CACA,aAAa;EACX,OAAO;EACP,aACE;EACF,gBAAgB;EAChB,eAAe;CACjB;CACA,SAAS;EACP,OAAO;EACP,aACE;EACF,eAAe;EACf,aAAa;EACb,cAAc;EACd,gBAAgB;EAChB,eAAe;CACjB;CACA,QAAQ;EACN,SAAS;EACT,OAAO;EACP,OAAO;EACP,MAAM;EACN,QAAQ;EACR,MAAM;EACN,OAAO;EACP,MAAM;CACR;AACF"}
1
+ {"version":3,"file":"en.js","names":["enTranslations"],"sources":["../../../src/theculturepost/translations/en.ts"],"sourcesContent":["export const enTranslations = {\n nav: {\n home: 'Home',\n overview: 'Overview',\n stories: 'Stories',\n topics: 'Topics',\n timeline: 'Timeline',\n discussions: 'Discussions',\n archive: 'Archive',\n },\n home: {\n hero: {\n eyebrow: 'TheCulturePost',\n title: 'Culture, religion, values & history — told with care',\n description:\n 'A space for respectful stories and thoughtful conversations that connect us across traditions and time — grounded in the record.',\n readStories: 'Read stories',\n },\n loading: 'Loading the latest…',\n welcome: {\n title: 'Welcome to TheCulturePost',\n description:\n 'This publication is just getting started. Curate a topic, draft a story, or begin building the archive.',\n draftStory: 'Draft a story',\n curateTopic: 'Curate a topic',\n },\n topics: {\n title: 'Featured topics',\n description: 'Curated subjects across culture, faith, history and heritage.',\n allTopics: 'All topics',\n emptyTitle: 'No topics yet',\n emptyDescription: 'Curate the first topic to organise the publication.',\n },\n stories: {\n title: 'Latest published stories',\n description: 'Freshly published pieces from the newsroom.',\n allStories: 'All stories',\n emptyTitle: 'No published stories yet',\n emptyDescription: 'Draft a story and move it through the editorial lifecycle to publish.',\n },\n discussions: {\n title: 'Active discussions',\n viewAll: 'View all',\n emptyTitle: 'No open discussions',\n emptyDescription: 'Open a discussion to invite thoughtful perspectives.',\n },\n archive: {\n title: 'From the archive',\n viewAll: 'View all',\n emptyTitle: 'The archive is empty',\n emptyDescription: 'Create a collection to begin preserving heritage.',\n },\n interfaith: 'Interfaith',\n },\n stories: {\n title: 'Stories',\n description:\n 'Articles, essays, explainers, photo stories and timelines — across the full editorial lifecycle.',\n newStory: 'New story',\n noStories: 'No stories yet',\n filterStatus: 'Filter by status',\n filterTopic: 'Filter by topic',\n },\n topics: {\n title: 'Topics',\n description: 'Curated subjects spanning culture, faith, history, heritage and thought.',\n newTopic: 'New topic',\n noTopics: 'No topics yet',\n },\n norms: {\n title: 'Community norms',\n respect: 'Treat every tradition, faith and community with respect.',\n ownVoice: 'Speak from your own experience; do not speak for others.',\n ideas: 'Challenge ideas, never people, and cite sources where you can.',\n },\n discussions: {\n title: 'Discussions',\n description:\n 'Respectful, moderated conversations — including interfaith spaces that welcome many traditions.',\n openDiscussion: 'Open discussion',\n noDiscussions: 'No open discussions',\n },\n archive: {\n title: 'Archive',\n description:\n 'A living archive of manuscripts, photographs, recordings, maps and objects — grouped into collections.',\n newCollection: 'New collection',\n newArtifact: 'Add artifact',\n newRecording: 'Record',\n openCollection: 'Open {{name}}',\n noCollections: 'No collections yet',\n },\n common: {\n loading: 'Loading…',\n error: 'An error occurred',\n retry: 'Retry',\n save: 'Save',\n cancel: 'Cancel',\n edit: 'Edit',\n share: 'Share',\n back: 'Back',\n },\n};\n"],"mappings":";AAAA,IAAaA,IAAiB;CAC5B,KAAK;EACH,MAAM;EACN,UAAU;EACV,SAAS;EACT,QAAQ;EACR,UAAU;EACV,aAAa;EACb,SAAS;CACX;CACA,MAAM;EACJ,MAAM;GACJ,SAAS;GACT,OAAO;GACP,aACE;GACF,aAAa;EACf;EACA,SAAS;EACT,SAAS;GACP,OAAO;GACP,aACE;GACF,YAAY;GACZ,aAAa;EACf;EACA,QAAQ;GACN,OAAO;GACP,aAAa;GACb,WAAW;GACX,YAAY;GACZ,kBAAkB;EACpB;EACA,SAAS;GACP,OAAO;GACP,aAAa;GACb,YAAY;GACZ,YAAY;GACZ,kBAAkB;EACpB;EACA,aAAa;GACX,OAAO;GACP,SAAS;GACT,YAAY;GACZ,kBAAkB;EACpB;EACA,SAAS;GACP,OAAO;GACP,SAAS;GACT,YAAY;GACZ,kBAAkB;EACpB;EACA,YAAY;CACd;CACA,SAAS;EACP,OAAO;EACP,aACE;EACF,UAAU;EACV,WAAW;EACX,cAAc;EACd,aAAa;CACf;CACA,QAAQ;EACN,OAAO;EACP,aAAa;EACb,UAAU;EACV,UAAU;CACZ;CACA,OAAO;EACL,OAAO;EACP,SAAS;EACT,UAAU;EACV,OAAO;CACT;CACA,aAAa;EACX,OAAO;EACP,aACE;EACF,gBAAgB;EAChB,eAAe;CACjB;CACA,SAAS;EACP,OAAO;EACP,aACE;EACF,eAAe;EACf,aAAa;EACb,cAAc;EACd,gBAAgB;EAChB,eAAe;CACjB;CACA,QAAQ;EACN,SAAS;EACT,OAAO;EACP,OAAO;EACP,MAAM;EACN,QAAQ;EACR,MAAM;EACN,OAAO;EACP,MAAM;CACR;AACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-theculturepost",
3
- "version": "2026.1113.1",
3
+ "version": "2026.1113.2",
4
4
  "description": "Burdenoff TheCulturePost Microfrontend",
5
5
  "type": "module",
6
6
  "files": [