@burdenoff/microfe-conversations 2026.527.1 → 2026.528.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/dist/conversations/ConversationsUserRoutes.js +6 -6
  2. package/dist/conversations/ConversationsUserRoutes.js.map +1 -1
  3. package/dist/conversations/components/ConversationRow.js +176 -0
  4. package/dist/conversations/components/ConversationRow.js.map +1 -0
  5. package/dist/conversations/components/EmptyState.js +10 -21
  6. package/dist/conversations/components/EmptyState.js.map +1 -1
  7. package/dist/conversations/components/InboxLayout.js +185 -0
  8. package/dist/conversations/components/InboxLayout.js.map +1 -0
  9. package/dist/conversations/components/LazyPageBoundary.js.map +1 -1
  10. package/dist/conversations/components/PageLayout.js +16 -34
  11. package/dist/conversations/components/PageLayout.js.map +1 -1
  12. package/dist/conversations/components/PageSection.js +10 -19
  13. package/dist/conversations/components/PageSection.js.map +1 -1
  14. package/dist/conversations/components/lazyRetry.js.map +1 -1
  15. package/dist/conversations/hooks/useConversationQueries.js +48 -34
  16. package/dist/conversations/hooks/useConversationQueries.js.map +1 -1
  17. package/dist/conversations/hooks/useMessageQueries.js.map +1 -1
  18. package/dist/conversations/pages/ConversationAdminPages.js.map +1 -1
  19. package/dist/conversations/pages/ConversationListPage.js +187 -226
  20. package/dist/conversations/pages/ConversationListPage.js.map +1 -1
  21. package/dist/conversations/pages/ConversationsLandingPage.js +93 -103
  22. package/dist/conversations/pages/ConversationsLandingPage.js.map +1 -1
  23. package/dist/conversations/pages/ConversationsSettingsPage.js +201 -182
  24. package/dist/conversations/pages/ConversationsSettingsPage.js.map +1 -1
  25. package/dist/generated/wspace-operations.js +72 -56
  26. package/dist/generated/wspace-operations.js.map +1 -1
  27. package/package.json +2 -2
  28. package/dist/conversations/components/ConversationCard.js +0 -119
  29. package/dist/conversations/components/ConversationCard.js.map +0 -1
@@ -2,8 +2,9 @@ import { cn as e } from "../utils/cn.js";
2
2
  import "./PageSection.js";
3
3
  import "./EmptyState.js";
4
4
  import { jsx as t, jsxs as n } from "react/jsx-runtime";
5
+ import { PageHeader as r } from "@burdenoff/fe-libs/chrome";
5
6
  //#region src/conversations/components/PageLayout.tsx
6
- var r = {
7
+ var i = {
7
8
  sm: "max-w-screen-sm",
8
9
  md: "max-w-screen-md",
9
10
  lg: "max-w-screen-lg",
@@ -12,47 +13,28 @@ var r = {
12
13
  "3xl": "max-w-[1600px]",
13
14
  full: "max-w-full"
14
15
  };
15
- function i({ children: i, title: a, subtitle: o, icon: s, headerActions: c, headerContent: l, maxWidth: u = "xl", showHeader: d = !0, className: f, contentClassName: p, dataTour: m }) {
16
+ function a({ children: a, title: o, subtitle: s, icon: c, headerActions: l, headerContent: u, maxWidth: d = "xl", showHeader: f = !0, className: p, contentClassName: m, dataTour: h }) {
16
17
  return /* @__PURE__ */ t("div", {
17
- "data-tour": m,
18
- className: e("min-h-full w-full", "px-4 sm:px-6 lg:px-8 xl:px-12", "py-6 sm:py-8 lg:py-10", "animate-in fade-in-0 slide-in-from-bottom-4 duration-500", f),
18
+ "data-tour": h,
19
+ className: e("min-h-full w-full", "px-4 sm:px-6 lg:px-8 xl:px-12", "py-6 sm:py-8 lg:py-10", "animate-in fade-in-0 slide-in-from-bottom-4 duration-500", p),
19
20
  children: /* @__PURE__ */ n("div", {
20
- className: e("mx-auto w-full", r[u], p),
21
- children: [d && (a || c) && /* @__PURE__ */ n("header", {
22
- className: "mb-6 sm:mb-8",
23
- children: [/* @__PURE__ */ n("div", {
24
- className: "flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",
25
- children: [/* @__PURE__ */ n("div", {
26
- className: "space-y-1",
27
- children: [(a || s) && /* @__PURE__ */ n("div", {
28
- className: "flex items-center gap-3",
29
- children: [s && /* @__PURE__ */ t("div", {
30
- className: "flex-shrink-0 p-2.5 rounded-xl bg-primary/10 text-primary",
31
- children: s
32
- }), a && /* @__PURE__ */ t("h1", {
33
- className: "text-2xl sm:text-3xl font-bold tracking-tight text-foreground",
34
- children: a
35
- })]
36
- }), o && /* @__PURE__ */ t("p", {
37
- className: "text-sm sm:text-base text-muted-foreground max-w-2xl",
38
- children: o
39
- })]
40
- }), c && /* @__PURE__ */ t("div", {
41
- className: "flex items-center gap-2 flex-shrink-0",
42
- children: c
43
- })]
44
- }), l && /* @__PURE__ */ t("div", {
45
- className: "mt-4",
46
- children: l
47
- })]
21
+ className: e("mx-auto w-full", i[d], m),
22
+ children: [f && (o || l) && /* @__PURE__ */ n("div", {
23
+ className: "mb-6 sm:mb-8 space-y-4",
24
+ children: [/* @__PURE__ */ t(r, {
25
+ title: o ?? "",
26
+ description: s,
27
+ icon: c,
28
+ actions: l
29
+ }), u && /* @__PURE__ */ t("div", { children: u })]
48
30
  }), /* @__PURE__ */ t("div", {
49
31
  className: "space-y-6",
50
- children: i
32
+ children: a
51
33
  })]
52
34
  })
53
35
  });
54
36
  }
55
37
  //#endregion
56
- export { i as PageLayout };
38
+ export { a as PageLayout };
57
39
 
58
40
  //# sourceMappingURL=PageLayout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/conversations/components/PageLayout.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\ninterface PageLayoutProps {\n children: ReactNode;\n /** Page title */\n title?: string;\n /** Page subtitle/description */\n subtitle?: string;\n /** Icon component to display next to title */\n icon?: ReactNode;\n /** Actions to display in header (buttons, etc.) */\n headerActions?: ReactNode;\n /** Additional header content below title */\n headerContent?: ReactNode;\n /** Maximum width of content: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full' */\n maxWidth?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"full\";\n /** Whether to show the header section */\n showHeader?: boolean;\n /** Additional CSS classes for the container */\n className?: string;\n /** Additional CSS classes for the content area */\n contentClassName?: string;\n /** Stable selector for guided tours and smoke tests */\n dataTour?: string;\n}\n\nconst maxWidthClasses = {\n sm: \"max-w-screen-sm\", // 640px\n md: \"max-w-screen-md\", // 768px\n lg: \"max-w-screen-lg\", // 1024px\n xl: \"max-w-screen-xl\", // 1280px\n \"2xl\": \"max-w-screen-2xl\", // 1536px\n \"3xl\": \"max-w-[1600px]\",\n full: \"max-w-full\",\n};\n\n/**\n * PageLayout - A consistent page wrapper with responsive design\n *\n * Features:\n * - Proper max-width constraints\n * - Responsive padding\n * - Animated entrance\n * - Consistent header styling\n */\nexport function PageLayout({\n children,\n title,\n subtitle,\n icon,\n headerActions,\n headerContent,\n maxWidth = \"xl\",\n showHeader = true,\n className,\n contentClassName,\n dataTour,\n}: PageLayoutProps) {\n return (\n <div\n data-tour={dataTour}\n className={cn(\n // Base styles - full width container with padding\n \"min-h-full w-full\",\n // Responsive horizontal padding\n \"px-4 sm:px-6 lg:px-8 xl:px-12\",\n // Responsive vertical padding\n \"py-6 sm:py-8 lg:py-10\",\n // Entrance animation\n \"animate-in fade-in-0 slide-in-from-bottom-4 duration-500\",\n className,\n )}\n >\n {/* Max-width constrained content container */}\n <div\n className={cn(\n \"mx-auto w-full\",\n maxWidthClasses[maxWidth],\n contentClassName,\n )}\n >\n {/* Page Header */}\n {showHeader && (title || headerActions) && (\n <header className=\"mb-6 sm:mb-8\">\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n {/* Title Section */}\n <div className=\"space-y-1\">\n {(title || icon) && (\n <div className=\"flex items-center gap-3\">\n {icon && (\n <div className=\"flex-shrink-0 p-2.5 rounded-xl bg-primary/10 text-primary\">\n {icon}\n </div>\n )}\n {title && (\n <h1 className=\"text-2xl sm:text-3xl font-bold tracking-tight text-foreground\">\n {title}\n </h1>\n )}\n </div>\n )}\n {subtitle && (\n <p className=\"text-sm sm:text-base text-muted-foreground max-w-2xl\">\n {subtitle}\n </p>\n )}\n </div>\n\n {/* Header Actions */}\n {headerActions && (\n <div className=\"flex items-center gap-2 flex-shrink-0\">\n {headerActions}\n </div>\n )}\n </div>\n\n {/* Additional Header Content */}\n {headerContent && <div className=\"mt-4\">{headerContent}</div>}\n </header>\n )}\n\n {/* Page content — must not use a <main> landmark here because the\n host shell (AppShellLayout) already renders one; nesting <main>\n elements is invalid HTML and an a11y violation. */}\n <div className=\"space-y-6\">{children}</div>\n </div>\n </div>\n );\n}\n\nexport { PageSection } from \"./PageSection\";\nexport { EmptyState } from \"./EmptyState\";\n"],"mappings":";;;;;AA2BA,IAAM,IAAkB;CACtB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,MAAM;CACP;AAWD,SAAgB,EAAW,EACzB,aACA,UACA,aACA,SACA,kBACA,kBACA,cAAW,MACX,gBAAa,IACb,cACA,qBACA,eACkB;AAClB,QACE,kBAAC,OAAD;EACE,aAAW;EACX,WAAW,EAET,qBAEA,iCAEA,yBAEA,4DACA,EACD;YAGD,kBAAC,OAAD;GACE,WAAW,EACT,kBACA,EAAgB,IAChB,EACD;aALH,CAQG,MAAe,KAAS,MACvB,kBAAC,UAAD;IAAQ,WAAU;cAAlB,CACE,kBAAC,OAAD;KAAK,WAAU;eAAf,CAEE,kBAAC,OAAD;MAAK,WAAU;gBAAf,EACI,KAAS,MACT,kBAAC,OAAD;OAAK,WAAU;iBAAf,CACG,KACC,kBAAC,OAAD;QAAK,WAAU;kBACZ;QACG,CAAA,EAEP,KACC,kBAAC,MAAD;QAAI,WAAU;kBACX;QACE,CAAA,CAEH;UAEP,KACC,kBAAC,KAAD;OAAG,WAAU;iBACV;OACC,CAAA,CAEF;SAGL,KACC,kBAAC,OAAD;MAAK,WAAU;gBACZ;MACG,CAAA,CAEJ;QAGL,KAAiB,kBAAC,OAAD;KAAK,WAAU;eAAQ;KAAoB,CAAA,CACtD;OAMX,kBAAC,OAAD;IAAK,WAAU;IAAa;IAAe,CAAA,CACvC;;EACF,CAAA"}
1
+ {"version":3,"file":"PageLayout.js","names":[],"sources":["../../../src/conversations/components/PageLayout.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { PageHeader as CanonicalPageHeader } from \"@burdenoff/fe-libs/chrome\";\nimport { cn } from \"../utils/cn\";\n\ninterface PageLayoutProps {\n children: ReactNode;\n /** Page title */\n title?: string;\n /** Page subtitle/description */\n subtitle?: string;\n /** Icon component to display next to title */\n icon?: ReactNode;\n /** Actions to display in header (buttons, etc.) */\n headerActions?: ReactNode;\n /** Additional header content below title */\n headerContent?: ReactNode;\n /** Maximum width of content: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | '3xl' | 'full' */\n maxWidth?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"full\";\n /** Whether to show the header section */\n showHeader?: boolean;\n /** Additional CSS classes for the container */\n className?: string;\n /** Additional CSS classes for the content area */\n contentClassName?: string;\n /** Stable selector for guided tours and smoke tests */\n dataTour?: string;\n}\n\nconst maxWidthClasses = {\n sm: \"max-w-screen-sm\", // 640px\n md: \"max-w-screen-md\", // 768px\n lg: \"max-w-screen-lg\", // 1024px\n xl: \"max-w-screen-xl\", // 1280px\n \"2xl\": \"max-w-screen-2xl\", // 1536px\n \"3xl\": \"max-w-[1600px]\",\n full: \"max-w-full\",\n};\n\n/**\n * PageLayout — local wrapper that delegates header rendering to the\n * canonical `<PageHeader>` from `@burdenoff/fe-libs/chrome` while\n * preserving the legacy `headerContent` slot and the max-width container\n * chrome that microfe-conversations pages rely on.\n */\nexport function PageLayout({\n children,\n title,\n subtitle,\n icon,\n headerActions,\n headerContent,\n maxWidth = \"xl\",\n showHeader = true,\n className,\n contentClassName,\n dataTour,\n}: PageLayoutProps) {\n return (\n <div\n data-tour={dataTour}\n className={cn(\n \"min-h-full w-full\",\n \"px-4 sm:px-6 lg:px-8 xl:px-12\",\n \"py-6 sm:py-8 lg:py-10\",\n \"animate-in fade-in-0 slide-in-from-bottom-4 duration-500\",\n className,\n )}\n >\n <div\n className={cn(\n \"mx-auto w-full\",\n maxWidthClasses[maxWidth],\n contentClassName,\n )}\n >\n {showHeader && (title || headerActions) && (\n <div className=\"mb-6 sm:mb-8 space-y-4\">\n <CanonicalPageHeader\n title={title ?? \"\"}\n description={subtitle}\n icon={icon}\n actions={headerActions}\n />\n {headerContent && <div>{headerContent}</div>}\n </div>\n )}\n\n <div className=\"space-y-6\">{children}</div>\n </div>\n </div>\n );\n}\n\nexport { PageSection } from \"./PageSection\";\nexport { EmptyState } from \"./EmptyState\";\n"],"mappings":";;;;;;AA4BA,IAAM,IAAkB;CACtB,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,IAAI;CACJ,OAAO;CACP,OAAO;CACP,MAAM;CACP;AAQD,SAAgB,EAAW,EACzB,aACA,UACA,aACA,SACA,kBACA,kBACA,cAAW,MACX,gBAAa,IACb,cACA,qBACA,eACkB;AAClB,QACE,kBAAC,OAAD;EACE,aAAW;EACX,WAAW,EACT,qBACA,iCACA,yBACA,4DACA,EACD;YAED,kBAAC,OAAD;GACE,WAAW,EACT,kBACA,EAAgB,IAChB,EACD;aALH,CAOG,MAAe,KAAS,MACvB,kBAAC,OAAD;IAAK,WAAU;cAAf,CACE,kBAAC,GAAD;KACE,OAAO,KAAS;KAChB,aAAa;KACP;KACN,SAAS;KACT,CAAA,EACD,KAAiB,kBAAC,OAAD,EAAA,UAAM,GAAoB,CAAA,CACxC;OAGR,kBAAC,OAAD;IAAK,WAAU;IAAa;IAAe,CAAA,CACvC;;EACF,CAAA"}
@@ -1,25 +1,16 @@
1
- import { cn as e } from "../utils/cn.js";
2
- import { jsx as t, jsxs as n } from "react/jsx-runtime";
1
+ import { jsx as e } from "react/jsx-runtime";
2
+ import { FormSection as t } from "@burdenoff/fe-libs/form";
3
3
  //#region src/conversations/components/PageSection.tsx
4
- function r({ children: r, title: i, description: a, actions: o, className: s }) {
5
- return /* @__PURE__ */ n("section", {
6
- className: e("space-y-4", s),
7
- children: [(i || o) && /* @__PURE__ */ n("div", {
8
- className: "flex items-center justify-between",
9
- children: [/* @__PURE__ */ n("div", { children: [i && /* @__PURE__ */ t("h2", {
10
- className: "text-lg font-semibold text-foreground",
11
- children: i
12
- }), a && /* @__PURE__ */ t("p", {
13
- className: "text-sm text-muted-foreground",
14
- children: a
15
- })] }), o && /* @__PURE__ */ t("div", {
16
- className: "flex items-center gap-2",
17
- children: o
18
- })]
19
- }), r]
4
+ function n({ children: n, title: r, description: i, actions: a, className: o }) {
5
+ return /* @__PURE__ */ e(t, {
6
+ title: r ?? "",
7
+ description: i,
8
+ actions: a,
9
+ className: o,
10
+ children: n
20
11
  });
21
12
  }
22
13
  //#endregion
23
- export { r as PageSection };
14
+ export { n as PageSection };
24
15
 
25
16
  //# sourceMappingURL=PageSection.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageSection.js","names":[],"sources":["../../../src/conversations/components/PageSection.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { cn } from \"../utils/cn\";\n\n/**\n * PageSection - A section within a page with consistent spacing\n */\nexport function PageSection({\n children,\n title,\n description,\n actions,\n className,\n}: {\n children: ReactNode;\n title?: string;\n description?: string;\n actions?: ReactNode;\n className?: string;\n}) {\n return (\n <section className={cn(\"space-y-4\", className)}>\n {(title || actions) && (\n <div className=\"flex items-center justify-between\">\n <div>\n {title && (\n <h2 className=\"text-lg font-semibold text-foreground\">{title}</h2>\n )}\n {description && (\n <p className=\"text-sm text-muted-foreground\">{description}</p>\n )}\n </div>\n {actions && <div className=\"flex items-center gap-2\">{actions}</div>}\n </div>\n )}\n {children}\n </section>\n );\n}\n"],"mappings":";;;AAMA,SAAgB,EAAY,EAC1B,aACA,UACA,gBACA,YACA,gBAOC;AACD,QACE,kBAAC,WAAD;EAAS,WAAW,EAAG,aAAa,EAAU;YAA9C,EACI,KAAS,MACT,kBAAC,OAAD;GAAK,WAAU;aAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACG,KACC,kBAAC,MAAD;IAAI,WAAU;cAAyC;IAAW,CAAA,EAEnE,KACC,kBAAC,KAAD;IAAG,WAAU;cAAiC;IAAgB,CAAA,CAE5D,EAAA,CAAA,EACL,KAAW,kBAAC,OAAD;IAAK,WAAU;cAA2B;IAAc,CAAA,CAChE;MAEP,EACO"}
1
+ {"version":3,"file":"PageSection.js","names":[],"sources":["../../../src/conversations/components/PageSection.tsx"],"sourcesContent":["import type { ReactNode } from \"react\";\nimport { FormSection } from \"@burdenoff/fe-libs/form\";\n\n/**\n * PageSection — local wrapper that delegates to the canonical\n * `<FormSection>` from `@burdenoff/fe-libs/form`. Keeps the legacy\n * `title`/`description`/`actions`/`className` shape so existing call\n * sites stay green.\n */\nexport function PageSection({\n children,\n title,\n description,\n actions,\n className,\n}: {\n children: ReactNode;\n title?: string;\n description?: string;\n actions?: ReactNode;\n className?: string;\n}) {\n return (\n <FormSection\n title={title ?? \"\"}\n description={description}\n actions={actions}\n className={className}\n >\n {children}\n </FormSection>\n );\n}\n"],"mappings":";;;AASA,SAAgB,EAAY,EAC1B,aACA,UACA,gBACA,YACA,gBAOC;AACD,QACE,kBAAC,GAAD;EACE,OAAO,KAAS;EACH;EACJ;EACE;EAEV;EACW,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"lazyRetry.js","names":[],"sources":["../../../src/conversations/components/lazyRetry.ts"],"sourcesContent":["import {\n lazy,\n type ComponentType,\n type LazyExoticComponent,\n} from \"react\";\n\nfunction isChunkLoadError(error: Error | null | undefined): boolean {\n if (!error) return false;\n if (error.name === \"ChunkLoadError\") return true;\n const message = error.message ?? \"\";\n return (\n message.includes(\"Loading chunk\") ||\n message.includes(\"Failed to fetch dynamically imported module\") ||\n message.includes(\"Importing a module script failed\") ||\n message.includes(\"Failed to fetch\")\n );\n}\n\nconst LAZY_RETRY_DELAY_MS = 300;\n\nexport function lazyRetry<TProps extends object = object>(\n factory: () => Promise<{ default: ComponentType<TProps> }>,\n): LazyExoticComponent<ComponentType<TProps>> {\n return lazy(() =>\n factory().catch((err: unknown) => {\n if (err instanceof Error && isChunkLoadError(err)) {\n return new Promise<{ default: ComponentType<TProps> }>(\n (resolve, reject) => {\n setTimeout(() => {\n factory().then(resolve, reject);\n }, LAZY_RETRY_DELAY_MS);\n },\n );\n }\n throw err;\n }),\n );\n}\n\nexport { isChunkLoadError };\n"],"mappings":";;AAMA,SAAS,EAAiB,GAA0C;AAClE,KAAI,CAAC,EAAO,QAAO;AACnB,KAAI,EAAM,SAAS,iBAAkB,QAAO;CAC5C,IAAM,IAAU,EAAM,WAAW;AACjC,QACE,EAAQ,SAAS,gBAAgB,IACjC,EAAQ,SAAS,8CAA8C,IAC/D,EAAQ,SAAS,mCAAmC,IACpD,EAAQ,SAAS,kBAAkB;;AAIvC,IAAM,IAAsB;AAE5B,SAAgB,EACd,GAC4C;AAC5C,QAAO,QACL,GAAS,CAAC,OAAO,MAAiB;AAChC,MAAI,aAAe,SAAS,EAAiB,EAAI,CAC/C,QAAO,IAAI,SACR,GAAS,MAAW;AACnB,oBAAiB;AACf,OAAS,CAAC,KAAK,GAAS,EAAO;MAC9B,EAAoB;IAE1B;AAEH,QAAM;GACN,CACH"}
1
+ {"version":3,"file":"lazyRetry.js","names":[],"sources":["../../../src/conversations/components/lazyRetry.ts"],"sourcesContent":["import { lazy, type ComponentType, type LazyExoticComponent } from \"react\";\n\nfunction isChunkLoadError(error: Error | null | undefined): boolean {\n if (!error) return false;\n if (error.name === \"ChunkLoadError\") return true;\n const message = error.message ?? \"\";\n return (\n message.includes(\"Loading chunk\") ||\n message.includes(\"Failed to fetch dynamically imported module\") ||\n message.includes(\"Importing a module script failed\") ||\n message.includes(\"Failed to fetch\")\n );\n}\n\nconst LAZY_RETRY_DELAY_MS = 300;\n\nexport function lazyRetry<TProps extends object = object>(\n factory: () => Promise<{ default: ComponentType<TProps> }>,\n): LazyExoticComponent<ComponentType<TProps>> {\n return lazy(() =>\n factory().catch((err: unknown) => {\n if (err instanceof Error && isChunkLoadError(err)) {\n return new Promise<{ default: ComponentType<TProps> }>(\n (resolve, reject) => {\n setTimeout(() => {\n factory().then(resolve, reject);\n }, LAZY_RETRY_DELAY_MS);\n },\n );\n }\n throw err;\n }),\n );\n}\n\nexport { isChunkLoadError };\n"],"mappings":";;AAEA,SAAS,EAAiB,GAA0C;AAClE,KAAI,CAAC,EAAO,QAAO;AACnB,KAAI,EAAM,SAAS,iBAAkB,QAAO;CAC5C,IAAM,IAAU,EAAM,WAAW;AACjC,QACE,EAAQ,SAAS,gBAAgB,IACjC,EAAQ,SAAS,8CAA8C,IAC/D,EAAQ,SAAS,mCAAmC,IACpD,EAAQ,SAAS,kBAAkB;;AAIvC,IAAM,IAAsB;AAE5B,SAAgB,EACd,GAC4C;AAC5C,QAAO,QACL,GAAS,CAAC,OAAO,MAAiB;AAChC,MAAI,aAAe,SAAS,EAAiB,EAAI,CAC/C,QAAO,IAAI,SACR,GAAS,MAAW;AACnB,oBAAiB;AACf,OAAS,CAAC,KAAK,GAAS,EAAO;MAC9B,EAAoB;IAE1B;AAEH,QAAM;GACN,CACH"}
@@ -1,21 +1,22 @@
1
1
  import { useConversations as e } from "../providers/ConversationsProvider.js";
2
- import { useArchiveConversationMutation as t, useCreateConversationMutation as n, useGetConversationQuery as r, useGetConversationsQuery as i, useMuteConversationMutation as a, usePinConversationMutation as o, useSearchConversationsQuery as s, useUnmuteConversationMutation as c, useUnpinConversationMutation as l, useUpdateConversationByHookMutation as u } from "../../generated/wspace-operations.js";
3
- import { mapConversation as d } from "../utils/mappers.js";
4
- import { useCallback as f, useMemo as p } from "react";
2
+ import { useArchiveConversationMutation as t, useCreateConversationMutation as n, useGetConversationQuery as r, useGetConversationsQuery as i, useMuteConversationMutation as a, usePinConversationMutation as o, useSearchConversationsQuery as s, useUnarchiveConversationMutation as c, useUnmuteConversationMutation as l, useUnpinConversationMutation as u, useUpdateConversationByHookMutation as d } from "../../generated/wspace-operations.js";
3
+ import { mapConversation as f } from "../utils/mappers.js";
4
+ import { useCallback as p, useMemo as m } from "react";
5
5
  //#region src/conversations/hooks/useConversationQueries.ts
6
- function m(t) {
6
+ function h(t) {
7
7
  let { workspaceId: n } = e(), r = i({
8
8
  variables: {
9
9
  first: t?.first ?? 25,
10
10
  after: t?.after,
11
11
  filter: {
12
12
  types: t?.types,
13
+ states: t?.states,
13
14
  hasUnread: t?.hasUnread,
14
15
  isPinned: t?.isPinned
15
16
  }
16
17
  },
17
18
  skip: !n
18
- }), a = p(() => r.data?.conversations.edges.map((e) => d(e.node)) ?? [], [r.data]), o = r.data?.conversations.pageInfo.hasNextPage ?? !1;
19
+ }), a = m(() => r.data?.conversations.edges.map((e) => f(e.node)) ?? [], [r.data]), o = r.data?.conversations.pageInfo.hasNextPage ?? !1;
19
20
  return {
20
21
  conversations: a,
21
22
  loading: r.loading,
@@ -28,6 +29,7 @@ function m(t) {
28
29
  after: e,
29
30
  filter: {
30
31
  types: t?.types,
32
+ states: t?.states,
31
33
  hasUnread: t?.hasUnread,
32
34
  isPinned: t?.isPinned
33
35
  }
@@ -38,13 +40,13 @@ function m(t) {
38
40
  }
39
41
  };
40
42
  }
41
- function h(t) {
43
+ function g(t) {
42
44
  let { workspaceId: n } = e(), i = r({
43
45
  variables: { id: t },
44
46
  skip: !n || !t
45
47
  });
46
48
  return {
47
- conversation: i.data?.conversation ? d(i.data.conversation) : null,
49
+ conversation: i.data?.conversation ? f(i.data.conversation) : null,
48
50
  loading: i.loading,
49
51
  error: i.error ?? null,
50
52
  refetch: () => {
@@ -52,7 +54,7 @@ function h(t) {
52
54
  }
53
55
  };
54
56
  }
55
- function g(t) {
57
+ function _(t) {
56
58
  let { workspaceId: n } = e(), r = t.trim(), i = s({
57
59
  variables: {
58
60
  query: r,
@@ -61,15 +63,15 @@ function g(t) {
61
63
  skip: !n || r.length < 2
62
64
  });
63
65
  return {
64
- conversations: i.data?.searchConversations.edges.map((e) => d(e.node)) ?? [],
66
+ conversations: i.data?.searchConversations.edges.map((e) => f(e.node)) ?? [],
65
67
  loading: i.loading,
66
68
  error: i.error ?? null
67
69
  };
68
70
  }
69
- function _() {
71
+ function v() {
70
72
  let { workspaceId: t } = e(), [r, i] = n();
71
73
  return {
72
- createConversation: f(async (e) => {
74
+ createConversation: p(async (e) => {
73
75
  if (!t) throw Error("Workspace context is required to create a conversation");
74
76
  try {
75
77
  let { data: n } = await r({ variables: { input: {
@@ -79,7 +81,7 @@ function _() {
79
81
  description: e.description,
80
82
  participantIds: e.participantIds
81
83
  } } }), i = n?.createConversation.conversation;
82
- return i ? d(i) : null;
84
+ return i ? f(i) : null;
83
85
  } catch (e) {
84
86
  throw e instanceof Error ? e : /* @__PURE__ */ Error("Failed to create conversation");
85
87
  }
@@ -88,40 +90,52 @@ function _() {
88
90
  error: i.error ?? null
89
91
  };
90
92
  }
91
- function v() {
92
- let [e, n] = t(), [r, i] = o(), [s, u] = l(), [d, p] = a(), [m, h] = c();
93
+ function y() {
94
+ let [e, n] = t(), [r, i] = c(), [s, d] = o(), [f, m] = u(), [h, g] = a(), [_, v] = l();
93
95
  return {
94
- archiveConversation: f(async (t) => {
95
- let { data: n } = await e({ variables: { id: t } });
96
+ archiveConversation: p(async (t) => {
97
+ let { data: n } = await e({
98
+ variables: { id: t },
99
+ refetchQueries: ["GetConversations"],
100
+ awaitRefetchQueries: !0
101
+ });
96
102
  return n?.archiveConversation.id === t;
97
103
  }, [e]),
98
- pinConversation: f(async (e) => {
99
- let { data: t } = await r({ variables: { conversationId: e } });
100
- return !!t?.pinConversation?.id;
104
+ unarchiveConversation: p(async (e) => {
105
+ let { data: t } = await r({
106
+ variables: { id: e },
107
+ refetchQueries: ["GetConversations"],
108
+ awaitRefetchQueries: !0
109
+ });
110
+ return t?.unarchiveConversation.id === e;
101
111
  }, [r]),
102
- unpinConversation: f(async (e) => {
112
+ pinConversation: p(async (e) => {
103
113
  let { data: t } = await s({ variables: { conversationId: e } });
104
- return !!t?.unpinConversation?.id;
114
+ return !!t?.pinConversation?.id;
105
115
  }, [s]),
106
- muteConversation: f(async (e) => {
107
- let { data: t } = await d({ variables: { conversationId: e } });
116
+ unpinConversation: p(async (e) => {
117
+ let { data: t } = await f({ variables: { conversationId: e } });
118
+ return !!t?.unpinConversation?.id;
119
+ }, [f]),
120
+ muteConversation: p(async (e) => {
121
+ let { data: t } = await h({ variables: { conversationId: e } });
108
122
  return !!t?.muteConversation?.id;
109
- }, [d]),
110
- unmuteConversation: f(async (e) => {
111
- let { data: t } = await m({ variables: { conversationId: e } });
123
+ }, [h]),
124
+ unmuteConversation: p(async (e) => {
125
+ let { data: t } = await _({ variables: { conversationId: e } });
112
126
  return !!t?.unmuteConversation?.id;
113
- }, [m]),
114
- loading: n.loading || i.loading || u.loading || p.loading || h.loading,
115
- error: n.error ?? i.error ?? u.error ?? p.error ?? h.error ?? null
127
+ }, [_]),
128
+ loading: n.loading || i.loading || d.loading || m.loading || g.loading || v.loading,
129
+ error: n.error ?? i.error ?? d.error ?? m.error ?? g.error ?? v.error ?? null
116
130
  };
117
131
  }
118
- function y() {
119
- let [e, t] = u();
132
+ function b() {
133
+ let [e, t] = d();
120
134
  return {
121
- updateConversation: f(async (t) => {
135
+ updateConversation: p(async (t) => {
122
136
  try {
123
137
  let { data: n } = await e({ variables: { input: t } }), r = n?.updateConversation?.conversation;
124
- return r ? d(r) : null;
138
+ return r ? f(r) : null;
125
139
  } catch (e) {
126
140
  throw e instanceof Error ? e : /* @__PURE__ */ Error("Failed to update conversation");
127
141
  }
@@ -131,6 +145,6 @@ function y() {
131
145
  };
132
146
  }
133
147
  //#endregion
134
- export { v as useConversationActions, _ as useCreateConversation, h as useGetConversation, m as useGetConversations, g as useSearchConversations, y as useUpdateConversation };
148
+ export { y as useConversationActions, v as useCreateConversation, g as useGetConversation, h as useGetConversations, _ as useSearchConversations, b as useUpdateConversation };
135
149
 
136
150
  //# sourceMappingURL=useConversationQueries.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useConversationQueries.js","names":[],"sources":["../../../src/conversations/hooks/useConversationQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useArchiveConversationMutation,\n useCreateConversationMutation,\n useGetConversationQuery,\n useGetConversationsQuery,\n useMuteConversationMutation,\n usePinConversationMutation,\n useSearchConversationsQuery,\n useUnmuteConversationMutation,\n useUnpinConversationMutation,\n useUpdateConversationByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type * as WspaceTypes from \"../../generated/wspace-types\";\nimport type {\n Conversation,\n ConversationType,\n ConversationVisibility,\n} from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapConversation } from \"../utils/mappers\";\n\ninterface UseGetConversationsOptions {\n first?: number;\n after?: string;\n types?: ConversationType[];\n hasUnread?: boolean;\n isPinned?: boolean;\n}\n\ninterface UseGetConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n fetchMore: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a paginated list of conversations.\n */\nexport function useGetConversations(\n options?: UseGetConversationsOptions,\n): UseGetConversationsResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationsQuery({\n variables: {\n first: options?.first ?? 25,\n after: options?.after,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n skip: !workspaceId,\n });\n\n const conversations = useMemo(\n () =>\n queryResult.data?.conversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const hasNextPage =\n queryResult.data?.conversations.pageInfo.hasNextPage ?? false;\n\n return {\n conversations,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage,\n fetchMore: () => {\n const endCursor = queryResult.data?.conversations.pageInfo.endCursor;\n if (!endCursor || !hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n first: options?.first ?? 25,\n after: endCursor,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseGetConversationResult {\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a single conversation by ID.\n */\nexport function useGetConversation(\n conversationId: string,\n): UseGetConversationResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationQuery({\n variables: { id: conversationId },\n skip: !workspaceId || !conversationId,\n });\n\n return {\n conversation: queryResult.data?.conversation\n ? mapConversation(queryResult.data.conversation)\n : null,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseSearchConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Search conversations by query string.\n */\nexport function useSearchConversations(\n query: string,\n): UseSearchConversationsResult {\n const { workspaceId } = useConversations();\n const trimmedQuery = query.trim();\n const queryResult = useSearchConversationsQuery({\n variables: { query: trimmedQuery, first: 25 },\n skip: !workspaceId || trimmedQuery.length < 2,\n });\n\n return {\n conversations:\n queryResult.data?.searchConversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n };\n}\n\ninterface CreateConversationInput {\n type: ConversationType;\n title?: string;\n description?: string;\n participantIds: string[];\n visibility?: ConversationVisibility;\n}\n\ninterface UseCreateConversationResult {\n createConversation: (\n input: CreateConversationInput,\n ) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Create a new conversation.\n */\nexport function useCreateConversation(): UseCreateConversationResult {\n const { workspaceId } = useConversations();\n const [createConversationMutation, mutationState] =\n useCreateConversationMutation();\n\n const createConversation = useCallback(\n async (input: CreateConversationInput): Promise<Conversation | null> => {\n if (!workspaceId) {\n throw new Error(\n \"Workspace context is required to create a conversation\",\n );\n }\n\n try {\n const { data } = await createConversationMutation({\n variables: {\n input: {\n workspaceId,\n type: input.type as WspaceTypes.ConversationType,\n title: input.title,\n description: input.description,\n participantIds: input.participantIds,\n },\n },\n });\n\n const conversation = data?.createConversation.conversation;\n return conversation ? mapConversation(conversation) : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to create conversation\");\n }\n },\n [createConversationMutation, workspaceId],\n );\n\n return {\n createConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseUpdateConversationResult {\n archiveConversation: (id: string) => Promise<boolean>;\n pinConversation: (id: string) => Promise<boolean>;\n unpinConversation: (id: string) => Promise<boolean>;\n muteConversation: (id: string) => Promise<boolean>;\n unmuteConversation: (id: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Conversation mutation operations.\n */\nexport function useConversationActions(): UseUpdateConversationResult {\n const [archiveConversationMutation, archiveState] =\n useArchiveConversationMutation();\n const [pinConversationMutation, pinState] = usePinConversationMutation();\n const [unpinConversationMutation, unpinState] =\n useUnpinConversationMutation();\n const [muteConversationMutation, muteState] = useMuteConversationMutation();\n const [unmuteConversationMutation, unmuteState] =\n useUnmuteConversationMutation();\n\n const archiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await archiveConversationMutation({ variables: { id } });\n return data?.archiveConversation.id === id;\n },\n [archiveConversationMutation],\n );\n\n const pinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await pinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.pinConversation?.id);\n },\n [pinConversationMutation],\n );\n\n const unpinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unpinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unpinConversation?.id);\n },\n [unpinConversationMutation],\n );\n\n const muteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await muteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.muteConversation?.id);\n },\n [muteConversationMutation],\n );\n\n const unmuteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unmuteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unmuteConversation?.id);\n },\n [unmuteConversationMutation],\n );\n\n return {\n archiveConversation,\n pinConversation,\n unpinConversation,\n muteConversation,\n unmuteConversation,\n loading:\n archiveState.loading ||\n pinState.loading ||\n unpinState.loading ||\n muteState.loading ||\n unmuteState.loading,\n error:\n (archiveState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n (muteState.error as Error | undefined) ??\n (unmuteState.error as Error | undefined) ??\n null,\n };\n}\n\ninterface UseUpdateConversationOptions {\n updateConversation: (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useUpdateConversation(): UseUpdateConversationOptions {\n const [updateConversationMutation, mutationState] =\n useUpdateConversationByHookMutation();\n\n const updateConversation = useCallback(\n async (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }): Promise<Conversation | null> => {\n try {\n const { data } = await updateConversationMutation({\n variables: { input },\n });\n const typedData = data as\n | {\n updateConversation?: {\n conversation?: Record<string, unknown> | null;\n };\n }\n | undefined;\n const conversation = typedData?.updateConversation?.conversation;\n return conversation\n ? mapConversation(conversation as Record<string, unknown>)\n : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to update conversation\");\n }\n },\n [updateConversationMutation],\n );\n\n return {\n updateConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useConversationQueries.js","names":[],"sources":["../../../src/conversations/hooks/useConversationQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useArchiveConversationMutation,\n useCreateConversationMutation,\n useGetConversationQuery,\n useGetConversationsQuery,\n useMuteConversationMutation,\n usePinConversationMutation,\n useSearchConversationsQuery,\n useUnarchiveConversationMutation,\n useUnmuteConversationMutation,\n useUnpinConversationMutation,\n useUpdateConversationByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type * as WspaceTypes from \"../../generated/wspace-types\";\nimport type {\n Conversation,\n ConversationState,\n ConversationType,\n ConversationVisibility,\n} from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapConversation } from \"../utils/mappers\";\n\ninterface UseGetConversationsOptions {\n first?: number;\n after?: string;\n types?: ConversationType[];\n /**\n * Conversation lifecycle states to include. When omitted the backend\n * returns ACTIVE conversations by default (filtering is union, not\n * exclusion, so `[\"ACTIVE\"]` and `undefined` are interchangeable for the\n * default inbox). Pass `[\"ARCHIVED\"]` to drive the archived tab.\n */\n states?: ConversationState[];\n hasUnread?: boolean;\n isPinned?: boolean;\n}\n\ninterface UseGetConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n fetchMore: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a paginated list of conversations.\n */\nexport function useGetConversations(\n options?: UseGetConversationsOptions,\n): UseGetConversationsResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationsQuery({\n variables: {\n first: options?.first ?? 25,\n after: options?.after,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n skip: !workspaceId,\n });\n\n const conversations = useMemo(\n () =>\n queryResult.data?.conversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const hasNextPage =\n queryResult.data?.conversations.pageInfo.hasNextPage ?? false;\n\n return {\n conversations,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage,\n fetchMore: () => {\n const endCursor = queryResult.data?.conversations.pageInfo.endCursor;\n if (!endCursor || !hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n first: options?.first ?? 25,\n after: endCursor,\n filter: {\n types: options?.types as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationType[]\n >,\n states: options?.states as WspaceTypes.InputMaybe<\n WspaceTypes.ConversationState[]\n >,\n hasUnread: options?.hasUnread,\n isPinned: options?.isPinned,\n },\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseGetConversationResult {\n conversation: Conversation | null;\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch a single conversation by ID.\n */\nexport function useGetConversation(\n conversationId: string,\n): UseGetConversationResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetConversationQuery({\n variables: { id: conversationId },\n skip: !workspaceId || !conversationId,\n });\n\n return {\n conversation: queryResult.data?.conversation\n ? mapConversation(queryResult.data.conversation)\n : null,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface UseSearchConversationsResult {\n conversations: Conversation[];\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Search conversations by query string.\n */\nexport function useSearchConversations(\n query: string,\n): UseSearchConversationsResult {\n const { workspaceId } = useConversations();\n const trimmedQuery = query.trim();\n const queryResult = useSearchConversationsQuery({\n variables: { query: trimmedQuery, first: 25 },\n skip: !workspaceId || trimmedQuery.length < 2,\n });\n\n return {\n conversations:\n queryResult.data?.searchConversations.edges.map(\n (edge: { node: Record<string, unknown> }) => mapConversation(edge.node),\n ) ?? [],\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n };\n}\n\ninterface CreateConversationInput {\n type: ConversationType;\n title?: string;\n description?: string;\n participantIds: string[];\n visibility?: ConversationVisibility;\n}\n\ninterface UseCreateConversationResult {\n createConversation: (\n input: CreateConversationInput,\n ) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Create a new conversation.\n */\nexport function useCreateConversation(): UseCreateConversationResult {\n const { workspaceId } = useConversations();\n const [createConversationMutation, mutationState] =\n useCreateConversationMutation();\n\n const createConversation = useCallback(\n async (input: CreateConversationInput): Promise<Conversation | null> => {\n if (!workspaceId) {\n throw new Error(\n \"Workspace context is required to create a conversation\",\n );\n }\n\n try {\n const { data } = await createConversationMutation({\n variables: {\n input: {\n workspaceId,\n type: input.type as WspaceTypes.ConversationType,\n title: input.title,\n description: input.description,\n participantIds: input.participantIds,\n },\n },\n });\n\n const conversation = data?.createConversation.conversation;\n return conversation ? mapConversation(conversation) : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to create conversation\");\n }\n },\n [createConversationMutation, workspaceId],\n );\n\n return {\n createConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseUpdateConversationResult {\n archiveConversation: (id: string) => Promise<boolean>;\n unarchiveConversation: (id: string) => Promise<boolean>;\n pinConversation: (id: string) => Promise<boolean>;\n unpinConversation: (id: string) => Promise<boolean>;\n muteConversation: (id: string) => Promise<boolean>;\n unmuteConversation: (id: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Conversation mutation operations.\n */\nexport function useConversationActions(): UseUpdateConversationResult {\n const [archiveConversationMutation, archiveState] =\n useArchiveConversationMutation();\n const [unarchiveConversationMutation, unarchiveState] =\n useUnarchiveConversationMutation();\n const [pinConversationMutation, pinState] = usePinConversationMutation();\n const [unpinConversationMutation, unpinState] =\n useUnpinConversationMutation();\n const [muteConversationMutation, muteState] = useMuteConversationMutation();\n const [unmuteConversationMutation, unmuteState] =\n useUnmuteConversationMutation();\n\n const archiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n // refetch GetConversations so the row drops out of the inbox (and the\n // Archived tab gains it) without waiting for a manual refresh.\n const { data } = await archiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.archiveConversation.id === id;\n },\n [archiveConversationMutation],\n );\n\n const unarchiveConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unarchiveConversationMutation({\n variables: { id },\n refetchQueries: [\"GetConversations\"],\n awaitRefetchQueries: true,\n });\n return data?.unarchiveConversation.id === id;\n },\n [unarchiveConversationMutation],\n );\n\n const pinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await pinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.pinConversation?.id);\n },\n [pinConversationMutation],\n );\n\n const unpinConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unpinConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unpinConversation?.id);\n },\n [unpinConversationMutation],\n );\n\n const muteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await muteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.muteConversation?.id);\n },\n [muteConversationMutation],\n );\n\n const unmuteConversation = useCallback(\n async (id: string): Promise<boolean> => {\n const { data } = await unmuteConversationMutation({\n variables: { conversationId: id },\n });\n return Boolean(data?.unmuteConversation?.id);\n },\n [unmuteConversationMutation],\n );\n\n return {\n archiveConversation,\n unarchiveConversation,\n pinConversation,\n unpinConversation,\n muteConversation,\n unmuteConversation,\n loading:\n archiveState.loading ||\n unarchiveState.loading ||\n pinState.loading ||\n unpinState.loading ||\n muteState.loading ||\n unmuteState.loading,\n error:\n (archiveState.error as Error | undefined) ??\n (unarchiveState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n (muteState.error as Error | undefined) ??\n (unmuteState.error as Error | undefined) ??\n null,\n };\n}\n\ninterface UseUpdateConversationOptions {\n updateConversation: (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }) => Promise<Conversation | null>;\n loading: boolean;\n error: Error | null;\n}\n\nexport function useUpdateConversation(): UseUpdateConversationOptions {\n const [updateConversationMutation, mutationState] =\n useUpdateConversationByHookMutation();\n\n const updateConversation = useCallback(\n async (input: {\n id: string;\n title?: string;\n description?: string;\n avatarUrl?: string;\n settings?: Record<string, unknown>;\n }): Promise<Conversation | null> => {\n try {\n const { data } = await updateConversationMutation({\n variables: { input },\n });\n const typedData = data as\n | {\n updateConversation?: {\n conversation?: Record<string, unknown> | null;\n };\n }\n | undefined;\n const conversation = typedData?.updateConversation?.conversation;\n return conversation\n ? mapConversation(conversation as Record<string, unknown>)\n : null;\n } catch (err) {\n throw err instanceof Error\n ? err\n : new Error(\"Failed to update conversation\");\n }\n },\n [updateConversationMutation],\n );\n\n return {\n updateConversation,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useMessageQueries.js","names":[],"sources":["../../../src/conversations/hooks/useMessageQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useAddReactionMutation,\n useDeleteMessageMutation,\n useEditMessageMutation,\n GetMessagesDocument,\n useGetMessagesQuery,\n usePinMessageByHookMutation,\n useRemoveReactionMutation,\n useSendMessageMutation,\n useUnpinMessageByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type { Message, MessageType } from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapMessage } from \"../utils/mappers\";\n\ninterface UseGetMessagesOptions {\n first?: number;\n after?: string;\n before?: string;\n}\n\ninterface UseGetMessagesResult {\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchMore: () => void;\n fetchPrevious: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch paginated messages for a conversation.\n */\nexport function useGetMessages(\n conversationId: string,\n options?: UseGetMessagesOptions,\n): UseGetMessagesResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetMessagesQuery({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: options?.after,\n before: options?.before,\n },\n skip: !workspaceId || !conversationId,\n });\n\n const messages = useMemo(\n () =>\n queryResult.data?.messages.edges.map(\n (edge: { node: Record<string, unknown> }) => mapMessage(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const pageInfo = queryResult.data?.messages.pageInfo;\n\n return {\n messages,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage: pageInfo?.hasNextPage ?? false,\n hasPreviousPage: pageInfo?.hasPreviousPage ?? false,\n fetchMore: () => {\n const endCursor = pageInfo?.endCursor;\n if (!endCursor || !pageInfo?.hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: endCursor,\n },\n });\n },\n fetchPrevious: () => {\n const startCursor = pageInfo?.startCursor;\n if (!startCursor || !pageInfo?.hasPreviousPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n before: startCursor,\n first: options?.first ?? 50,\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface SendMessageInput {\n conversationId: string;\n content: string;\n type?: MessageType;\n parentMessageId?: string;\n attachmentIds?: string[];\n mentionUserIds?: string[];\n refetchFirst?: number;\n}\n\ninterface UseSendMessageResult {\n sendMessage: (input: SendMessageInput) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Send a message to a conversation.\n */\nexport function useSendMessage(): UseSendMessageResult {\n const [sendMessageMutation, mutationState] = useSendMessageMutation();\n\n const sendMessage = useCallback(\n async (input: SendMessageInput): Promise<Message | null> => {\n try {\n const { data } = await sendMessageMutation({\n variables: {\n input: {\n conversationId: input.conversationId,\n type: input.type ?? \"TEXT\",\n content: { text: input.content },\n parentMessageId: input.parentMessageId,\n attachmentIds: input.attachmentIds,\n mentionUserIds: input.mentionUserIds,\n },\n },\n refetchQueries: [\n {\n query: GetMessagesDocument,\n variables: {\n conversationId: input.conversationId,\n first: input.refetchFirst ?? 50,\n },\n },\n ],\n });\n\n const message = data?.sendMessage.message;\n return message ? mapMessage(message) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to send message\");\n }\n },\n [sendMessageMutation],\n );\n\n return {\n sendMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseEditMessageResult {\n editMessage: (\n messageId: string,\n content: string,\n reason?: string,\n ) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Edit an existing message.\n */\nexport function useEditMessage(): UseEditMessageResult {\n const [editMessageMutation, mutationState] = useEditMessageMutation();\n\n const editMessage = useCallback(\n async (\n messageId: string,\n content: string,\n reason?: string,\n ): Promise<Message | null> => {\n try {\n const { data } = await editMessageMutation({\n variables: {\n input: {\n id: messageId,\n content: { text: content },\n reason,\n },\n },\n });\n const message = data?.editMessage;\n return message ? mapMessage(message as Record<string, unknown>) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to edit message\");\n }\n },\n [editMessageMutation],\n );\n\n return {\n editMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseMessageActionsResult {\n deleteMessage: (messageId: string) => Promise<boolean>;\n addReaction: (messageId: string, emoji: string) => Promise<boolean>;\n removeReaction: (messageId: string, emoji: string) => Promise<boolean>;\n pinMessage: (messageId: string) => Promise<boolean>;\n unpinMessage: (messageId: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Message action mutations (delete, react, pin).\n */\nexport function useMessageActions(): UseMessageActionsResult {\n const [deleteMessageMutation, deleteState] = useDeleteMessageMutation();\n const [addReactionMutation, addReactionState] = useAddReactionMutation();\n const [removeReactionMutation, removeReactionState] =\n useRemoveReactionMutation();\n const [pinMessageMutation, pinState] = usePinMessageByHookMutation();\n const [unpinMessageMutation, unpinState] = useUnpinMessageByHookMutation();\n\n const deleteMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await deleteMessageMutation({\n variables: { id: messageId },\n });\n return data?.deleteMessage.success ?? false;\n },\n [deleteMessageMutation],\n );\n\n const addReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await addReactionMutation({\n variables: { messageId, emoji },\n });\n return Boolean(data?.addReaction.id);\n },\n [addReactionMutation],\n );\n\n const removeReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await removeReactionMutation({\n variables: { messageId, emoji },\n });\n return data?.removeReaction.success ?? false;\n },\n [removeReactionMutation],\n );\n\n const pinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await pinMessageMutation({ variables: { messageId } });\n return Boolean(data?.pinMessage?.id);\n },\n [pinMessageMutation],\n );\n\n const unpinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await unpinMessageMutation({ variables: { messageId } });\n return Boolean(data?.unpinMessage?.id);\n },\n [unpinMessageMutation],\n );\n\n return {\n deleteMessage,\n addReaction,\n removeReaction,\n pinMessage,\n unpinMessage,\n loading:\n deleteState.loading ||\n addReactionState.loading ||\n removeReactionState.loading ||\n pinState.loading ||\n unpinState.loading,\n error:\n (deleteState.error as Error | undefined) ??\n (addReactionState.error as Error | undefined) ??\n (removeReactionState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n null,\n };\n}\n\n"],"mappings":"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"}
1
+ {"version":3,"file":"useMessageQueries.js","names":[],"sources":["../../../src/conversations/hooks/useMessageQueries.ts"],"sourcesContent":["import { useCallback, useMemo } from \"react\";\nimport {\n useAddReactionMutation,\n useDeleteMessageMutation,\n useEditMessageMutation,\n GetMessagesDocument,\n useGetMessagesQuery,\n usePinMessageByHookMutation,\n useRemoveReactionMutation,\n useSendMessageMutation,\n useUnpinMessageByHookMutation,\n} from \"../../generated/wspace-operations\";\nimport type { Message, MessageType } from \"../types\";\nimport { useConversations } from \"../providers/ConversationsProvider\";\nimport { mapMessage } from \"../utils/mappers\";\n\ninterface UseGetMessagesOptions {\n first?: number;\n after?: string;\n before?: string;\n}\n\ninterface UseGetMessagesResult {\n messages: Message[];\n loading: boolean;\n error: Error | null;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n fetchMore: () => void;\n fetchPrevious: () => void;\n refetch: () => void;\n}\n\n/**\n * Hook: Fetch paginated messages for a conversation.\n */\nexport function useGetMessages(\n conversationId: string,\n options?: UseGetMessagesOptions,\n): UseGetMessagesResult {\n const { workspaceId } = useConversations();\n const queryResult = useGetMessagesQuery({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: options?.after,\n before: options?.before,\n },\n skip: !workspaceId || !conversationId,\n });\n\n const messages = useMemo(\n () =>\n queryResult.data?.messages.edges.map(\n (edge: { node: Record<string, unknown> }) => mapMessage(edge.node),\n ) ?? [],\n [queryResult.data],\n );\n\n const pageInfo = queryResult.data?.messages.pageInfo;\n\n return {\n messages,\n loading: queryResult.loading,\n error: queryResult.error ?? null,\n hasNextPage: pageInfo?.hasNextPage ?? false,\n hasPreviousPage: pageInfo?.hasPreviousPage ?? false,\n fetchMore: () => {\n const endCursor = pageInfo?.endCursor;\n if (!endCursor || !pageInfo?.hasNextPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n first: options?.first ?? 50,\n after: endCursor,\n },\n });\n },\n fetchPrevious: () => {\n const startCursor = pageInfo?.startCursor;\n if (!startCursor || !pageInfo?.hasPreviousPage) return;\n void queryResult.fetchMore({\n variables: {\n conversationId,\n before: startCursor,\n first: options?.first ?? 50,\n },\n });\n },\n refetch: () => {\n void queryResult.refetch();\n },\n };\n}\n\ninterface SendMessageInput {\n conversationId: string;\n content: string;\n type?: MessageType;\n parentMessageId?: string;\n attachmentIds?: string[];\n mentionUserIds?: string[];\n refetchFirst?: number;\n}\n\ninterface UseSendMessageResult {\n sendMessage: (input: SendMessageInput) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Send a message to a conversation.\n */\nexport function useSendMessage(): UseSendMessageResult {\n const [sendMessageMutation, mutationState] = useSendMessageMutation();\n\n const sendMessage = useCallback(\n async (input: SendMessageInput): Promise<Message | null> => {\n try {\n const { data } = await sendMessageMutation({\n variables: {\n input: {\n conversationId: input.conversationId,\n type: input.type ?? \"TEXT\",\n content: { text: input.content },\n parentMessageId: input.parentMessageId,\n attachmentIds: input.attachmentIds,\n mentionUserIds: input.mentionUserIds,\n },\n },\n refetchQueries: [\n {\n query: GetMessagesDocument,\n variables: {\n conversationId: input.conversationId,\n first: input.refetchFirst ?? 50,\n },\n },\n ],\n });\n\n const message = data?.sendMessage.message;\n return message ? mapMessage(message) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to send message\");\n }\n },\n [sendMessageMutation],\n );\n\n return {\n sendMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseEditMessageResult {\n editMessage: (\n messageId: string,\n content: string,\n reason?: string,\n ) => Promise<Message | null>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Edit an existing message.\n */\nexport function useEditMessage(): UseEditMessageResult {\n const [editMessageMutation, mutationState] = useEditMessageMutation();\n\n const editMessage = useCallback(\n async (\n messageId: string,\n content: string,\n reason?: string,\n ): Promise<Message | null> => {\n try {\n const { data } = await editMessageMutation({\n variables: {\n input: {\n id: messageId,\n content: { text: content },\n reason,\n },\n },\n });\n const message = data?.editMessage;\n return message ? mapMessage(message as Record<string, unknown>) : null;\n } catch (err) {\n throw err instanceof Error ? err : new Error(\"Failed to edit message\");\n }\n },\n [editMessageMutation],\n );\n\n return {\n editMessage,\n loading: mutationState.loading,\n error: mutationState.error ?? null,\n };\n}\n\ninterface UseMessageActionsResult {\n deleteMessage: (messageId: string) => Promise<boolean>;\n addReaction: (messageId: string, emoji: string) => Promise<boolean>;\n removeReaction: (messageId: string, emoji: string) => Promise<boolean>;\n pinMessage: (messageId: string) => Promise<boolean>;\n unpinMessage: (messageId: string) => Promise<boolean>;\n loading: boolean;\n error: Error | null;\n}\n\n/**\n * Hook: Message action mutations (delete, react, pin).\n */\nexport function useMessageActions(): UseMessageActionsResult {\n const [deleteMessageMutation, deleteState] = useDeleteMessageMutation();\n const [addReactionMutation, addReactionState] = useAddReactionMutation();\n const [removeReactionMutation, removeReactionState] =\n useRemoveReactionMutation();\n const [pinMessageMutation, pinState] = usePinMessageByHookMutation();\n const [unpinMessageMutation, unpinState] = useUnpinMessageByHookMutation();\n\n const deleteMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await deleteMessageMutation({\n variables: { id: messageId },\n });\n return data?.deleteMessage.success ?? false;\n },\n [deleteMessageMutation],\n );\n\n const addReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await addReactionMutation({\n variables: { messageId, emoji },\n });\n return Boolean(data?.addReaction.id);\n },\n [addReactionMutation],\n );\n\n const removeReaction = useCallback(\n async (messageId: string, emoji: string): Promise<boolean> => {\n const { data } = await removeReactionMutation({\n variables: { messageId, emoji },\n });\n return data?.removeReaction.success ?? false;\n },\n [removeReactionMutation],\n );\n\n const pinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await pinMessageMutation({ variables: { messageId } });\n return Boolean(data?.pinMessage?.id);\n },\n [pinMessageMutation],\n );\n\n const unpinMessage = useCallback(\n async (messageId: string): Promise<boolean> => {\n const { data } = await unpinMessageMutation({ variables: { messageId } });\n return Boolean(data?.unpinMessage?.id);\n },\n [unpinMessageMutation],\n );\n\n return {\n deleteMessage,\n addReaction,\n removeReaction,\n pinMessage,\n unpinMessage,\n loading:\n deleteState.loading ||\n addReactionState.loading ||\n removeReactionState.loading ||\n pinState.loading ||\n unpinState.loading,\n error:\n (deleteState.error as Error | undefined) ??\n (addReactionState.error as Error | undefined) ??\n (removeReactionState.error as Error | undefined) ??\n (pinState.error as Error | undefined) ??\n (unpinState.error as Error | undefined) ??\n null,\n };\n}\n"],"mappings":"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"}