@w100n/documents 0.4.0 → 0.10.0

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 (55) hide show
  1. package/dist/SheetView-3XTEV2VT.css +319 -0
  2. package/dist/SheetView-3XTEV2VT.css.map +1 -0
  3. package/dist/SheetView-JYH2ZUZF.js +928 -0
  4. package/dist/SheetView-JYH2ZUZF.js.map +1 -0
  5. package/dist/TextEditor-X3X62R46.js +982 -0
  6. package/dist/TextEditor-X3X62R46.js.map +1 -0
  7. package/dist/caveat-cyrillic-XVO43JCM.woff2 +0 -0
  8. package/dist/caveat-latin-IUBKKMHQ.woff2 +0 -0
  9. package/dist/caveat-latin-ext-5S7R5SZN.woff2 +0 -0
  10. package/dist/chunk-CE3AADY6.js +3447 -0
  11. package/dist/chunk-CE3AADY6.js.map +1 -0
  12. package/dist/chunk-ISOOUYLI.js +150 -0
  13. package/dist/chunk-ISOOUYLI.js.map +1 -0
  14. package/dist/{chunk-KEV4R7W5.js → chunk-K364NAYP.js} +4 -1
  15. package/dist/chunk-K364NAYP.js.map +1 -0
  16. package/dist/chunk-QDH7EZAF.js +27 -0
  17. package/dist/chunk-QDH7EZAF.js.map +1 -0
  18. package/dist/chunk-SVRYWMES.js +196 -0
  19. package/dist/chunk-SVRYWMES.js.map +1 -0
  20. package/dist/chunk-TDP6OJET.js +31 -0
  21. package/dist/chunk-TDP6OJET.js.map +1 -0
  22. package/dist/chunk-TNSN4ZQ5.js +2909 -0
  23. package/dist/chunk-TNSN4ZQ5.js.map +1 -0
  24. package/dist/collab.cjs +6312 -0
  25. package/dist/collab.cjs.map +1 -0
  26. package/dist/collab.d.cts +39 -0
  27. package/dist/collab.d.ts +39 -0
  28. package/dist/collab.js +30 -0
  29. package/dist/collab.js.map +1 -0
  30. package/dist/grid-EI5JNZAA.js +88 -0
  31. package/dist/grid-EI5JNZAA.js.map +1 -0
  32. package/dist/index.cjs +12134 -457
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.css +2999 -95
  35. package/dist/index.css.map +1 -1
  36. package/dist/index.d.cts +143 -6
  37. package/dist/index.d.ts +143 -6
  38. package/dist/index.js +3377 -450
  39. package/dist/index.js.map +1 -1
  40. package/dist/memory.cjs +59 -7
  41. package/dist/memory.cjs.map +1 -1
  42. package/dist/memory.d.cts +7 -2
  43. package/dist/memory.d.ts +7 -2
  44. package/dist/memory.js +57 -8
  45. package/dist/memory.js.map +1 -1
  46. package/dist/pdfWrite-EM6GJDBF.js +76 -0
  47. package/dist/pdfWrite-EM6GJDBF.js.map +1 -0
  48. package/dist/types-B5oF25dn.d.cts +165 -0
  49. package/dist/types-B5oF25dn.d.ts +165 -0
  50. package/dist/write-DaVtTJCS.d.cts +6 -0
  51. package/dist/write-DaVtTJCS.d.ts +6 -0
  52. package/package.json +45 -3
  53. package/dist/chunk-KEV4R7W5.js.map +0 -1
  54. package/dist/types-DshXPnWA.d.cts +0 -62
  55. package/dist/types-DshXPnWA.d.ts +0 -62
package/dist/memory.cjs CHANGED
@@ -33,6 +33,9 @@ var byExtension = {
33
33
  pdf: "pdf",
34
34
  xlsx: "sheet",
35
35
  csv: "sheet",
36
+ xls: "sheet",
37
+ ods: "sheet",
38
+ tsv: "sheet",
36
39
  html: "slides",
37
40
  htm: "slides"
38
41
  };
@@ -50,13 +53,19 @@ function kindOf(name, mimeType) {
50
53
  }
51
54
 
52
55
  // src/memory.ts
56
+ var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
53
57
  var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
54
- function memoryHost({ me, spaces, files }) {
58
+ function memoryHost({ me, spaces, files, collab }) {
55
59
  const find = (id) => {
56
60
  const file = files.find((item) => item.id === id);
57
61
  if (!file) throw new Error("document not found");
58
62
  return file;
59
63
  };
64
+ const own = (file, commentId) => {
65
+ const found = file.comments?.find((c) => c.id === commentId);
66
+ if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
67
+ return found;
68
+ };
60
69
  const summary = (file) => ({
61
70
  id: file.id,
62
71
  spaceId: file.spaceId,
@@ -67,30 +76,73 @@ function memoryHost({ me, spaces, files }) {
67
76
  updatedBy: me,
68
77
  folder: file.folder ?? null
69
78
  });
79
+ const archive = (file, bytes, note) => {
80
+ const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
81
+ const version = `v${versions.length + 1}`;
82
+ Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
83
+ return version;
84
+ };
70
85
  return {
71
86
  me,
87
+ ...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
72
88
  spaces: async () => spaces,
73
89
  documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
74
- document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
90
+ document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
75
91
  versions: async (id) => {
76
92
  const file = find(id);
77
93
  return [
78
- { id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
94
+ { id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
79
95
  ...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
80
96
  ];
81
97
  },
82
98
  content: async (id, versionId) => {
83
99
  const file = find(id);
84
- const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
100
+ const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
85
101
  return encode(old ? old.bytes : file.bytes);
86
102
  },
87
103
  restore: async (id, versionId) => {
88
104
  const file = find(id);
89
105
  const old = file.versions?.find((v) => v.id === versionId);
90
106
  if (!old) throw new Error("version not found");
91
- file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes }, ...file.versions ?? []];
92
- file.bytes = old.bytes;
93
- file.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
107
+ archive(file, old.bytes);
108
+ },
109
+ save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
110
+ signatures: async (id) => [...find(id).signatures ?? []].reverse(),
111
+ sign: async (id, entry) => {
112
+ const file = find(id);
113
+ const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
114
+ file.signatures = [...file.signatures ?? [], signature];
115
+ return signature;
116
+ },
117
+ comments: async (id) => [...find(id).comments ?? []],
118
+ comment: async (id, entry) => {
119
+ const file = find(id);
120
+ let n = (file.comments?.length ?? 0) + 1;
121
+ while (file.comments?.some((c) => c.id === `c${n}`)) n++;
122
+ const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
123
+ file.comments = [...file.comments ?? [], made];
124
+ return made;
125
+ },
126
+ resolveComment: async (id, commentId, resolved) => {
127
+ const file = find(id);
128
+ file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
129
+ },
130
+ editComment: async (id, commentId, body) => {
131
+ const file = find(id);
132
+ const mine = own(file, commentId);
133
+ const edited = { ...mine, body };
134
+ file.comments = file.comments.map((c) => c === mine ? edited : c);
135
+ return edited;
136
+ },
137
+ deleteComment: async (id, commentId) => {
138
+ const file = find(id);
139
+ own(file, commentId);
140
+ file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
141
+ },
142
+ exportAs: async (id, format) => {
143
+ const file = find(id);
144
+ if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
145
+ return new Blob([encode(file.bytes)], { type: mimes[format] });
94
146
  }
95
147
  };
96
148
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes }, ...(file.versions ?? [])];\n file.bytes = old.bytes;\n file.updatedAt = new Date().toISOString();\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/memory.ts","../src/kinds.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n","import type { DocumentKind } from './types';\n\nconst byExtension: Record<string, DocumentKind> = {\n docx: 'docx', md: 'markdown', markdown: 'markdown', pdf: 'pdf', xlsx: 'sheet', csv: 'sheet', xls: 'sheet', ods: 'sheet', tsv: 'sheet', html: 'slides', htm: 'slides',\n};\n\nconst byMime: Record<string, DocumentKind> = {\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',\n 'text/markdown': 'markdown',\n 'application/pdf': 'pdf',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'sheet',\n 'text/csv': 'sheet',\n 'text/html': 'slides',\n};\n\nexport const kinds: DocumentKind[] = ['docx', 'markdown', 'pdf', 'sheet', 'slides'];\n\nexport function kindOf(name: string, mimeType?: string | null): DocumentKind | null {\n const extension = name.includes('.') ? name.split('.').pop()!.toLowerCase() : '';\n return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(';')[0].trim().toLowerCase()] : undefined) ?? null;\n}\n\nexport function matches(doc: { name: string; kind: DocumentKind }, query: string, kind: DocumentKind | 'all') {\n const words = query.toLocaleLowerCase().split(/\\s+/).filter(Boolean);\n return (kind === 'all' || doc.kind === kind) && words.every(word => doc.name.toLocaleLowerCase().includes(word));\n}\n"],"mappings":"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","names":[]}
package/dist/memory.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as Rights, e as Person, S as Space, D as DocumentsHost } from './types-DshXPnWA.cjs';
1
+ import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.cjs';
2
2
 
3
3
  type Bytes = ArrayBuffer | string;
4
4
  type MemoryFile = {
@@ -7,6 +7,8 @@ type MemoryFile = {
7
7
  name: string;
8
8
  folder?: string;
9
9
  bytes: Bytes;
10
+ version?: string;
11
+ note?: string;
10
12
  updatedAt?: string;
11
13
  rights?: Partial<Rights>;
12
14
  versions?: {
@@ -15,11 +17,14 @@ type MemoryFile = {
15
17
  bytes: Bytes;
16
18
  note?: string;
17
19
  }[];
20
+ signatures?: Signature[];
21
+ comments?: Comment[];
18
22
  };
19
- declare function memoryHost({ me, spaces, files }: {
23
+ declare function memoryHost({ me, spaces, files, collab }: {
20
24
  me: Person;
21
25
  spaces: Space[];
22
26
  files: MemoryFile[];
27
+ collab?: string;
23
28
  }): DocumentsHost;
24
29
 
25
30
  export { type MemoryFile, memoryHost };
package/dist/memory.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { R as Rights, e as Person, S as Space, D as DocumentsHost } from './types-DshXPnWA.js';
1
+ import { R as Rights, S as Signature, C as Comment, h as Person, j as Space, D as DocumentsHost } from './types-B5oF25dn.js';
2
2
 
3
3
  type Bytes = ArrayBuffer | string;
4
4
  type MemoryFile = {
@@ -7,6 +7,8 @@ type MemoryFile = {
7
7
  name: string;
8
8
  folder?: string;
9
9
  bytes: Bytes;
10
+ version?: string;
11
+ note?: string;
10
12
  updatedAt?: string;
11
13
  rights?: Partial<Rights>;
12
14
  versions?: {
@@ -15,11 +17,14 @@ type MemoryFile = {
15
17
  bytes: Bytes;
16
18
  note?: string;
17
19
  }[];
20
+ signatures?: Signature[];
21
+ comments?: Comment[];
18
22
  };
19
- declare function memoryHost({ me, spaces, files }: {
23
+ declare function memoryHost({ me, spaces, files, collab }: {
20
24
  me: Person;
21
25
  spaces: Space[];
22
26
  files: MemoryFile[];
27
+ collab?: string;
23
28
  }): DocumentsHost;
24
29
 
25
30
  export { type MemoryFile, memoryHost };
package/dist/memory.js CHANGED
@@ -1,16 +1,22 @@
1
1
  'use client';
2
2
  import {
3
3
  kindOf
4
- } from "./chunk-KEV4R7W5.js";
4
+ } from "./chunk-K364NAYP.js";
5
5
 
6
6
  // src/memory.ts
7
+ var mimes = { pdf: "application/pdf", docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", md: "text/markdown" };
7
8
  var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
8
- function memoryHost({ me, spaces, files }) {
9
+ function memoryHost({ me, spaces, files, collab }) {
9
10
  const find = (id) => {
10
11
  const file = files.find((item) => item.id === id);
11
12
  if (!file) throw new Error("document not found");
12
13
  return file;
13
14
  };
15
+ const own = (file, commentId) => {
16
+ const found = file.comments?.find((c) => c.id === commentId);
17
+ if (!found || found.author.id !== me.id) throw new Error("only the author changes a comment");
18
+ return found;
19
+ };
14
20
  const summary = (file) => ({
15
21
  id: file.id,
16
22
  spaceId: file.spaceId,
@@ -21,30 +27,73 @@ function memoryHost({ me, spaces, files }) {
21
27
  updatedBy: me,
22
28
  folder: file.folder ?? null
23
29
  });
30
+ const archive = (file, bytes, note) => {
31
+ const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes, note: file.note }, ...file.versions ?? []];
32
+ const version = `v${versions.length + 1}`;
33
+ Object.assign(file, { versions, version, bytes, note, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
34
+ return version;
35
+ };
24
36
  return {
25
37
  me,
38
+ ...collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {},
26
39
  spaces: async () => spaces,
27
40
  documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
28
- document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
41
+ document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),
29
42
  versions: async (id) => {
30
43
  const file = find(id);
31
44
  return [
32
- { id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
45
+ { id: file.version ?? "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },
33
46
  ...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
34
47
  ];
35
48
  },
36
49
  content: async (id, versionId) => {
37
50
  const file = find(id);
38
- const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
51
+ const old = versionId && versionId !== "current" && versionId !== file.version ? file.versions?.find((v) => v.id === versionId) : void 0;
39
52
  return encode(old ? old.bytes : file.bytes);
40
53
  },
41
54
  restore: async (id, versionId) => {
42
55
  const file = find(id);
43
56
  const old = file.versions?.find((v) => v.id === versionId);
44
57
  if (!old) throw new Error("version not found");
45
- file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? "2026-10-19T09:00:00Z", bytes: file.bytes }, ...file.versions ?? []];
46
- file.bytes = old.bytes;
47
- file.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
58
+ archive(file, old.bytes);
59
+ },
60
+ save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),
61
+ signatures: async (id) => [...find(id).signatures ?? []].reverse(),
62
+ sign: async (id, entry) => {
63
+ const file = find(id);
64
+ const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: (/* @__PURE__ */ new Date()).toISOString(), ...entry };
65
+ file.signatures = [...file.signatures ?? [], signature];
66
+ return signature;
67
+ },
68
+ comments: async (id) => [...find(id).comments ?? []],
69
+ comment: async (id, entry) => {
70
+ const file = find(id);
71
+ let n = (file.comments?.length ?? 0) + 1;
72
+ while (file.comments?.some((c) => c.id === `c${n}`)) n++;
73
+ const made = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: (/* @__PURE__ */ new Date()).toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };
74
+ file.comments = [...file.comments ?? [], made];
75
+ return made;
76
+ },
77
+ resolveComment: async (id, commentId, resolved) => {
78
+ const file = find(id);
79
+ file.comments = (file.comments ?? []).map((c) => c.id === commentId ? { ...c, resolved } : c);
80
+ },
81
+ editComment: async (id, commentId, body) => {
82
+ const file = find(id);
83
+ const mine = own(file, commentId);
84
+ const edited = { ...mine, body };
85
+ file.comments = file.comments.map((c) => c === mine ? edited : c);
86
+ return edited;
87
+ },
88
+ deleteComment: async (id, commentId) => {
89
+ const file = find(id);
90
+ own(file, commentId);
91
+ file.comments = file.comments.filter((c) => c.id !== commentId && c.replyTo !== commentId);
92
+ },
93
+ exportAs: async (id, format) => {
94
+ const file = find(id);
95
+ if ((format === "md" ? "markdown" : format) !== kindOf(file.name)) throw new Error("this format needs a converter on the host");
96
+ return new Blob([encode(file.bytes)], { type: mimes[format] });
48
97
  }
49
98
  };
50
99
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { DocumentsHost, Person, Rights, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n};\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files }: { me: Person; spaces: Space[]; files: MemoryFile[] }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n return {\n me,\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),\n versions: async id => {\n const file = find(id);\n return [\n { id: 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n file.versions = [{ id: `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes }, ...(file.versions ?? [])];\n file.bytes = old.bytes;\n file.updatedAt = new Date().toISOString();\n },\n };\n}\n"],"mappings":";;;;;;AAgBA,IAAM,SAAS,CAAC,UAAiB,OAAO,UAAU,WAAW,IAAI,YAAY,EAAE,OAAO,KAAK,EAAE,SAAwB;AAE9G,SAAS,WAAW,EAAE,IAAI,QAAQ,MAAM,GAAwE;AACrH,QAAM,OAAO,CAAC,OAAe;AAC3B,UAAM,OAAO,MAAM,KAAK,UAAQ,KAAK,OAAO,EAAE;AAC9C,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,oBAAoB;AAC/C,WAAO;AAAA,EACT;AACA,QAAM,UAAU,CAAC,UAAsB;AAAA,IACrC,IAAI,KAAK;AAAA,IAAI,SAAS,KAAK;AAAA,IAAS,MAAM,KAAK;AAAA,IAAM,MAAM,OAAO,KAAK,IAAI;AAAA,IAAI,MAAM,OAAO,KAAK,KAAK,EAAE;AAAA,IACxG,WAAW,KAAK,aAAa;AAAA,IAAwB,WAAW;AAAA,IAAI,QAAQ,KAAK,UAAU;AAAA,EAC7F;AACA,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,YAAY;AAAA,IACpB,WAAW,OAAM,YAAW,MAAM,OAAO,UAAQ,KAAK,YAAY,WAAW,OAAO,KAAK,IAAI,CAAC,EAAE,IAAI,OAAO;AAAA,IAC3G,UAAU,OAAM,QAAO,EAAE,GAAG,QAAQ,KAAK,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,MAAM,SAAS,MAAM,MAAM,MAAM,GAAG,KAAK,EAAE,EAAE,OAAO,EAAE;AAAA,IACrH,UAAU,OAAM,OAAM;AACpB,YAAM,OAAO,KAAK,EAAE;AACpB,aAAO;AAAA,QACL,EAAE,IAAI,WAAW,WAAW,QAAQ,IAAI,EAAE,WAAW,MAAM,QAAQ,IAAI,EAAE,MAAM,QAAQ,IAAI,SAAS,KAAK;AAAA,QACzG,IAAI,KAAK,YAAY,CAAC,GAAG,IAAI,QAAM,EAAE,IAAI,EAAE,IAAI,WAAW,EAAE,WAAW,MAAM,OAAO,EAAE,KAAK,EAAE,YAAY,QAAQ,IAAI,MAAM,EAAE,QAAQ,MAAM,SAAS,MAAM,EAAE;AAAA,MAC9J;AAAA,IACF;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,aAAa,cAAc,YAAY,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS,IAAI;AAClG,aAAO,OAAO,MAAM,IAAI,QAAQ,KAAK,KAAK;AAAA,IAC5C;AAAA,IACA,SAAS,OAAO,IAAI,cAAc;AAChC,YAAM,OAAO,KAAK,EAAE;AACpB,YAAM,MAAM,KAAK,UAAU,KAAK,OAAK,EAAE,OAAO,SAAS;AACvD,UAAI,CAAC,IAAK,OAAM,IAAI,MAAM,mBAAmB;AAC7C,WAAK,WAAW,CAAC,EAAE,IAAI,KAAK,KAAK,UAAU,UAAU,KAAK,CAAC,IAAI,WAAW,KAAK,aAAa,wBAAwB,OAAO,KAAK,MAAM,GAAG,GAAI,KAAK,YAAY,CAAC,CAAE;AACjK,WAAK,QAAQ,IAAI;AACjB,WAAK,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/memory.ts"],"sourcesContent":["import { kindOf } from './kinds';\nimport type { Comment, DocumentsHost, Person, Rights, Signature, Space } from './types';\n\ntype Bytes = ArrayBuffer | string;\n\nexport type MemoryFile = {\n id: string;\n spaceId: string;\n name: string;\n folder?: string;\n bytes: Bytes;\n version?: string;\n note?: string;\n updatedAt?: string;\n rights?: Partial<Rights>;\n versions?: { id: string; createdAt: string; bytes: Bytes; note?: string }[];\n signatures?: Signature[];\n comments?: Comment[];\n};\n\nconst mimes = { pdf: 'application/pdf', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', md: 'text/markdown' };\n\nconst encode = (bytes: Bytes) => typeof bytes === 'string' ? new TextEncoder().encode(bytes).buffer as ArrayBuffer : bytes;\n\nexport function memoryHost({ me, spaces, files, collab }: { me: Person; spaces: Space[]; files: MemoryFile[]; collab?: string }): DocumentsHost {\n const find = (id: string) => {\n const file = files.find(item => item.id === id);\n if (!file) throw new Error('document not found');\n return file;\n };\n const own = (file: MemoryFile, commentId: string) => {\n const found = file.comments?.find(c => c.id === commentId);\n if (!found || found.author.id !== me.id) throw new Error('only the author changes a comment');\n return found;\n };\n const summary = (file: MemoryFile) => ({\n id: file.id, spaceId: file.spaceId, name: file.name, kind: kindOf(file.name)!, size: encode(file.bytes).byteLength,\n updatedAt: file.updatedAt ?? '2026-10-19T09:00:00Z', updatedBy: me, folder: file.folder ?? null,\n });\n const archive = (file: MemoryFile, bytes: Bytes, note?: string) => {\n const versions = [{ id: file.version ?? `v${(file.versions?.length ?? 0) + 1}`, createdAt: file.updatedAt ?? '2026-10-19T09:00:00Z', bytes: file.bytes, note: file.note }, ...(file.versions ?? [])];\n const version = `v${versions.length + 1}`;\n Object.assign(file, { versions, version, bytes, note, updatedAt: new Date().toISOString() });\n return version;\n };\n return {\n me,\n ...(collab ? { collab: { url: `memory:${collab}`, token: async () => me.id } } : {}),\n spaces: async () => spaces,\n documents: async spaceId => files.filter(file => file.spaceId === spaceId && kindOf(file.name)).map(summary),\n document: async id => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights }, live: !!collab }),\n versions: async id => {\n const file = find(id);\n return [\n { id: file.version ?? 'current', createdAt: summary(file).updatedAt, size: summary(file).size, author: me, note: file.note ?? null, current: true },\n ...(file.versions ?? []).map(v => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false })),\n ];\n },\n content: async (id, versionId) => {\n const file = find(id);\n const old = versionId && versionId !== 'current' && versionId !== file.version ? file.versions?.find(v => v.id === versionId) : undefined;\n return encode(old ? old.bytes : file.bytes);\n },\n restore: async (id, versionId) => {\n const file = find(id);\n const old = file.versions?.find(v => v.id === versionId);\n if (!old) throw new Error('version not found');\n archive(file, old.bytes);\n },\n save: async (id, bytes, note) => ({ versionId: archive(find(id), bytes, note) }),\n signatures: async id => [...(find(id).signatures ?? [])].reverse(),\n sign: async (id, entry) => {\n const file = find(id);\n const signature = { id: `s${(file.signatures?.length ?? 0) + 1}`, signer: me, signedAt: new Date().toISOString(), ...entry };\n file.signatures = [...(file.signatures ?? []), signature];\n return signature;\n },\n comments: async id => [...(find(id).comments ?? [])],\n comment: async (id, entry) => {\n const file = find(id);\n let n = (file.comments?.length ?? 0) + 1;\n while (file.comments?.some(c => c.id === `c${n}`)) n++;\n const made: Comment = { id: `c${n}`, documentId: id, author: me, body: entry.body, createdAt: new Date().toISOString(), quote: entry.quote, replyTo: entry.replyTo, resolved: false };\n file.comments = [...(file.comments ?? []), made];\n return made;\n },\n resolveComment: async (id, commentId, resolved) => {\n const file = find(id);\n file.comments = (file.comments ?? []).map(c => c.id === commentId ? { ...c, resolved } : c);\n },\n editComment: async (id, commentId, body) => {\n const file = find(id);\n const mine = own(file, commentId);\n const edited = { ...mine, body };\n file.comments = file.comments!.map(c => c === mine ? edited : c);\n return edited;\n },\n deleteComment: async (id, commentId) => {\n const file = find(id);\n own(file, commentId);\n file.comments = file.comments!.filter(c => c.id !== commentId && c.replyTo !== commentId);\n },\n exportAs: async (id, format) => {\n const file = find(id);\n if ((format === 'md' ? 'markdown' : format) !== kindOf(file.name)) throw new Error('this format needs a converter on the host');\n return new Blob([encode(file.bytes)], { type: mimes[format] });\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+
3
+ // src/viewers/pdfWrite.ts
4
+ import { init } from "@embedpdf/pdfium";
5
+ import { PdfiumNative } from "@embedpdf/engines/pdfium";
6
+ import { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode } from "@embedpdf/models";
7
+ var engine = null;
8
+ var rect = (box) => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });
9
+ var around = (boxes) => {
10
+ const x = Math.min(...boxes.map((b) => b.x));
11
+ const y = Math.min(...boxes.map((b) => b.y));
12
+ return { x, y, w: Math.max(...boxes.map((b) => b.x + b.w)) - x, h: Math.max(...boxes.map((b) => b.y + b.h)) - y };
13
+ };
14
+ var png = (url) => Uint8Array.from(atob(url.slice(url.indexOf(",") + 1)), (c) => c.charCodeAt(0)).buffer;
15
+ var types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT };
16
+ function annotation(mark) {
17
+ const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };
18
+ if (mark.kind === "note") {
19
+ return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };
20
+ }
21
+ if (mark.kind === "ink") {
22
+ const spread = mark.width / 2 + 1;
23
+ const bounds = around(mark.lines.flat().map((p) => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));
24
+ return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map((points) => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };
25
+ }
26
+ if (mark.kind === "sign") return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };
27
+ return {
28
+ ...base,
29
+ type: types[mark.kind],
30
+ rect: rect(around(mark.rects)),
31
+ segmentRects: mark.rects.map(rect),
32
+ contents: mark.text,
33
+ strokeColor: mark.color,
34
+ opacity: 1,
35
+ ...mark.kind === "highlight" ? { blendMode: PdfBlendMode.Multiply } : {}
36
+ };
37
+ }
38
+ async function write(bytes, marks, fields) {
39
+ engine ?? (engine = init({}).then((module) => new PdfiumNative(module)));
40
+ const pdfium = await engine;
41
+ const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();
42
+ try {
43
+ for (const n of new Set(fields.map((field) => field.page))) {
44
+ const page = doc.pages[n - 1];
45
+ const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();
46
+ for (const field of fields.filter((f) => f.page === n)) {
47
+ const centre = (r) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);
48
+ const widget = widgets.filter((w) => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];
49
+ if (!widget) continue;
50
+ const { type } = widget.field;
51
+ if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {
52
+ await pdfium.setFormFieldValue(doc, page, widget, { kind: "text", text: String(field.value) }).toPromise();
53
+ } else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true) {
54
+ await pdfium.setFormFieldValue(doc, page, widget, { kind: "checked", checked: field.value === true }).toPromise();
55
+ } else if ("options" in widget.field && Array.isArray(field.value)) {
56
+ for (const [index, option] of widget.field.options.entries()) {
57
+ const wanted = field.value.includes(option.label);
58
+ if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: "selection", index, isSelected: wanted }).toPromise();
59
+ }
60
+ }
61
+ }
62
+ }
63
+ for (const mark of marks) {
64
+ const page = doc.pages[mark.page - 1];
65
+ if (mark.kind === "sign") await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: "image/png" }).toPromise();
66
+ else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();
67
+ }
68
+ return await pdfium.saveAsCopy(doc).toPromise();
69
+ } finally {
70
+ await pdfium.closeDocument(doc).toPromise();
71
+ }
72
+ }
73
+ export {
74
+ write
75
+ };
76
+ //# sourceMappingURL=pdfWrite-EM6GJDBF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viewers/pdfWrite.ts"],"sourcesContent":["import { init } from '@embedpdf/pdfium';\nimport { PdfiumNative } from '@embedpdf/engines/pdfium';\nimport { PDF_FORM_FIELD_TYPE, PdfAnnotationSubtype, PdfBlendMode, type PdfAnnotationObject, type Rect } from '@embedpdf/models';\nimport type { SignatureMethod } from '../types';\n\nexport type Point = { x: number; y: number };\nexport type Box = Point & { w: number; h: number };\n\nexport type Mark = { id: string; page: number; author: string; at: string } & (\n | { kind: 'highlight' | 'underline' | 'strike'; rects: Box[]; text: string; color: string }\n | { kind: 'note'; spot: Point; text: string; color: string }\n | { kind: 'ink'; lines: Point[][]; width: number; color: string }\n | { kind: 'sign'; box: Box; image: string; method: SignatureMethod }\n);\n\nexport type Field = { page: number; name: string; box: Box; value: string | boolean | string[] };\n\nlet engine: Promise<PdfiumNative> | null = null;\n\nconst rect = (box: Box): Rect => ({ origin: { x: box.x, y: box.y }, size: { width: box.w, height: box.h } });\n\nconst around = (boxes: Box[]): Box => {\n const x = Math.min(...boxes.map(b => b.x));\n const y = Math.min(...boxes.map(b => b.y));\n return { x, y, w: Math.max(...boxes.map(b => b.x + b.w)) - x, h: Math.max(...boxes.map(b => b.y + b.h)) - y };\n};\n\nconst png = (url: string) => Uint8Array.from(atob(url.slice(url.indexOf(',') + 1)), c => c.charCodeAt(0)).buffer;\n\nconst types = { highlight: PdfAnnotationSubtype.HIGHLIGHT, underline: PdfAnnotationSubtype.UNDERLINE, strike: PdfAnnotationSubtype.STRIKEOUT } as const;\n\nfunction annotation(mark: Mark): PdfAnnotationObject {\n const base = { id: mark.id, pageIndex: mark.page - 1, author: mark.author, created: new Date(mark.at), modified: new Date(mark.at) };\n if (mark.kind === 'note') {\n return { ...base, type: PdfAnnotationSubtype.TEXT, rect: rect({ ...mark.spot, w: 20, h: 20 }), contents: mark.text, strokeColor: mark.color, opacity: 1 };\n }\n if (mark.kind === 'ink') {\n const spread = mark.width / 2 + 1;\n const bounds = around(mark.lines.flat().map(p => ({ x: p.x - spread, y: p.y - spread, w: spread * 2, h: spread * 2 })));\n return { ...base, type: PdfAnnotationSubtype.INK, rect: rect(bounds), inkList: mark.lines.map(points => ({ points })), strokeColor: mark.color, strokeWidth: mark.width, opacity: 1 };\n }\n if (mark.kind === 'sign') return { ...base, type: PdfAnnotationSubtype.STAMP, rect: rect(mark.box) };\n return {\n ...base, type: types[mark.kind], rect: rect(around(mark.rects)), segmentRects: mark.rects.map(rect), contents: mark.text, strokeColor: mark.color, opacity: 1,\n ...(mark.kind === 'highlight' ? { blendMode: PdfBlendMode.Multiply } : {}),\n } as PdfAnnotationObject;\n}\n\nexport async function write(bytes: ArrayBuffer, marks: Mark[], fields: Field[]): Promise<ArrayBuffer> {\n engine ??= init({}).then(module => new PdfiumNative(module));\n const pdfium = await engine;\n const doc = await pdfium.openDocumentBuffer({ id: Math.random().toString(36).slice(2), content: bytes.slice(0) }).toPromise();\n try {\n for (const n of new Set(fields.map(field => field.page))) {\n const page = doc.pages[n - 1];\n const widgets = await pdfium.getPageAnnoWidgets(doc, page).toPromise();\n for (const field of fields.filter(f => f.page === n)) {\n const centre = (r: Rect) => Math.hypot(r.origin.x + r.size.width / 2 - field.box.x - field.box.w / 2, r.origin.y + r.size.height / 2 - field.box.y - field.box.h / 2);\n const widget = widgets.filter(w => w.field.name === field.name).sort((a, b) => centre(a.rect) - centre(b.rect))[0];\n if (!widget) continue;\n const { type } = widget.field;\n if (type === PDF_FORM_FIELD_TYPE.TEXTFIELD) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'text', text: String(field.value) }).toPromise();\n } else if (type === PDF_FORM_FIELD_TYPE.CHECKBOX || (type === PDF_FORM_FIELD_TYPE.RADIOBUTTON && field.value === true)) {\n await pdfium.setFormFieldValue(doc, page, widget, { kind: 'checked', checked: field.value === true }).toPromise();\n } else if ('options' in widget.field && Array.isArray(field.value)) {\n for (const [index, option] of widget.field.options.entries()) {\n const wanted = field.value.includes(option.label);\n if (wanted !== option.isSelected) await pdfium.setFormFieldValue(doc, page, widget, { kind: 'selection', index, isSelected: wanted }).toPromise();\n }\n }\n }\n }\n for (const mark of marks) {\n const page = doc.pages[mark.page - 1];\n if (mark.kind === 'sign') await pdfium.createPageAnnotation(doc, page, annotation(mark), { data: png(mark.image), mimeType: 'image/png' } as never).toPromise();\n else await pdfium.createPageAnnotation(doc, page, annotation(mark)).toPromise();\n }\n return await pdfium.saveAsCopy(doc).toPromise();\n } finally {\n await pdfium.closeDocument(doc).toPromise();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,165 @@
1
+ type DocumentKind = 'docx' | 'markdown' | 'pdf' | 'sheet' | 'slides';
2
+ type Language = 'en' | 'pl' | 'uk';
3
+ type Person = {
4
+ id: string;
5
+ name: string;
6
+ avatarUrl?: string | null;
7
+ };
8
+ type Space = {
9
+ id: string;
10
+ name: string;
11
+ color?: string | null;
12
+ group?: string | null;
13
+ };
14
+ type Rights = {
15
+ view: boolean;
16
+ comment: boolean;
17
+ edit: boolean;
18
+ };
19
+ type DocumentSummary = {
20
+ id: string;
21
+ spaceId: string;
22
+ name: string;
23
+ kind: DocumentKind;
24
+ size: number;
25
+ updatedAt: string;
26
+ updatedBy?: Person | null;
27
+ thumbnailUrl?: string | null;
28
+ excerpt?: string | null;
29
+ folder?: string | null;
30
+ };
31
+ type DocumentFile = DocumentSummary & {
32
+ rights: Rights;
33
+ mimeType?: string | null;
34
+ exports?: ('pdf' | 'docx' | 'md')[];
35
+ live?: boolean;
36
+ convert?: 'xlsx';
37
+ };
38
+ type DocumentVersion = {
39
+ id: string;
40
+ createdAt: string;
41
+ size: number;
42
+ author?: Person | null;
43
+ note?: string | null;
44
+ current: boolean;
45
+ };
46
+ type Fetch = {
47
+ signal?: AbortSignal;
48
+ };
49
+ type SignatureMethod = 'typed' | 'drawn' | 'image';
50
+ type Signature = {
51
+ id: string;
52
+ signer: Person;
53
+ signedAt: string;
54
+ page: number;
55
+ method: SignatureMethod;
56
+ versionId: string | null;
57
+ };
58
+ type Comment = {
59
+ id: string;
60
+ documentId: string;
61
+ author: Person;
62
+ body: string;
63
+ createdAt: string;
64
+ quote: string;
65
+ replyTo: string | null;
66
+ resolved: boolean;
67
+ };
68
+ type GuestLink = {
69
+ id: string;
70
+ url: string;
71
+ comment: boolean;
72
+ download: boolean;
73
+ askName: boolean;
74
+ password: boolean;
75
+ endsAt: string | null;
76
+ ended: boolean;
77
+ createdAt: string;
78
+ createdBy: Person;
79
+ guests: {
80
+ name: string;
81
+ opens: number;
82
+ comments: number;
83
+ lastAt: string;
84
+ }[];
85
+ };
86
+ type LinkEntry = {
87
+ comment: boolean;
88
+ download: boolean;
89
+ askName: boolean;
90
+ endsAt: string | null;
91
+ password: string | null;
92
+ };
93
+ type GuestFile = {
94
+ id: string;
95
+ name: string;
96
+ mimeType: string;
97
+ size: number;
98
+ updatedAt: string;
99
+ sharedBy: string;
100
+ comment: boolean;
101
+ download: boolean;
102
+ bytes: ArrayBuffer;
103
+ };
104
+ interface GuestHost {
105
+ pdfWorker?: () => Worker;
106
+ open(entry: {
107
+ password?: string;
108
+ name?: string;
109
+ }, opts?: Fetch): Promise<GuestFile>;
110
+ comments(opts?: Fetch): Promise<Comment[]>;
111
+ comment(entry: {
112
+ body: string;
113
+ quote: string;
114
+ replyTo: string | null;
115
+ anchor: string;
116
+ name: string;
117
+ }): Promise<Comment>;
118
+ download(format: 'file' | 'pdf'): Promise<void>;
119
+ }
120
+ interface DocumentsHost {
121
+ me: Person;
122
+ pdfWorker?: () => Worker;
123
+ spaces(opts?: Fetch): Promise<Space[]>;
124
+ documents(spaceId: string, opts?: Fetch): Promise<DocumentSummary[]>;
125
+ everything?(opts?: Fetch): Promise<DocumentSummary[]>;
126
+ document(id: string, opts?: Fetch): Promise<DocumentFile>;
127
+ versions(id: string, opts?: Fetch): Promise<DocumentVersion[]>;
128
+ content(id: string, versionId?: string | null, opts?: Fetch): Promise<ArrayBuffer>;
129
+ restore?(id: string, versionId: string): Promise<void>;
130
+ save?(id: string, bytes: ArrayBuffer, note: string): Promise<{
131
+ versionId: string;
132
+ }>;
133
+ signatures?(id: string, opts?: Fetch): Promise<Signature[]>;
134
+ sign?(id: string, entry: {
135
+ versionId: string;
136
+ page: number;
137
+ method: SignatureMethod;
138
+ }): Promise<Signature>;
139
+ comments?(id: string, opts?: Fetch): Promise<Comment[]>;
140
+ comment?(id: string, entry: {
141
+ body: string;
142
+ quote: string;
143
+ replyTo: string | null;
144
+ anchor: string;
145
+ }): Promise<Comment>;
146
+ resolveComment?(id: string, commentId: string, resolved: boolean): Promise<void>;
147
+ editComment?(id: string, commentId: string, body: string): Promise<Comment>;
148
+ deleteComment?(id: string, commentId: string): Promise<void>;
149
+ exportAs?(id: string, format: 'pdf' | 'docx' | 'md'): Promise<Blob>;
150
+ copyAs?(id: string, format: 'xlsx'): Promise<DocumentSummary>;
151
+ links?(id: string, opts?: Fetch): Promise<GuestLink[]>;
152
+ share?(id: string, entry: LinkEntry): Promise<GuestLink>;
153
+ relink?(linkId: string, entry: LinkEntry): Promise<GuestLink>;
154
+ unshare?(linkId: string): Promise<void>;
155
+ collab?: {
156
+ url: string;
157
+ token: () => Promise<string>;
158
+ };
159
+ }
160
+ type Place = {
161
+ spaceId: string | null;
162
+ documentId: string | null;
163
+ };
164
+
165
+ export type { Comment as C, DocumentsHost as D, Fetch as F, GuestHost as G, Language as L, Place as P, Rights as R, Signature as S, DocumentFile as a, DocumentKind as b, DocumentSummary as c, DocumentVersion as d, GuestFile as e, GuestLink as f, LinkEntry as g, Person as h, SignatureMethod as i, Space as j };