react-embed-docs 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/client/components/Breadcrumbs.d.ts.map +1 -1
  2. package/dist/client/components/Breadcrumbs.js +9 -6
  3. package/dist/client/components/DocumentEdit.d.ts.map +1 -1
  4. package/dist/client/components/DocumentEdit.js +336 -8
  5. package/dist/client/components/DocumentList.d.ts.map +1 -1
  6. package/dist/client/components/DocumentList.js +18 -8
  7. package/dist/client/components/DocumentProvider.d.ts +1 -1
  8. package/dist/client/components/DocumentProvider.d.ts.map +1 -1
  9. package/dist/client/components/DocumentProvider.js +5 -1
  10. package/dist/client/components/DocumentView.d.ts.map +1 -1
  11. package/dist/client/components/DocumentView.js +5 -3
  12. package/dist/client/components/EmojiPicker.d.ts.map +1 -1
  13. package/dist/client/components/EmojiPicker.js +3 -1
  14. package/dist/client/components/ExportButton.d.ts.map +1 -1
  15. package/dist/client/components/ExportButton.js +14 -12
  16. package/dist/client/components/Layout.d.ts.map +1 -1
  17. package/dist/client/components/Layout.js +7 -3
  18. package/dist/client/components/ReactEmbedDocs.d.ts.map +1 -1
  19. package/dist/client/components/ReactEmbedDocs.js +2 -1
  20. package/dist/client/components/Sidebar.d.ts.map +1 -1
  21. package/dist/client/components/Sidebar.js +4 -2
  22. package/dist/client/components/VersionHistory.d.ts.map +1 -1
  23. package/dist/client/components/VersionHistory.js +13 -11
  24. package/dist/client/hooks/useTranslation.d.ts +13 -0
  25. package/dist/client/hooks/useTranslation.d.ts.map +1 -0
  26. package/dist/client/hooks/useTranslation.js +27 -0
  27. package/dist/client/index.d.ts +1 -0
  28. package/dist/client/index.d.ts.map +1 -1
  29. package/dist/client/index.js +1 -0
  30. package/dist/client/locales/en.json +83 -0
  31. package/dist/client/locales/ru.json +83 -0
  32. package/package.json +1 -1
  33. package/dist/client/components/DocsLayout.d.ts +0 -20
  34. package/dist/client/components/DocsLayout.d.ts.map +0 -1
  35. package/dist/client/components/DocsLayout.js +0 -387
  36. package/dist/client/providers/DocumentProvider.d.ts +0 -1
  37. package/dist/client/providers/DocumentProvider.d.ts.map +0 -1
  38. package/dist/client/providers/DocumentProvider.js +0 -1
@@ -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: "Remove emoji" }))] }))] }));
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":"AAIA,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,2CAoHnB"}
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
- label: 'Microsoft Word',
9
- description: 'Editable document format',
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
- label: 'PDF Document',
16
- description: 'Print-ready format',
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
- label: 'HTML Page',
23
- description: 'Web page format',
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
- label: 'Markdown',
30
- description: 'Plain text with formatting',
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(`Missing dependency: ${message}\n\nInstall with:\n${format === 'docx' ? 'npm install docx' : 'npm install puppeteer'}`);
77
+ alert(t('export.missingDep', { message, command: format === 'docx' ? 'npm install docx' : 'npm install puppeteer' }));
76
78
  }
77
79
  else {
78
- alert(`Export failed: ${message}`);
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: "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: `
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: "Export as" }), 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: option.label }), _jsx("div", { className: "text-xs text-gray-500", children: option.description })] }), _jsxs("div", { className: "flex-shrink-0 text-xs text-gray-400 uppercase", children: [".", option.extension] })] }, option.format)))] }) }))] }));
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":"AAgBA,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,2CA8J/D"}
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,2CAmK/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,16 @@ 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 ? 'Close sidebar' : 'Open sidebar', children: isSidebarOpen ? (_jsx(PanelLeftCloseIcon, { className: "h-6 w-6" })) : (_jsx(PanelLeftOpenIcon, { className: "h-6 w-6" })) }), _jsx(Breadcrumbs, { homeLabel: "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: "Search documentation...", 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) => {
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
158
+ ? t('layout.closeSidebar')
159
+ : 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
160
  setHeaderSearchQuery(e.target.value);
157
161
  setShowSearchResults(e.target.value.length > 0);
158
162
  }, onFocus: () => {
159
163
  if (headerSearchQuery.length > 0) {
160
164
  setShowSearchResults(true);
161
165
  }
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: ["No results found for \"", headerSearchQuery, "\""] })) : (_jsx("div", { className: "py-1", children: searchResults.map((doc) => {
166
+ } }), 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
167
  const breadcrumb = doc.parentId
164
168
  ? buildBreadcrumb(doc, documents)
165
169
  : null;
@@ -168,5 +172,5 @@ export function Layout({ children, userAvatar }) {
168
172
  setHeaderSearchQuery('');
169
173
  setShowSearchResults(false);
170
174
  }, 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" }), "Create"] }), userAvatar] })] })), _jsx("div", { className: "flex-1 overflow-auto p-6", children: children })] })] }));
175
+ }) })) }))] }), _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
176
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ReactEmbedDocs.d.ts","sourceRoot":"","sources":["../../../src/client/components/ReactEmbedDocs.tsx"],"names":[],"mappings":"AAKA,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,2CAcxD"}
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;AAMnE,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,2CA0Q5E"}
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: "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
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('new'), 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: "No documents yet" }))] })] }));
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":"AAoBA,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,2CAsQrB;AAED,eAAe,cAAc,CAAA"}
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 || `Version created by ${userName}`,
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('Failed to create version');
34
+ alert(t('versions.createFailed'));
33
35
  }
34
36
  };
35
37
  const handleRestore = async (version) => {
36
- if (!confirm(`Restore "${documentTitle}" to version ${version.versionNumber}?\n\nCurrent state will be saved as a backup.`)) {
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(`Restored to version ${version.versionNumber}`);
52
+ alert(t('versions.restored', { version: version.versionNumber }));
51
53
  }
52
54
  catch (error) {
53
- alert('Failed to restore version');
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(`Delete version ${version.versionNumber}? This cannot be undone.`)) {
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('Failed to delete version');
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" }), "Loading versions..."] }));
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: "Failed to load version history" }));
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: "Version History" }), _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" }), "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: "Save Version" })] })] }), 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: "Describe what's changed in this version...", 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 ? 'Saving...' : 'Save' }), _jsx("button", { className: "px-3 py-1.5 text-sm text-gray-600 hover:text-gray-900", onClick: () => {
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: "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: "No versions yet" }), _jsx("p", { className: "text-sm mt-1", children: "Save a version to track changes" })] })) : (_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: "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: "Restore this version", 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: "Delete version", children: _jsx(Trash2, { className: "w-4 h-4" }) })] })] }) }, version.id))) })) })] }));
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
+ }
@@ -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;AAC7B,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"}
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"}
@@ -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,83 @@
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.slugRequired": "Please enter a document slug",
16
+ "editor.saveFailed": "Failed to save document. Please try again.",
17
+ "editor.view": "View",
18
+ "editor.saving": "Saving...",
19
+ "editor.create": "Create",
20
+ "editor.save": "Save",
21
+ "editor.slug": "Slug",
22
+ "editor.coverAlt": "Cover",
23
+ "editor.removeCover": "Remove cover",
24
+ "editor.coverDropzone": "Drag & drop cover image here or click to upload",
25
+ "editor.coverFormats": "JPEG, PNG, GIF, WebP up to 5MB",
26
+ "view.loadFailed": "Failed to load document. Please try again.",
27
+ "view.edit": "Edit",
28
+ "view.authorId": "Author ID",
29
+ "view.updated": "Updated",
30
+ "docList.welcome": "Welcome to Documentation",
31
+ "docList.welcomeDescription": "Browse and manage your documentation. Create new documents or organize them into folders.",
32
+ "docList.folders": "Folders",
33
+ "docList.docs": "docs",
34
+ "docList.newFolder": "New Folder",
35
+ "docList.documents": "Documents",
36
+ "docList.recentDocuments": "Recent Documents",
37
+ "docList.newDocument": "New Document",
38
+ "docList.noDocuments": "No documents yet",
39
+ "docList.getStarted": "Get started by creating your first document",
40
+ "docList.createDocument": "Create Document",
41
+ "docList.updated": "Updated",
42
+ "docList.open": "Open",
43
+ "docList.justNow": "just now",
44
+ "docList.minuteAgo": "{n} minute ago",
45
+ "docList.minutesAgo": "{n} minutes ago",
46
+ "docList.hourAgo": "{n} hour ago",
47
+ "docList.hoursAgo": "{n} hours ago",
48
+ "docList.dayAgo": "{n} day ago",
49
+ "docList.daysAgo": "{n} days ago",
50
+ "export.export": "Export",
51
+ "export.exportAs": "Export as",
52
+ "export.word": "Microsoft Word",
53
+ "export.wordDesc": "Editable document format",
54
+ "export.pdf": "PDF Document",
55
+ "export.pdfDesc": "Print-ready format",
56
+ "export.html": "HTML Page",
57
+ "export.htmlDesc": "Web page format",
58
+ "export.markdown": "Markdown",
59
+ "export.markdownDesc": "Plain text with formatting",
60
+ "export.missingDep": "Missing dependency: {message}\n\nInstall with:\n{command}",
61
+ "export.failed": "Export failed: {message}",
62
+ "versions.title": "Version History",
63
+ "versions.compare": "Compare",
64
+ "versions.saveVersion": "Save Version",
65
+ "versions.descPlaceholder": "Describe what's changed in this version...",
66
+ "versions.saving": "Saving...",
67
+ "versions.save": "Save",
68
+ "versions.cancel": "Cancel",
69
+ "versions.noVersions": "No versions yet",
70
+ "versions.noVersionsHint": "Save a version to track changes",
71
+ "versions.latest": "Latest",
72
+ "versions.restore": "Restore this version",
73
+ "versions.delete": "Delete version",
74
+ "versions.createdBy": "Version created by {name}",
75
+ "versions.createFailed": "Failed to create version",
76
+ "versions.restoreConfirm": "Restore \"{title}\" to version {version}?\n\nCurrent state will be saved as a backup.",
77
+ "versions.restored": "Restored to version {version}",
78
+ "versions.restoreFailed": "Failed to restore version",
79
+ "versions.deleteConfirm": "Delete version {version}? This cannot be undone.",
80
+ "versions.deleteFailed": "Failed to delete version",
81
+ "versions.loading": "Loading versions...",
82
+ "versions.loadFailed": "Failed to load version history"
83
+ }
@@ -0,0 +1,83 @@
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.slugRequired": "Пожалуйста, введите slug документа",
16
+ "editor.saveFailed": "Не удалось сохранить документ. Попробуйте ещё раз.",
17
+ "editor.view": "Просмотр",
18
+ "editor.saving": "Сохранение...",
19
+ "editor.create": "Создать",
20
+ "editor.save": "Сохранить",
21
+ "editor.slug": "Slug",
22
+ "editor.coverAlt": "Обложка",
23
+ "editor.removeCover": "Удалить обложку",
24
+ "editor.coverDropzone": "Перетащите изображение обложки сюда или нажмите для загрузки",
25
+ "editor.coverFormats": "JPEG, PNG, GIF, WebP до 5МБ",
26
+ "view.loadFailed": "Не удалось загрузить документ. Попробуйте ещё раз.",
27
+ "view.edit": "Редактировать",
28
+ "view.authorId": "ID автора",
29
+ "view.updated": "Обновлено",
30
+ "docList.welcome": "Добро пожаловать в Документацию",
31
+ "docList.welcomeDescription": "Просматривайте и управляйте документацией. Создавайте новые документы или организуйте их в папки.",
32
+ "docList.folders": "Папки",
33
+ "docList.docs": "док.",
34
+ "docList.newFolder": "Новая папка",
35
+ "docList.documents": "Документы",
36
+ "docList.recentDocuments": "Недавние документы",
37
+ "docList.newDocument": "Новый документ",
38
+ "docList.noDocuments": "Документов пока нет",
39
+ "docList.getStarted": "Начните с создания первого документа",
40
+ "docList.createDocument": "Создать документ",
41
+ "docList.updated": "Обновлено",
42
+ "docList.open": "Открыть",
43
+ "docList.justNow": "только что",
44
+ "docList.minuteAgo": "{n} минуту назад",
45
+ "docList.minutesAgo": "{n} минут назад",
46
+ "docList.hourAgo": "{n} час назад",
47
+ "docList.hoursAgo": "{n} часов назад",
48
+ "docList.dayAgo": "{n} день назад",
49
+ "docList.daysAgo": "{n} дней назад",
50
+ "export.export": "Экспорт",
51
+ "export.exportAs": "Экспортировать как",
52
+ "export.word": "Microsoft Word",
53
+ "export.wordDesc": "Редактируемый формат документа",
54
+ "export.pdf": "PDF документ",
55
+ "export.pdfDesc": "Формат для печати",
56
+ "export.html": "HTML страница",
57
+ "export.htmlDesc": "Формат веб-страницы",
58
+ "export.markdown": "Markdown",
59
+ "export.markdownDesc": "Текст с форматированием",
60
+ "export.missingDep": "Отсутствует зависимость: {message}\n\nУстановите:\n{command}",
61
+ "export.failed": "Ошибка экспорта: {message}",
62
+ "versions.title": "История версий",
63
+ "versions.compare": "Сравнить",
64
+ "versions.saveVersion": "Сохранить версию",
65
+ "versions.descPlaceholder": "Опишите изменения в этой версии...",
66
+ "versions.saving": "Сохранение...",
67
+ "versions.save": "Сохранить",
68
+ "versions.cancel": "Отмена",
69
+ "versions.noVersions": "Версий пока нет",
70
+ "versions.noVersionsHint": "Сохраните версию для отслеживания изменений",
71
+ "versions.latest": "Последняя",
72
+ "versions.restore": "Восстановить эту версию",
73
+ "versions.delete": "Удалить версию",
74
+ "versions.createdBy": "Версия создана пользователем {name}",
75
+ "versions.createFailed": "Не удалось создать версию",
76
+ "versions.restoreConfirm": "Восстановить \"{title}\" до версии {version}?\n\nТекущее состояние будет сохранено как резервная копия.",
77
+ "versions.restored": "Восстановлено до версии {version}",
78
+ "versions.restoreFailed": "Не удалось восстановить версию",
79
+ "versions.deleteConfirm": "Удалить версию {version}? Это действие нельзя отменить.",
80
+ "versions.deleteFailed": "Не удалось удалить версию",
81
+ "versions.loading": "Загрузка версий...",
82
+ "versions.loadFailed": "Не удалось загрузить историю версий"
83
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-embed-docs",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Full-stack documentation system with BlockNote editor, hierarchical structure, and file uploads",
5
5
  "type": "module",
6
6
  "main": "./dist/server/index.js",
@@ -1,20 +0,0 @@
1
- import { DocumentSummary } from '../../shared/types.js';
2
- interface DocsLayoutProps {
3
- theme?: 'light' | 'dark';
4
- children: React.ReactNode;
5
- currentDocId?: string;
6
- /**
7
- * Called when navigating to a document.
8
- * `path` is the full path from root to the document (e.g., "/docs/parent/child")
9
- */
10
- onNavigate?: (path: string) => void;
11
- /**
12
- * Base path for document URLs (default: "/docs")
13
- */
14
- basePath?: string;
15
- userAvatar?: React.ReactNode;
16
- onSearch?: (query: string) => DocumentSummary[];
17
- }
18
- export declare function DocsLayout({ children, currentDocId, onNavigate, basePath, userAvatar, onSearch, }: DocsLayoutProps): import("react/jsx-runtime").JSX.Element;
19
- export {};
20
- //# sourceMappingURL=DocsLayout.d.ts.map