@burdenoff/microfe-comradecircle 2026.704.1 → 2026.704.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/comradecircle/components/Avatar.js +52 -17
- package/dist/comradecircle/components/Avatar.js.map +1 -1
- package/dist/comradecircle/components/AvatarUploadField.js +91 -0
- package/dist/comradecircle/components/AvatarUploadField.js.map +1 -0
- package/dist/comradecircle/components/CircleCard.js +55 -52
- package/dist/comradecircle/components/CircleCard.js.map +1 -1
- package/dist/comradecircle/components/CommentThread.js +80 -64
- package/dist/comradecircle/components/CommentThread.js.map +1 -1
- package/dist/comradecircle/components/CreateCircleDialog.js +74 -63
- package/dist/comradecircle/components/CreateCircleDialog.js.map +1 -1
- package/dist/comradecircle/components/EventCard.js +84 -58
- package/dist/comradecircle/components/EventCard.js.map +1 -1
- package/dist/comradecircle/components/FileImage.js +20 -0
- package/dist/comradecircle/components/FileImage.js.map +1 -0
- package/dist/comradecircle/components/ImageAttachments.js +97 -0
- package/dist/comradecircle/components/ImageAttachments.js.map +1 -0
- package/dist/comradecircle/components/MemberIdentity.js +4 -2
- package/dist/comradecircle/components/MemberIdentity.js.map +1 -1
- package/dist/comradecircle/components/PollCard.js +65 -44
- package/dist/comradecircle/components/PollCard.js.map +1 -1
- package/dist/comradecircle/components/PostCard.js +8 -15
- package/dist/comradecircle/components/PostCard.js.map +1 -1
- package/dist/comradecircle/components/PostComposer.js +45 -35
- package/dist/comradecircle/components/PostComposer.js.map +1 -1
- package/dist/comradecircle/components/ReactionBar.js +1 -1
- package/dist/comradecircle/components/ReactionBar.js.map +1 -1
- package/dist/comradecircle/components/StateViews.js +1 -16
- package/dist/comradecircle/components/StateViews.js.map +1 -1
- package/dist/comradecircle/components/StatusBadge.js +1 -1
- package/dist/comradecircle/components/StatusBadge.js.map +1 -1
- package/dist/comradecircle/hooks/index.js +1 -0
- package/dist/comradecircle/hooks/useComradeCircleApi.js +244 -241
- package/dist/comradecircle/hooks/useComradeCircleApi.js.map +1 -1
- package/dist/comradecircle/hooks/useFiles.js +78 -0
- package/dist/comradecircle/hooks/useFiles.js.map +1 -0
- package/dist/comradecircle/lib/graphql-cache.js +9 -0
- package/dist/comradecircle/lib/graphql-cache.js.map +1 -0
- package/dist/comradecircle/pages/FeedPage.js +79 -33
- package/dist/comradecircle/pages/FeedPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CircleDetailPage.js +354 -242
- package/dist/comradecircle/pages/circles/CircleDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/circles/CirclesPage.js +97 -47
- package/dist/comradecircle/pages/circles/CirclesPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventDetailPage.js +193 -126
- package/dist/comradecircle/pages/events/EventDetailPage.js.map +1 -1
- package/dist/comradecircle/pages/events/EventsPage.js +74 -34
- package/dist/comradecircle/pages/events/EventsPage.js.map +1 -1
- package/dist/comradecircle/pages/members/MemberProfilePage.js +154 -81
- package/dist/comradecircle/pages/members/MemberProfilePage.js.map +1 -1
- package/dist/comradecircle/pages/members/MembersPage.js +141 -71
- package/dist/comradecircle/pages/members/MembersPage.js.map +1 -1
- package/dist/comradecircle/pages/profile/MyProfilePage.js +298 -191
- package/dist/comradecircle/pages/profile/MyProfilePage.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PostComposer.js","names":[],"sources":["../../../src/comradecircle/components/PostComposer.tsx"],"sourcesContent":["/**\n * PostComposer — compose and publish a post to a channel.\n * @module comradecircle/components\n *\n * Writes `comCreatePost({ channelId, body, tags })`. Text + tags only (file\n * attachments are a future enhancement — the svc accepts attachmentFileIds but\n * file upload/preview is out of scope for v1).\n */\n\nimport { useState } from 'react';\nimport { Send } from 'lucide-react';\nimport { Button, Textarea, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { Avatar } from './Avatar';\nimport { useComCreatePost } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\n\ninterface PostComposerProps {\n channelId: string;\n channelName?: string;\n onPosted?: () => void;\n}\n\nexport function PostComposer({ channelId, channelName, onPosted }: PostComposerProps) {\n const { currentUser } = useComradeCircle();\n const createPost = useComCreatePost();\n const [body, setBody] = useState('');\n const [tags, setTags] = useState<string[]>([]);\n const [showTags, setShowTags] = useState(false);\n\n const submit = async () => {\n const text = body.trim();\n if (!text) return;\n try {\n await createPost.mutateAsync({
|
|
1
|
+
{"version":3,"file":"PostComposer.js","names":[],"sources":["../../../src/comradecircle/components/PostComposer.tsx"],"sourcesContent":["/**\n * PostComposer — compose and publish a post to a channel.\n * @module comradecircle/components\n *\n * Writes `comCreatePost({ channelId, body, tags })`. Text + tags only (file\n * attachments are a future enhancement — the svc accepts attachmentFileIds but\n * file upload/preview is out of scope for v1).\n */\n\nimport { useState } from 'react';\nimport { Send } from 'lucide-react';\nimport { Button, Textarea, GlassCard } from '@burdenoff/fe-libs/ui';\nimport { TagInput } from './TagInput';\nimport { Avatar } from './Avatar';\nimport { AttachmentPicker } from './ImageAttachments';\nimport { useComCreatePost } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\n\ninterface PostComposerProps {\n channelId: string;\n channelName?: string;\n onPosted?: () => void;\n}\n\nexport function PostComposer({ channelId, channelName, onPosted }: PostComposerProps) {\n const { currentUser } = useComradeCircle();\n const createPost = useComCreatePost();\n const [body, setBody] = useState('');\n const [tags, setTags] = useState<string[]>([]);\n const [showTags, setShowTags] = useState(false);\n const [attachmentFileIds, setAttachmentFileIds] = useState<string[]>([]);\n\n const submit = async () => {\n const text = body.trim();\n if (!text && attachmentFileIds.length === 0) return;\n try {\n await createPost.mutateAsync({\n channelId,\n body: text,\n tags: tags.length ? tags : null,\n attachmentFileIds: attachmentFileIds.length ? attachmentFileIds : null,\n });\n setBody('');\n setTags([]);\n setAttachmentFileIds([]);\n setShowTags(false);\n notify.success('Posted', channelName ? `Shared to #${channelName}` : undefined);\n onPosted?.();\n } catch (err) {\n notify.error('Could not publish post', describeError(err));\n }\n };\n\n return (\n <GlassCard treatment=\"plain\" className=\"p-4\">\n <div className=\"flex gap-3\">\n <Avatar name={currentUser?.name ?? currentUser?.email ?? 'You'} size=\"md\" />\n <div className=\"flex-1\">\n <Textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n placeholder={channelName ? `Share something in #${channelName}…` : 'Share something…'}\n rows={2}\n className=\"resize-none border-0 bg-transparent px-0 shadow-none focus-visible:ring-0\"\n onKeyDown={(e) => {\n if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n void submit();\n }\n }}\n />\n {showTags && (\n <div className=\"mt-2\">\n <TagInput value={tags} onChange={setTags} placeholder=\"Add topics…\" />\n </div>\n )}\n <div className=\"mt-2\">\n <AttachmentPicker\n fileIds={attachmentFileIds}\n onChange={setAttachmentFileIds}\n disabled={createPost.isPending}\n />\n </div>\n <div className=\"mt-3 flex items-center justify-between\">\n <button\n type=\"button\"\n onClick={() => setShowTags((s) => !s)}\n className=\"text-xs font-medium text-text-secondary transition-colors hover:text-text-primary\"\n >\n {showTags ? 'Hide topics' : '# Add topics'}\n </button>\n <Button\n size=\"sm\"\n onClick={submit}\n disabled={(!body.trim() && attachmentFileIds.length === 0) || createPost.isPending}\n >\n <Send className=\"mr-1.5 h-4 w-4\" /> Post\n </Button>\n </div>\n </div>\n </div>\n </GlassCard>\n );\n}\n"],"mappings":";;;;;;;;;;;;;AAyBA,SAAgB,EAAa,EAAE,cAAW,gBAAa,eAA+B;CACpF,IAAM,EAAE,mBAAgB,GAAkB,EACpC,IAAa,GAAkB,EAC/B,CAAC,GAAM,KAAW,EAAS,GAAG,EAC9B,CAAC,GAAM,KAAW,EAAmB,EAAE,CAAC,EACxC,CAAC,GAAU,KAAe,EAAS,GAAM,EACzC,CAAC,GAAmB,KAAwB,EAAmB,EAAE,CAAC,EAElE,IAAS,YAAY;EACzB,IAAM,IAAO,EAAK,MAAM;AACpB,SAAC,KAAQ,EAAkB,WAAW,GAC1C,KAAI;AAYF,GAXA,MAAM,EAAW,YAAY;IAC3B;IACA,MAAM;IACN,MAAM,EAAK,SAAS,IAAO;IAC3B,mBAAmB,EAAkB,SAAS,IAAoB;IACnE,CAAC,EACF,EAAQ,GAAG,EACX,EAAQ,EAAE,CAAC,EACX,EAAqB,EAAE,CAAC,EACxB,EAAY,GAAM,EAClB,EAAO,QAAQ,UAAU,IAAc,cAAc,MAAgB,KAAA,EAAU,EAC/E,KAAY;WACL,GAAK;AACZ,KAAO,MAAM,0BAA0B,EAAc,EAAI,CAAC;;;AAI9D,QACE,kBAAC,GAAD;EAAW,WAAU;EAAQ,WAAU;YACrC,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,GAAD;IAAQ,MAAM,GAAa,QAAQ,GAAa,SAAS;IAAO,MAAK;IAAO,CAAA,EAC5E,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,GAAD;MACE,OAAO;MACP,WAAW,MAAM,EAAQ,EAAE,OAAO,MAAM;MACxC,aAAa,IAAc,uBAAuB,EAAY,KAAK;MACnE,MAAM;MACN,WAAU;MACV,YAAY,MAAM;AAChB,OAAI,EAAE,QAAQ,YAAY,EAAE,WAAW,EAAE,aACvC,EAAE,gBAAgB,EACb,GAAQ;;MAGjB,CAAA;KACD,KACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OAAU,OAAO;OAAM,UAAU;OAAS,aAAY;OAAgB,CAAA;MAClE,CAAA;KAER,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD;OACE,SAAS;OACT,UAAU;OACV,UAAU,EAAW;OACrB,CAAA;MACE,CAAA;KACN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,GAAa,MAAM,CAAC,EAAE;OACrC,WAAU;iBAET,IAAW,gBAAgB;OACrB,CAAA,EACT,kBAAC,GAAD;OACE,MAAK;OACL,SAAS;OACT,UAAW,CAAC,EAAK,MAAM,IAAI,EAAkB,WAAW,KAAM,EAAW;iBAH3E,CAKE,kBAAC,GAAD,EAAM,WAAU,kBAAmB,CAAA,EAAA,QAC5B;SACL;;KACF;MACF;;EACI,CAAA"}
|
|
@@ -71,7 +71,7 @@ function p({ post: p }) {
|
|
|
71
71
|
disabled: h.isPending,
|
|
72
72
|
"aria-pressed": n.mine,
|
|
73
73
|
"aria-label": `${e.label} (${n.count})`,
|
|
74
|
-
className: t("inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-
|
|
74
|
+
className: t("inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-transform duration-150 active:scale-90", n.mine ? "border-accent bg-[var(--color-accent-soft)] text-text-primary shadow-[0_0_0_2px_var(--color-accent-soft)]" : "border-border-seam bg-bg-surface text-text-secondary hover:-translate-y-px hover:bg-bg-sunken"),
|
|
75
75
|
children: [/* @__PURE__ */ s("span", {
|
|
76
76
|
"aria-hidden": "true",
|
|
77
77
|
children: e.emoji
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactionBar.js","names":[],"sources":["../../../src/comradecircle/components/ReactionBar.tsx"],"sourcesContent":["/**\n * ReactionBar — Slack-style multi-reaction control for a post.\n * @module comradecircle/components\n *\n * `comReactToPost(postId, type)` is an idempotent toggle for one typed reaction,\n * so a member may hold several distinct reactions on a post. We render a chip\n * per reaction type that has a count (highlighted when the caller reacted) plus\n * a popover to add any of the six types.\n */\n\nimport { useState } from 'react';\nimport { SmilePlus } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComReactToPost } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComPost, ComReactionType } from '../types';\n\nconst REACTIONS: { type: ComReactionType; emoji: string; label: string }[] = [\n { type: 'LIKE', emoji: '👍', label: 'Like' },\n { type: 'LOVE', emoji: '❤️', label: 'Love' },\n { type: 'CELEBRATE', emoji: '🎉', label: 'Celebrate' },\n { type: 'INSIGHTFUL', emoji: '💡', label: 'Insightful' },\n { type: 'LAUGH', emoji: '😄', label: 'Funny' },\n { type: 'SUPPORT', emoji: '🤝', label: 'Support' },\n];\n\ninterface ReactionBarProps {\n post: ComPost;\n}\n\nexport function ReactionBar({ post }: ReactionBarProps) {\n const { currentUser } = useComradeCircle();\n const react = useComReactToPost();\n const [open, setOpen] = useState(false);\n\n const meId = currentUser?.id;\n const counts = new Map<ComReactionType, { count: number; mine: boolean }>();\n for (const r of post.reactions ?? []) {\n const cur = counts.get(r.type) ?? { count: 0, mine: false };\n cur.count += 1;\n if (meId && r.memberId === meId) cur.mine = true;\n counts.set(r.type, cur);\n }\n\n const toggle = async (type: ComReactionType) => {\n setOpen(false);\n try {\n await react.mutateAsync({ postId: post.id, type });\n } catch (err) {\n notify.error('Could not react', describeError(err));\n }\n };\n\n const active = REACTIONS.filter((r) => (counts.get(r.type)?.count ?? 0) > 0);\n\n return (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {active.map((r) => {\n const info = counts.get(r.type)!;\n return (\n <button\n key={r.type}\n type=\"button\"\n onClick={() => toggle(r.type)}\n disabled={react.isPending}\n aria-pressed={info.mine}\n aria-label={`${r.label} (${info.count})`}\n className={cn(\n 'inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-
|
|
1
|
+
{"version":3,"file":"ReactionBar.js","names":[],"sources":["../../../src/comradecircle/components/ReactionBar.tsx"],"sourcesContent":["/**\n * ReactionBar — Slack-style multi-reaction control for a post.\n * @module comradecircle/components\n *\n * `comReactToPost(postId, type)` is an idempotent toggle for one typed reaction,\n * so a member may hold several distinct reactions on a post. We render a chip\n * per reaction type that has a count (highlighted when the caller reacted) plus\n * a popover to add any of the six types.\n */\n\nimport { useState } from 'react';\nimport { SmilePlus } from 'lucide-react';\nimport { Popover, PopoverContent, PopoverTrigger } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useComReactToPost } from '../hooks';\nimport { useComradeCircle } from '../context';\nimport { notify, describeError } from '../lib/toast';\nimport type { ComPost, ComReactionType } from '../types';\n\nconst REACTIONS: { type: ComReactionType; emoji: string; label: string }[] = [\n { type: 'LIKE', emoji: '👍', label: 'Like' },\n { type: 'LOVE', emoji: '❤️', label: 'Love' },\n { type: 'CELEBRATE', emoji: '🎉', label: 'Celebrate' },\n { type: 'INSIGHTFUL', emoji: '💡', label: 'Insightful' },\n { type: 'LAUGH', emoji: '😄', label: 'Funny' },\n { type: 'SUPPORT', emoji: '🤝', label: 'Support' },\n];\n\ninterface ReactionBarProps {\n post: ComPost;\n}\n\nexport function ReactionBar({ post }: ReactionBarProps) {\n const { currentUser } = useComradeCircle();\n const react = useComReactToPost();\n const [open, setOpen] = useState(false);\n\n const meId = currentUser?.id;\n const counts = new Map<ComReactionType, { count: number; mine: boolean }>();\n for (const r of post.reactions ?? []) {\n const cur = counts.get(r.type) ?? { count: 0, mine: false };\n cur.count += 1;\n if (meId && r.memberId === meId) cur.mine = true;\n counts.set(r.type, cur);\n }\n\n const toggle = async (type: ComReactionType) => {\n setOpen(false);\n try {\n await react.mutateAsync({ postId: post.id, type });\n } catch (err) {\n notify.error('Could not react', describeError(err));\n }\n };\n\n const active = REACTIONS.filter((r) => (counts.get(r.type)?.count ?? 0) > 0);\n\n return (\n <div className=\"flex flex-wrap items-center gap-1.5\">\n {active.map((r) => {\n const info = counts.get(r.type)!;\n return (\n <button\n key={r.type}\n type=\"button\"\n onClick={() => toggle(r.type)}\n disabled={react.isPending}\n aria-pressed={info.mine}\n aria-label={`${r.label} (${info.count})`}\n className={cn(\n 'inline-flex items-center gap-1 rounded-full border px-2 py-0.5 text-xs font-medium transition-transform duration-150 active:scale-90',\n info.mine\n ? 'border-accent bg-[var(--color-accent-soft)] text-text-primary shadow-[0_0_0_2px_var(--color-accent-soft)]'\n : 'border-border-seam bg-bg-surface text-text-secondary hover:-translate-y-px hover:bg-bg-sunken'\n )}\n >\n <span aria-hidden=\"true\">{r.emoji}</span>\n <span className=\"tabular-nums\">{info.count}</span>\n </button>\n );\n })}\n\n <Popover open={open} onOpenChange={setOpen}>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n aria-label=\"Add reaction\"\n className=\"inline-flex items-center gap-1 rounded-full border border-border-seam bg-bg-surface px-2 py-0.5 text-xs text-text-secondary transition-colors hover:bg-bg-sunken hover:text-text-primary\"\n >\n <SmilePlus className=\"h-3.5 w-3.5\" />\n </button>\n </PopoverTrigger>\n <PopoverContent className=\"w-auto p-1.5\" align=\"start\">\n <div className=\"flex items-center gap-0.5\">\n {REACTIONS.map((r) => {\n const mine = counts.get(r.type)?.mine ?? false;\n return (\n <button\n key={r.type}\n type=\"button\"\n onClick={() => toggle(r.type)}\n disabled={react.isPending}\n title={r.label}\n aria-label={r.label}\n className={cn(\n 'flex h-9 w-9 items-center justify-center rounded-lg text-lg transition-transform hover:scale-110 hover:bg-bg-sunken',\n mine && 'bg-[var(--color-accent-soft)]'\n )}\n >\n <span aria-hidden=\"true\">{r.emoji}</span>\n </button>\n );\n })}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;AAmBA,IAAM,IAAuE;CAC3E;EAAE,MAAM;EAAQ,OAAO;EAAM,OAAO;EAAQ;CAC5C;EAAE,MAAM;EAAQ,OAAO;EAAM,OAAO;EAAQ;CAC5C;EAAE,MAAM;EAAa,OAAO;EAAM,OAAO;EAAa;CACtD;EAAE,MAAM;EAAc,OAAO;EAAM,OAAO;EAAc;CACxD;EAAE,MAAM;EAAS,OAAO;EAAM,OAAO;EAAS;CAC9C;EAAE,MAAM;EAAW,OAAO;EAAM,OAAO;EAAW;CACnD;AAMD,SAAgB,EAAY,EAAE,WAA0B;CACtD,IAAM,EAAE,mBAAgB,GAAkB,EACpC,IAAQ,GAAmB,EAC3B,CAAC,GAAM,KAAW,EAAS,GAAM,EAEjC,IAAO,GAAa,IACpB,oBAAS,IAAI,KAAwD;AAC3E,MAAK,IAAM,KAAK,EAAK,aAAa,EAAE,EAAE;EACpC,IAAM,IAAM,EAAO,IAAI,EAAE,KAAK,IAAI;GAAE,OAAO;GAAG,MAAM;GAAO;AAG3D,EAFA,EAAI,SAAS,GACT,KAAQ,EAAE,aAAa,MAAM,EAAI,OAAO,KAC5C,EAAO,IAAI,EAAE,MAAM,EAAI;;CAGzB,IAAM,IAAS,OAAO,MAA0B;AAC9C,IAAQ,GAAM;AACd,MAAI;AACF,SAAM,EAAM,YAAY;IAAE,QAAQ,EAAK;IAAI;IAAM,CAAC;WAC3C,GAAK;AACZ,KAAO,MAAM,mBAAmB,EAAc,EAAI,CAAC;;;AAMvD,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CAHa,EAAU,QAAQ,OAAO,EAAO,IAAI,EAAE,KAAK,EAAE,SAAS,KAAK,EAAE,CAIhE,KAAK,MAAM;GACjB,IAAM,IAAO,EAAO,IAAI,EAAE,KAAK;AAC/B,UACE,kBAAC,UAAD;IAEE,MAAK;IACL,eAAe,EAAO,EAAE,KAAK;IAC7B,UAAU,EAAM;IAChB,gBAAc,EAAK;IACnB,cAAY,GAAG,EAAE,MAAM,IAAI,EAAK,MAAM;IACtC,WAAW,EACT,wIACA,EAAK,OACD,8GACA,gGACL;cAZH,CAcE,kBAAC,QAAD;KAAM,eAAY;eAAQ,EAAE;KAAa,CAAA,EACzC,kBAAC,QAAD;KAAM,WAAU;eAAgB,EAAK;KAAa,CAAA,CAC3C;MAfF,EAAE,KAeA;IAEX,EAEF,kBAAC,GAAD;GAAe;GAAM,cAAc;aAAnC,CACE,kBAAC,GAAD;IAAgB,SAAA;cACd,kBAAC,UAAD;KACE,MAAK;KACL,cAAW;KACX,WAAU;eAEV,kBAAC,GAAD,EAAW,WAAU,eAAgB,CAAA;KAC9B,CAAA;IACM,CAAA,EACjB,kBAAC,GAAD;IAAgB,WAAU;IAAe,OAAM;cAC7C,kBAAC,OAAD;KAAK,WAAU;eACZ,EAAU,KAAK,MAAM;MACpB,IAAM,IAAO,EAAO,IAAI,EAAE,KAAK,EAAE,QAAQ;AACzC,aACE,kBAAC,UAAD;OAEE,MAAK;OACL,eAAe,EAAO,EAAE,KAAK;OAC7B,UAAU,EAAM;OAChB,OAAO,EAAE;OACT,cAAY,EAAE;OACd,WAAW,EACT,uHACA,KAAQ,gCACT;iBAED,kBAAC,QAAD;QAAM,eAAY;kBAAQ,EAAE;QAAa,CAAA;OAClC,EAZF,EAAE,KAYA;OAEX;KACE,CAAA;IACS,CAAA,CACT;KACN"}
|
|
@@ -27,23 +27,8 @@ var a = ({ label: t = "Loading…", className: a }) => /* @__PURE__ */ r("div",
|
|
|
27
27
|
children: "Retry"
|
|
28
28
|
})
|
|
29
29
|
]
|
|
30
|
-
}), s = ({ title: t, description: i, action: a, children: o, className: s }) => /* @__PURE__ */ r("section", {
|
|
31
|
-
className: e("mt-8 first:mt-0", s),
|
|
32
|
-
children: [/* @__PURE__ */ r("div", {
|
|
33
|
-
className: "mb-3 flex items-end justify-between gap-3",
|
|
34
|
-
children: [/* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("h2", {
|
|
35
|
-
className: "text-base font-semibold text-text-primary",
|
|
36
|
-
children: t
|
|
37
|
-
}), i && /* @__PURE__ */ n("p", {
|
|
38
|
-
className: "mt-0.5 text-sm text-text-secondary",
|
|
39
|
-
children: i
|
|
40
|
-
})] }), a && /* @__PURE__ */ n("div", {
|
|
41
|
-
className: "shrink-0",
|
|
42
|
-
children: a
|
|
43
|
-
})]
|
|
44
|
-
}), o]
|
|
45
30
|
});
|
|
46
31
|
//#endregion
|
|
47
|
-
export { o as ErrorView, a as LoadingView
|
|
32
|
+
export { o as ErrorView, a as LoadingView };
|
|
48
33
|
|
|
49
34
|
//# sourceMappingURL=StateViews.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/comradecircle/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module comradecircle/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label = 'Loading…', className }) => (\n <div className={cn('flex min-h-[40vh] flex-col items-center justify-center gap-3', className)}>\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-text-secondary\">{label}</p>\n </div>\n);\n\ninterface ErrorViewProps {\n title?: string;\n message?: string;\n onRetry?: () => void;\n className?: string;\n}\n\nexport const ErrorView: FC<ErrorViewProps> = ({\n title = 'Something went wrong',\n message,\n onRetry,\n className,\n}) => (\n <div\n className={cn(\n 'flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center',\n className\n )}\n >\n <AlertCircle className=\"h-10 w-10 text-status-error-text\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">{title}</h2>\n {message && <p className=\"mt-1 max-w-md text-sm text-text-secondary\">{message}</p>}\n </div>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Retry\n </button>\n )}\n </div>\n);\n\ninterface SectionProps {\n title: string;\n description?: string;\n action?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const Section: FC<SectionProps> = ({ title, description, action, children, className }) => (\n <section className={cn('mt-8 first:mt-0', className)}>\n <div className=\"mb-3 flex items-end justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n {description && <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n {children}\n </section>\n);\n"],"mappings":";;;;;AAeA,IAAa,KAAqC,EAAE,WAAQ,YAAY,mBACtE,kBAAC,OAAD;CAAK,WAAW,EAAG,gEAAgE,EAAU;WAA7F,CACE,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA,EACrB,kBAAC,KAAD;EAAG,WAAU;YAA+B;EAAU,CAAA,CAClD;IAUK,KAAiC,EAC5C,WAAQ,wBACR,YACA,YACA,mBAEA,kBAAC,OAAD;CACE,WAAW,EACT,4EACA,EACD;WAJH;EAME,kBAAC,GAAD,EAAa,WAAU,oCAAqC,CAAA;EAC5D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAA2C;GAAW,CAAA,EACnE,KAAW,kBAAC,KAAD;GAAG,WAAU;aAA6C;GAAY,CAAA,CAC9E,EAAA,CAAA;EACL,KACC,kBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAU;aACX;GAEQ,CAAA;EAEP
|
|
1
|
+
{"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/comradecircle/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module comradecircle/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label = 'Loading…', className }) => (\n <div className={cn('flex min-h-[40vh] flex-col items-center justify-center gap-3', className)}>\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-text-secondary\">{label}</p>\n </div>\n);\n\ninterface ErrorViewProps {\n title?: string;\n message?: string;\n onRetry?: () => void;\n className?: string;\n}\n\nexport const ErrorView: FC<ErrorViewProps> = ({\n title = 'Something went wrong',\n message,\n onRetry,\n className,\n}) => (\n <div\n className={cn(\n 'flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center',\n className\n )}\n >\n <AlertCircle className=\"h-10 w-10 text-status-error-text\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">{title}</h2>\n {message && <p className=\"mt-1 max-w-md text-sm text-text-secondary\">{message}</p>}\n </div>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Retry\n </button>\n )}\n </div>\n);\n\ninterface SectionProps {\n title: string;\n description?: string;\n action?: ReactNode;\n children: ReactNode;\n className?: string;\n}\n\nexport const Section: FC<SectionProps> = ({ title, description, action, children, className }) => (\n <section className={cn('mt-8 first:mt-0', className)}>\n <div className=\"mb-3 flex items-end justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n {description && <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n {children}\n </section>\n);\n"],"mappings":";;;;;AAeA,IAAa,KAAqC,EAAE,WAAQ,YAAY,mBACtE,kBAAC,OAAD;CAAK,WAAW,EAAG,gEAAgE,EAAU;WAA7F,CACE,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA,EACrB,kBAAC,KAAD;EAAG,WAAU;YAA+B;EAAU,CAAA,CAClD;IAUK,KAAiC,EAC5C,WAAQ,wBACR,YACA,YACA,mBAEA,kBAAC,OAAD;CACE,WAAW,EACT,4EACA,EACD;WAJH;EAME,kBAAC,GAAD,EAAa,WAAU,oCAAqC,CAAA;EAC5D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAA2C;GAAW,CAAA,EACnE,KAAW,kBAAC,KAAD;GAAG,WAAU;aAA6C;GAAY,CAAA,CAC9E,EAAA,CAAA;EACL,KACC,kBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAU;aACX;GAEQ,CAAA;EAEP"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/comradecircle/components/StatusBadge.tsx"],"sourcesContent":["/**\n * Status Badge Component\n * @module comradecircle/components\n *\n * A colored badge for ComradeCircle domain statuses (circle status/visibility,\n * event status/mode, membership status, member role, poll status, post status,\n * presence, RSVP status) with semantic color mapping. Accepts the raw server\n * enum value.\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatEnumLabel } from '../utils/formatters';\n\ninterface StatusBadgeProps {\n status: string;\n className?: string;\n}\n\ntype BadgeVariant = 'success' | 'warning' | 'destructive' | 'secondary' | 'info' | 'outline';\n\nconst variantStyles: Record<BadgeVariant, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n destructive: 'bg-status-error-bg-subtle text-status-error-text',\n secondary: 'bg-bg-sunken text-text-secondary',\n info: 'bg-[var(--color-accent-soft)] text-text-primary',\n outline: 'border border-border-seam text-text-primary',\n};\n\n// Statuses that represent a \"live\" / active condition get a subtle opacity-only\n// glow pulse (reduced-motion safe via motion-safe:).\nconst liveStatuses = new Set(['LIVE', 'ONLINE', 'ACTIVE']);\n\nconst statusVariantMap: Record<string, BadgeVariant> = {\n // Circle status\n ACTIVE: 'success',\n ARCHIVED: 'outline',\n SUSPENDED: 'destructive',\n\n // Circle visibility\n PUBLIC: 'success',\n PRIVATE: 'secondary',\n SECRET: 'warning',\n\n // Channel visibility\n CIRCLE: 'info',\n\n // Channel type\n ANNOUNCEMENT: 'warning',\n FORUM: 'info',\n TEXT: 'secondary',\n VOICE: 'info',\n\n // Event status\n SCHEDULED: 'info',\n LIVE: 'success',\n COMPLETED: 'secondary',\n CANCELLED: 'destructive',\n\n // Event mode\n ONLINE: '
|
|
1
|
+
{"version":3,"file":"StatusBadge.js","names":[],"sources":["../../../src/comradecircle/components/StatusBadge.tsx"],"sourcesContent":["/**\n * Status Badge Component\n * @module comradecircle/components\n *\n * A colored badge for ComradeCircle domain statuses (circle status/visibility,\n * event status/mode, membership status, member role, poll status, post status,\n * presence, RSVP status) with semantic color mapping. Accepts the raw server\n * enum value.\n */\n\nimport type { FC } from 'react';\nimport { cn } from '../utils/cn';\nimport { formatEnumLabel } from '../utils/formatters';\n\ninterface StatusBadgeProps {\n status: string;\n className?: string;\n}\n\ntype BadgeVariant = 'success' | 'warning' | 'destructive' | 'secondary' | 'info' | 'outline';\n\nconst variantStyles: Record<BadgeVariant, string> = {\n success: 'bg-status-success-bg-subtle text-status-success-text',\n warning: 'bg-status-warning-bg-subtle text-status-warning-text',\n destructive: 'bg-status-error-bg-subtle text-status-error-text',\n secondary: 'bg-bg-sunken text-text-secondary',\n info: 'bg-[var(--color-accent-soft)] text-text-primary',\n outline: 'border border-border-seam text-text-primary',\n};\n\n// Statuses that represent a \"live\" / active condition get a subtle opacity-only\n// glow pulse (reduced-motion safe via motion-safe:).\nconst liveStatuses = new Set(['LIVE', 'ONLINE', 'ACTIVE']);\n\nconst statusVariantMap: Record<string, BadgeVariant> = {\n // Circle status\n ACTIVE: 'success',\n ARCHIVED: 'outline',\n SUSPENDED: 'destructive',\n\n // Circle visibility\n PUBLIC: 'success',\n PRIVATE: 'secondary',\n SECRET: 'warning',\n\n // Channel visibility\n CIRCLE: 'info',\n\n // Channel type\n ANNOUNCEMENT: 'warning',\n FORUM: 'info',\n TEXT: 'secondary',\n VOICE: 'info',\n\n // Event status\n SCHEDULED: 'info',\n LIVE: 'success',\n COMPLETED: 'secondary',\n CANCELLED: 'destructive',\n\n // Event mode\n ONLINE: 'success',\n IN_PERSON: 'success',\n HYBRID: 'warning',\n\n // Membership status\n PENDING: 'warning',\n BANNED: 'destructive',\n LEFT: 'outline',\n\n // Member role\n OWNER: 'info',\n ADMIN: 'warning',\n MODERATOR: 'info',\n MEMBER: 'secondary',\n\n // Poll status\n OPEN: 'success',\n CLOSED: 'outline',\n\n // Post status\n PUBLISHED: 'success',\n DRAFT: 'secondary',\n HIDDEN: 'warning',\n REMOVED: 'destructive',\n\n // Presence (ONLINE handled by ACTIVE→success above; keep the green convention)\n AWAY: 'warning',\n BUSY: 'destructive',\n OFFLINE: 'secondary',\n\n // RSVP status\n GOING: 'success',\n INTERESTED: 'info',\n WAITLISTED: 'warning',\n NOT_GOING: 'outline',\n};\n\nexport const StatusBadge: FC<StatusBadgeProps> = ({ status, className }) => {\n const key = status.toUpperCase();\n const variant = statusVariantMap[key] ?? 'secondary';\n const isLive = liveStatuses.has(key);\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-medium',\n variantStyles[variant],\n className\n )}\n >\n {isLive && (\n <span\n aria-hidden=\"true\"\n className=\"size-1.5 rounded-full bg-current motion-safe:animate-vc-glow-pulse\"\n />\n )}\n {formatEnumLabel(status)}\n </span>\n );\n};\n"],"mappings":";;;;AAqBA,IAAM,IAA8C;CAClD,SAAS;CACT,SAAS;CACT,aAAa;CACb,WAAW;CACX,MAAM;CACN,SAAS;CACV,EAIK,IAAe,IAAI,IAAI;CAAC;CAAQ;CAAU;CAAS,CAAC,EAEpD,IAAiD;CAErD,QAAQ;CACR,UAAU;CACV,WAAW;CAGX,QAAQ;CACR,SAAS;CACT,QAAQ;CAGR,QAAQ;CAGR,cAAc;CACd,OAAO;CACP,MAAM;CACN,OAAO;CAGP,WAAW;CACX,MAAM;CACN,WAAW;CACX,WAAW;CAGX,QAAQ;CACR,WAAW;CACX,QAAQ;CAGR,SAAS;CACT,QAAQ;CACR,MAAM;CAGN,OAAO;CACP,OAAO;CACP,WAAW;CACX,QAAQ;CAGR,MAAM;CACN,QAAQ;CAGR,WAAW;CACX,OAAO;CACP,QAAQ;CACR,SAAS;CAGT,MAAM;CACN,MAAM;CACN,SAAS;CAGT,OAAO;CACP,YAAY;CACZ,YAAY;CACZ,WAAW;CACZ,EAEY,KAAqC,EAAE,WAAQ,mBAAgB;CAC1E,IAAM,IAAM,EAAO,aAAa,EAC1B,IAAU,EAAiB,MAAQ,aACnC,IAAS,EAAa,IAAI,EAAI;AAEpC,QACE,kBAAC,QAAD;EACE,WAAW,EACT,mFACA,EAAc,IACd,EACD;YALH,CAOG,KACC,kBAAC,QAAD;GACE,eAAY;GACZ,WAAU;GACV,CAAA,EAEH,EAAgB,EAAO,CACnB"}
|