documentation-hub 5.7.2

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 (271) hide show
  1. package/.eslintrc.json +43 -0
  2. package/.github/workflows/build.yml +64 -0
  3. package/.github/workflows/ci.yml +39 -0
  4. package/.vscode/extensions.json +3 -0
  5. package/Current.md +97 -0
  6. package/DocHub_Image.png +0 -0
  7. package/README.md +666 -0
  8. package/USER_GUIDE.md +1173 -0
  9. package/Updater.md +311 -0
  10. package/build/256x256.png +0 -0
  11. package/build/512x512.png +0 -0
  12. package/build/app-update.yml +4 -0
  13. package/build/create-icon.js +208 -0
  14. package/build/icon.ico +0 -0
  15. package/build/icon.png +0 -0
  16. package/build/icon_1024x1024.png +0 -0
  17. package/dist/assets/Analytics-BpsG9895.js +1 -0
  18. package/dist/assets/Card-IAZin8kp.js +1 -0
  19. package/dist/assets/CurrentSession-B-rFkHvf.js +12 -0
  20. package/dist/assets/Dashboard-C_5gMb0q.js +1 -0
  21. package/dist/assets/Documents-CqZ25axS.js +1 -0
  22. package/dist/assets/Input-l89xwXBi.js +1 -0
  23. package/dist/assets/Reporting-DqdHJY_a.js +1 -0
  24. package/dist/assets/Search-XNbu5z_3.js +1 -0
  25. package/dist/assets/SessionManager-lH9hZfzH.js +1 -0
  26. package/dist/assets/Sessions-ClZOPYNc.js +1 -0
  27. package/dist/assets/Settings-DUEHGURa.js +11 -0
  28. package/dist/assets/index-8xUe8ptc.js +24 -0
  29. package/dist/assets/index-RYyJqF7O.css +1 -0
  30. package/dist/assets/path-BkOl0AGO.js +1 -0
  31. package/dist/assets/promises-ID_B9S-h.js +1 -0
  32. package/dist/assets/urlHelpers-TvgahX0r.js +1 -0
  33. package/dist/assets/useToast-yRSO1dkm.js +1 -0
  34. package/dist/assets/vendor-charts-RkGK5ROP.js +36 -0
  35. package/dist/assets/vendor-db-l0sNRNKZ.js +1 -0
  36. package/dist/assets/vendor-react-BVZ_anCF.js +4 -0
  37. package/dist/assets/vendor-search-Dw8P0qyA.js +1 -0
  38. package/dist/assets/vendor-ui-BU7NfluV.js +53 -0
  39. package/dist/electron/PowerAutomateApiService-LfW09ZGr.js +147 -0
  40. package/dist/electron/main-CXkNtyv-.js +19789 -0
  41. package/dist/electron/main.js +5 -0
  42. package/dist/electron/preload.js +1 -0
  43. package/dist/icon.png +0 -0
  44. package/dist/index.html +27 -0
  45. package/docs/CODEBASE_ANALYSIS_REPORT.md +309 -0
  46. package/docs/DEBUG_LOGGING_GUIDE.md +244 -0
  47. package/docs/README.md +115 -0
  48. package/docs/TOC_WIRING_GUIDE.md +344 -0
  49. package/docs/analysis/Bullet_Symbol_Bug_Analysis.md +136 -0
  50. package/docs/analysis/DOCXMLATER_ANALYSIS_SUMMARY.txt +169 -0
  51. package/docs/analysis/Document_Processing_Issues_Analysis.md +704 -0
  52. package/docs/analysis/FIELD_PRESERVATION_ANALYSIS.md +1200 -0
  53. package/docs/analysis/INDENTATION_PRESERVE_ANALYSIS.md +181 -0
  54. package/docs/analysis/INDENTATION_PRESERVE_IMPLEMENTATION.md +207 -0
  55. package/docs/analysis/List_Implementation.md +206 -0
  56. package/docs/analysis/List_Implementation_Accuracy_Report.md +366 -0
  57. package/docs/analysis/PROCESSING_OPTIONS_UI_UPDATES.md +220 -0
  58. package/docs/analysis/RefactorStyles.md +852 -0
  59. package/docs/analysis/STYLE_PARAMETER_ENHANCEMENT.md +143 -0
  60. package/docs/analysis/docxmlater-comparison-todo-2025-11-13.md +636 -0
  61. package/docs/analysis/docxmlater-implementation-analysis-2025-11-13.md +340 -0
  62. package/docs/analysis/docxmlater-template_ui-integration-analysis.md +263 -0
  63. package/docs/analysis/github-issues-to-create.md +237 -0
  64. package/docs/api/API_README.md +538 -0
  65. package/docs/api/API_REFERENCE.md +751 -0
  66. package/docs/api/TYPE_DEFINITIONS.md +869 -0
  67. package/docs/architecture/FONT_EMBEDDING_GUIDE.md +318 -0
  68. package/docs/architecture/docxmlater-functions-and-structure.md +726 -0
  69. package/docs/docxmlater-readme.md +1341 -0
  70. package/docs/fixes/EXECUTION_LOG_TEST_BASE.md +573 -0
  71. package/docs/fixes/HYPERLINK_TEXT_SANITIZATION.md +253 -0
  72. package/docs/fixes/README.md +37 -0
  73. package/docs/github-issues/issue-1-body.md +125 -0
  74. package/docs/github-issues/issue-10-body.md +850 -0
  75. package/docs/github-issues/issue-2-body.md +200 -0
  76. package/docs/github-issues/issue-3-body.md +270 -0
  77. package/docs/github-issues/issue-4-body.md +169 -0
  78. package/docs/github-issues/issue-5-body.md +173 -0
  79. package/docs/github-issues/issue-6-body.md +158 -0
  80. package/docs/github-issues/issue-7-body.md +171 -0
  81. package/docs/github-issues/issue-8-body.md +407 -0
  82. package/docs/github-issues/issue-9-body.md +515 -0
  83. package/docs/github-issues/issue-tracker.md +274 -0
  84. package/docs/github-issues/predictive-analysis-2025-10-18.md +2131 -0
  85. package/docs/implementation/List_Framework_Refactor_Plan.md +336 -0
  86. package/docs/implementation/PRIMARY_TEXT_COLOR_FEATURE.md +217 -0
  87. package/docs/implementation/RELEASE_PLAN_v2.1.0.md +362 -0
  88. package/docs/implementation/RefactorStyles.md +588 -0
  89. package/docs/implementation/implement-plan.md +489 -0
  90. package/docs/implementation/missing-helpers-implementation.md +391 -0
  91. package/docs/implementation/refactor-plan.md +520 -0
  92. package/docs/implementation/session-implementation-complete.md +233 -0
  93. package/docs/implementation/session-management-plan.md +250 -0
  94. package/docs/setup-checklist.md +77 -0
  95. package/docs/versions/changelog.md +345 -0
  96. package/electron/customUpdater.ts +656 -0
  97. package/electron/main.ts +2441 -0
  98. package/electron/memoryConfig.ts +187 -0
  99. package/electron/preload.ts +394 -0
  100. package/electron/proxyConfig.ts +340 -0
  101. package/electron/services/BackupService.ts +452 -0
  102. package/electron/services/DictionaryService.ts +402 -0
  103. package/electron/services/LocalDictionaryLookupService.ts +147 -0
  104. package/electron/services/PowerAutomateApiService.ts +231 -0
  105. package/electron/services/SharePointSyncService.ts +474 -0
  106. package/electron/windowsCertStore.ts +427 -0
  107. package/electron/zscalerConfig.ts +381 -0
  108. package/eslint.config.js +92 -0
  109. package/jest.config.js +52 -0
  110. package/package.json +214 -0
  111. package/postcss.config.mjs +6 -0
  112. package/public/icon.png +0 -0
  113. package/publish-release.ps1 +5 -0
  114. package/renovate.json +30 -0
  115. package/src/App.tsx +216 -0
  116. package/src/__mocks__/p-limit.js +12 -0
  117. package/src/__mocks__/styleMock.js +1 -0
  118. package/src/components/common/BugReportButton.tsx +44 -0
  119. package/src/components/common/BugReportDialog.tsx +193 -0
  120. package/src/components/common/Button.tsx +153 -0
  121. package/src/components/common/Card.tsx +86 -0
  122. package/src/components/common/ColorPickerDialog.tsx +177 -0
  123. package/src/components/common/ConfirmDialog.tsx +96 -0
  124. package/src/components/common/DebugConsole.tsx +275 -0
  125. package/src/components/common/EmptyState.tsx +183 -0
  126. package/src/components/common/ErrorBoundary.tsx +98 -0
  127. package/src/components/common/ErrorDetailsDialog.tsx +153 -0
  128. package/src/components/common/ErrorFallback.tsx +218 -0
  129. package/src/components/common/Input.tsx +109 -0
  130. package/src/components/common/Skeleton.tsx +184 -0
  131. package/src/components/common/SplashScreen.tsx +81 -0
  132. package/src/components/common/Toast.tsx +155 -0
  133. package/src/components/common/Tooltip.tsx +79 -0
  134. package/src/components/common/UpdateNotification.tsx +320 -0
  135. package/src/components/comparison/ComparisonWindow.tsx +374 -0
  136. package/src/components/comparison/SideBySideDiff.tsx +486 -0
  137. package/src/components/comparison/index.ts +8 -0
  138. package/src/components/document/DocumentUploader.tsx +288 -0
  139. package/src/components/document/HyperlinkPreview.tsx +430 -0
  140. package/src/components/document/HyperlinkService.md +1484 -0
  141. package/src/components/document/Hyperlink_Technical_Documentation.md +496 -0
  142. package/src/components/document/InlineChangesView.tsx +707 -0
  143. package/src/components/document/ProcessingProgress.tsx +303 -0
  144. package/src/components/document/ProcessingResults.tsx +256 -0
  145. package/src/components/document/TrackedChangesDetail.tsx +530 -0
  146. package/src/components/document/TrackedChangesPanel.tsx +546 -0
  147. package/src/components/document/VirtualDocumentList.tsx +240 -0
  148. package/src/components/editor/DocumentEditor.tsx +723 -0
  149. package/src/components/editor/DocumentEditorModal.tsx +640 -0
  150. package/src/components/editor/EditorQuickActions.tsx +502 -0
  151. package/src/components/editor/EditorToolbar.tsx +312 -0
  152. package/src/components/editor/TableEditor.tsx +926 -0
  153. package/src/components/editor/index.ts +18 -0
  154. package/src/components/layout/Header.tsx +190 -0
  155. package/src/components/layout/Sidebar.tsx +313 -0
  156. package/src/components/layout/TitleBar.tsx +190 -0
  157. package/src/components/navigation/CommandPalette.tsx +233 -0
  158. package/src/components/navigation/KeyboardShortcutsModal.tsx +173 -0
  159. package/src/components/sessions/ChangeItem.tsx +408 -0
  160. package/src/components/sessions/ChangeViewer.tsx +1155 -0
  161. package/src/components/sessions/DocumentComparisonModal.tsx +314 -0
  162. package/src/components/sessions/ProcessingOptions.tsx +297 -0
  163. package/src/components/sessions/ReplacementsTab.tsx +438 -0
  164. package/src/components/sessions/RevisionHandlingOptions.tsx +87 -0
  165. package/src/components/sessions/SessionManager.tsx +188 -0
  166. package/src/components/sessions/StylesEditor.tsx +1335 -0
  167. package/src/components/sessions/TabContainer.tsx +151 -0
  168. package/src/components/sessions/VirtualSessionList.tsx +157 -0
  169. package/src/components/sessions/sessionToProcessorManager.tsx +420 -0
  170. package/src/components/settings/CertificateManager.tsx +410 -0
  171. package/src/components/settings/SegmentedControl.tsx +88 -0
  172. package/src/components/settings/SettingRow.tsx +52 -0
  173. package/src/contexts/GlobalStatsContext.tsx +396 -0
  174. package/src/contexts/SessionContext.tsx +2129 -0
  175. package/src/contexts/ThemeContext.tsx +428 -0
  176. package/src/contexts/UserSettingsContext.tsx +290 -0
  177. package/src/contexts/__tests__/GlobalStatsContext.test.tsx +390 -0
  178. package/src/global.d.ts +273 -0
  179. package/src/hooks/useDocumentQueue.tsx +210 -0
  180. package/src/hooks/useToast.tsx +55 -0
  181. package/src/main.tsx +10 -0
  182. package/src/pages/Analytics.tsx +386 -0
  183. package/src/pages/CurrentSession.tsx +1174 -0
  184. package/src/pages/Dashboard.tsx +319 -0
  185. package/src/pages/Documents.tsx +317 -0
  186. package/src/pages/Projects.tsx +250 -0
  187. package/src/pages/Reporting.tsx +386 -0
  188. package/src/pages/Search.tsx +349 -0
  189. package/src/pages/Sessions.tsx +285 -0
  190. package/src/pages/Settings.tsx +2662 -0
  191. package/src/services/HyperlinkService.ts +1085 -0
  192. package/src/services/document/DocXMLaterProcessor.ts +617 -0
  193. package/src/services/document/DocumentProcessingComparison.ts +856 -0
  194. package/src/services/document/DocumentSnapshotService.ts +575 -0
  195. package/src/services/document/WordDocumentProcessor.ts +10509 -0
  196. package/src/services/document/__tests__/DocXMLaterProcessor.hyperlinks.test.md +311 -0
  197. package/src/services/document/__tests__/WordDocumentProcessor.integration.test.ts +515 -0
  198. package/src/services/document/__tests__/WordDocumentProcessor.test.ts +812 -0
  199. package/src/services/document/blanklines/BlankLineManager.ts +658 -0
  200. package/src/services/document/blanklines/__tests__/paragraphChecks.test.ts +281 -0
  201. package/src/services/document/blanklines/helpers/blankLineInsertion.ts +87 -0
  202. package/src/services/document/blanklines/helpers/blankLineSnapshot.ts +251 -0
  203. package/src/services/document/blanklines/helpers/clearCustom.ts +121 -0
  204. package/src/services/document/blanklines/helpers/contextChecks.ts +117 -0
  205. package/src/services/document/blanklines/helpers/imageChecks.ts +51 -0
  206. package/src/services/document/blanklines/helpers/paragraphChecks.ts +236 -0
  207. package/src/services/document/blanklines/helpers/removeBlanksBetweenListItems.ts +91 -0
  208. package/src/services/document/blanklines/helpers/removeTrailingBlanks.ts +35 -0
  209. package/src/services/document/blanklines/helpers/tableGuards.ts +21 -0
  210. package/src/services/document/blanklines/index.ts +67 -0
  211. package/src/services/document/blanklines/rules/additionRules.ts +337 -0
  212. package/src/services/document/blanklines/rules/indentationRules.ts +317 -0
  213. package/src/services/document/blanklines/rules/removalRules.ts +362 -0
  214. package/src/services/document/blanklines/rules/ruleTypes.ts +92 -0
  215. package/src/services/document/blanklines/types.ts +29 -0
  216. package/src/services/document/helpers/ImageBorderCropper.ts +377 -0
  217. package/src/services/document/helpers/__tests__/whitespace.test.ts +272 -0
  218. package/src/services/document/helpers/whitespace.ts +117 -0
  219. package/src/services/document/list/ListNormalizer.ts +947 -0
  220. package/src/services/document/list/index.ts +45 -0
  221. package/src/services/document/list/list-detection.ts +275 -0
  222. package/src/services/document/list/list-types.ts +162 -0
  223. package/src/services/document/processors/HyperlinkProcessor.ts +370 -0
  224. package/src/services/document/processors/ListProcessor.ts +257 -0
  225. package/src/services/document/processors/StructureProcessor.ts +176 -0
  226. package/src/services/document/processors/StyleProcessor.ts +389 -0
  227. package/src/services/document/processors/TableProcessor.ts +2238 -0
  228. package/src/services/document/processors/__tests__/HyperlinkProcessor.test.ts +314 -0
  229. package/src/services/document/processors/__tests__/ListProcessor.test.ts +291 -0
  230. package/src/services/document/processors/__tests__/StructureProcessor.test.ts +257 -0
  231. package/src/services/document/processors/__tests__/TableProcessor.hlp-tips-bullets.test.ts +459 -0
  232. package/src/services/document/processors/__tests__/TableProcessor.test.ts +1604 -0
  233. package/src/services/document/processors/index.ts +28 -0
  234. package/src/services/document/types/docx-processing.ts +310 -0
  235. package/src/services/editor/EditorActionHandlers.ts +901 -0
  236. package/src/services/editor/index.ts +13 -0
  237. package/src/setupTests.ts +47 -0
  238. package/src/styles/global.css +782 -0
  239. package/src/types/backup.ts +132 -0
  240. package/src/types/dictionary.ts +125 -0
  241. package/src/types/document-processing.ts +331 -0
  242. package/src/types/docxmlater-augments.d.ts +142 -0
  243. package/src/types/editor.ts +280 -0
  244. package/src/types/electron.ts +340 -0
  245. package/src/types/globalStats.ts +155 -0
  246. package/src/types/hyperlink.ts +471 -0
  247. package/src/types/operations.ts +354 -0
  248. package/src/types/session.ts +427 -0
  249. package/src/types/settings.ts +112 -0
  250. package/src/utils/MemoryMonitor.ts +248 -0
  251. package/src/utils/cn.ts +6 -0
  252. package/src/utils/colorConvert.ts +306 -0
  253. package/src/utils/diffUtils.ts +347 -0
  254. package/src/utils/documentUtils.ts +202 -0
  255. package/src/utils/electronGuard.ts +62 -0
  256. package/src/utils/indexedDB.ts +915 -0
  257. package/src/utils/logger.ts +717 -0
  258. package/src/utils/pathSecurity.ts +232 -0
  259. package/src/utils/pathValidator.ts +236 -0
  260. package/src/utils/processingTimeEstimator.ts +153 -0
  261. package/src/utils/safeJsonParse.ts +62 -0
  262. package/src/utils/textSanitizer.ts +162 -0
  263. package/src/utils/urlHelpers.ts +304 -0
  264. package/src/utils/urlPatterns.ts +198 -0
  265. package/src/utils/urlSanitizer.ts +152 -0
  266. package/src/vite-env.d.ts +11 -0
  267. package/tsconfig.electron.json +19 -0
  268. package/tsconfig.json +36 -0
  269. package/tsconfig.node.json +12 -0
  270. package/typedoc.json +45 -0
  271. package/vite.config.ts +152 -0
@@ -0,0 +1,303 @@
1
+ import { cn } from '@/utils/cn';
2
+ import { motion } from 'framer-motion';
3
+ import {
4
+ Activity,
5
+ AlertCircle,
6
+ CheckCircle,
7
+ Clock,
8
+ Database,
9
+ FileText,
10
+ Link,
11
+ Shield,
12
+ } from 'lucide-react';
13
+ import { useEffect, useState } from 'react';
14
+
15
+ interface ProcessingStep {
16
+ id: string;
17
+ name: string;
18
+ description: string;
19
+ status: 'pending' | 'processing' | 'completed' | 'error' | 'skipped';
20
+ progress?: number;
21
+ duration?: number;
22
+ error?: string;
23
+ icon: React.ReactNode;
24
+ }
25
+
26
+ interface ProcessingProgressProps {
27
+ documentName: string;
28
+ currentStep?: string;
29
+ progress: number;
30
+ steps?: ProcessingStep[];
31
+ statistics?: {
32
+ totalElements: number;
33
+ processedElements: number;
34
+ modifiedElements: number;
35
+ hyperlinksProcessed?: number;
36
+ errors?: number;
37
+ warnings?: number;
38
+ };
39
+ estimatedTimeRemaining?: number;
40
+ onCancel?: () => void;
41
+ className?: string;
42
+ }
43
+
44
+ const defaultSteps: ProcessingStep[] = [
45
+ {
46
+ id: 'backup',
47
+ name: 'Creating Backup',
48
+ description: 'Saving original document',
49
+ status: 'pending',
50
+ icon: <Database className="w-4 h-4" />,
51
+ },
52
+ {
53
+ id: 'validation',
54
+ name: 'Validating Document',
55
+ description: 'Checking document structure',
56
+ status: 'pending',
57
+ icon: <Shield className="w-4 h-4" />,
58
+ },
59
+ {
60
+ id: 'scanning',
61
+ name: 'Scanning Hyperlinks',
62
+ description: 'Finding all hyperlinks',
63
+ status: 'pending',
64
+ icon: <Activity className="w-4 h-4" />,
65
+ },
66
+ {
67
+ id: 'processing',
68
+ name: 'Processing Hyperlinks',
69
+ description: 'Applying modifications',
70
+ status: 'pending',
71
+ icon: <Link className="w-4 h-4" />,
72
+ },
73
+ {
74
+ id: 'saving',
75
+ name: 'Saving Document',
76
+ description: 'Writing changes to file',
77
+ status: 'pending',
78
+ icon: <FileText className="w-4 h-4" />,
79
+ },
80
+ ];
81
+
82
+ export function ProcessingProgress({
83
+ documentName,
84
+ currentStep,
85
+ progress,
86
+ steps = defaultSteps,
87
+ statistics,
88
+ estimatedTimeRemaining,
89
+ onCancel,
90
+ className,
91
+ }: ProcessingProgressProps) {
92
+ const [animatedProgress, setAnimatedProgress] = useState(0);
93
+ const [elapsedTime, setElapsedTime] = useState(0);
94
+
95
+ useEffect(() => {
96
+ setAnimatedProgress(progress);
97
+ }, [progress]);
98
+
99
+ useEffect(() => {
100
+ const interval = setInterval(() => {
101
+ setElapsedTime((prev) => prev + 1);
102
+ }, 1000);
103
+
104
+ return () => clearInterval(interval);
105
+ }, []);
106
+
107
+ const formatTime = (seconds: number): string => {
108
+ if (seconds < 60) return `${seconds}s`;
109
+ const minutes = Math.floor(seconds / 60);
110
+ const remainingSeconds = seconds % 60;
111
+ return `${minutes}m ${remainingSeconds}s`;
112
+ };
113
+
114
+ const getStepStatus = (step: ProcessingStep) => {
115
+ if (currentStep === step.id) return 'processing';
116
+ const currentIndex = steps.findIndex((s) => s.id === currentStep);
117
+ const stepIndex = steps.findIndex((s) => s.id === step.id);
118
+ if (currentIndex > stepIndex) return 'completed';
119
+ return step.status;
120
+ };
121
+
122
+ const getStepIcon = (status: ProcessingStep['status']) => {
123
+ switch (status) {
124
+ case 'completed':
125
+ return <CheckCircle className="w-5 h-5 text-green-500" />;
126
+ case 'error':
127
+ return <AlertCircle className="w-5 h-5 text-red-500" />;
128
+ case 'processing':
129
+ return (
130
+ <motion.div
131
+ animate={{ rotate: 360 }}
132
+ transition={{ duration: 2, repeat: Infinity, ease: 'linear' }}
133
+ className="w-5 h-5 border-2 border-primary border-t-transparent rounded-full"
134
+ />
135
+ );
136
+ case 'skipped':
137
+ return <div className="w-5 h-5 rounded-full bg-muted" />;
138
+ default:
139
+ return <Clock className="w-5 h-5 text-muted-foreground" />;
140
+ }
141
+ };
142
+
143
+ return (
144
+ <div className={cn('space-y-6', className)}>
145
+ {/* Header */}
146
+ <div className="space-y-2">
147
+ <div className="flex items-center justify-between">
148
+ <div>
149
+ <h3 className="font-semibold text-lg">Processing Document</h3>
150
+ <p className="text-sm text-muted-foreground truncate max-w-md">{documentName}</p>
151
+ </div>
152
+ {onCancel && (
153
+ <button
154
+ onClick={onCancel}
155
+ className="px-3 py-1 text-sm border border-border rounded-lg hover:bg-destructive/10 hover:border-destructive transition-colors"
156
+ >
157
+ Cancel
158
+ </button>
159
+ )}
160
+ </div>
161
+ </div>
162
+
163
+ {/* Main Progress Bar */}
164
+ <div className="space-y-2">
165
+ <div className="flex justify-between text-sm">
166
+ <span className="text-muted-foreground">Overall Progress</span>
167
+ <span className="font-medium">{Math.round(animatedProgress)}%</span>
168
+ </div>
169
+ <div className="relative h-3 bg-muted rounded-full overflow-hidden">
170
+ <motion.div
171
+ className="absolute inset-y-0 left-0 bg-linear-to-r from-primary via-primary to-primary/80"
172
+ initial={{ width: '0%' }}
173
+ animate={{ width: `${animatedProgress}%` }}
174
+ transition={{ duration: 0.5, ease: 'easeOut' }}
175
+ >
176
+ {/* Shimmer effect */}
177
+ <motion.div
178
+ className="absolute inset-0 bg-linear-to-r from-transparent via-white/20 to-transparent"
179
+ animate={{ x: ['0%', '200%'] }}
180
+ transition={{ duration: 1.5, repeat: Infinity, ease: 'linear' }}
181
+ />
182
+ </motion.div>
183
+ </div>
184
+ </div>
185
+
186
+ {/* Processing Steps */}
187
+ <div className="space-y-3">
188
+ {steps.map((step, index) => {
189
+ const status = getStepStatus(step);
190
+ const isActive = currentStep === step.id;
191
+
192
+ return (
193
+ <motion.div
194
+ key={step.id}
195
+ initial={{ opacity: 0, x: -20 }}
196
+ animate={{ opacity: 1, x: 0 }}
197
+ transition={{ delay: index * 0.1 }}
198
+ className={cn(
199
+ 'flex items-start gap-3 p-3 rounded-lg transition-all',
200
+ isActive && 'bg-primary/5 border border-primary/20',
201
+ status === 'completed' && 'opacity-70',
202
+ status === 'error' && 'bg-destructive/5 border border-destructive/20'
203
+ )}
204
+ >
205
+ <div className="mt-0.5">{getStepIcon(status)}</div>
206
+
207
+ <div className="flex-1 space-y-1">
208
+ <div className="flex items-center gap-2">
209
+ <span className="font-medium">{step.name}</span>
210
+ {isActive && (
211
+ <motion.span
212
+ initial={{ opacity: 0 }}
213
+ animate={{ opacity: [0.5, 1, 0.5] }}
214
+ transition={{ duration: 2, repeat: Infinity }}
215
+ className="text-xs text-primary px-2 py-0.5 bg-primary/10 rounded-full"
216
+ >
217
+ Processing...
218
+ </motion.span>
219
+ )}
220
+ </div>
221
+ <p className="text-sm text-muted-foreground">{step.description}</p>
222
+ {step.error && <p className="text-sm text-destructive">{step.error}</p>}
223
+ {isActive && step.progress !== undefined && (
224
+ <div className="mt-2">
225
+ <div className="h-1 bg-muted rounded-full overflow-hidden">
226
+ <motion.div
227
+ className="h-full bg-primary"
228
+ initial={{ width: '0%' }}
229
+ animate={{ width: `${step.progress}%` }}
230
+ transition={{ duration: 0.3 }}
231
+ />
232
+ </div>
233
+ </div>
234
+ )}
235
+ </div>
236
+
237
+ <div className="flex items-center gap-2 text-muted-foreground">
238
+ {step.icon}
239
+ {status === 'completed' && step.duration && (
240
+ <span className="text-xs">{formatTime(step.duration)}</span>
241
+ )}
242
+ </div>
243
+ </motion.div>
244
+ );
245
+ })}
246
+ </div>
247
+
248
+ {/* Statistics */}
249
+ {statistics && (
250
+ <div className="grid grid-cols-2 sm:grid-cols-4 gap-3">
251
+ <div className="text-center p-3 bg-muted/30 rounded-lg">
252
+ <p className="text-lg font-bold">{statistics.totalElements}</p>
253
+ <p className="text-xs text-muted-foreground">Total Elements</p>
254
+ </div>
255
+ <div className="text-center p-3 bg-muted/30 rounded-lg">
256
+ <p className="text-lg font-bold text-primary">{statistics.processedElements}</p>
257
+ <p className="text-xs text-muted-foreground">Processed</p>
258
+ </div>
259
+ <div className="text-center p-3 bg-muted/30 rounded-lg">
260
+ <p className="text-lg font-bold text-green-500">{statistics.modifiedElements}</p>
261
+ <p className="text-xs text-muted-foreground">Modified</p>
262
+ </div>
263
+ <div className="text-center p-3 bg-muted/30 rounded-lg">
264
+ <p className="text-lg font-bold text-blue-500">{statistics.hyperlinksProcessed || 0}</p>
265
+ <p className="text-xs text-muted-foreground">Hyperlinks</p>
266
+ </div>
267
+ </div>
268
+ )}
269
+
270
+ {/* Time Information */}
271
+ <div className="flex justify-between items-center text-sm text-muted-foreground">
272
+ <div className="flex items-center gap-4">
273
+ <span>Elapsed: {formatTime(elapsedTime)}</span>
274
+ {estimatedTimeRemaining !== undefined && (
275
+ <span>Remaining: ~{formatTime(estimatedTimeRemaining)}</span>
276
+ )}
277
+ </div>
278
+ {statistics?.warnings !== undefined && statistics.warnings > 0 && (
279
+ <span className="text-yellow-500">
280
+ {statistics.warnings} warning{statistics.warnings !== 1 ? 's' : ''}
281
+ </span>
282
+ )}
283
+ </div>
284
+
285
+ {/* Animated background effect */}
286
+ <div className="absolute inset-0 pointer-events-none overflow-hidden rounded-lg">
287
+ <motion.div
288
+ className="absolute -inset-40 opacity-5"
289
+ animate={{
290
+ rotate: [0, 360],
291
+ }}
292
+ transition={{
293
+ duration: 20,
294
+ repeat: Infinity,
295
+ ease: 'linear',
296
+ }}
297
+ >
298
+ <div className="w-full h-full bg-linear-to-r from-primary to-transparent" />
299
+ </motion.div>
300
+ </div>
301
+ </div>
302
+ );
303
+ }
@@ -0,0 +1,256 @@
1
+ import { Button } from '@/components/common/Button';
2
+ import type { Document, DocumentChange } from '@/types/session';
3
+ import { cn } from '@/utils/cn';
4
+ import { motion } from 'framer-motion';
5
+ import {
6
+ AlertCircle,
7
+ Archive,
8
+ ArrowRight,
9
+ CheckCircle,
10
+ Clock,
11
+ Download,
12
+ FileText,
13
+ Hash,
14
+ Link,
15
+ RotateCcw,
16
+ Share2,
17
+ TrendingUp,
18
+ } from 'lucide-react';
19
+ import { TrackedChangesDetail } from './TrackedChangesDetail';
20
+
21
+ interface ProcessingResultsProps {
22
+ document: Document;
23
+ onDownload?: () => void;
24
+ onReprocess?: () => void;
25
+ onShare?: () => void;
26
+ onViewBackup?: () => void;
27
+ className?: string;
28
+ }
29
+
30
+ export function ProcessingResults({
31
+ document,
32
+ onDownload,
33
+ onReprocess,
34
+ onShare,
35
+ onViewBackup,
36
+ className,
37
+ }: ProcessingResultsProps) {
38
+ const { processingResult } = document;
39
+
40
+ if (!processingResult) {
41
+ return (
42
+ <div className={cn('text-center py-8', className)}>
43
+ <AlertCircle className="w-12 h-12 text-muted-foreground mx-auto mb-3" />
44
+ <p className="text-muted-foreground">No processing results available</p>
45
+ </div>
46
+ );
47
+ }
48
+
49
+ const isSuccess = document.status === 'completed';
50
+ const hasErrors = document.status === 'error';
51
+
52
+ const formatDuration = (ms: number): string => {
53
+ if (ms < 1000) return `${ms}ms`;
54
+ if (ms < 60000) return `${(ms / 1000).toFixed(1)}s`;
55
+ const minutes = Math.floor(ms / 60000);
56
+ const seconds = ((ms % 60000) / 1000).toFixed(0);
57
+ return `${minutes}m ${seconds}s`;
58
+ };
59
+
60
+ const getChangeIcon = (type: DocumentChange['type']) => {
61
+ switch (type) {
62
+ case 'hyperlink':
63
+ return <Link className="w-4 h-4 text-blue-500" />;
64
+ case 'text':
65
+ return <FileText className="w-4 h-4 text-green-500" />;
66
+ case 'style':
67
+ return <TrendingUp className="w-4 h-4 text-purple-500" />;
68
+ case 'structure':
69
+ return <Archive className="w-4 h-4 text-orange-500" />;
70
+ }
71
+ };
72
+
73
+ return (
74
+ <div className={cn('space-y-6', className)}>
75
+ {/* Status Header */}
76
+ <motion.div
77
+ initial={{ opacity: 0, y: 20 }}
78
+ animate={{ opacity: 1, y: 0 }}
79
+ className={cn(
80
+ 'p-6 rounded-xl border-2',
81
+ isSuccess
82
+ ? 'bg-green-500/5 border-green-500/20'
83
+ : hasErrors
84
+ ? 'bg-red-500/5 border-red-500/20'
85
+ : 'bg-muted/30 border-border'
86
+ )}
87
+ >
88
+ <div className="flex items-start gap-4">
89
+ {isSuccess ? (
90
+ <CheckCircle className="w-8 h-8 text-green-500 mt-1" />
91
+ ) : hasErrors ? (
92
+ <AlertCircle className="w-8 h-8 text-red-500 mt-1" />
93
+ ) : (
94
+ <FileText className="w-8 h-8 text-muted-foreground mt-1" />
95
+ )}
96
+
97
+ <div className="flex-1">
98
+ <h3 className="text-xl font-semibold mb-1">
99
+ {isSuccess
100
+ ? 'Processing Completed Successfully'
101
+ : hasErrors
102
+ ? 'Processing Failed'
103
+ : 'Processing Results'}
104
+ </h3>
105
+ <p className="text-muted-foreground">{document.name}</p>
106
+
107
+ {processingResult.duration && (
108
+ <div className="flex items-center gap-2 mt-3 text-sm text-muted-foreground">
109
+ <Clock className="w-4 h-4" />
110
+ <span>Completed in {formatDuration(processingResult.duration)}</span>
111
+ </div>
112
+ )}
113
+
114
+ {hasErrors && document.errors && document.errors.length > 0 && (
115
+ <div className="mt-3 p-3 bg-red-500/10 rounded-lg">
116
+ <p className="text-sm text-red-600 font-medium mb-1">Errors:</p>
117
+ <ul className="text-sm text-red-600 space-y-1">
118
+ {document.errors.map((error, index) => (
119
+ <li key={index}>• {error}</li>
120
+ ))}
121
+ </ul>
122
+ </div>
123
+ )}
124
+ </div>
125
+
126
+ <div className="flex flex-col gap-2">
127
+ {onDownload && (
128
+ <Button variant="outline" size="sm" onClick={onDownload} className="gap-2">
129
+ <Download className="w-4 h-4" />
130
+ Download
131
+ </Button>
132
+ )}
133
+ {onShare && (
134
+ <Button variant="outline" size="sm" onClick={onShare} className="gap-2">
135
+ <Share2 className="w-4 h-4" />
136
+ Share
137
+ </Button>
138
+ )}
139
+ </div>
140
+ </div>
141
+ </motion.div>
142
+
143
+ {/* Statistics Grid */}
144
+ <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
145
+ <motion.div
146
+ initial={{ opacity: 0, scale: 0.9 }}
147
+ animate={{ opacity: 1, scale: 1 }}
148
+ transition={{ delay: 0.1 }}
149
+ className="bg-muted/30 rounded-lg p-4 text-center"
150
+ >
151
+ <Link className="w-6 h-6 text-blue-500 mx-auto mb-2" />
152
+ <p className="text-2xl font-bold">{processingResult.hyperlinksProcessed || 0}</p>
153
+ <p className="text-xs text-muted-foreground">Hyperlinks Processed</p>
154
+ </motion.div>
155
+
156
+ <motion.div
157
+ initial={{ opacity: 0, scale: 0.9 }}
158
+ animate={{ opacity: 1, scale: 1 }}
159
+ transition={{ delay: 0.2 }}
160
+ className="bg-muted/30 rounded-lg p-4 text-center"
161
+ >
162
+ <ArrowRight className="w-6 h-6 text-green-500 mx-auto mb-2" />
163
+ <p className="text-2xl font-bold text-green-500">
164
+ {processingResult.hyperlinksModified || 0}
165
+ </p>
166
+ <p className="text-xs text-muted-foreground">Links Modified</p>
167
+ </motion.div>
168
+
169
+ <motion.div
170
+ initial={{ opacity: 0, scale: 0.9 }}
171
+ animate={{ opacity: 1, scale: 1 }}
172
+ transition={{ delay: 0.3 }}
173
+ className="bg-muted/30 rounded-lg p-4 text-center"
174
+ >
175
+ <Hash className="w-6 h-6 text-purple-500 mx-auto mb-2" />
176
+ <p className="text-2xl font-bold text-purple-500">
177
+ {processingResult.contentIdsAppended || 0}
178
+ </p>
179
+ <p className="text-xs text-muted-foreground">Content IDs Added</p>
180
+ </motion.div>
181
+
182
+ <motion.div
183
+ initial={{ opacity: 0, scale: 0.9 }}
184
+ animate={{ opacity: 1, scale: 1 }}
185
+ transition={{ delay: 0.4 }}
186
+ className="bg-muted/30 rounded-lg p-4 text-center"
187
+ >
188
+ <Clock className="w-6 h-6 text-orange-500 mx-auto mb-2" />
189
+ <p className="text-2xl font-bold text-orange-500">
190
+ {processingResult.duration ? formatDuration(processingResult.duration) : 'N/A'}
191
+ </p>
192
+ <p className="text-xs text-muted-foreground">Processing Time</p>
193
+ </motion.div>
194
+ </div>
195
+
196
+ {/* Enhanced Tracked Changes */}
197
+ {processingResult.changes && processingResult.changes.length > 0 && (
198
+ <TrackedChangesDetail changes={processingResult.changes} />
199
+ )}
200
+
201
+ {/* Backup Information */}
202
+ {processingResult.backupPath && (
203
+ <div className="p-4 bg-muted/20 rounded-lg">
204
+ <div className="flex items-center justify-between">
205
+ <div className="flex items-center gap-3">
206
+ <Archive className="w-5 h-5 text-muted-foreground" />
207
+ <div>
208
+ <p className="font-medium text-sm">Backup Created</p>
209
+ <p className="text-xs text-muted-foreground">
210
+ Original document saved before processing
211
+ </p>
212
+ </div>
213
+ </div>
214
+ {onViewBackup && (
215
+ <Button variant="ghost" size="sm" onClick={onViewBackup}>
216
+ View Backup
217
+ </Button>
218
+ )}
219
+ </div>
220
+ </div>
221
+ )}
222
+
223
+ {/* Action Buttons */}
224
+ <div className="flex justify-between items-center pt-4 border-t">
225
+ <div>
226
+ {isSuccess && (
227
+ <p className="text-sm text-green-600 flex items-center gap-2">
228
+ <CheckCircle className="w-4 h-4" />
229
+ All changes applied successfully
230
+ </p>
231
+ )}
232
+ </div>
233
+ <div className="flex items-center gap-2">
234
+ {onReprocess && (
235
+ <Button variant="outline" onClick={onReprocess} className="gap-2">
236
+ <RotateCcw className="w-4 h-4" />
237
+ Reprocess
238
+ </Button>
239
+ )}
240
+ </div>
241
+ </div>
242
+
243
+ {/* Success Animation Overlay */}
244
+ {isSuccess && (
245
+ <motion.div
246
+ initial={{ scale: 0, opacity: 0 }}
247
+ animate={{ scale: [0, 1.2, 1], opacity: [0, 0.2, 0] }}
248
+ transition={{ duration: 1 }}
249
+ className="absolute inset-0 pointer-events-none"
250
+ >
251
+ <div className="w-full h-full bg-green-500 rounded-xl" />
252
+ </motion.div>
253
+ )}
254
+ </div>
255
+ );
256
+ }