react-embed-docs 0.1.0 → 0.2.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/client/components/Breadcrumbs.d.ts.map +1 -1
- package/dist/client/components/Breadcrumbs.js +9 -6
- package/dist/client/components/DocumentEdit.d.ts.map +1 -1
- package/dist/client/components/DocumentEdit.js +6 -4
- package/dist/client/components/DocumentList.d.ts.map +1 -1
- package/dist/client/components/DocumentList.js +16 -8
- package/dist/client/components/DocumentView.d.ts.map +1 -1
- package/dist/client/components/DocumentView.js +4 -2
- package/dist/client/components/EmojiPicker.d.ts.map +1 -1
- package/dist/client/components/EmojiPicker.js +3 -1
- package/dist/client/components/ExportButton.d.ts.map +1 -1
- package/dist/client/components/ExportButton.js +14 -12
- package/dist/client/components/Layout.d.ts.map +1 -1
- package/dist/client/components/Layout.js +5 -3
- package/dist/client/components/ReactEmbedDocs.d.ts.map +1 -1
- package/dist/client/components/ReactEmbedDocs.js +2 -1
- package/dist/client/components/Sidebar.d.ts.map +1 -1
- package/dist/client/components/Sidebar.js +4 -2
- package/dist/client/components/VersionHistory.d.ts.map +1 -1
- package/dist/client/components/VersionHistory.js +13 -11
- package/dist/client/hooks/useTranslation.d.ts +13 -0
- package/dist/client/hooks/useTranslation.d.ts.map +1 -0
- package/dist/client/hooks/useTranslation.js +27 -0
- package/dist/client/index.d.ts +1 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +1 -0
- package/dist/client/locales/en.json +82 -0
- package/dist/client/locales/ru.json +82 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../src/client/components/Breadcrumbs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Breadcrumbs.d.ts","sourceRoot":"","sources":["../../../src/client/components/Breadcrumbs.tsx"],"names":[],"mappings":"AAMA,UAAU,aAAa;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACzB;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,aAAa,EAAE,CAAA;IAC3B,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACnC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAwCD,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAc,GACf,EAAE,gBAAgB,2CAqLlB"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { ChevronRight, Home, Loader2 } from 'lucide-react';
|
|
4
4
|
import { useEffect, useMemo, useState } from 'react';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
5
6
|
// Fetch breadcrumbs from API
|
|
6
7
|
async function fetchBreadcrumbs(docId) {
|
|
7
8
|
const response = await fetch(`/api/docs/${docId}/breadcrumbs`);
|
|
@@ -31,7 +32,9 @@ function buildPath(docId, allDocs, basePath = '/docs') {
|
|
|
31
32
|
return basePath;
|
|
32
33
|
return `${basePath}/${pathParts.join('/')}`;
|
|
33
34
|
}
|
|
34
|
-
export function Breadcrumbs({ docId, documents, onNavigate, homeLabel
|
|
35
|
+
export function Breadcrumbs({ docId, documents, onNavigate, homeLabel, className = '', }) {
|
|
36
|
+
const { t } = useTranslation();
|
|
37
|
+
const label = homeLabel || t('breadcrumbs.home');
|
|
35
38
|
const [fetchedBreadcrumbs, setFetchedBreadcrumbs] = useState([]);
|
|
36
39
|
const [isLoading, setIsLoading] = useState(false);
|
|
37
40
|
const [error, setError] = useState(null);
|
|
@@ -104,18 +107,18 @@ export function Breadcrumbs({ docId, documents, onNavigate, homeLabel = 'Home',
|
|
|
104
107
|
}
|
|
105
108
|
};
|
|
106
109
|
if (!docId) {
|
|
107
|
-
return (_jsx("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: _jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children:
|
|
110
|
+
return (_jsx("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: _jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children: label })] }) }));
|
|
108
111
|
}
|
|
109
112
|
if (isLoading && !documents) {
|
|
110
|
-
return (_jsxs("div", { className: `flex items-center gap-2 text-sm text-gray-400 ${className}`, children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), _jsx("span", { children:
|
|
113
|
+
return (_jsxs("div", { className: `flex items-center gap-2 text-sm text-gray-400 ${className}`, children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), _jsx("span", { children: t('breadcrumbs.loading') })] }));
|
|
111
114
|
}
|
|
112
115
|
if (error && !documents) {
|
|
113
|
-
return (_jsxs("div", { className: `flex items-center gap-1 text-sm text-gray-500 ${className}`, children: [_jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children:
|
|
116
|
+
return (_jsxs("div", { className: `flex items-center gap-1 text-sm text-gray-500 ${className}`, children: [_jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children: label })] }), _jsx(ChevronRight, { className: "h-4 w-4 text-gray-400" }), _jsx("span", { className: "text-gray-400", children: t('breadcrumbs.error') })] }));
|
|
114
117
|
}
|
|
115
118
|
if (breadcrumbs.length === 0) {
|
|
116
|
-
return (_jsx("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: _jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children:
|
|
119
|
+
return (_jsx("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: _jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors", children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { children: label })] }) }));
|
|
117
120
|
}
|
|
118
|
-
return (_jsxs("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: [_jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors shrink-0", title:
|
|
121
|
+
return (_jsxs("nav", { className: `flex items-center gap-1 text-sm ${className}`, children: [_jsxs("button", { onClick: () => handleNavigate(null), className: "flex items-center gap-1.5 text-gray-500 hover:text-gray-700 transition-colors shrink-0", title: label, children: [_jsx(Home, { className: "h-4 w-4" }), _jsx("span", { className: "hidden sm:inline", children: label })] }), breadcrumbs.map((doc, index) => {
|
|
119
122
|
const isLast = index === breadcrumbs.length - 1;
|
|
120
123
|
const displayTitle = doc.title || 'Untitled';
|
|
121
124
|
return (_jsxs("span", { className: "flex items-center gap-1 min-w-0", children: [_jsx(ChevronRight, { className: "h-4 w-4 text-gray-400 shrink-0" }), isLast ? (_jsxs("span", { className: "font-medium text-gray-900 truncate max-w-[200px] sm:max-w-[300px] md:max-w-[400px]", title: displayTitle, children: [doc.emoji && _jsx("span", { className: "mr-1", children: doc.emoji }), displayTitle] })) : (_jsxs("button", { onClick: () => handleNavigate(doc.id), className: "text-gray-500 hover:text-gray-700 transition-colors truncate max-w-[150px] sm:max-w-[200px]", title: displayTitle, children: [doc.emoji && _jsx("span", { className: "mr-1", children: doc.emoji }), displayTitle] }))] }, doc.id));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentEdit.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentEdit.tsx"],"names":[],"mappings":"AAIA,OAAO,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"DocumentEdit.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentEdit.tsx"],"names":[],"mappings":"AAIA,OAAO,8BAA8B,CAAA;AAgBrC,UAAU,iBAAiB;CAAG;AAqB9B,wBAAgB,YAAY,CAAC,EAAE,EAAE,iBAAiB,2CA8PjD"}
|
|
@@ -8,6 +8,7 @@ import { useEffect, useState } from 'react';
|
|
|
8
8
|
import { useCreateDocumentMutation, useDocumentQuery, useUpdateDocumentMutation, } from '../hooks/useDocsQuery.js';
|
|
9
9
|
import { useFileUpload } from '../hooks/useFileUpload.js';
|
|
10
10
|
import { blockNoteTheme } from '../lib/blocknoteTheme.js';
|
|
11
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
11
12
|
import { useDocument } from './DocumentProvider.js';
|
|
12
13
|
import { EmojiPicker } from './EmojiPicker.js';
|
|
13
14
|
// Default initial content for new documents
|
|
@@ -27,6 +28,7 @@ const generateSlug = (title) => {
|
|
|
27
28
|
};
|
|
28
29
|
export function DocumentEdit({}) {
|
|
29
30
|
const { onOpen, onEdit, theme, params } = useDocument();
|
|
31
|
+
const { t } = useTranslation();
|
|
30
32
|
const isNewDocument = params.documentSlug === undefined;
|
|
31
33
|
// Fetch existing document data if editing
|
|
32
34
|
const { data: existingDoc, isLoading: isLoadingDoc } = useDocumentQuery(params.documentSlug);
|
|
@@ -78,7 +80,7 @@ export function DocumentEdit({}) {
|
|
|
78
80
|
};
|
|
79
81
|
const handleSave = async () => {
|
|
80
82
|
if (!title.trim()) {
|
|
81
|
-
alert('
|
|
83
|
+
alert(t('editor.titleRequired'));
|
|
82
84
|
return;
|
|
83
85
|
}
|
|
84
86
|
setIsSaving(true);
|
|
@@ -114,7 +116,7 @@ export function DocumentEdit({}) {
|
|
|
114
116
|
}
|
|
115
117
|
catch (error) {
|
|
116
118
|
console.error('Failed to save document:', error);
|
|
117
|
-
alert('
|
|
119
|
+
alert(t('editor.saveFailed'));
|
|
118
120
|
}
|
|
119
121
|
finally {
|
|
120
122
|
setIsSaving(false);
|
|
@@ -147,7 +149,7 @@ export function DocumentEdit({}) {
|
|
|
147
149
|
if (!isNewDocument && isLoadingDoc) {
|
|
148
150
|
return (_jsx("div", { className: "flex items-center justify-center min-h-100", children: _jsx(Loader2, { className: "h-8 w-8 animate-spin text-gray-400" }) }));
|
|
149
151
|
}
|
|
150
|
-
return (_jsxs("div", { className: "mx-auto h-full flex flex-col", children: [_jsxs("div", { className: "mb-6 shrink-0", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-1", children: [_jsx(EmojiPicker, { value: emoji, onChange: setEmoji }), _jsx("input", { type: "text", value: title, onChange: (e) => setTitle(e.target.value), placeholder:
|
|
152
|
+
return (_jsxs("div", { className: "mx-auto h-full flex flex-col", children: [_jsxs("div", { className: "mb-6 shrink-0", children: [_jsxs("div", { className: "flex items-start justify-between gap-4", children: [_jsxs("div", { className: "flex items-center gap-2 flex-1", children: [_jsx(EmojiPicker, { value: emoji, onChange: setEmoji }), _jsx("input", { type: "text", value: title, onChange: (e) => setTitle(e.target.value), placeholder: t('editor.titlePlaceholder'), className: "text-2xl font-bold bg-transparent border-none outline-none px-0 flex-1 placeholder:text-gray-400" })] }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [!isNewDocument && existingDoc && (_jsxs("button", { onClick: handleView, className: "px-3 py-1.5 text-sm border border-border rounded-md hover:bg-gray-50 flex items-center gap-2 transition-colors", children: [_jsx(Eye, { className: "h-4 w-4" }), t('editor.view')] })), _jsx("button", { onClick: handleSave, disabled: isSaving || createMutation.isPending || updateMutation.isPending, className: "px-3 py-1.5 text-sm bg-primary text-white rounded-md hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed flex items-center gap-2 transition-colors", children: isSaving ||
|
|
151
153
|
createMutation.isPending ||
|
|
152
|
-
updateMutation.isPending ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
154
|
+
updateMutation.isPending ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "h-4 w-4 animate-spin" }), t('editor.saving')] })) : (_jsxs(_Fragment, { children: [_jsx(Save, { className: "h-4 w-4" }), isNewDocument ? t('editor.create') : t('editor.save')] })) })] })] }), _jsxs("div", { className: "text-sm text-gray-500 mt-1", children: [t('editor.slug'), ": ", generateSlug(title)] })] }), _jsx("div", { className: "mb-6 shrink-0", children: cover ? (_jsxs("div", { className: "relative w-full h-80 rounded-lg overflow-hidden bg-gray-100", children: [_jsx("img", { src: cover, alt: t('editor.coverAlt'), className: "w-full h-full object-cover" }), _jsx("button", { onClick: () => setCover(null), className: "absolute top-2 right-2 p-1.5 bg-secondary hover:bg-white rounded-md shadow-sm transition-colors", title: t('editor.removeCover'), children: _jsx(X, { className: "h-4 w-4" }) })] })) : (_jsxs("div", { onDrop: handleDrop, onDragOver: handleDragOver, className: "relative w-full h-32 border-2 border-dashed border-border rounded-lg bg-secondary hover:bg-gray-100 transition-colors cursor-pointer", children: [_jsx("input", { type: "file", accept: "image/jpeg,image/png,image/gif,image/webp", onChange: handleFileInput, className: "absolute inset-0 w-full h-full opacity-0 cursor-pointer" }), _jsx("div", { className: "flex flex-col items-center justify-center h-full gap-2 text-gray-400", children: isUploadingCover ? (_jsx(Loader2, { className: "h-6 w-6 animate-spin" })) : (_jsxs(_Fragment, { children: [_jsx(ImageIcon, { className: "h-6 w-6" }), _jsx("span", { className: "text-sm", children: t('editor.coverDropzone') }), _jsx("span", { className: "text-xs text-gray-400", children: t('editor.coverFormats') })] })) })] })) }), _jsx("div", { className: "flex-1 min-h-0 overflow-auto", children: _jsx("div", { className: "h-full", children: _jsx(BlockNoteView, { editor: editor, theme: blockNoteTheme[theme], className: "h-full" }) }) })] }));
|
|
153
155
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentList.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DocumentList.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentList.tsx"],"names":[],"mappings":"AAkBA,UAAU,iBAAiB;CAAG;AAgC9B,wBAAgB,YAAY,CAAC,EAAE,EAAE,iBAAiB,2CAiIjD"}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { FileText, Folder, Plus } from 'lucide-react';
|
|
4
4
|
import { useDocumentsQuery } from '../hooks/useDocsQuery.js';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
5
6
|
import { useDocument } from './DocumentProvider.js';
|
|
6
|
-
function formatDistanceToNow(date) {
|
|
7
|
+
function formatDistanceToNow(date, t) {
|
|
7
8
|
const now = new Date();
|
|
8
9
|
const diffMs = now.getTime() - new Date(date).getTime();
|
|
9
10
|
const diffSec = Math.round(diffMs / 1000);
|
|
@@ -11,16 +12,22 @@ function formatDistanceToNow(date) {
|
|
|
11
12
|
const diffHour = Math.round(diffMin / 60);
|
|
12
13
|
const diffDay = Math.round(diffHour / 24);
|
|
13
14
|
if (diffSec < 60) {
|
|
14
|
-
return '
|
|
15
|
+
return t('docList.justNow');
|
|
15
16
|
}
|
|
16
17
|
else if (diffMin < 60) {
|
|
17
|
-
return
|
|
18
|
+
return diffMin === 1
|
|
19
|
+
? t('docList.minuteAgo', { n: diffMin })
|
|
20
|
+
: t('docList.minutesAgo', { n: diffMin });
|
|
18
21
|
}
|
|
19
22
|
else if (diffHour < 24) {
|
|
20
|
-
return
|
|
23
|
+
return diffHour === 1
|
|
24
|
+
? t('docList.hourAgo', { n: diffHour })
|
|
25
|
+
: t('docList.hoursAgo', { n: diffHour });
|
|
21
26
|
}
|
|
22
27
|
else if (diffDay < 7) {
|
|
23
|
-
return
|
|
28
|
+
return diffDay === 1
|
|
29
|
+
? t('docList.dayAgo', { n: diffDay })
|
|
30
|
+
: t('docList.daysAgo', { n: diffDay });
|
|
24
31
|
}
|
|
25
32
|
else {
|
|
26
33
|
return date.toLocaleDateString();
|
|
@@ -28,12 +35,13 @@ function formatDistanceToNow(date) {
|
|
|
28
35
|
}
|
|
29
36
|
export function DocumentList({}) {
|
|
30
37
|
const { onOpen, onCreate } = useDocument();
|
|
38
|
+
const { t } = useTranslation();
|
|
31
39
|
const { data, isLoading, error } = useDocumentsQuery();
|
|
32
40
|
const documents = data?.documents ?? [];
|
|
33
41
|
// Separate documents into folders (documents with children) and regular documents
|
|
34
42
|
const folders = documents.filter((doc) => documents.some((d) => d.parentId === doc.id));
|
|
35
43
|
const regularDocuments = documents.filter((doc) => !doc.parentId && !folders.some((f) => f.id === doc.id));
|
|
36
|
-
return (_jsxs("div", { className: "space-y-6 max-w-5xl mx-auto", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("h2", { className: "text-2xl font-bold", children:
|
|
37
|
-
? formatDistanceToNow(new Date(doc.updatedAt))
|
|
38
|
-
: 'N/A'] })] })] }), _jsx("button", { className: "px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-100 rounded-md transition-colors", children:
|
|
44
|
+
return (_jsxs("div", { className: "space-y-6 max-w-5xl mx-auto", children: [_jsxs("div", { className: "space-y-2", children: [_jsx("h2", { className: "text-2xl font-bold", children: t('docList.welcome') }), _jsx("p", { className: "text-gray-500", children: t('docList.welcomeDescription') })] }), folders.length > 0 && (_jsxs("section", { children: [_jsx("h3", { className: "text-lg font-semibold mb-4", children: t('docList.folders') }), _jsxs("div", { className: "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4", children: [folders.map((folder) => (_jsxs("div", { onClick: () => onOpen?.(folder.slug), className: "border border-gray-200 rounded-lg p-4 hover:bg-gray-50 transition-colors cursor-pointer", children: [_jsxs("div", { className: "flex items-start justify-between mb-2", children: [folder.emoji ? (_jsx("span", { className: "text-2xl", children: folder.emoji })) : (_jsx(Folder, { className: "h-8 w-8 text-blue-600" })), _jsxs("span", { className: "text-xs text-gray-500", children: [documents.filter((d) => d.parentId === folder.id).length, ' ', t('docList.docs')] })] }), _jsx("h4", { className: "text-base font-medium", children: folder.title })] }, folder.id))), _jsxs("div", { onClick: onCreate, className: "border border-dashed border-gray-300 rounded-lg p-4 hover:bg-gray-50 transition-colors cursor-pointer", children: [_jsx("div", { className: "flex items-center justify-center h-8 mb-2", children: _jsx(Plus, { className: "h-6 w-6 text-gray-400" }) }), _jsx("h4", { className: "text-base font-medium text-center text-gray-500", children: t('docList.newFolder') })] })] })] })), _jsxs("section", { children: [_jsxs("div", { className: "flex items-center justify-between mb-4", children: [_jsx("h3", { className: "text-lg font-semibold", children: folders.length > 0 ? t('docList.documents') : t('docList.recentDocuments') }), _jsxs("button", { onClick: onCreate, className: "px-3 py-1.5 text-sm bg-gray-900 text-white rounded-md hover:bg-gray-800 flex items-center gap-2 transition-colors", children: [_jsx(Plus, { className: "h-4 w-4" }), t('docList.newDocument')] })] }), regularDocuments.length === 0 ? (_jsx("div", { className: "border border-dashed border-gray-300 rounded-lg p-8", children: _jsxs("div", { className: "flex flex-col items-center justify-center text-center", children: [_jsx(FileText, { className: "h-12 w-12 text-gray-400 mb-4" }), _jsx("h4", { className: "text-lg font-medium mb-2", children: t('docList.noDocuments') }), _jsx("p", { className: "text-sm text-gray-500 mb-4", children: t('docList.getStarted') }), _jsxs("button", { onClick: onCreate, className: "px-4 py-2 bg-gray-900 text-white rounded-md hover:bg-gray-800 flex items-center gap-2 transition-colors", children: [_jsx(Plus, { className: "h-4 w-4" }), t('docList.createDocument')] })] }) })) : (_jsx("div", { className: "space-y-2", children: regularDocuments.map((doc) => (_jsxs("div", { onClick: () => onOpen?.(doc.slug), className: "flex items-center justify-between p-4 rounded-lg border border-gray-200 bg-white hover:bg-gray-50 transition-colors group cursor-pointer", children: [_jsxs("div", { className: "flex items-center gap-3", children: [doc.emoji ? (_jsx("span", { className: "text-xl", children: doc.emoji })) : (_jsx(FileText, { className: "h-5 w-5 text-gray-400 group-hover:text-gray-600 transition-colors" })), _jsxs("div", { children: [_jsx("h4", { className: "font-medium text-gray-900", children: doc.title }), _jsxs("p", { className: "text-sm text-gray-500", children: [t('docList.updated'), ' ', doc.updatedAt
|
|
45
|
+
? formatDistanceToNow(new Date(doc.updatedAt), t)
|
|
46
|
+
: 'N/A'] })] })] }), _jsx("button", { className: "px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-100 rounded-md transition-colors", children: t('docList.open') })] }, doc.id))) }))] })] }));
|
|
39
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentView.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentView.tsx"],"names":[],"mappings":"AAIA,OAAO,8BAA8B,CAAA;
|
|
1
|
+
{"version":3,"file":"DocumentView.d.ts","sourceRoot":"","sources":["../../../src/client/components/DocumentView.tsx"],"names":[],"mappings":"AAIA,OAAO,8BAA8B,CAAA;AAUrC,UAAU,iBAAiB;CAAG;AAU9B,wBAAgB,YAAY,CAAC,EAAE,EAAE,iBAAiB,2CA2HjD"}
|
|
@@ -7,6 +7,7 @@ import { Clock, Edit, Loader2, User } from 'lucide-react';
|
|
|
7
7
|
import { useCallback, useEffect, useState } from 'react';
|
|
8
8
|
import { useDocumentQuery } from '../hooks/useDocsQuery.js';
|
|
9
9
|
import { blockNoteTheme } from '../lib/blocknoteTheme.js';
|
|
10
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
10
11
|
import { useDocument } from './DocumentProvider.js';
|
|
11
12
|
import { ExportButton } from './ExportButton.js';
|
|
12
13
|
// Default content when document has no content
|
|
@@ -18,6 +19,7 @@ const getDefaultContent = () => [
|
|
|
18
19
|
];
|
|
19
20
|
export function DocumentView({}) {
|
|
20
21
|
const { params, onCreate, onEdit, theme } = useDocument();
|
|
22
|
+
const { t } = useTranslation();
|
|
21
23
|
const { data: doc, isLoading, error } = useDocumentQuery(params.documentSlug);
|
|
22
24
|
const [hasLoaded, setHasLoaded] = useState(false);
|
|
23
25
|
// Creates a new editor instance in read-only mode
|
|
@@ -50,9 +52,9 @@ export function DocumentView({}) {
|
|
|
50
52
|
return (_jsx("div", { className: "flex items-center justify-center min-h-[400px]", children: _jsx(Loader2, { className: "h-8 w-8 animate-spin text-gray-400" }) }));
|
|
51
53
|
}
|
|
52
54
|
if (error || !doc) {
|
|
53
|
-
return (_jsx("div", { className: "flex items-center justify-center min-h-[400px]", children: _jsx("p", { className: "text-red-500", children:
|
|
55
|
+
return (_jsx("div", { className: "flex items-center justify-center min-h-[400px]", children: _jsx("p", { className: "text-red-500", children: t('view.loadFailed') }) }));
|
|
54
56
|
}
|
|
55
|
-
return (_jsxs("div", { className: "max-w-[80%] mx-auto", children: [_jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-start justify-between gap-4 mb-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [doc.emoji && (_jsx("span", { className: "text-5xl leading-none", role: "img", "aria-label": "document emoji", children: doc.emoji })), _jsx("h1", { className: "text-3xl font-bold", children: doc.title })] }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [doc && (_jsx(ExportButton, { documentId: doc.id, documentTitle: doc.title })), _jsxs("button", { onClick: handleEdit, className: "px-3 py-1.5 text-sm bg-secondary text-white rounded-md hover:bg-primary flex items-center gap-2 transition-colors", children: [_jsx(Edit, { className: "h-4 w-4" }),
|
|
57
|
+
return (_jsxs("div", { className: "max-w-[80%] mx-auto", children: [_jsxs("div", { className: "mb-8", children: [_jsxs("div", { className: "flex items-start justify-between gap-4 mb-4", children: [_jsxs("div", { className: "flex items-center gap-3", children: [doc.emoji && (_jsx("span", { className: "text-5xl leading-none", role: "img", "aria-label": "document emoji", children: doc.emoji })), _jsx("h1", { className: "text-3xl font-bold", children: doc.title })] }), _jsxs("div", { className: "flex items-center gap-2 shrink-0", children: [doc && (_jsx(ExportButton, { documentId: doc.id, documentTitle: doc.title })), _jsxs("button", { onClick: handleEdit, className: "px-3 py-1.5 text-sm bg-secondary text-white rounded-md hover:bg-primary flex items-center gap-2 transition-colors", children: [_jsx(Edit, { className: "h-4 w-4" }), t('view.edit')] })] })] }), _jsxs("div", { className: "flex items-center gap-6 text-sm text-gray-500", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(User, { className: "h-4 w-4" }), _jsxs("span", { children: [t('view.authorId'), ": ", doc.authorId] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Clock, { className: "h-4 w-4" }), _jsxs("span", { children: [t('view.updated'), ' ', doc.updatedAt
|
|
56
58
|
? new Date(doc.updatedAt).toLocaleDateString()
|
|
57
59
|
: 'N/A'] })] })] })] }), doc.cover && (_jsx("div", { className: "mb-8 -mx-4 sm:-mx-8 lg:-mx-12", children: _jsx("div", { className: "relative w-full max-h-80 overflow-hidden", children: _jsx("img", { src: doc.cover, alt: doc.title, className: "w-full h-full object-cover" }) }) })), _jsx("div", { children: _jsx(BlockNoteView, { editor: editor, editable: false, theme: blockNoteTheme[theme], className: "[&_.bn-editor]:p-0 [&_.bn-editor]:px-0 [&_.bn-container]:max-w-none [&_.bn-editor]:!px-0" }) })] }));
|
|
58
60
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/client/components/EmojiPicker.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"EmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/client/components/EmojiPicker.tsx"],"names":[],"mappings":"AAKA,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAChC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAgBD,wBAAgB,WAAW,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,2CAqE3E"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
3
4
|
import { useState, useRef, useEffect } from 'react';
|
|
4
5
|
// Popular emojis for documents
|
|
5
6
|
const POPULAR_EMOJIS = [
|
|
@@ -15,6 +16,7 @@ const POPULAR_EMOJIS = [
|
|
|
15
16
|
'✅', '❌', '⭕', '🚫', '💯', '💢', '♨️', '🚷', '🚯', '🚳',
|
|
16
17
|
];
|
|
17
18
|
export function EmojiPicker({ value, onChange, className }) {
|
|
19
|
+
const { t } = useTranslation();
|
|
18
20
|
const [isOpen, setIsOpen] = useState(false);
|
|
19
21
|
const dropdownRef = useRef(null);
|
|
20
22
|
// Close dropdown when clicking outside
|
|
@@ -44,5 +46,5 @@ export function EmojiPicker({ value, onChange, className }) {
|
|
|
44
46
|
].join(' '), children: emoji }, emoji))) }), value && (_jsx("button", { onClick: () => {
|
|
45
47
|
onChange('');
|
|
46
48
|
setIsOpen(false);
|
|
47
|
-
}, className: "mt-2 w-full py-1.5 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded transition-colors", children:
|
|
49
|
+
}, className: "mt-2 w-full py-1.5 text-sm text-gray-500 dark:text-gray-400 hover:text-gray-900 dark:hover:text-gray-100 hover:bg-gray-100 dark:hover:bg-gray-800 rounded transition-colors", children: t('emoji.remove') }))] }))] }));
|
|
48
50
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExportButton.d.ts","sourceRoot":"","sources":["../../../src/client/components/ExportButton.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExportButton.d.ts","sourceRoot":"","sources":["../../../src/client/components/ExportButton.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAyCD;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,UAAU,EACV,aAAa,EACb,OAAO,EACP,SAAc,EACd,eAAoB,EACpB,aAAkB,GACnB,EAAE,iBAAiB,2CAqHnB"}
|
|
@@ -2,32 +2,33 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useRef, useEffect } from 'react';
|
|
3
3
|
import { Download, FileText, FileType, FileCode, File } from 'lucide-react';
|
|
4
4
|
import { useExport } from '../hooks/useExport.js';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
5
6
|
const EXPORT_OPTIONS = [
|
|
6
7
|
{
|
|
7
8
|
format: 'docx',
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
labelKey: 'export.word',
|
|
10
|
+
descKey: 'export.wordDesc',
|
|
10
11
|
icon: _jsx(FileText, { className: "w-4 h-4 text-blue-600" }),
|
|
11
12
|
extension: 'docx',
|
|
12
13
|
},
|
|
13
14
|
{
|
|
14
15
|
format: 'pdf',
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
labelKey: 'export.pdf',
|
|
17
|
+
descKey: 'export.pdfDesc',
|
|
17
18
|
icon: _jsx(FileType, { className: "w-4 h-4 text-red-600" }),
|
|
18
19
|
extension: 'pdf',
|
|
19
20
|
},
|
|
20
21
|
{
|
|
21
22
|
format: 'html',
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
labelKey: 'export.html',
|
|
24
|
+
descKey: 'export.htmlDesc',
|
|
24
25
|
icon: _jsx(FileCode, { className: "w-4 h-4 text-orange-600" }),
|
|
25
26
|
extension: 'html',
|
|
26
27
|
},
|
|
27
28
|
{
|
|
28
29
|
format: 'markdown',
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
labelKey: 'export.markdown',
|
|
31
|
+
descKey: 'export.markdownDesc',
|
|
31
32
|
icon: _jsx(File, { className: "w-4 h-4 text-gray-600" }),
|
|
32
33
|
extension: 'md',
|
|
33
34
|
},
|
|
@@ -48,6 +49,7 @@ export function ExportButton({ documentId, documentTitle, baseUrl, className = '
|
|
|
48
49
|
const [isOpen, setIsOpen] = useState(false);
|
|
49
50
|
const menuRef = useRef(null);
|
|
50
51
|
const { exportDocument, isExporting } = useExport({ baseUrl });
|
|
52
|
+
const { t } = useTranslation();
|
|
51
53
|
// Close menu when clicking outside
|
|
52
54
|
useEffect(() => {
|
|
53
55
|
function handleClickOutside(event) {
|
|
@@ -72,10 +74,10 @@ export function ExportButton({ documentId, documentTitle, baseUrl, className = '
|
|
|
72
74
|
const message = error instanceof Error ? error.message : 'Export failed';
|
|
73
75
|
// Show alert for now - could be replaced with a toast notification
|
|
74
76
|
if (message.includes('docx') || message.includes('puppeteer') || message.includes('playwright')) {
|
|
75
|
-
alert(
|
|
77
|
+
alert(t('export.missingDep', { message, command: format === 'docx' ? 'npm install docx' : 'npm install puppeteer' }));
|
|
76
78
|
}
|
|
77
79
|
else {
|
|
78
|
-
alert(
|
|
80
|
+
alert(t('export.failed', { message }));
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
};
|
|
@@ -88,10 +90,10 @@ export function ExportButton({ documentId, documentTitle, baseUrl, className = '
|
|
|
88
90
|
disabled:opacity-50 disabled:cursor-not-allowed
|
|
89
91
|
transition-colors
|
|
90
92
|
${buttonClassName}
|
|
91
|
-
`, children: [_jsx(Download, { className: `w-4 h-4 ${isExporting ? 'animate-bounce' : ''}` }), _jsx("span", { children:
|
|
93
|
+
`, children: [_jsx(Download, { className: `w-4 h-4 ${isExporting ? 'animate-bounce' : ''}` }), _jsx("span", { children: t('export.export') }), _jsx("svg", { className: `w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 9l-7 7-7-7" }) })] }), isOpen && (_jsx("div", { className: `
|
|
92
94
|
absolute right-0 mt-2 w-64
|
|
93
95
|
bg-white border border-gray-200 rounded-lg shadow-lg
|
|
94
96
|
z-50 overflow-hidden
|
|
95
97
|
${menuClassName}
|
|
96
|
-
`, children: _jsxs("div", { className: "py-1", children: [_jsx("div", { className: "px-3 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider", children:
|
|
98
|
+
`, children: _jsxs("div", { className: "py-1", children: [_jsx("div", { className: "px-3 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wider", children: t('export.exportAs') }), EXPORT_OPTIONS.map((option) => (_jsxs("button", { onClick: () => handleExport(option.format), disabled: isExporting, className: "\n w-full flex items-start gap-3 px-3 py-2.5\n text-left hover:bg-gray-50\n focus:outline-none focus:bg-gray-50\n disabled:opacity-50 disabled:cursor-not-allowed\n transition-colors\n ", children: [_jsx("div", { className: "flex-shrink-0 mt-0.5", children: option.icon }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "text-sm font-medium text-gray-900", children: t(option.labelKey) }), _jsx("div", { className: "text-xs text-gray-500", children: t(option.descKey) })] }), _jsxs("div", { className: "flex-shrink-0 text-xs text-gray-400 uppercase", children: [".", option.extension] })] }, option.format)))] }) }))] }));
|
|
97
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/client/components/Layout.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../../src/client/components/Layout.tsx"],"names":[],"mappings":"AAiBA,UAAU,eAAe;IACvB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AAmJD,wBAAgB,MAAM,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,EAAE,eAAe,2CA+J/D"}
|
|
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { FileText, PanelLeftCloseIcon, PanelLeftOpenIcon, Plus, Search, } from 'lucide-react';
|
|
4
4
|
import { useEffect, useRef, useState } from 'react';
|
|
5
5
|
import { useDocumentsQuery } from '../hooks/useDocsQuery.js';
|
|
6
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
6
7
|
import { Breadcrumbs } from './Breadcrumbs.js';
|
|
7
8
|
import { useDocument } from './DocumentProvider.js';
|
|
8
9
|
import { Sidebar } from './Sidebar.js';
|
|
@@ -129,6 +130,7 @@ function extractTextSnippets(content, query) {
|
|
|
129
130
|
}
|
|
130
131
|
export function Layout({ children, userAvatar }) {
|
|
131
132
|
const { onOpen, onCreate, params } = useDocument();
|
|
133
|
+
const { t } = useTranslation();
|
|
132
134
|
const [expandedFolders, setExpandedFolders] = useState(new Set());
|
|
133
135
|
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
134
136
|
// Header search state
|
|
@@ -152,14 +154,14 @@ export function Layout({ children, userAvatar }) {
|
|
|
152
154
|
document.addEventListener('mousedown', handleClickOutside);
|
|
153
155
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
154
156
|
}, []);
|
|
155
|
-
return (_jsxs("div", { className: "flex h-screen w-full", children: [_jsx(Sidebar, { isOpen: isSidebarOpen, onToggle: setIsSidebarOpen, documents: documents }), _jsxs("main", { className: "flex-1 flex flex-col min-w-0 overflow-hidden", children: [params.mode === 'view' && (_jsxs("header", { className: "h-16 border-b border-border flex items-center justify-between px-6 shrink-0", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("button", { onClick: () => setIsSidebarOpen(!isSidebarOpen), className: "p-2 hover:bg-primary rounded-md transition-colors text-muted-foreground", title: isSidebarOpen ? '
|
|
157
|
+
return (_jsxs("div", { className: "flex h-screen w-full", children: [_jsx(Sidebar, { isOpen: isSidebarOpen, onToggle: setIsSidebarOpen, documents: documents }), _jsxs("main", { className: "flex-1 flex flex-col min-w-0 overflow-hidden", children: [params.mode === 'view' && (_jsxs("header", { className: "h-16 border-b border-border flex items-center justify-between px-6 shrink-0", children: [_jsxs("div", { className: "flex items-center gap-3", children: [_jsx("button", { onClick: () => setIsSidebarOpen(!isSidebarOpen), className: "p-2 hover:bg-primary rounded-md transition-colors text-muted-foreground", title: isSidebarOpen ? t('layout.closeSidebar') : t('layout.openSidebar'), children: isSidebarOpen ? (_jsx(PanelLeftCloseIcon, { className: "h-6 w-6" })) : (_jsx(PanelLeftOpenIcon, { className: "h-6 w-6" })) }), _jsx(Breadcrumbs, { homeLabel: t('sidebar.documents') })] }), _jsxs("div", { className: "flex items-center gap-4 py-2", children: [_jsxs("div", { ref: searchInputRef, className: "relative w-64", children: [_jsx(Search, { className: "absolute left-2 top-2.5 h-4 w-4 z-10" }), _jsx("input", { type: "text", placeholder: t('layout.searchPlaceholder'), className: "w-full pl-8 pr-3 py-2 text-sm border border-border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent", value: headerSearchQuery, onChange: (e) => {
|
|
156
158
|
setHeaderSearchQuery(e.target.value);
|
|
157
159
|
setShowSearchResults(e.target.value.length > 0);
|
|
158
160
|
}, onFocus: () => {
|
|
159
161
|
if (headerSearchQuery.length > 0) {
|
|
160
162
|
setShowSearchResults(true);
|
|
161
163
|
}
|
|
162
|
-
} }), showSearchResults && headerSearchQuery.length > 0 && (_jsx("div", { className: "absolute top-full left-0 right-0 mt-1 bg-background border border-border rounded-md shadow-2xl max-h-80 overflow-y-auto z-50", children: searchResults.length === 0 ? (_jsxs("div", { className: "px-4 py-3 text-sm text-gray-500", children: ["
|
|
164
|
+
} }), showSearchResults && headerSearchQuery.length > 0 && (_jsx("div", { className: "absolute top-full left-0 right-0 mt-1 bg-background border border-border rounded-md shadow-2xl max-h-80 overflow-y-auto z-50", children: searchResults.length === 0 ? (_jsxs("div", { className: "px-4 py-3 text-sm text-gray-500", children: [t('layout.noResults'), " \"", headerSearchQuery, "\""] })) : (_jsx("div", { className: "py-1", children: searchResults.map((doc) => {
|
|
163
165
|
const breadcrumb = doc.parentId
|
|
164
166
|
? buildBreadcrumb(doc, documents)
|
|
165
167
|
: null;
|
|
@@ -168,5 +170,5 @@ export function Layout({ children, userAvatar }) {
|
|
|
168
170
|
setHeaderSearchQuery('');
|
|
169
171
|
setShowSearchResults(false);
|
|
170
172
|
}, className: "w-full px-3 py-2 text-left hover:bg-primary hover:text-primary-foreground transition-colors", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx("div", { className: "shrink-0 mt-0.5", children: doc.emoji ? (_jsx("span", { className: "text-base", children: doc.emoji })) : (_jsx(FileText, { className: "h-4 w-4 text-muted-foreground" })) }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "font-medium text-sm truncate", children: doc.title }), breadcrumb && (_jsx("div", { className: "text-xs text-muted-foreground truncate", children: breadcrumb }))] })] }) }, doc.id));
|
|
171
|
-
}) })) }))] }), _jsxs("button", { onClick: onCreate, className: "px-4 py-2 bg-secondary text-white text-sm rounded-md hover:bg-gray-800 flex items-center gap-2 transition-colors", children: [_jsx(Plus, { className: "h-4 w-4" }),
|
|
173
|
+
}) })) }))] }), _jsxs("button", { onClick: onCreate, className: "px-4 py-2 bg-secondary text-white text-sm rounded-md hover:bg-gray-800 flex items-center gap-2 transition-colors", children: [_jsx(Plus, { className: "h-4 w-4" }), t('layout.create')] }), userAvatar] })] })), _jsx("div", { className: "flex-1 overflow-auto p-6", children: children })] })] }));
|
|
172
174
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReactEmbedDocs.d.ts","sourceRoot":"","sources":["../../../src/client/components/ReactEmbedDocs.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ReactEmbedDocs.d.ts","sourceRoot":"","sources":["../../../src/client/components/ReactEmbedDocs.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,mBAAmB;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IACxB,MAAM,CAAC,EAAE,IAAI,GAAG,IAAI,CAAA;IACpB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CACpC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,2CAgBxD"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { TranslationProvider } from '../hooks/useTranslation.js';
|
|
2
3
|
import { processPath } from '../lib/path.js';
|
|
3
4
|
import { DocumentContent } from './DocumentContent.js';
|
|
4
5
|
import { DocumentProvider } from './DocumentProvider.js';
|
|
5
6
|
import { Layout } from './Layout.js';
|
|
6
7
|
export function ReactEmbedDocs(props) {
|
|
7
|
-
return (_jsx(DocumentProvider, { theme: props.theme, path: props.path ?? '', locale: props.locale, onNavigate: props.onNavigate, params: processPath(props.path), children: _jsx(Layout, { children: _jsx(DocumentContent, {}) }) }));
|
|
8
|
+
return (_jsx(TranslationProvider, { locale: props.locale, children: _jsx(DocumentProvider, { theme: props.theme, path: props.path ?? '', locale: props.locale, onNavigate: props.onNavigate, params: processPath(props.path), children: _jsx(Layout, { children: _jsx(DocumentContent, {}) }) }) }));
|
|
8
9
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/client/components/Sidebar.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAiB,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/client/components/Sidebar.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,eAAe,EAAiB,MAAM,oBAAoB,CAAA;AAOnE,UAAU,MAAM;IACd,MAAM,EAAE,OAAO,CAAA;IACf,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,SAAS,EAAE,eAAe,EAAE,CAAA;IAC5B,QAAQ,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAA;CACpC;AACD,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE,MAAM,2CA2Q5E"}
|
|
@@ -3,11 +3,13 @@ import { closestCenter, DndContext, DragOverlay, KeyboardSensor, PointerSensor,
|
|
|
3
3
|
import { Plus } from 'lucide-react';
|
|
4
4
|
import { useCallback, useMemo, useState } from 'react';
|
|
5
5
|
import { useReorderDocumentMutation } from '../hooks/useDocsQuery';
|
|
6
|
+
import { useTranslation } from '../hooks/useTranslation';
|
|
6
7
|
import { useDocument } from './DocumentProvider';
|
|
7
8
|
import { DragOverlayItem } from './DragOverlayItem';
|
|
8
9
|
import { SortableTreeItem } from './SortableTreeItem';
|
|
9
10
|
export function Sidebar({ isOpen, onToggle, documents, currentDocId }) {
|
|
10
11
|
const { onCreate, onOpen } = useDocument();
|
|
12
|
+
const { t } = useTranslation();
|
|
11
13
|
const [expandedFolders, setExpandedFolders] = useState(new Set());
|
|
12
14
|
const [activeId, setActiveId] = useState(null);
|
|
13
15
|
const [dropIndicator, setDropIndicator] = useState(null);
|
|
@@ -170,7 +172,7 @@ export function Sidebar({ isOpen, onToggle, documents, currentDocId }) {
|
|
|
170
172
|
return (_jsxs("aside", { className: [
|
|
171
173
|
'border-r border-border flex flex-col transition-all duration-200 ease-in-out overflow-hidden',
|
|
172
174
|
isOpen ? 'w-64 opacity-100' : 'w-0 opacity-0',
|
|
173
|
-
].join(' '), children: [_jsx("div", { className: "p-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "font-semibold text-sm text-muted-foreground", children:
|
|
175
|
+
].join(' '), children: [_jsx("div", { className: "p-4", children: _jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h2", { className: "font-semibold text-sm text-muted-foreground", children: t('sidebar.documents') }), _jsx("button", { className: "p-2 hover:bg-primary rounded-md transition-colors cursor-pointer", onClick: onCreate, children: _jsx(Plus, { className: "h-4 w-4" }) })] }) }), _jsxs("div", { className: "flex-1 overflow-y-auto p-2 space-y-1 relative", children: [_jsxs(DndContext, { sensors: sensors, collisionDetection: closestCenter, onDragStart: handleDragStart, onDragOver: handleDragOver, onDragEnd: handleDragEnd, onDragCancel: handleDragCancel, children: [flattenedTree
|
|
174
176
|
// .filter((doc) => doc.id !== activeId)
|
|
175
|
-
.map((doc) => (_jsx(SortableTreeItem, { id: doc.id, doc: doc, isExpanded: expandedFolders.has(doc.id), isCurrent: doc.id === resolvedCurrentDocId, dropIndicator: dropIndicator?.id === doc.id ? dropIndicator.position : null, onToggle: toggleFolder, onOpen: onOpen }, doc.id))), _jsx(DragOverlay, { dropAnimation: dropAnimation, children: activeDoc ? _jsx(DragOverlayItem, { doc: activeDoc }) : null })] }), documents.length === 0 && (_jsx("div", { className: "text-sm text-gray-500 text-center py-4", children:
|
|
177
|
+
.map((doc) => (_jsx(SortableTreeItem, { id: doc.id, doc: doc, isExpanded: expandedFolders.has(doc.id), isCurrent: doc.id === resolvedCurrentDocId, dropIndicator: dropIndicator?.id === doc.id ? dropIndicator.position : null, onToggle: toggleFolder, onOpen: onOpen }, doc.id))), _jsx(DragOverlay, { dropAnimation: dropAnimation, children: activeDoc ? _jsx(DragOverlayItem, { doc: activeDoc }) : null })] }), documents.length === 0 && (_jsx("div", { className: "text-sm text-gray-500 text-center py-4", children: t('sidebar.noDocuments') }))] })] }));
|
|
176
178
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VersionHistory.d.ts","sourceRoot":"","sources":["../../../src/client/components/VersionHistory.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"VersionHistory.d.ts","sourceRoot":"","sources":["../../../src/client/components/VersionHistory.tsx"],"names":[],"mappings":"AAqBA,MAAM,WAAW,mBAAmB;IAClC,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,UAAU,EACV,aAAa,EACb,OAAgB,EAChB,SAAS,EACT,QAAsB,EACtB,MAAM,GACP,EAAE,mBAAmB,2CAuQrB;AAED,eAAe,cAAc,CAAA"}
|
|
@@ -2,10 +2,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState } from 'react';
|
|
3
3
|
import { History, RotateCcw, Trash2, GitCompare, Clock, User, MessageSquare, } from 'lucide-react';
|
|
4
4
|
import { useDocumentVersionsQuery, useCreateVersionMutation, useRestoreVersionMutation, useDeleteVersionMutation, } from '../hooks/useVersions.js';
|
|
5
|
+
import { useTranslation } from '../hooks/useTranslation.js';
|
|
5
6
|
/**
|
|
6
7
|
* Component for viewing and managing document version history
|
|
7
8
|
*/
|
|
8
9
|
export function VersionHistory({ documentId, documentTitle, baseUrl = '/api', onRestore, userName = 'Anonymous', userId, }) {
|
|
10
|
+
const { t } = useTranslation();
|
|
9
11
|
const { data, isLoading, error } = useDocumentVersionsQuery(documentId, baseUrl);
|
|
10
12
|
const createVersionMutation = useCreateVersionMutation(baseUrl);
|
|
11
13
|
const restoreMutation = useRestoreVersionMutation(baseUrl);
|
|
@@ -20,7 +22,7 @@ export function VersionHistory({ documentId, documentTitle, baseUrl = '/api', on
|
|
|
20
22
|
await createVersionMutation.mutateAsync({
|
|
21
23
|
documentId,
|
|
22
24
|
data: {
|
|
23
|
-
description: versionDescription ||
|
|
25
|
+
description: versionDescription || t('versions.createdBy', { name: userName }),
|
|
24
26
|
createdBy: userId,
|
|
25
27
|
createdByName: userName,
|
|
26
28
|
},
|
|
@@ -29,11 +31,11 @@ export function VersionHistory({ documentId, documentTitle, baseUrl = '/api', on
|
|
|
29
31
|
setVersionDescription('');
|
|
30
32
|
}
|
|
31
33
|
catch (error) {
|
|
32
|
-
alert('
|
|
34
|
+
alert(t('versions.createFailed'));
|
|
33
35
|
}
|
|
34
36
|
};
|
|
35
37
|
const handleRestore = async (version) => {
|
|
36
|
-
if (!confirm(
|
|
38
|
+
if (!confirm(t('versions.restoreConfirm', { title: documentTitle, version: version.versionNumber }))) {
|
|
37
39
|
return;
|
|
38
40
|
}
|
|
39
41
|
setRestoringVersion(version.id);
|
|
@@ -47,24 +49,24 @@ export function VersionHistory({ documentId, documentTitle, baseUrl = '/api', on
|
|
|
47
49
|
},
|
|
48
50
|
});
|
|
49
51
|
onRestore?.();
|
|
50
|
-
alert(
|
|
52
|
+
alert(t('versions.restored', { version: version.versionNumber }));
|
|
51
53
|
}
|
|
52
54
|
catch (error) {
|
|
53
|
-
alert('
|
|
55
|
+
alert(t('versions.restoreFailed'));
|
|
54
56
|
}
|
|
55
57
|
finally {
|
|
56
58
|
setRestoringVersion(null);
|
|
57
59
|
}
|
|
58
60
|
};
|
|
59
61
|
const handleDelete = async (version) => {
|
|
60
|
-
if (!confirm(
|
|
62
|
+
if (!confirm(t('versions.deleteConfirm', { version: version.versionNumber }))) {
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
63
65
|
try {
|
|
64
66
|
await deleteMutation.mutateAsync({ versionId: version.id, documentId });
|
|
65
67
|
}
|
|
66
68
|
catch (error) {
|
|
67
|
-
alert('
|
|
69
|
+
alert(t('versions.deleteFailed'));
|
|
68
70
|
}
|
|
69
71
|
};
|
|
70
72
|
const toggleVersionSelection = (versionId) => {
|
|
@@ -89,14 +91,14 @@ export function VersionHistory({ documentId, documentTitle, baseUrl = '/api', on
|
|
|
89
91
|
});
|
|
90
92
|
};
|
|
91
93
|
if (isLoading) {
|
|
92
|
-
return (_jsxs("div", { className: "p-4 text-center text-gray-500", children: [_jsx("div", { className: "animate-spin inline-block w-5 h-5 border-2 border-gray-300 border-t-gray-600 rounded-full mr-2" }),
|
|
94
|
+
return (_jsxs("div", { className: "p-4 text-center text-gray-500", children: [_jsx("div", { className: "animate-spin inline-block w-5 h-5 border-2 border-gray-300 border-t-gray-600 rounded-full mr-2" }), t('versions.loading')] }));
|
|
93
95
|
}
|
|
94
96
|
if (error) {
|
|
95
|
-
return (_jsx("div", { className: "p-4 text-center text-red-500", children:
|
|
97
|
+
return (_jsx("div", { className: "p-4 text-center text-red-500", children: t('versions.loadFailed') }));
|
|
96
98
|
}
|
|
97
|
-
return (_jsxs("div", { className: "version-history bg-white rounded-lg border border-gray-200", children: [_jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(History, { className: "w-5 h-5 text-gray-500" }), _jsx("h3", { className: "font-semibold text-gray-900", children:
|
|
99
|
+
return (_jsxs("div", { className: "version-history bg-white rounded-lg border border-gray-200", children: [_jsxs("div", { className: "flex items-center justify-between p-4 border-b border-gray-200", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(History, { className: "w-5 h-5 text-gray-500" }), _jsx("h3", { className: "font-semibold text-gray-900", children: t('versions.title') }), _jsxs("span", { className: "text-sm text-gray-500", children: ["(", versions.length, ")"] })] }), _jsxs("div", { className: "flex items-center gap-2", children: [selectedVersions.length === 2 && (_jsxs("button", { className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-blue-50 text-blue-600 rounded-md hover:bg-blue-100", onClick: () => { }, children: [_jsx(GitCompare, { className: "w-4 h-4" }), t('versions.compare')] })), _jsx("button", { className: "flex items-center gap-1 px-3 py-1.5 text-sm bg-gray-900 text-white rounded-md hover:bg-gray-800", onClick: () => setShowCreateDialog(true), children: t('versions.saveVersion') })] })] }), showCreateDialog && (_jsx("div", { className: "p-4 bg-gray-50 border-b border-gray-200", children: _jsxs("div", { className: "flex items-start gap-2", children: [_jsx(MessageSquare, { className: "w-5 h-5 text-gray-400 mt-2" }), _jsxs("div", { className: "flex-1", children: [_jsx("input", { type: "text", placeholder: t('versions.descPlaceholder'), className: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500", value: versionDescription, onChange: (e) => setVersionDescription(e.target.value), onKeyDown: (e) => e.key === 'Enter' && handleCreateVersion() }), _jsxs("div", { className: "flex items-center gap-2 mt-2", children: [_jsx("button", { className: "px-3 py-1.5 text-sm bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50", onClick: handleCreateVersion, disabled: createVersionMutation.isPending, children: createVersionMutation.isPending ? t('versions.saving') : t('versions.save') }), _jsx("button", { className: "px-3 py-1.5 text-sm text-gray-600 hover:text-gray-900", onClick: () => {
|
|
98
100
|
setShowCreateDialog(false);
|
|
99
101
|
setVersionDescription('');
|
|
100
|
-
}, children:
|
|
102
|
+
}, children: t('versions.cancel') })] })] })] }) })), _jsx("div", { className: "max-h-96 overflow-y-auto", children: versions.length === 0 ? (_jsxs("div", { className: "p-8 text-center text-gray-500", children: [_jsx(History, { className: "w-12 h-12 mx-auto mb-3 text-gray-300" }), _jsx("p", { children: t('versions.noVersions') }), _jsx("p", { className: "text-sm mt-1", children: t('versions.noVersionsHint') })] })) : (_jsx("div", { className: "divide-y divide-gray-100", children: versions.map((version) => (_jsx("div", { className: `p-4 hover:bg-gray-50 transition-colors ${selectedVersions.includes(version.id) ? 'bg-blue-50' : ''}`, children: _jsxs("div", { className: "flex items-start gap-3", children: [_jsx("input", { type: "checkbox", checked: selectedVersions.includes(version.id), onChange: () => toggleVersionSelection(version.id), className: "mt-1 w-4 h-4 text-blue-600 rounded border-gray-300" }), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs("span", { className: "font-mono text-sm font-medium text-gray-900", children: ["v", version.versionNumber] }), version.versionNumber === versions[0]?.versionNumber && (_jsx("span", { className: "px-2 py-0.5 text-xs bg-blue-100 text-blue-700 rounded-full", children: t('versions.latest') }))] }), version.changeDescription && (_jsx("p", { className: "text-sm text-gray-700 mt-1", children: version.changeDescription })), _jsxs("div", { className: "flex items-center gap-4 mt-2 text-xs text-gray-500", children: [_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(Clock, { className: "w-3 h-3" }), formatDate(version.createdAt)] }), version.createdByName && (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(User, { className: "w-3 h-3" }), version.createdByName] }))] })] }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { className: "p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 rounded", onClick: () => handleRestore(version), disabled: restoringVersion === version.id, title: t('versions.restore'), children: restoringVersion === version.id ? (_jsx("div", { className: "w-4 h-4 border-2 border-blue-300 border-t-blue-600 rounded-full animate-spin" })) : (_jsx(RotateCcw, { className: "w-4 h-4" })) }), _jsx("button", { className: "p-1.5 text-gray-400 hover:text-red-600 hover:bg-red-50 rounded", onClick: () => handleDelete(version), disabled: deleteMutation.isPending, title: t('versions.delete'), children: _jsx(Trash2, { className: "w-4 h-4" }) })] })] }) }, version.id))) })) })] }));
|
|
101
103
|
}
|
|
102
104
|
export default VersionHistory;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
interface TranslationContextValue {
|
|
3
|
+
t: (key: string, params?: Record<string, string | number>) => string;
|
|
4
|
+
locale: string;
|
|
5
|
+
}
|
|
6
|
+
interface TranslationProviderProps {
|
|
7
|
+
locale?: string;
|
|
8
|
+
children: ReactNode;
|
|
9
|
+
}
|
|
10
|
+
export declare function TranslationProvider({ locale, children, }: TranslationProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function useTranslation(): TranslationContextValue;
|
|
12
|
+
export {};
|
|
13
|
+
//# sourceMappingURL=useTranslation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTranslation.d.ts","sourceRoot":"","sources":["../../../src/client/hooks/useTranslation.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiB,SAAS,EAA2B,MAAM,OAAO,CAAA;AAQzE,UAAU,uBAAuB;IAC/B,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,KAAK,MAAM,CAAA;IACpE,MAAM,EAAE,MAAM,CAAA;CACf;AAID,UAAU,wBAAwB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED,wBAAgB,mBAAmB,CAAC,EAClC,MAAa,EACb,QAAQ,GACT,EAAE,wBAAwB,2CAqB1B;AAED,wBAAgB,cAAc,IAAI,uBAAuB,CAMxD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useCallback, useContext } from 'react';
|
|
4
|
+
import en from '../locales/en.json';
|
|
5
|
+
import ru from '../locales/ru.json';
|
|
6
|
+
const locales = { en, ru };
|
|
7
|
+
const TranslationContext = createContext(null);
|
|
8
|
+
export function TranslationProvider({ locale = 'en', children, }) {
|
|
9
|
+
const translations = locales[locale] || locales.en;
|
|
10
|
+
const t = useCallback((key, params) => {
|
|
11
|
+
let value = translations[key] || locales.en[key] || key;
|
|
12
|
+
if (params) {
|
|
13
|
+
for (const [k, v] of Object.entries(params)) {
|
|
14
|
+
value = value.replace(`{${k}}`, String(v));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}, [translations]);
|
|
19
|
+
return (_jsx(TranslationContext.Provider, { value: { t, locale }, children: children }));
|
|
20
|
+
}
|
|
21
|
+
export function useTranslation() {
|
|
22
|
+
const context = useContext(TranslationContext);
|
|
23
|
+
if (!context) {
|
|
24
|
+
throw new Error('useTranslation must be used within a TranslationProvider');
|
|
25
|
+
}
|
|
26
|
+
return context;
|
|
27
|
+
}
|
package/dist/client/index.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export { VersionHistory } from './components/VersionHistory.js';
|
|
|
10
10
|
export { docsQueryKeys, useCreateDocumentMutation, useDeleteDocumentMutation, useDocumentBySlugQuery, useDocumentQuery, useDocumentsQuery, useReorderDocumentMutation, useUpdateDocumentMutation, useUpdateOrderMutation } from './hooks/useDocsQuery.js';
|
|
11
11
|
export { useFileUpload, useMultiFileUpload } from './hooks/useFileUpload.js';
|
|
12
12
|
export { useExport } from './hooks/useExport.js';
|
|
13
|
+
export { TranslationProvider, useTranslation } from './hooks/useTranslation.js';
|
|
13
14
|
export type { ExportFormat, UseExportOptions, UseExportReturn } from './hooks/useExport.js';
|
|
14
15
|
export { useCollaborativeEditor, useCollaborators, useEditor } from './hooks/useCollaboration.js';
|
|
15
16
|
export type { CollaboratorInfo, CollaboratorState, UseCollaborativeEditorOptions, UseCollaborativeEditorReturn } from './hooks/useCollaboration.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAG/D,OAAO,EACL,aAAa,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,sBAAsB,EAChN,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,aAAa,EACb,kBAAkB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,SAAS,EACV,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAG/D,OAAO,EACL,aAAa,EAAE,yBAAyB,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,sBAAsB,EAChN,MAAM,yBAAyB,CAAA;AAEhC,OAAO,EACL,aAAa,EACb,kBAAkB,EACnB,MAAM,0BAA0B,CAAA;AAEjC,OAAO,EACL,SAAS,EACV,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,mBAAmB,EACnB,cAAc,EACf,MAAM,2BAA2B,CAAA;AAClC,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAG3F,OAAO,EACL,sBAAsB,EAAE,gBAAgB,EAAE,SAAS,EACpD,MAAM,6BAA6B,CAAA;AACpC,YAAY,EACV,gBAAgB,EAChB,iBAAiB,EACjB,6BAA6B,EAC7B,4BAA4B,EAC7B,MAAM,6BAA6B,CAAA;AAGpC,OAAO,EACL,uBAAuB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,eAAe,EAAE,iBAAiB,EACrK,MAAM,wBAAwB,CAAA;AAC/B,YAAY,EACV,eAAe,EACf,WAAW,EACZ,MAAM,wBAAwB,CAAA;AAG/B,YAAY,EACV,cAAc,EAEd,gBAAgB,EAAE,oBAAoB,EAAE,oBAAoB,EAE5D,QAAQ,EAAE,kBAAkB,EAE5B,cAAc,EAAE,UAAU,EAE1B,UAAU,EAAE,cAAc,IAAI,cAAc,EAAE,gBAAgB,EAG9D,oBAAoB,EACpB,oBAAoB,EACpB,mBAAmB,EAEnB,YAAY,EACZ,gBAAgB,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EACzE,MAAM,oBAAoB,CAAA;AAG3B,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,YAAY,EACb,MAAM,0BAA0B,CAAA;AAGjC,YAAY,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAA;AAClH,YAAY,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AACrE,YAAY,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA"}
|
package/dist/client/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { VersionHistory } from './components/VersionHistory.js';
|
|
|
12
12
|
export { docsQueryKeys, useCreateDocumentMutation, useDeleteDocumentMutation, useDocumentBySlugQuery, useDocumentQuery, useDocumentsQuery, useReorderDocumentMutation, useUpdateDocumentMutation, useUpdateOrderMutation } from './hooks/useDocsQuery.js';
|
|
13
13
|
export { useFileUpload, useMultiFileUpload } from './hooks/useFileUpload.js';
|
|
14
14
|
export { useExport } from './hooks/useExport.js';
|
|
15
|
+
export { TranslationProvider, useTranslation } from './hooks/useTranslation.js';
|
|
15
16
|
// Collaboration hooks
|
|
16
17
|
export { useCollaborativeEditor, useCollaborators, useEditor } from './hooks/useCollaboration.js';
|
|
17
18
|
// Versioning hooks
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sidebar.documents": "Documents",
|
|
3
|
+
"sidebar.noDocuments": "No documents yet",
|
|
4
|
+
"layout.closeSidebar": "Close sidebar",
|
|
5
|
+
"layout.openSidebar": "Open sidebar",
|
|
6
|
+
"layout.searchPlaceholder": "Search documentation...",
|
|
7
|
+
"layout.noResults": "No results found for",
|
|
8
|
+
"layout.create": "Create",
|
|
9
|
+
"breadcrumbs.home": "Home",
|
|
10
|
+
"breadcrumbs.loading": "Loading...",
|
|
11
|
+
"breadcrumbs.error": "Error loading path",
|
|
12
|
+
"emoji.remove": "Remove emoji",
|
|
13
|
+
"editor.titlePlaceholder": "Document title",
|
|
14
|
+
"editor.titleRequired": "Please enter a document title",
|
|
15
|
+
"editor.saveFailed": "Failed to save document. Please try again.",
|
|
16
|
+
"editor.view": "View",
|
|
17
|
+
"editor.saving": "Saving...",
|
|
18
|
+
"editor.create": "Create",
|
|
19
|
+
"editor.save": "Save",
|
|
20
|
+
"editor.slug": "Slug",
|
|
21
|
+
"editor.coverAlt": "Cover",
|
|
22
|
+
"editor.removeCover": "Remove cover",
|
|
23
|
+
"editor.coverDropzone": "Drag & drop cover image here or click to upload",
|
|
24
|
+
"editor.coverFormats": "JPEG, PNG, GIF, WebP up to 5MB",
|
|
25
|
+
"view.loadFailed": "Failed to load document. Please try again.",
|
|
26
|
+
"view.edit": "Edit",
|
|
27
|
+
"view.authorId": "Author ID",
|
|
28
|
+
"view.updated": "Updated",
|
|
29
|
+
"docList.welcome": "Welcome to Documentation",
|
|
30
|
+
"docList.welcomeDescription": "Browse and manage your documentation. Create new documents or organize them into folders.",
|
|
31
|
+
"docList.folders": "Folders",
|
|
32
|
+
"docList.docs": "docs",
|
|
33
|
+
"docList.newFolder": "New Folder",
|
|
34
|
+
"docList.documents": "Documents",
|
|
35
|
+
"docList.recentDocuments": "Recent Documents",
|
|
36
|
+
"docList.newDocument": "New Document",
|
|
37
|
+
"docList.noDocuments": "No documents yet",
|
|
38
|
+
"docList.getStarted": "Get started by creating your first document",
|
|
39
|
+
"docList.createDocument": "Create Document",
|
|
40
|
+
"docList.updated": "Updated",
|
|
41
|
+
"docList.open": "Open",
|
|
42
|
+
"docList.justNow": "just now",
|
|
43
|
+
"docList.minuteAgo": "{n} minute ago",
|
|
44
|
+
"docList.minutesAgo": "{n} minutes ago",
|
|
45
|
+
"docList.hourAgo": "{n} hour ago",
|
|
46
|
+
"docList.hoursAgo": "{n} hours ago",
|
|
47
|
+
"docList.dayAgo": "{n} day ago",
|
|
48
|
+
"docList.daysAgo": "{n} days ago",
|
|
49
|
+
"export.export": "Export",
|
|
50
|
+
"export.exportAs": "Export as",
|
|
51
|
+
"export.word": "Microsoft Word",
|
|
52
|
+
"export.wordDesc": "Editable document format",
|
|
53
|
+
"export.pdf": "PDF Document",
|
|
54
|
+
"export.pdfDesc": "Print-ready format",
|
|
55
|
+
"export.html": "HTML Page",
|
|
56
|
+
"export.htmlDesc": "Web page format",
|
|
57
|
+
"export.markdown": "Markdown",
|
|
58
|
+
"export.markdownDesc": "Plain text with formatting",
|
|
59
|
+
"export.missingDep": "Missing dependency: {message}\n\nInstall with:\n{command}",
|
|
60
|
+
"export.failed": "Export failed: {message}",
|
|
61
|
+
"versions.title": "Version History",
|
|
62
|
+
"versions.compare": "Compare",
|
|
63
|
+
"versions.saveVersion": "Save Version",
|
|
64
|
+
"versions.descPlaceholder": "Describe what's changed in this version...",
|
|
65
|
+
"versions.saving": "Saving...",
|
|
66
|
+
"versions.save": "Save",
|
|
67
|
+
"versions.cancel": "Cancel",
|
|
68
|
+
"versions.noVersions": "No versions yet",
|
|
69
|
+
"versions.noVersionsHint": "Save a version to track changes",
|
|
70
|
+
"versions.latest": "Latest",
|
|
71
|
+
"versions.restore": "Restore this version",
|
|
72
|
+
"versions.delete": "Delete version",
|
|
73
|
+
"versions.createdBy": "Version created by {name}",
|
|
74
|
+
"versions.createFailed": "Failed to create version",
|
|
75
|
+
"versions.restoreConfirm": "Restore \"{title}\" to version {version}?\n\nCurrent state will be saved as a backup.",
|
|
76
|
+
"versions.restored": "Restored to version {version}",
|
|
77
|
+
"versions.restoreFailed": "Failed to restore version",
|
|
78
|
+
"versions.deleteConfirm": "Delete version {version}? This cannot be undone.",
|
|
79
|
+
"versions.deleteFailed": "Failed to delete version",
|
|
80
|
+
"versions.loading": "Loading versions...",
|
|
81
|
+
"versions.loadFailed": "Failed to load version history"
|
|
82
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"sidebar.documents": "Документы",
|
|
3
|
+
"sidebar.noDocuments": "Документов пока нет",
|
|
4
|
+
"layout.closeSidebar": "Закрыть боковую панель",
|
|
5
|
+
"layout.openSidebar": "Открыть боковую панель",
|
|
6
|
+
"layout.searchPlaceholder": "Поиск по документации...",
|
|
7
|
+
"layout.noResults": "Ничего не найдено по запросу",
|
|
8
|
+
"layout.create": "Создать",
|
|
9
|
+
"breadcrumbs.home": "Главная",
|
|
10
|
+
"breadcrumbs.loading": "Загрузка...",
|
|
11
|
+
"breadcrumbs.error": "Ошибка загрузки пути",
|
|
12
|
+
"emoji.remove": "Убрать эмодзи",
|
|
13
|
+
"editor.titlePlaceholder": "Название документа",
|
|
14
|
+
"editor.titleRequired": "Пожалуйста, введите название документа",
|
|
15
|
+
"editor.saveFailed": "Не удалось сохранить документ. Попробуйте ещё раз.",
|
|
16
|
+
"editor.view": "Просмотр",
|
|
17
|
+
"editor.saving": "Сохранение...",
|
|
18
|
+
"editor.create": "Создать",
|
|
19
|
+
"editor.save": "Сохранить",
|
|
20
|
+
"editor.slug": "Slug",
|
|
21
|
+
"editor.coverAlt": "Обложка",
|
|
22
|
+
"editor.removeCover": "Удалить обложку",
|
|
23
|
+
"editor.coverDropzone": "Перетащите изображение обложки сюда или нажмите для загрузки",
|
|
24
|
+
"editor.coverFormats": "JPEG, PNG, GIF, WebP до 5МБ",
|
|
25
|
+
"view.loadFailed": "Не удалось загрузить документ. Попробуйте ещё раз.",
|
|
26
|
+
"view.edit": "Редактировать",
|
|
27
|
+
"view.authorId": "ID автора",
|
|
28
|
+
"view.updated": "Обновлено",
|
|
29
|
+
"docList.welcome": "Добро пожаловать в Документацию",
|
|
30
|
+
"docList.welcomeDescription": "Просматривайте и управляйте документацией. Создавайте новые документы или организуйте их в папки.",
|
|
31
|
+
"docList.folders": "Папки",
|
|
32
|
+
"docList.docs": "док.",
|
|
33
|
+
"docList.newFolder": "Новая папка",
|
|
34
|
+
"docList.documents": "Документы",
|
|
35
|
+
"docList.recentDocuments": "Недавние документы",
|
|
36
|
+
"docList.newDocument": "Новый документ",
|
|
37
|
+
"docList.noDocuments": "Документов пока нет",
|
|
38
|
+
"docList.getStarted": "Начните с создания первого документа",
|
|
39
|
+
"docList.createDocument": "Создать документ",
|
|
40
|
+
"docList.updated": "Обновлено",
|
|
41
|
+
"docList.open": "Открыть",
|
|
42
|
+
"docList.justNow": "только что",
|
|
43
|
+
"docList.minuteAgo": "{n} минуту назад",
|
|
44
|
+
"docList.minutesAgo": "{n} минут назад",
|
|
45
|
+
"docList.hourAgo": "{n} час назад",
|
|
46
|
+
"docList.hoursAgo": "{n} часов назад",
|
|
47
|
+
"docList.dayAgo": "{n} день назад",
|
|
48
|
+
"docList.daysAgo": "{n} дней назад",
|
|
49
|
+
"export.export": "Экспорт",
|
|
50
|
+
"export.exportAs": "Экспортировать как",
|
|
51
|
+
"export.word": "Microsoft Word",
|
|
52
|
+
"export.wordDesc": "Редактируемый формат документа",
|
|
53
|
+
"export.pdf": "PDF документ",
|
|
54
|
+
"export.pdfDesc": "Формат для печати",
|
|
55
|
+
"export.html": "HTML страница",
|
|
56
|
+
"export.htmlDesc": "Формат веб-страницы",
|
|
57
|
+
"export.markdown": "Markdown",
|
|
58
|
+
"export.markdownDesc": "Текст с форматированием",
|
|
59
|
+
"export.missingDep": "Отсутствует зависимость: {message}\n\nУстановите:\n{command}",
|
|
60
|
+
"export.failed": "Ошибка экспорта: {message}",
|
|
61
|
+
"versions.title": "История версий",
|
|
62
|
+
"versions.compare": "Сравнить",
|
|
63
|
+
"versions.saveVersion": "Сохранить версию",
|
|
64
|
+
"versions.descPlaceholder": "Опишите изменения в этой версии...",
|
|
65
|
+
"versions.saving": "Сохранение...",
|
|
66
|
+
"versions.save": "Сохранить",
|
|
67
|
+
"versions.cancel": "Отмена",
|
|
68
|
+
"versions.noVersions": "Версий пока нет",
|
|
69
|
+
"versions.noVersionsHint": "Сохраните версию для отслеживания изменений",
|
|
70
|
+
"versions.latest": "Последняя",
|
|
71
|
+
"versions.restore": "Восстановить эту версию",
|
|
72
|
+
"versions.delete": "Удалить версию",
|
|
73
|
+
"versions.createdBy": "Версия создана пользователем {name}",
|
|
74
|
+
"versions.createFailed": "Не удалось создать версию",
|
|
75
|
+
"versions.restoreConfirm": "Восстановить \"{title}\" до версии {version}?\n\nТекущее состояние будет сохранено как резервная копия.",
|
|
76
|
+
"versions.restored": "Восстановлено до версии {version}",
|
|
77
|
+
"versions.restoreFailed": "Не удалось восстановить версию",
|
|
78
|
+
"versions.deleteConfirm": "Удалить версию {version}? Это действие нельзя отменить.",
|
|
79
|
+
"versions.deleteFailed": "Не удалось удалить версию",
|
|
80
|
+
"versions.loading": "Загрузка версий...",
|
|
81
|
+
"versions.loadFailed": "Не удалось загрузить историю версий"
|
|
82
|
+
}
|
package/package.json
CHANGED