@w100n/documents 0.1.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.
package/dist/index.js ADDED
@@ -0,0 +1,412 @@
1
+ 'use client';
2
+ import {
3
+ kindOf,
4
+ kinds,
5
+ matches
6
+ } from "./chunk-KEV4R7W5.js";
7
+
8
+ // src/DocumentsWorkspace.tsx
9
+ import { useState as useState4 } from "react";
10
+ import { ChevronDown, FileSpreadsheet, FileText, FileType, Files, History, Info, ListTree, PanelLeftClose, PanelLeftOpen, Presentation, Search } from "lucide-react";
11
+
12
+ // src/text.ts
13
+ var en = {
14
+ documents: "Documents",
15
+ search: "Search documents",
16
+ all: "All",
17
+ empty: "No documents here yet",
18
+ nothing: "Nothing matches the search",
19
+ space: "Project",
20
+ pick: "Choose a document on the left",
21
+ closeList: "Hide the list",
22
+ openList: "Show the list",
23
+ outline: "Outline",
24
+ versions: "Versions",
25
+ details: "Details",
26
+ noOutline: "This document has no headings",
27
+ current: "Current",
28
+ size: "Size",
29
+ updated: "Updated",
30
+ by: "By",
31
+ kind: "Format",
32
+ rights: "You can",
33
+ view: "View",
34
+ comment: "Comment",
35
+ edit: "Edit",
36
+ failed: "Could not load",
37
+ retry: "Try again",
38
+ loading: "Loading",
39
+ sheet: "Sheet",
40
+ unsupported: "This file cannot be shown yet",
41
+ kinds: { docx: "DOCX", markdown: "Markdown", pdf: "PDF", sheet: "Sheets", slides: "Slides" }
42
+ };
43
+ var pl = {
44
+ documents: "Dokumenty",
45
+ search: "Szukaj dokument\xF3w",
46
+ all: "Wszystkie",
47
+ empty: "Nie ma tu jeszcze dokument\xF3w",
48
+ nothing: "Nic nie pasuje do wyszukiwania",
49
+ space: "Projekt",
50
+ pick: "Wybierz dokument po lewej",
51
+ closeList: "Ukryj list\u0119",
52
+ openList: "Poka\u017C list\u0119",
53
+ outline: "Spis tre\u015Bci",
54
+ versions: "Wersje",
55
+ details: "Szczeg\xF3\u0142y",
56
+ noOutline: "Ten dokument nie ma nag\u0142\xF3wk\xF3w",
57
+ current: "Bie\u017C\u0105ca",
58
+ size: "Rozmiar",
59
+ updated: "Zmieniono",
60
+ by: "Autor",
61
+ kind: "Format",
62
+ rights: "Mo\u017Cesz",
63
+ view: "Ogl\u0105da\u0107",
64
+ comment: "Komentowa\u0107",
65
+ edit: "Edytowa\u0107",
66
+ failed: "Nie uda\u0142o si\u0119 wczyta\u0107",
67
+ retry: "Spr\xF3buj ponownie",
68
+ loading: "Wczytywanie",
69
+ sheet: "Arkusz",
70
+ unsupported: "Tego pliku nie da si\u0119 jeszcze pokaza\u0107",
71
+ kinds: { docx: "DOCX", markdown: "Markdown", pdf: "PDF", sheet: "Arkusze", slides: "Slajdy" }
72
+ };
73
+ var uk = {
74
+ documents: "\u0414\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0438",
75
+ search: "\u041F\u043E\u0448\u0443\u043A \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432",
76
+ all: "\u0423\u0441\u0456",
77
+ empty: "\u0422\u0443\u0442 \u0449\u0435 \u043D\u0435\u043C\u0430\u0454 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456\u0432",
78
+ nothing: "\u041D\u0456\u0447\u043E\u0433\u043E \u043D\u0435 \u0437\u043D\u0430\u0439\u0434\u0435\u043D\u043E",
79
+ space: "\u041F\u0440\u043E\u0454\u043A\u0442",
80
+ pick: "\u0412\u0438\u0431\u0435\u0440\u0456\u0442\u044C \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442 \u043B\u0456\u0432\u043E\u0440\u0443\u0447",
81
+ closeList: "\u0421\u0445\u043E\u0432\u0430\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A",
82
+ openList: "\u041F\u043E\u043A\u0430\u0437\u0430\u0442\u0438 \u0441\u043F\u0438\u0441\u043E\u043A",
83
+ outline: "\u0417\u043C\u0456\u0441\u0442",
84
+ versions: "\u0412\u0435\u0440\u0441\u0456\u0457",
85
+ details: "\u0414\u0435\u0442\u0430\u043B\u0456",
86
+ noOutline: "\u0423 \u0434\u043E\u043A\u0443\u043C\u0435\u043D\u0442\u0456 \u043D\u0435\u043C\u0430\u0454 \u0437\u0430\u0433\u043E\u043B\u043E\u0432\u043A\u0456\u0432",
87
+ current: "\u041F\u043E\u0442\u043E\u0447\u043D\u0430",
88
+ size: "\u0420\u043E\u0437\u043C\u0456\u0440",
89
+ updated: "\u0417\u043C\u0456\u043D\u0435\u043D\u043E",
90
+ by: "\u0410\u0432\u0442\u043E\u0440",
91
+ kind: "\u0424\u043E\u0440\u043C\u0430\u0442",
92
+ rights: "\u0412\u0438 \u043C\u043E\u0436\u0435\u0442\u0435",
93
+ view: "\u0414\u0438\u0432\u0438\u0442\u0438\u0441\u044F",
94
+ comment: "\u041A\u043E\u043C\u0435\u043D\u0442\u0443\u0432\u0430\u0442\u0438",
95
+ edit: "\u041F\u0440\u0430\u0432\u0438\u0442\u0438",
96
+ failed: "\u041D\u0435 \u0432\u0434\u0430\u043B\u043E\u0441\u044F \u0437\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0438\u0442\u0438",
97
+ retry: "\u0421\u043F\u0440\u043E\u0431\u0443\u0432\u0430\u0442\u0438 \u0449\u0435",
98
+ loading: "\u0417\u0430\u0432\u0430\u043D\u0442\u0430\u0436\u0435\u043D\u043D\u044F",
99
+ sheet: "\u0410\u0440\u043A\u0443\u0448",
100
+ unsupported: "\u0426\u0435\u0439 \u0444\u0430\u0439\u043B \u043F\u043E\u043A\u0438 \u043D\u0435 \u043F\u043E\u043A\u0430\u0437\u0443\u0454\u0442\u044C\u0441\u044F",
101
+ kinds: { docx: "DOCX", markdown: "Markdown", pdf: "PDF", sheet: "\u0422\u0430\u0431\u043B\u0438\u0446\u0456", slides: "\u0421\u043B\u0430\u0439\u0434\u0438" }
102
+ };
103
+ var texts = { en, pl, uk };
104
+
105
+ // src/useLoad.ts
106
+ import { useEffect, useState } from "react";
107
+ function useLoad(load, key) {
108
+ const [state, setState] = useState({ data: null, error: null, loading: true });
109
+ const [attempt, setAttempt] = useState(0);
110
+ useEffect(() => {
111
+ const controller = new AbortController();
112
+ setState((current) => ({ ...current, loading: true, error: null }));
113
+ load(controller.signal).then(
114
+ (data) => {
115
+ if (!controller.signal.aborted) setState({ data, error: null, loading: false });
116
+ },
117
+ (error) => {
118
+ if (!controller.signal.aborted) setState({ data: null, error: error instanceof Error ? error : new Error(String(error)), loading: false });
119
+ }
120
+ );
121
+ return () => controller.abort();
122
+ }, [...key, attempt]);
123
+ return { ...state, retry: () => setAttempt((n) => n + 1) };
124
+ }
125
+
126
+ // src/viewers/DocxView.tsx
127
+ import { useLayoutEffect, useRef, useState as useState2 } from "react";
128
+
129
+ // src/viewers/headings.ts
130
+ var last = 0;
131
+ function collect(root, selector, level = (el) => Number(el.tagName.slice(1))) {
132
+ return [...root.querySelectorAll(selector)].flatMap((el) => {
133
+ const text = el.textContent?.trim() ?? "";
134
+ if (!text) return [];
135
+ if (!el.id) el.id = `w100n-docs-h${++last}`;
136
+ return [{ id: el.id, level: Math.min(3, Math.max(1, level(el) || 1)), text }];
137
+ });
138
+ }
139
+
140
+ // src/viewers/DocxView.tsx
141
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
142
+ function DocxView({ bytes, onOutline, failed }) {
143
+ const box = useRef(null);
144
+ const [error, setError] = useState2(false);
145
+ useLayoutEffect(() => {
146
+ let live = true;
147
+ let width = 0;
148
+ const root = box.current;
149
+ const fit = () => {
150
+ const wrapper = root.querySelector(".w100n-docx-wrapper");
151
+ if (wrapper && width) wrapper.style.zoom = String(Math.min(1, root.clientWidth / width));
152
+ };
153
+ const watch = new ResizeObserver(fit);
154
+ root.replaceChildren();
155
+ setError(false);
156
+ import("docx-preview").then(({ renderAsync }) => renderAsync(bytes, root, void 0, { inWrapper: true, className: "w100n-docx", ignoreLastRenderedPageBreak: true })).then(() => {
157
+ if (!live) return;
158
+ width = Math.max(0, ...[...root.querySelectorAll("section.w100n-docx")].map((page) => page.offsetWidth));
159
+ fit();
160
+ watch.observe(root);
161
+ onOutline(collect(root, '[class*="heading"]', (el) => Number(/heading(\d)/i.exec(el.className)?.[1] ?? 1)));
162
+ }).catch(() => {
163
+ if (live) setError(true);
164
+ });
165
+ return () => {
166
+ live = false;
167
+ watch.disconnect();
168
+ };
169
+ }, [bytes, onOutline]);
170
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
171
+ error && /* @__PURE__ */ jsx("p", { className: "w100n-docs-note", children: failed }),
172
+ /* @__PURE__ */ jsx("div", { ref: box, className: "w100n-docs-docx" })
173
+ ] });
174
+ }
175
+
176
+ // src/viewers/MarkdownView.tsx
177
+ import DOMPurify from "dompurify";
178
+ import { marked } from "marked";
179
+ import { useLayoutEffect as useLayoutEffect2, useRef as useRef2 } from "react";
180
+ import { jsx as jsx2 } from "react/jsx-runtime";
181
+ function MarkdownView({ bytes, onOutline }) {
182
+ const box = useRef2(null);
183
+ useLayoutEffect2(() => {
184
+ const root = box.current;
185
+ root.innerHTML = DOMPurify.sanitize(marked.parse(new TextDecoder().decode(bytes), { async: false }));
186
+ onOutline(collect(root, "h1, h2, h3"));
187
+ }, [bytes, onOutline]);
188
+ return /* @__PURE__ */ jsx2("article", { ref: box, className: "w100n-docs-page w100n-docs-prose" });
189
+ }
190
+
191
+ // src/viewers/PdfView.tsx
192
+ import { useEffect as useEffect2, useRef as useRef3, useState as useState3 } from "react";
193
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
194
+ var last2 = 0;
195
+ function PdfView({ bytes, worker, onOutline, failed }) {
196
+ const box = useRef3(null);
197
+ const [error, setError] = useState3(false);
198
+ useEffect2(() => {
199
+ const root = box.current;
200
+ const prefix = `w100n-docs-p${++last2}`;
201
+ let stop = false;
202
+ let close = () => {
203
+ };
204
+ root.replaceChildren();
205
+ setError(false);
206
+ (async () => {
207
+ var _a;
208
+ const pdfjs = await import("pdfjs-dist");
209
+ if (worker) (_a = pdfjs.GlobalWorkerOptions).workerPort ?? (_a.workerPort = worker());
210
+ const task = pdfjs.getDocument({ data: new Uint8Array(bytes.slice(0)) });
211
+ close = () => {
212
+ void task.destroy();
213
+ };
214
+ const pdf = await task.promise;
215
+ const width = Math.max(320, root.clientWidth - 48);
216
+ for (let n = 1; n <= pdf.numPages && !stop; n++) {
217
+ const page = await pdf.getPage(n);
218
+ const scale = Math.min(2, width / page.getViewport({ scale: 1 }).width);
219
+ const viewport = page.getViewport({ scale: scale * window.devicePixelRatio });
220
+ const canvas = document.createElement("canvas");
221
+ canvas.id = `${prefix}-${n}`;
222
+ canvas.className = "w100n-docs-sheet";
223
+ canvas.width = viewport.width;
224
+ canvas.height = viewport.height;
225
+ canvas.style.width = `${viewport.width / window.devicePixelRatio}px`;
226
+ root.append(canvas);
227
+ await page.render({ canvas, canvasContext: canvas.getContext("2d"), viewport }).promise;
228
+ }
229
+ const flat = async (items, level) => (await Promise.all(items.map(async (item) => {
230
+ const dest = typeof item.dest === "string" ? await pdf.getDestination(item.dest) : item.dest;
231
+ const ref = Array.isArray(dest) ? dest[0] : null;
232
+ const index = ref && typeof ref === "object" ? await pdf.getPageIndex(ref) : null;
233
+ const here = index === null ? [] : [{ id: `${prefix}-${index + 1}`, level, text: item.title }];
234
+ return [...here, ...level < 3 ? await flat(item.items ?? [], level + 1) : []];
235
+ }))).flat();
236
+ if (!stop) onOutline(await flat(await pdf.getOutline() ?? [], 1));
237
+ })().catch(() => {
238
+ if (!stop) setError(true);
239
+ });
240
+ return () => {
241
+ stop = true;
242
+ close();
243
+ };
244
+ }, [bytes, worker, onOutline]);
245
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
246
+ error && /* @__PURE__ */ jsx3("p", { className: "w100n-docs-note", children: failed }),
247
+ /* @__PURE__ */ jsx3("div", { ref: box, className: "w100n-docs-pdf" })
248
+ ] });
249
+ }
250
+
251
+ // src/viewers/SlidesView.tsx
252
+ import { jsx as jsx4 } from "react/jsx-runtime";
253
+ function SlidesView({ bytes, title }) {
254
+ return /* @__PURE__ */ jsx4("iframe", { className: "w100n-docs-slides", sandbox: "allow-scripts", title, srcDoc: new TextDecoder().decode(bytes) });
255
+ }
256
+
257
+ // src/DocumentsWorkspace.tsx
258
+ import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
259
+ var icons = { docx: FileText, markdown: FileType, pdf: Files, sheet: FileSpreadsheet, slides: Presentation };
260
+ function DocumentsWorkspace({ host, language = "en", theme = "light", place, onPlace, start, end }) {
261
+ const t = texts[language];
262
+ const [own, setOwn] = useState4({ spaceId: null, documentId: null });
263
+ const here = place ?? own;
264
+ const go = (next) => {
265
+ setOwn(next);
266
+ onPlace?.(next);
267
+ };
268
+ const [query, setQuery] = useState4("");
269
+ const [kind, setKind] = useState4("all");
270
+ const [listOpen, setListOpen] = useState4(true);
271
+ const [picking, setPicking] = useState4(false);
272
+ const [tab, setTab] = useState4("outline");
273
+ const [outline, setOutline] = useState4([]);
274
+ const [version, setVersion] = useState4({ documentId: null, id: null });
275
+ const versionId = version.documentId === here.documentId ? version.id : null;
276
+ const spaces = useLoad((signal) => host.spaces({ signal }), [host]);
277
+ const spaceId = here.spaceId ?? spaces.data?.[0]?.id ?? null;
278
+ const space = spaces.data?.find((item) => item.id === spaceId);
279
+ const list = useLoad((signal) => spaceId ? host.documents(spaceId, { signal }) : Promise.resolve([]), [host, spaceId]);
280
+ const doc = useLoad((signal) => here.documentId ? host.document(here.documentId, { signal }) : Promise.resolve(null), [host, here.documentId]);
281
+ const versions = useLoad((signal) => here.documentId ? host.versions(here.documentId, { signal }) : Promise.resolve([]), [host, here.documentId]);
282
+ const content = useLoad((signal) => here.documentId ? host.content(here.documentId, versionId, { signal }) : Promise.resolve(null), [host, here.documentId, versionId]);
283
+ const shown = (list.data ?? []).filter((item) => matches(item, query, kind));
284
+ const date = (iso) => new Intl.DateTimeFormat(language, { day: "numeric", month: "short", year: "numeric", hour: "2-digit", minute: "2-digit" }).format(new Date(iso));
285
+ const size = (bytes) => bytes < 1024 ? `${bytes} B` : bytes < 1048576 ? `${(bytes / 1024).toFixed(0)} KB` : `${(bytes / 1048576).toFixed(1)} MB`;
286
+ const failed = (retry) => /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-note", children: [
287
+ t.failed,
288
+ /* @__PURE__ */ jsx5("button", { type: "button", onClick: retry, children: t.retry })
289
+ ] });
290
+ const open = (documentId) => {
291
+ setOutline([]);
292
+ setTab("outline");
293
+ go({ spaceId, documentId });
294
+ };
295
+ let stage = /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-empty", children: [
296
+ /* @__PURE__ */ jsx5(FileText, { "aria-hidden": true }),
297
+ t.pick
298
+ ] });
299
+ if (here.documentId) {
300
+ if (doc.error || content.error) stage = failed(() => {
301
+ doc.retry();
302
+ content.retry();
303
+ });
304
+ else if (!doc.data || !content.data) stage = /* @__PURE__ */ jsx5("div", { className: "w100n-docs-empty", children: t.loading });
305
+ else if (doc.data.kind === "markdown") stage = /* @__PURE__ */ jsx5(MarkdownView, { bytes: content.data, onOutline: setOutline });
306
+ else if (doc.data.kind === "docx") stage = /* @__PURE__ */ jsx5(DocxView, { bytes: content.data, onOutline: setOutline, failed: t.failed });
307
+ else if (doc.data.kind === "pdf") stage = /* @__PURE__ */ jsx5(PdfView, { bytes: content.data, worker: host.pdfWorker, onOutline: setOutline, failed: t.failed });
308
+ else if (doc.data.kind === "slides") stage = /* @__PURE__ */ jsx5(SlidesView, { bytes: content.data, title: doc.data.name });
309
+ else stage = /* @__PURE__ */ jsx5("div", { className: "w100n-docs-empty", children: t.unsupported });
310
+ }
311
+ const panelTabs = [["outline", ListTree, t.outline], ["versions", History, t.versions], ["details", Info, t.details]];
312
+ return /* @__PURE__ */ jsxs3("div", { className: "w100n-docs", "data-theme": theme, children: [
313
+ /* @__PURE__ */ jsxs3("header", { className: "w100n-docs-bar w100n-docs-island", children: [
314
+ start,
315
+ /* @__PURE__ */ jsx5("button", { type: "button", className: "w100n-docs-icon", onClick: () => setListOpen(!listOpen), "aria-label": listOpen ? t.closeList : t.openList, title: listOpen ? t.closeList : t.openList, children: listOpen ? /* @__PURE__ */ jsx5(PanelLeftClose, {}) : /* @__PURE__ */ jsx5(PanelLeftOpen, {}) }),
316
+ /* @__PURE__ */ jsx5("strong", { className: "w100n-docs-title", children: doc.data?.name ?? t.documents }),
317
+ doc.data && /* @__PURE__ */ jsx5("span", { className: "w100n-docs-badge", "data-kind": doc.data.kind, children: t.kinds[doc.data.kind] }),
318
+ versionId && /* @__PURE__ */ jsx5("span", { className: "w100n-docs-badge", children: versions.data?.find((v) => v.id === versionId) && date(versions.data.find((v) => v.id === versionId).createdAt) }),
319
+ end && /* @__PURE__ */ jsx5("div", { className: "w100n-docs-end", children: end })
320
+ ] }),
321
+ /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-body", children: [
322
+ listOpen && /* @__PURE__ */ jsxs3("aside", { className: "w100n-docs-list w100n-docs-island", "aria-label": t.documents, children: [
323
+ /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-picker", children: [
324
+ /* @__PURE__ */ jsxs3("button", { type: "button", className: "w100n-docs-field", "aria-haspopup": "listbox", "aria-expanded": picking, onClick: () => setPicking(!picking), children: [
325
+ /* @__PURE__ */ jsx5("span", { className: "w100n-docs-dot", style: { background: space?.color ?? void 0 } }),
326
+ space?.name ?? t.space,
327
+ /* @__PURE__ */ jsx5(ChevronDown, { "aria-hidden": true })
328
+ ] }),
329
+ picking && /* @__PURE__ */ jsx5("ul", { role: "listbox", className: "w100n-docs-menu", children: (spaces.data ?? []).map((item) => /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs3("button", { type: "button", role: "option", "aria-selected": item.id === spaceId, onClick: () => {
330
+ setPicking(false);
331
+ go({ spaceId: item.id, documentId: null });
332
+ }, children: [
333
+ /* @__PURE__ */ jsx5("span", { className: "w100n-docs-dot", style: { background: item.color ?? void 0 } }),
334
+ item.name
335
+ ] }) }, item.id)) })
336
+ ] }),
337
+ /* @__PURE__ */ jsxs3("label", { className: "w100n-docs-field w100n-docs-search", children: [
338
+ /* @__PURE__ */ jsx5(Search, { "aria-hidden": true }),
339
+ /* @__PURE__ */ jsx5("input", { value: query, onChange: (event) => setQuery(event.target.value), placeholder: t.search, "aria-label": t.search })
340
+ ] }),
341
+ /* @__PURE__ */ jsx5("div", { className: "w100n-docs-chips", role: "group", children: ["all", ...kinds].map((item) => /* @__PURE__ */ jsx5("button", { type: "button", "aria-pressed": kind === item, onClick: () => setKind(item), children: item === "all" ? t.all : t.kinds[item] }, item)) }),
342
+ /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-cards", children: [
343
+ list.error && failed(list.retry),
344
+ list.loading && !list.data && /* @__PURE__ */ jsx5("p", { className: "w100n-docs-muted", children: t.loading }),
345
+ list.data && !shown.length && /* @__PURE__ */ jsx5("p", { className: "w100n-docs-muted", children: list.data.length ? t.nothing : t.empty }),
346
+ shown.map((item) => {
347
+ const Icon = icons[item.kind];
348
+ return /* @__PURE__ */ jsxs3("button", { type: "button", className: "w100n-docs-card", "aria-current": item.id === here.documentId, onClick: () => open(item.id), children: [
349
+ item.thumbnailUrl ? /* @__PURE__ */ jsx5("img", { src: item.thumbnailUrl, alt: "", className: "w100n-docs-thumb" }) : /* @__PURE__ */ jsx5("span", { className: "w100n-docs-thumb", "data-kind": item.kind, children: /* @__PURE__ */ jsx5(Icon, { "aria-hidden": true }) }),
350
+ /* @__PURE__ */ jsxs3("span", { className: "w100n-docs-card-text", children: [
351
+ /* @__PURE__ */ jsx5("b", { children: item.name }),
352
+ /* @__PURE__ */ jsxs3("small", { children: [
353
+ t.kinds[item.kind],
354
+ " \xB7 ",
355
+ date(item.updatedAt)
356
+ ] })
357
+ ] })
358
+ ] }, item.id);
359
+ })
360
+ ] })
361
+ ] }),
362
+ /* @__PURE__ */ jsx5("main", { className: "w100n-docs-stage", children: stage }),
363
+ doc.data && /* @__PURE__ */ jsxs3("aside", { className: "w100n-docs-panel w100n-docs-island", children: [
364
+ /* @__PURE__ */ jsx5("div", { className: "w100n-docs-tabs", role: "tablist", children: panelTabs.map(([key, Icon, label]) => /* @__PURE__ */ jsxs3("button", { type: "button", role: "tab", "aria-selected": tab === key, onClick: () => setTab(key), children: [
365
+ /* @__PURE__ */ jsx5(Icon, { "aria-hidden": true }),
366
+ label
367
+ ] }, key)) }),
368
+ tab === "outline" && (outline.length ? /* @__PURE__ */ jsx5("nav", { className: "w100n-docs-outline", children: outline.map((item) => /* @__PURE__ */ jsx5("button", { type: "button", "data-level": item.level, onClick: () => document.getElementById(item.id)?.scrollIntoView({ behavior: "smooth", block: "start" }), children: item.text }, item.id)) }) : /* @__PURE__ */ jsx5("p", { className: "w100n-docs-muted", children: t.noOutline })),
369
+ tab === "versions" && /* @__PURE__ */ jsxs3("div", { className: "w100n-docs-versions", children: [
370
+ versions.error && failed(versions.retry),
371
+ (versions.data ?? []).map((item) => /* @__PURE__ */ jsxs3(
372
+ "button",
373
+ {
374
+ type: "button",
375
+ "aria-pressed": (versionId ?? "current") === item.id || !versionId && item.current,
376
+ onClick: () => setVersion({ documentId: here.documentId, id: item.current ? null : item.id }),
377
+ children: [
378
+ /* @__PURE__ */ jsxs3("b", { children: [
379
+ date(item.createdAt),
380
+ item.current && /* @__PURE__ */ jsx5("span", { className: "w100n-docs-badge", children: t.current })
381
+ ] }),
382
+ /* @__PURE__ */ jsx5("small", { children: [item.author?.name, size(item.size), item.note].filter(Boolean).join(" \xB7 ") })
383
+ ]
384
+ },
385
+ item.id
386
+ ))
387
+ ] }),
388
+ tab === "details" && /* @__PURE__ */ jsxs3("dl", { className: "w100n-docs-details", children: [
389
+ /* @__PURE__ */ jsx5("dt", { children: t.kind }),
390
+ /* @__PURE__ */ jsx5("dd", { children: t.kinds[doc.data.kind] }),
391
+ /* @__PURE__ */ jsx5("dt", { children: t.size }),
392
+ /* @__PURE__ */ jsx5("dd", { children: size(doc.data.size) }),
393
+ /* @__PURE__ */ jsx5("dt", { children: t.updated }),
394
+ /* @__PURE__ */ jsx5("dd", { children: date(doc.data.updatedAt) }),
395
+ doc.data.updatedBy && /* @__PURE__ */ jsxs3(Fragment3, { children: [
396
+ /* @__PURE__ */ jsx5("dt", { children: t.by }),
397
+ /* @__PURE__ */ jsx5("dd", { children: doc.data.updatedBy.name })
398
+ ] }),
399
+ /* @__PURE__ */ jsx5("dt", { children: t.rights }),
400
+ /* @__PURE__ */ jsx5("dd", { children: [doc.data.rights.view && t.view, doc.data.rights.comment && t.comment, doc.data.rights.edit && t.edit].filter(Boolean).join(", ") })
401
+ ] })
402
+ ] })
403
+ ] })
404
+ ] });
405
+ }
406
+ export {
407
+ DocumentsWorkspace,
408
+ kindOf,
409
+ kinds,
410
+ matches
411
+ };
412
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/DocumentsWorkspace.tsx","../src/text.ts","../src/useLoad.ts","../src/viewers/DocxView.tsx","../src/viewers/headings.ts","../src/viewers/MarkdownView.tsx","../src/viewers/PdfView.tsx","../src/viewers/SlidesView.tsx"],"sourcesContent":["import { useState, type ReactNode } from 'react';\nimport { ChevronDown, FileSpreadsheet, FileText, FileType, Files, History, Info, ListTree, PanelLeftClose, PanelLeftOpen, Presentation, Search, type LucideIcon } from 'lucide-react';\nimport { kinds, matches } from './kinds';\nimport { texts } from './text';\nimport type { DocumentKind, DocumentsHost, Language, Place } from './types';\nimport { useLoad } from './useLoad';\nimport DocxView from './viewers/DocxView';\nimport type { Heading } from './viewers/headings';\nimport MarkdownView from './viewers/MarkdownView';\nimport PdfView from './viewers/PdfView';\nimport SlidesView from './viewers/SlidesView';\nimport './styles.css';\n\nconst icons: Record<DocumentKind, LucideIcon> = { docx: FileText, markdown: FileType, pdf: Files, sheet: FileSpreadsheet, slides: Presentation };\n\ntype Tab = 'outline' | 'versions' | 'details';\n\nexport function DocumentsWorkspace({ host, language = 'en', theme = 'light', place, onPlace, start, end }: {\n host: DocumentsHost; language?: Language; theme?: 'light' | 'dark'; place?: Place; onPlace?: (place: Place) => void; start?: ReactNode; end?: ReactNode;\n}) {\n const t = texts[language];\n const [own, setOwn] = useState<Place>({ spaceId: null, documentId: null });\n const here = place ?? own;\n const go = (next: Place) => { setOwn(next); onPlace?.(next); };\n const [query, setQuery] = useState('');\n const [kind, setKind] = useState<DocumentKind | 'all'>('all');\n const [listOpen, setListOpen] = useState(true);\n const [picking, setPicking] = useState(false);\n const [tab, setTab] = useState<Tab>('outline');\n const [outline, setOutline] = useState<Heading[]>([]);\n const [version, setVersion] = useState<{ documentId: string | null; id: string | null }>({ documentId: null, id: null });\n const versionId = version.documentId === here.documentId ? version.id : null;\n\n const spaces = useLoad(signal => host.spaces({ signal }), [host]);\n const spaceId = here.spaceId ?? spaces.data?.[0]?.id ?? null;\n const space = spaces.data?.find(item => item.id === spaceId);\n const list = useLoad(signal => spaceId ? host.documents(spaceId, { signal }) : Promise.resolve([]), [host, spaceId]);\n const doc = useLoad(signal => here.documentId ? host.document(here.documentId, { signal }) : Promise.resolve(null), [host, here.documentId]);\n const versions = useLoad(signal => here.documentId ? host.versions(here.documentId, { signal }) : Promise.resolve([]), [host, here.documentId]);\n const content = useLoad(signal => here.documentId ? host.content(here.documentId, versionId, { signal }) : Promise.resolve(null), [host, here.documentId, versionId]);\n\n const shown = (list.data ?? []).filter(item => matches(item, query, kind));\n const date = (iso: string) => new Intl.DateTimeFormat(language, { day: 'numeric', month: 'short', year: 'numeric', hour: '2-digit', minute: '2-digit' }).format(new Date(iso));\n const size = (bytes: number) => bytes < 1024 ? `${bytes} B` : bytes < 1048576 ? `${(bytes / 1024).toFixed(0)} KB` : `${(bytes / 1048576).toFixed(1)} MB`;\n const failed = (retry: () => void) => <div className=\"w100n-docs-note\">{t.failed}<button type=\"button\" onClick={retry}>{t.retry}</button></div>;\n const open = (documentId: string) => { setOutline([]); setTab('outline'); go({ spaceId, documentId }); };\n\n let stage: ReactNode = <div className=\"w100n-docs-empty\"><FileText aria-hidden />{t.pick}</div>;\n if (here.documentId) {\n if (doc.error || content.error) stage = failed(() => { doc.retry(); content.retry(); });\n else if (!doc.data || !content.data) stage = <div className=\"w100n-docs-empty\">{t.loading}</div>;\n else if (doc.data.kind === 'markdown') stage = <MarkdownView bytes={content.data} onOutline={setOutline} />;\n else if (doc.data.kind === 'docx') stage = <DocxView bytes={content.data} onOutline={setOutline} failed={t.failed} />;\n else if (doc.data.kind === 'pdf') stage = <PdfView bytes={content.data} worker={host.pdfWorker} onOutline={setOutline} failed={t.failed} />;\n else if (doc.data.kind === 'slides') stage = <SlidesView bytes={content.data} title={doc.data.name} />;\n else stage = <div className=\"w100n-docs-empty\">{t.unsupported}</div>;\n }\n\n const panelTabs: [Tab, LucideIcon, string][] = [['outline', ListTree, t.outline], ['versions', History, t.versions], ['details', Info, t.details]];\n return <div className=\"w100n-docs\" data-theme={theme}>\n <header className=\"w100n-docs-bar w100n-docs-island\">\n {start}\n <button type=\"button\" className=\"w100n-docs-icon\" onClick={() => setListOpen(!listOpen)} aria-label={listOpen ? t.closeList : t.openList} title={listOpen ? t.closeList : t.openList}>\n {listOpen ? <PanelLeftClose /> : <PanelLeftOpen />}\n </button>\n <strong className=\"w100n-docs-title\">{doc.data?.name ?? t.documents}</strong>\n {doc.data && <span className=\"w100n-docs-badge\" data-kind={doc.data.kind}>{t.kinds[doc.data.kind]}</span>}\n {versionId && <span className=\"w100n-docs-badge\">{versions.data?.find(v => v.id === versionId) && date(versions.data.find(v => v.id === versionId)!.createdAt)}</span>}\n {end && <div className=\"w100n-docs-end\">{end}</div>}\n </header>\n <div className=\"w100n-docs-body\">\n {listOpen && <aside className=\"w100n-docs-list w100n-docs-island\" aria-label={t.documents}>\n <div className=\"w100n-docs-picker\">\n <button type=\"button\" className=\"w100n-docs-field\" aria-haspopup=\"listbox\" aria-expanded={picking} onClick={() => setPicking(!picking)}>\n <span className=\"w100n-docs-dot\" style={{ background: space?.color ?? undefined }} />{space?.name ?? t.space}<ChevronDown aria-hidden />\n </button>\n {picking && <ul role=\"listbox\" className=\"w100n-docs-menu\">{(spaces.data ?? []).map(item => <li key={item.id}>\n <button type=\"button\" role=\"option\" aria-selected={item.id === spaceId} onClick={() => { setPicking(false); go({ spaceId: item.id, documentId: null }); }}>\n <span className=\"w100n-docs-dot\" style={{ background: item.color ?? undefined }} />{item.name}\n </button></li>)}</ul>}\n </div>\n <label className=\"w100n-docs-field w100n-docs-search\"><Search aria-hidden /><input value={query} onChange={event => setQuery(event.target.value)} placeholder={t.search} aria-label={t.search} /></label>\n <div className=\"w100n-docs-chips\" role=\"group\">{(['all', ...kinds] as const).map(item => <button key={item} type=\"button\" aria-pressed={kind === item} onClick={() => setKind(item)}>{item === 'all' ? t.all : t.kinds[item]}</button>)}</div>\n <div className=\"w100n-docs-cards\">\n {list.error && failed(list.retry)}\n {list.loading && !list.data && <p className=\"w100n-docs-muted\">{t.loading}</p>}\n {list.data && !shown.length && <p className=\"w100n-docs-muted\">{list.data.length ? t.nothing : t.empty}</p>}\n {shown.map(item => {\n const Icon = icons[item.kind];\n return <button key={item.id} type=\"button\" className=\"w100n-docs-card\" aria-current={item.id === here.documentId} onClick={() => open(item.id)}>\n {item.thumbnailUrl ? <img src={item.thumbnailUrl} alt=\"\" className=\"w100n-docs-thumb\" /> : <span className=\"w100n-docs-thumb\" data-kind={item.kind}><Icon aria-hidden /></span>}\n <span className=\"w100n-docs-card-text\"><b>{item.name}</b><small>{t.kinds[item.kind]} · {date(item.updatedAt)}</small></span>\n </button>;\n })}\n </div>\n </aside>}\n <main className=\"w100n-docs-stage\">{stage}</main>\n {doc.data && <aside className=\"w100n-docs-panel w100n-docs-island\">\n <div className=\"w100n-docs-tabs\" role=\"tablist\">{panelTabs.map(([key, Icon, label]) =>\n <button key={key} type=\"button\" role=\"tab\" aria-selected={tab === key} onClick={() => setTab(key)}><Icon aria-hidden />{label}</button>)}</div>\n {tab === 'outline' && (outline.length ? <nav className=\"w100n-docs-outline\">{outline.map(item =>\n <button key={item.id} type=\"button\" data-level={item.level} onClick={() => document.getElementById(item.id)?.scrollIntoView({ behavior: 'smooth', block: 'start' })}>{item.text}</button>)}</nav>\n : <p className=\"w100n-docs-muted\">{t.noOutline}</p>)}\n {tab === 'versions' && <div className=\"w100n-docs-versions\">\n {versions.error && failed(versions.retry)}\n {(versions.data ?? []).map(item => <button key={item.id} type=\"button\" aria-pressed={(versionId ?? 'current') === item.id || (!versionId && item.current)}\n onClick={() => setVersion({ documentId: here.documentId, id: item.current ? null : item.id })}>\n <b>{date(item.createdAt)}{item.current && <span className=\"w100n-docs-badge\">{t.current}</span>}</b>\n <small>{[item.author?.name, size(item.size), item.note].filter(Boolean).join(' · ')}</small>\n </button>)}\n </div>}\n {tab === 'details' && <dl className=\"w100n-docs-details\">\n <dt>{t.kind}</dt><dd>{t.kinds[doc.data.kind]}</dd>\n <dt>{t.size}</dt><dd>{size(doc.data.size)}</dd>\n <dt>{t.updated}</dt><dd>{date(doc.data.updatedAt)}</dd>\n {doc.data.updatedBy && <><dt>{t.by}</dt><dd>{doc.data.updatedBy.name}</dd></>}\n <dt>{t.rights}</dt><dd>{[doc.data.rights.view && t.view, doc.data.rights.comment && t.comment, doc.data.rights.edit && t.edit].filter(Boolean).join(', ')}</dd>\n </dl>}\n </aside>}\n </div>\n </div>;\n}\n","import type { DocumentKind, Language } from './types';\n\nconst en = {\n documents: 'Documents', search: 'Search documents', all: 'All', empty: 'No documents here yet', nothing: 'Nothing matches the search',\n space: 'Project', pick: 'Choose a document on the left', closeList: 'Hide the list', openList: 'Show the list',\n outline: 'Outline', versions: 'Versions', details: 'Details', noOutline: 'This document has no headings', current: 'Current',\n size: 'Size', updated: 'Updated', by: 'By', kind: 'Format', rights: 'You can', view: 'View', comment: 'Comment', edit: 'Edit',\n failed: 'Could not load', retry: 'Try again', loading: 'Loading', sheet: 'Sheet', unsupported: 'This file cannot be shown yet',\n kinds: { docx: 'DOCX', markdown: 'Markdown', pdf: 'PDF', sheet: 'Sheets', slides: 'Slides' } satisfies Record<DocumentKind, string>,\n};\n\nexport type Text = typeof en;\n\nconst pl: Text = {\n documents: 'Dokumenty', search: 'Szukaj dokumentów', all: 'Wszystkie', empty: 'Nie ma tu jeszcze dokumentów', nothing: 'Nic nie pasuje do wyszukiwania',\n space: 'Projekt', pick: 'Wybierz dokument po lewej', closeList: 'Ukryj listę', openList: 'Pokaż listę',\n outline: 'Spis treści', versions: 'Wersje', details: 'Szczegóły', noOutline: 'Ten dokument nie ma nagłówków', current: 'Bieżąca',\n size: 'Rozmiar', updated: 'Zmieniono', by: 'Autor', kind: 'Format', rights: 'Możesz', view: 'Oglądać', comment: 'Komentować', edit: 'Edytować',\n failed: 'Nie udało się wczytać', retry: 'Spróbuj ponownie', loading: 'Wczytywanie', sheet: 'Arkusz', unsupported: 'Tego pliku nie da się jeszcze pokazać',\n kinds: { docx: 'DOCX', markdown: 'Markdown', pdf: 'PDF', sheet: 'Arkusze', slides: 'Slajdy' },\n};\n\nconst uk: Text = {\n documents: 'Документи', search: 'Пошук документів', all: 'Усі', empty: 'Тут ще немає документів', nothing: 'Нічого не знайдено',\n space: 'Проєкт', pick: 'Виберіть документ ліворуч', closeList: 'Сховати список', openList: 'Показати список',\n outline: 'Зміст', versions: 'Версії', details: 'Деталі', noOutline: 'У документі немає заголовків', current: 'Поточна',\n size: 'Розмір', updated: 'Змінено', by: 'Автор', kind: 'Формат', rights: 'Ви можете', view: 'Дивитися', comment: 'Коментувати', edit: 'Правити',\n failed: 'Не вдалося завантажити', retry: 'Спробувати ще', loading: 'Завантаження', sheet: 'Аркуш', unsupported: 'Цей файл поки не показується',\n kinds: { docx: 'DOCX', markdown: 'Markdown', pdf: 'PDF', sheet: 'Таблиці', slides: 'Слайди' },\n};\n\nexport const texts: Record<Language, Text> = { en, pl, uk };\n","import { useEffect, useState } from 'react';\n\nexport type Loaded<T> = { data: T | null; error: Error | null; loading: boolean; retry: () => void };\n\nexport function useLoad<T>(load: (signal: AbortSignal) => Promise<T>, key: unknown[]): Loaded<T> {\n const [state, setState] = useState<{ data: T | null; error: Error | null; loading: boolean }>({ data: null, error: null, loading: true });\n const [attempt, setAttempt] = useState(0);\n useEffect(() => {\n const controller = new AbortController();\n setState(current => ({ ...current, loading: true, error: null }));\n load(controller.signal).then(\n data => { if (!controller.signal.aborted) setState({ data, error: null, loading: false }); },\n error => { if (!controller.signal.aborted) setState({ data: null, error: error instanceof Error ? error : new Error(String(error)), loading: false }); },\n );\n return () => controller.abort();\n }, [...key, attempt]);\n return { ...state, retry: () => setAttempt(n => n + 1) };\n}\n","import { useLayoutEffect, useRef, useState } from 'react';\nimport { collect, type Heading } from './headings';\n\nexport default function DocxView({ bytes, onOutline, failed }: { bytes: ArrayBuffer; onOutline: (headings: Heading[]) => void; failed: string }) {\n const box = useRef<HTMLDivElement>(null);\n const [error, setError] = useState(false);\n useLayoutEffect(() => {\n let live = true;\n let width = 0;\n const root = box.current!;\n const fit = () => {\n const wrapper = root.querySelector<HTMLElement>('.w100n-docx-wrapper');\n if (wrapper && width) wrapper.style.zoom = String(Math.min(1, root.clientWidth / width));\n };\n const watch = new ResizeObserver(fit);\n root.replaceChildren();\n setError(false);\n import('docx-preview')\n .then(({ renderAsync }) => renderAsync(bytes, root, undefined, { inWrapper: true, className: 'w100n-docx', ignoreLastRenderedPageBreak: true }))\n .then(() => {\n if (!live) return;\n width = Math.max(0, ...[...root.querySelectorAll<HTMLElement>('section.w100n-docx')].map(page => page.offsetWidth));\n fit();\n watch.observe(root);\n onOutline(collect(root, '[class*=\"heading\"]', el => Number(/heading(\\d)/i.exec(el.className)?.[1] ?? 1)));\n })\n .catch(() => { if (live) setError(true); });\n return () => { live = false; watch.disconnect(); };\n }, [bytes, onOutline]);\n return <>{error && <p className=\"w100n-docs-note\">{failed}</p>}<div ref={box} className=\"w100n-docs-docx\" /></>;\n}\n","export type Heading = { id: string; level: number; text: string };\n\nlet last = 0;\n\nexport function collect(root: HTMLElement, selector: string, level: (el: Element) => number = el => Number(el.tagName.slice(1))): Heading[] {\n return [...root.querySelectorAll(selector)].flatMap(el => {\n const text = el.textContent?.trim() ?? '';\n if (!text) return [];\n if (!el.id) el.id = `w100n-docs-h${++last}`;\n return [{ id: el.id, level: Math.min(3, Math.max(1, level(el) || 1)), text }];\n });\n}\n","import DOMPurify from 'dompurify';\nimport { marked } from 'marked';\nimport { useLayoutEffect, useRef } from 'react';\nimport { collect, type Heading } from './headings';\n\nexport default function MarkdownView({ bytes, onOutline }: { bytes: ArrayBuffer; onOutline: (headings: Heading[]) => void }) {\n const box = useRef<HTMLElement>(null);\n useLayoutEffect(() => {\n const root = box.current!;\n root.innerHTML = DOMPurify.sanitize(marked.parse(new TextDecoder().decode(bytes), { async: false }));\n onOutline(collect(root, 'h1, h2, h3'));\n }, [bytes, onOutline]);\n return <article ref={box} className=\"w100n-docs-page w100n-docs-prose\" />;\n}\n","import { useEffect, useRef, useState } from 'react';\nimport type { Heading } from './headings';\n\ntype Outline = { title: string; dest: string | unknown[] | null; items: Outline[] };\n\nlet last = 0;\n\nexport default function PdfView({ bytes, worker, onOutline, failed }: { bytes: ArrayBuffer; worker?: () => Worker; onOutline: (headings: Heading[]) => void; failed: string }) {\n const box = useRef<HTMLDivElement>(null);\n const [error, setError] = useState(false);\n useEffect(() => {\n const root = box.current!;\n const prefix = `w100n-docs-p${++last}`;\n let stop = false;\n let close = () => {};\n root.replaceChildren();\n setError(false);\n (async () => {\n const pdfjs = await import('pdfjs-dist');\n if (worker) pdfjs.GlobalWorkerOptions.workerPort ??= worker();\n const task = pdfjs.getDocument({ data: new Uint8Array(bytes.slice(0)) });\n close = () => { void task.destroy(); };\n const pdf = await task.promise;\n const width = Math.max(320, root.clientWidth - 48);\n for (let n = 1; n <= pdf.numPages && !stop; n++) {\n const page = await pdf.getPage(n);\n const scale = Math.min(2, width / page.getViewport({ scale: 1 }).width);\n const viewport = page.getViewport({ scale: scale * window.devicePixelRatio });\n const canvas = document.createElement('canvas');\n canvas.id = `${prefix}-${n}`;\n canvas.className = 'w100n-docs-sheet';\n canvas.width = viewport.width;\n canvas.height = viewport.height;\n canvas.style.width = `${viewport.width / window.devicePixelRatio}px`;\n root.append(canvas);\n await page.render({ canvas, canvasContext: canvas.getContext('2d')!, viewport }).promise;\n }\n const flat = async (items: Outline[], level: number): Promise<Heading[]> => (await Promise.all(items.map(async item => {\n const dest = typeof item.dest === 'string' ? await pdf.getDestination(item.dest) : item.dest;\n const ref = Array.isArray(dest) ? dest[0] : null;\n const index = ref && typeof ref === 'object' ? await pdf.getPageIndex(ref as never) : null;\n const here = index === null ? [] : [{ id: `${prefix}-${index + 1}`, level, text: item.title }];\n return [...here, ...(level < 3 ? await flat(item.items ?? [], level + 1) : [])];\n }))).flat();\n if (!stop) onOutline(await flat(((await pdf.getOutline()) ?? []) as Outline[], 1));\n })().catch(() => { if (!stop) setError(true); });\n return () => { stop = true; close(); };\n }, [bytes, worker, onOutline]);\n return <>{error && <p className=\"w100n-docs-note\">{failed}</p>}<div ref={box} className=\"w100n-docs-pdf\" /></>;\n}\n","export default function SlidesView({ bytes, title }: { bytes: ArrayBuffer; title: string }) {\n return <iframe className=\"w100n-docs-slides\" sandbox=\"allow-scripts\" title={title} srcDoc={new TextDecoder().decode(bytes)} />;\n}\n"],"mappings":"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","names":["useState","useState","useState","useLayoutEffect","useRef","jsx","useRef","useLayoutEffect","useEffect","useRef","useState","Fragment","jsx","jsxs","last","jsx","Fragment","jsx","jsxs","useState"]}
@@ -0,0 +1,92 @@
1
+ 'use client';
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/memory.ts
22
+ var memory_exports = {};
23
+ __export(memory_exports, {
24
+ memoryHost: () => memoryHost
25
+ });
26
+ module.exports = __toCommonJS(memory_exports);
27
+
28
+ // src/kinds.ts
29
+ var byExtension = {
30
+ docx: "docx",
31
+ md: "markdown",
32
+ markdown: "markdown",
33
+ pdf: "pdf",
34
+ xlsx: "sheet",
35
+ csv: "sheet",
36
+ html: "slides",
37
+ htm: "slides"
38
+ };
39
+ var byMime = {
40
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
41
+ "text/markdown": "markdown",
42
+ "application/pdf": "pdf",
43
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "sheet",
44
+ "text/csv": "sheet",
45
+ "text/html": "slides"
46
+ };
47
+ function kindOf(name, mimeType) {
48
+ const extension = name.includes(".") ? name.split(".").pop().toLowerCase() : "";
49
+ return byExtension[extension] ?? (mimeType ? byMime[mimeType.split(";")[0].trim().toLowerCase()] : void 0) ?? null;
50
+ }
51
+
52
+ // src/memory.ts
53
+ var encode = (bytes) => typeof bytes === "string" ? new TextEncoder().encode(bytes).buffer : bytes;
54
+ function memoryHost({ me, spaces, files }) {
55
+ const find = (id) => {
56
+ const file = files.find((item) => item.id === id);
57
+ if (!file) throw new Error("document not found");
58
+ return file;
59
+ };
60
+ const summary = (file) => ({
61
+ id: file.id,
62
+ spaceId: file.spaceId,
63
+ name: file.name,
64
+ kind: kindOf(file.name),
65
+ size: encode(file.bytes).byteLength,
66
+ updatedAt: file.updatedAt ?? "2026-10-19T09:00:00Z",
67
+ updatedBy: me
68
+ });
69
+ return {
70
+ me,
71
+ spaces: async () => spaces,
72
+ documents: async (spaceId) => files.filter((file) => file.spaceId === spaceId && kindOf(file.name)).map(summary),
73
+ document: async (id) => ({ ...summary(find(id)), rights: { view: true, comment: true, edit: true, ...find(id).rights } }),
74
+ versions: async (id) => {
75
+ const file = find(id);
76
+ return [
77
+ { id: "current", createdAt: summary(file).updatedAt, size: summary(file).size, author: me, current: true },
78
+ ...(file.versions ?? []).map((v) => ({ id: v.id, createdAt: v.createdAt, size: encode(v.bytes).byteLength, author: me, note: v.note ?? null, current: false }))
79
+ ];
80
+ },
81
+ content: async (id, versionId) => {
82
+ const file = find(id);
83
+ const old = versionId && versionId !== "current" ? file.versions?.find((v) => v.id === versionId) : void 0;
84
+ return encode(old ? old.bytes : file.bytes);
85
+ }
86
+ };
87
+ }
88
+ // Annotate the CommonJS export names for ESM import in node:
89
+ 0 && (module.exports = {
90
+ memoryHost
91
+ });
92
+ //# sourceMappingURL=memory.cjs.map
@@ -0,0 +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 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,\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 };\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":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,cAA4C;AAAA,EAChD,MAAM;AAAA,EAAQ,IAAI;AAAA,EAAY,UAAU;AAAA,EAAY,KAAK;AAAA,EAAO,MAAM;AAAA,EAAS,KAAK;AAAA,EAAS,MAAM;AAAA,EAAU,KAAK;AACpH;AAEA,IAAM,SAAuC;AAAA,EAC3C,2EAA2E;AAAA,EAC3E,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,qEAAqE;AAAA,EACrE,YAAY;AAAA,EACZ,aAAa;AACf;AAIO,SAAS,OAAO,MAAc,UAA+C;AAClF,QAAM,YAAY,KAAK,SAAS,GAAG,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,EAAG,YAAY,IAAI;AAC9E,SAAO,YAAY,SAAS,MAAM,WAAW,OAAO,SAAS,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,WAAc;AACnH;;;ADLA,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,EAClE;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,EACF;AACF;","names":[]}
@@ -0,0 +1,24 @@
1
+ import { R as Rights, e as Person, S as Space, D as DocumentsHost } from './types-aZrEQFiC.cjs';
2
+
3
+ type Bytes = ArrayBuffer | string;
4
+ type MemoryFile = {
5
+ id: string;
6
+ spaceId: string;
7
+ name: string;
8
+ bytes: Bytes;
9
+ updatedAt?: string;
10
+ rights?: Partial<Rights>;
11
+ versions?: {
12
+ id: string;
13
+ createdAt: string;
14
+ bytes: Bytes;
15
+ note?: string;
16
+ }[];
17
+ };
18
+ declare function memoryHost({ me, spaces, files }: {
19
+ me: Person;
20
+ spaces: Space[];
21
+ files: MemoryFile[];
22
+ }): DocumentsHost;
23
+
24
+ export { type MemoryFile, memoryHost };