@burdenoff/microfe-planmagnet 2026.1001.8 → 2026.1002.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 (49) hide show
  1. package/dist/generated/global-types.d.ts +5 -0
  2. package/dist/generated/global-types.d.ts.map +1 -1
  3. package/dist/planmagnet/comments/CommentAttachmentUpload.d.ts +16 -0
  4. package/dist/planmagnet/comments/CommentAttachmentUpload.d.ts.map +1 -0
  5. package/dist/planmagnet/comments/CommentAttachmentUpload.js +218 -0
  6. package/dist/planmagnet/comments/CommentAttachmentUpload.js.map +1 -0
  7. package/dist/planmagnet/comments/CommentAttachments.d.ts +15 -0
  8. package/dist/planmagnet/comments/CommentAttachments.d.ts.map +1 -0
  9. package/dist/planmagnet/comments/CommentAttachments.js +74 -0
  10. package/dist/planmagnet/comments/CommentAttachments.js.map +1 -0
  11. package/dist/planmagnet/comments/CommentBody.d.ts +11 -0
  12. package/dist/planmagnet/comments/CommentBody.d.ts.map +1 -0
  13. package/dist/planmagnet/comments/CommentBody.js +130 -0
  14. package/dist/planmagnet/comments/CommentBody.js.map +1 -0
  15. package/dist/planmagnet/comments/CommentThread.d.ts +7 -2
  16. package/dist/planmagnet/comments/CommentThread.d.ts.map +1 -1
  17. package/dist/planmagnet/comments/CommentThread.js +288 -233
  18. package/dist/planmagnet/comments/CommentThread.js.map +1 -1
  19. package/dist/planmagnet/comments/MentionComposer.d.ts +0 -7
  20. package/dist/planmagnet/comments/MentionComposer.d.ts.map +1 -1
  21. package/dist/planmagnet/comments/MentionComposer.js +225 -86
  22. package/dist/planmagnet/comments/MentionComposer.js.map +1 -1
  23. package/dist/planmagnet/comments/TargetComments.d.ts.map +1 -1
  24. package/dist/planmagnet/comments/TargetComments.js +44 -6
  25. package/dist/planmagnet/comments/TargetComments.js.map +1 -1
  26. package/dist/planmagnet/comments/WorkItemComments.d.ts.map +1 -1
  27. package/dist/planmagnet/comments/WorkItemComments.js +22 -3
  28. package/dist/planmagnet/comments/WorkItemComments.js.map +1 -1
  29. package/dist/planmagnet/comments/commentAttachmentUploadClient.d.ts +102 -0
  30. package/dist/planmagnet/comments/commentAttachmentUploadClient.d.ts.map +1 -0
  31. package/dist/planmagnet/comments/commentAttachmentUploadClient.js +298 -0
  32. package/dist/planmagnet/comments/commentAttachmentUploadClient.js.map +1 -0
  33. package/dist/planmagnet/comments/commentImageTokens.d.ts +5 -0
  34. package/dist/planmagnet/comments/commentImageTokens.d.ts.map +1 -0
  35. package/dist/planmagnet/comments/commentImageTokens.js +14 -0
  36. package/dist/planmagnet/comments/commentImageTokens.js.map +1 -0
  37. package/dist/planmagnet/comments/commentTokens.d.ts +31 -0
  38. package/dist/planmagnet/comments/commentTokens.d.ts.map +1 -0
  39. package/dist/planmagnet/comments/commentTokens.js +142 -0
  40. package/dist/planmagnet/comments/commentTokens.js.map +1 -0
  41. package/dist/planmagnet/comments/fileDisplay.d.ts +22 -0
  42. package/dist/planmagnet/comments/fileDisplay.d.ts.map +1 -0
  43. package/dist/planmagnet/comments/fileDisplay.js +48 -0
  44. package/dist/planmagnet/comments/fileDisplay.js.map +1 -0
  45. package/dist/planmagnet/comments/useCommentFileUrl.d.ts +22 -0
  46. package/dist/planmagnet/comments/useCommentFileUrl.d.ts.map +1 -0
  47. package/dist/planmagnet/comments/useCommentFileUrl.js +54 -0
  48. package/dist/planmagnet/comments/useCommentFileUrl.js.map +1 -0
  49. package/package.json +3 -2
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fileDisplay.js","names":[],"sources":["../../../src/planmagnet/comments/fileDisplay.tsx"],"sourcesContent":["import {\n FileArchive,\n FileAudio,\n FileCode2,\n FileSpreadsheet,\n FileText,\n FileVideo,\n File as FileGenericIcon,\n Image as ImageIcon,\n} from 'lucide-react';\nimport type { ReactElement } from 'react';\n\n/**\n * Shared display helpers for CWF-12 comment attachments (and the pending attachments still uploading in the\n * composer) — byte-count formatting and a mime-type → icon mapping, used by `CommentAttachments.tsx` (posted\n * attachments) and `CommentAttachmentUpload.tsx` (files queued/uploading before the comment is posted).\n *\n * `mimeTypeIcon` returns the icon ELEMENT directly (never a component reference picked by a lookup and then\n * rendered as a JSX tag, e.g. `const Icon = ...; <Icon/>`) — `react-hooks/static-components` (this repo's\n * eslint config enables the full React Compiler rule set) rejects that shape outright, on the reasoning that a\n * JSX tag resolved from a value computed during render cannot be proven stable across renders. Returning the\n * element from a plain call (`{mimeTypeIcon(type)}`) sidesteps the rule entirely — it's never a JSX tag, just an\n * ordinary value embedded in the tree, same as any other expression child.\n */\n\n/** `1536` -> `\"1.5 KB\"`. Binary (1024) units, one decimal place under 10 of a unit, whole otherwise — matches the\n * precision wspace-files-svc's own file browser shows elsewhere in the platform. */\nexport function formatBytes(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes <= 0) return '0 B';\n const units = ['B', 'KB', 'MB', 'GB', 'TB'];\n const exp = Math.min(Math.floor(Math.log(bytes) / Math.log(1024)), units.length - 1);\n if (exp === 0) return `${bytes} B`;\n const value = bytes / 1024 ** exp;\n return `${value < 10 ? value.toFixed(1) : Math.round(value)} ${units[exp]}`;\n}\n\n/** A representative icon for a comment attachment's snapshotted `mimeType` — purely decorative (chips always\n * also show the real file name), so an unrecognized type falls back to a generic file glyph rather than\n * guessing wrong. */\nexport function mimeTypeIcon(\n mimeType: string,\n className = 'h-3.5 w-3.5 shrink-0 text-muted-foreground'\n): ReactElement {\n const type = mimeType.toLowerCase();\n if (type.startsWith('image/')) return <ImageIcon className={className} aria-hidden=\"true\" />;\n if (type.startsWith('video/')) return <FileVideo className={className} aria-hidden=\"true\" />;\n if (type.startsWith('audio/')) return <FileAudio className={className} aria-hidden=\"true\" />;\n if (type === 'application/pdf') return <FileText className={className} aria-hidden=\"true\" />;\n if (type.includes('spreadsheet') || type.includes('csv') || type.includes('excel')) {\n return <FileSpreadsheet className={className} aria-hidden=\"true\" />;\n }\n if (type.includes('zip') || type.includes('compressed') || type.includes('tar')) {\n return <FileArchive className={className} aria-hidden=\"true\" />;\n }\n if (type.startsWith('text/') || type.includes('json') || type.includes('xml')) {\n return <FileCode2 className={className} aria-hidden=\"true\" />;\n }\n return <FileGenericIcon className={className} aria-hidden=\"true\" />;\n}\n"],"mappings":";;;AA2BA,SAAgB,EAAY,GAAuB;AACjD,KAAI,CAAC,OAAO,SAAS,EAAM,IAAI,KAAS,EAAG,QAAO;CAClD,IAAM,IAAQ;EAAC;EAAK;EAAM;EAAM;EAAM;EAAK,EACrC,IAAM,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,EAAM,GAAG,KAAK,IAAI,KAAK,CAAC,EAAE,EAAM,SAAS,EAAE;AACpF,KAAI,MAAQ,EAAG,QAAO,GAAG,EAAM;CAC/B,IAAM,IAAQ,IAAQ,QAAQ;AAC9B,QAAO,GAAG,IAAQ,KAAK,EAAM,QAAQ,EAAE,GAAG,KAAK,MAAM,EAAM,CAAC,GAAG,EAAM;;AAMvE,SAAgB,EACd,GACA,IAAY,8CACE;CACd,IAAM,IAAO,EAAS,aAAa;AAcnC,QAbI,EAAK,WAAW,SAAS,GAAS,kBAAC,GAAD;EAAsB;EAAW,eAAY;EAAS,CAAA,GACxF,EAAK,WAAW,SAAS,GAAS,kBAAC,GAAD;EAAsB;EAAW,eAAY;EAAS,CAAA,GACxF,EAAK,WAAW,SAAS,GAAS,kBAAC,GAAD;EAAsB;EAAW,eAAY;EAAS,CAAA,GACxF,MAAS,oBAA0B,kBAAC,GAAD;EAAqB;EAAW,eAAY;EAAS,CAAA,GACxF,EAAK,SAAS,cAAc,IAAI,EAAK,SAAS,MAAM,IAAI,EAAK,SAAS,QAAQ,GACzE,kBAAC,GAAD;EAA4B;EAAW,eAAY;EAAS,CAAA,GAEjE,EAAK,SAAS,MAAM,IAAI,EAAK,SAAS,aAAa,IAAI,EAAK,SAAS,MAAM,GACtE,kBAAC,GAAD;EAAwB;EAAW,eAAY;EAAS,CAAA,GAE7D,EAAK,WAAW,QAAQ,IAAI,EAAK,SAAS,OAAO,IAAI,EAAK,SAAS,MAAM,GACpE,kBAAC,GAAD;EAAsB;EAAW,eAAY;EAAS,CAAA,GAExD,kBAAC,GAAD;EAA4B;EAAW,eAAY;EAAS,CAAA"}
@@ -0,0 +1,22 @@
1
+ import { ApolloClient } from '@apollo/client';
2
+
3
+ /** The target is explicit: project, doc and work-item readers have different RBAC resources. */
4
+ export type CommentFileTarget = {
5
+ type: 'WORK_ITEM';
6
+ id: string;
7
+ } | {
8
+ type: 'PROJECT';
9
+ id: string;
10
+ } | {
11
+ type: 'DOC';
12
+ id: string;
13
+ };
14
+ /**
15
+ * A Files URL is a short-lived bearer credential. Never resolve one while rendering a list, and never let
16
+ * Apollo or the gateway cache an expired URL. These operations are Mutations precisely so the gateway's
17
+ * optional query-response cache cannot replay a URL without rerunning the reader check. The product resolver
18
+ * validates the attachment row and current reader before issuing a fresh Files delegation.
19
+ */
20
+ export declare function requestCommentFileUrl(client: ApolloClient, target: CommentFileTarget, attachmentId: string): Promise<string>;
21
+ export declare function useCommentFileUrl(): (target: CommentFileTarget, attachmentId: string) => Promise<string>;
22
+ //# sourceMappingURL=useCommentFileUrl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCommentFileUrl.d.ts","sourceRoot":"","sources":["../../../src/planmagnet/comments/useCommentFileUrl.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAqB,MAAM,gBAAgB,CAAC;AAI3E,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAwBhC;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,iBAAiB,EACzB,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,CAAC,CAgBjB;AAED,wBAAgB,iBAAiB,aAGpB,iBAAiB,gBAAgB,MAAM,qBAInD"}
@@ -0,0 +1,54 @@
1
+ import { useCallback as e } from "react";
2
+ import { gql as t } from "@apollo/client";
3
+ import { useApolloClient as n } from "@apollo/client/react";
4
+ //#region src/planmagnet/comments/useCommentFileUrl.ts
5
+ var r = t`
6
+ mutation PlanmagnetWorkItemCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {
7
+ planmagnetWorkItemCommentAttachmentUrl(workItemId: $targetId, attachmentId: $attachmentId)
8
+ }
9
+ `, i = t`
10
+ mutation PlanmagnetProjectCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {
11
+ planmagnetProjectCommentAttachmentUrl(projectId: $targetId, attachmentId: $attachmentId)
12
+ }
13
+ `, a = t`
14
+ mutation PlanmagnetDocCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {
15
+ planmagnetDocCommentAttachmentUrl(docId: $targetId, attachmentId: $attachmentId)
16
+ }
17
+ `, o = {
18
+ WORK_ITEM: {
19
+ document: r,
20
+ field: "planmagnetWorkItemCommentAttachmentUrl"
21
+ },
22
+ PROJECT: {
23
+ document: i,
24
+ field: "planmagnetProjectCommentAttachmentUrl"
25
+ },
26
+ DOC: {
27
+ document: a,
28
+ field: "planmagnetDocCommentAttachmentUrl"
29
+ }
30
+ };
31
+ async function s(e, t, n) {
32
+ let r = o[t.type], i = (await e.mutate({
33
+ mutation: r.document,
34
+ variables: {
35
+ targetId: t.id,
36
+ attachmentId: n
37
+ },
38
+ fetchPolicy: "no-cache",
39
+ errorPolicy: "none"
40
+ })).data?.[r.field];
41
+ if (typeof i != "string" || !i) throw Error("The attachment is unavailable.");
42
+ try {
43
+ if (new URL(i).protocol === "https:") return i;
44
+ } catch {}
45
+ throw Error("The attachment URL is unavailable.");
46
+ }
47
+ function c() {
48
+ let t = n();
49
+ return e((e, n) => s(t, e, n), [t]);
50
+ }
51
+ //#endregion
52
+ export { c as useCommentFileUrl };
53
+
54
+ //# sourceMappingURL=useCommentFileUrl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCommentFileUrl.js","names":[],"sources":["../../../src/planmagnet/comments/useCommentFileUrl.ts"],"sourcesContent":["import { gql, type ApolloClient, type DocumentNode } from '@apollo/client';\nimport { useApolloClient } from '@apollo/client/react';\nimport { useCallback } from 'react';\n\n/** The target is explicit: project, doc and work-item readers have different RBAC resources. */\nexport type CommentFileTarget =\n | { type: 'WORK_ITEM'; id: string }\n | { type: 'PROJECT'; id: string }\n | { type: 'DOC'; id: string };\n\nconst WORK_ITEM_URL = gql`\n mutation PlanmagnetWorkItemCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {\n planmagnetWorkItemCommentAttachmentUrl(workItemId: $targetId, attachmentId: $attachmentId)\n }\n`;\nconst PROJECT_URL = gql`\n mutation PlanmagnetProjectCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {\n planmagnetProjectCommentAttachmentUrl(projectId: $targetId, attachmentId: $attachmentId)\n }\n`;\nconst DOC_URL = gql`\n mutation PlanmagnetDocCommentAttachmentUrl($targetId: ID!, $attachmentId: ID!) {\n planmagnetDocCommentAttachmentUrl(docId: $targetId, attachmentId: $attachmentId)\n }\n`;\n\nconst QUERIES: Record<CommentFileTarget['type'], { document: DocumentNode; field: string }> = {\n WORK_ITEM: { document: WORK_ITEM_URL, field: 'planmagnetWorkItemCommentAttachmentUrl' },\n PROJECT: { document: PROJECT_URL, field: 'planmagnetProjectCommentAttachmentUrl' },\n DOC: { document: DOC_URL, field: 'planmagnetDocCommentAttachmentUrl' },\n};\n\n/**\n * A Files URL is a short-lived bearer credential. Never resolve one while rendering a list, and never let\n * Apollo or the gateway cache an expired URL. These operations are Mutations precisely so the gateway's\n * optional query-response cache cannot replay a URL without rerunning the reader check. The product resolver\n * validates the attachment row and current reader before issuing a fresh Files delegation.\n */\nexport async function requestCommentFileUrl(\n client: ApolloClient,\n target: CommentFileTarget,\n attachmentId: string\n): Promise<string> {\n const operation = QUERIES[target.type];\n const result = await client.mutate<Record<string, string>>({\n mutation: operation.document,\n variables: { targetId: target.id, attachmentId },\n fetchPolicy: 'no-cache',\n errorPolicy: 'none',\n });\n const value = result.data?.[operation.field];\n if (typeof value !== 'string' || !value) throw new Error('The attachment is unavailable.');\n try {\n if (new URL(value).protocol === 'https:') return value;\n } catch {\n // Fail closed on a malformed URL; never put it in a link or image source.\n }\n throw new Error('The attachment URL is unavailable.');\n}\n\nexport function useCommentFileUrl() {\n const client = useApolloClient();\n return useCallback(\n (target: CommentFileTarget, attachmentId: string) =>\n requestCommentFileUrl(client, target, attachmentId),\n [client]\n );\n}\n"],"mappings":";;;;AAUA,IAAM,IAAgB,CAAG;;;;GAKnB,IAAc,CAAG;;;;GAKjB,IAAU,CAAG;;;;GAMb,IAAwF;CAC5F,WAAW;EAAE,UAAU;EAAe,OAAO;EAA0C;CACvF,SAAS;EAAE,UAAU;EAAa,OAAO;EAAyC;CAClF,KAAK;EAAE,UAAU;EAAS,OAAO;EAAqC;CACvE;AAQD,eAAsB,EACpB,GACA,GACA,GACiB;CACjB,IAAM,IAAY,EAAQ,EAAO,OAO3B,KANS,MAAM,EAAO,OAA+B;EACzD,UAAU,EAAU;EACpB,WAAW;GAAE,UAAU,EAAO;GAAI;GAAc;EAChD,aAAa;EACb,aAAa;EACd,CAAC,EACmB,OAAO,EAAU;AACtC,KAAI,OAAO,KAAU,YAAY,CAAC,EAAO,OAAU,MAAM,iCAAiC;AAC1F,KAAI;AACF,MAAI,IAAI,IAAI,EAAM,CAAC,aAAa,SAAU,QAAO;SAC3C;AAGR,OAAU,MAAM,qCAAqC;;AAGvD,SAAgB,IAAoB;CAClC,IAAM,IAAS,GAAiB;AAChC,QAAO,GACJ,GAA2B,MAC1B,EAAsB,GAAQ,GAAQ,EAAa,EACrD,CAAC,EAAO,CACT"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burdenoff/microfe-planmagnet",
3
- "version": "2026.1001.8",
3
+ "version": "2026.1002.1",
4
4
  "description": "Burdenoff PlanMagnet Microfrontend",
5
5
  "type": "module",
6
6
  "files": [
@@ -26,7 +26,8 @@
26
26
  "lint": "eslint .",
27
27
  "format": "prettier --write \"src/**/*.{ts,tsx}\"",
28
28
  "type:check": "bash scripts/build-limits.sh tsc --noEmit",
29
- "sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run codegen && bun run validate:schema && bun run check:nav && bun run check:mutations && bun run check:refetch && bun run lint && bun run format && bun run type:check && bun run build && bun run build-storybook'",
29
+ "test": "bun test tests",
30
+ "sanity": "bash scripts/build-limits.sh --gate bash -c 'bun run codegen && bun run validate:schema && bun run check:nav && bun run check:mutations && bun run check:refetch && bun run lint && bun run format && bun run test && bun run type:check && bun run build && bun run build-storybook'",
30
31
  "validate:schema": "graphql-schema-drift",
31
32
  "check:nav": "bun scripts/check-nav-targets.ts",
32
33
  "check:mutations": "bun scripts/check-mutation-errors.ts",