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,374 @@
1
+ /**
2
+ * ComparisonWindow - Displays before/after document processing changes
3
+ *
4
+ * This component shows a detailed comparison of what changed during
5
+ * document processing in a separate Electron window.
6
+ */
7
+
8
+ import React, { useState } from 'react';
9
+ import { motion, AnimatePresence } from 'framer-motion';
10
+ import {
11
+ FileText,
12
+ Link,
13
+ Type,
14
+ Palette,
15
+ Activity,
16
+ ChevronDown,
17
+ ChevronUp,
18
+ Clock,
19
+ CheckCircle,
20
+ AlertCircle,
21
+ X,
22
+ } from 'lucide-react';
23
+ import {
24
+ ProcessingComparison,
25
+ HyperlinkChange,
26
+ StyleChange,
27
+ } from '@/services/document/DocumentProcessingComparison';
28
+ import { cn } from '@/utils/cn';
29
+
30
+ interface ComparisonWindowProps {
31
+ comparison: ProcessingComparison;
32
+ onClose?: () => void;
33
+ }
34
+
35
+ export const ComparisonWindow: React.FC<ComparisonWindowProps> = ({ comparison, onClose }) => {
36
+ const [expandedSections, setExpandedSections] = useState<Set<string>>(new Set(['hyperlinks']));
37
+ const [filter, setFilter] = useState<'all' | 'urls' | 'texts' | 'styles'>('all');
38
+
39
+ // Toggle section expansion
40
+ const toggleSection = (section: string) => {
41
+ setExpandedSections((prev) => {
42
+ const next = new Set(prev);
43
+ if (next.has(section)) {
44
+ next.delete(section);
45
+ } else {
46
+ next.add(section);
47
+ }
48
+ return next;
49
+ });
50
+ };
51
+
52
+ // Calculate processing time
53
+ const processingTime = comparison.statistics.processingDurationMs;
54
+ const formattedTime =
55
+ processingTime < 1000
56
+ ? `${processingTime.toFixed(0)}ms`
57
+ : `${(processingTime / 1000).toFixed(2)}s`;
58
+
59
+ // Filter changes based on selected filter
60
+ const filteredHyperlinkChanges = comparison.hyperlinkChanges.filter((change) => {
61
+ if (filter === 'all') return true;
62
+ if (filter === 'urls') return change.originalUrl !== change.modifiedUrl;
63
+ if (filter === 'texts') return change.originalText !== change.modifiedText;
64
+ return false;
65
+ });
66
+
67
+ return (
68
+ <div className="min-h-screen bg-gray-50 dark:bg-gray-900">
69
+ {/* Header */}
70
+ <div className="sticky top-0 z-50 bg-white dark:bg-gray-800 border-b border-gray-200 dark:border-gray-700">
71
+ <div className="px-6 py-4">
72
+ <div className="flex items-center justify-between">
73
+ <div className="flex items-center gap-3">
74
+ <FileText className="w-6 h-6 text-blue-500" />
75
+ <div>
76
+ <h1 className="text-xl font-semibold text-gray-900 dark:text-white">
77
+ Document Processing Comparison
78
+ </h1>
79
+ <p className="text-sm text-gray-500 dark:text-gray-400">
80
+ {comparison.documentPath.split('/').pop()}
81
+ </p>
82
+ </div>
83
+ </div>
84
+ {onClose && (
85
+ <button
86
+ onClick={onClose}
87
+ className="p-2 hover:bg-gray-100 dark:hover:bg-gray-700 rounded-lg transition-colors"
88
+ aria-label="Close comparison window"
89
+ >
90
+ <X className="w-5 h-5 text-gray-500 dark:text-gray-400" />
91
+ </button>
92
+ )}
93
+ </div>
94
+
95
+ {/* Statistics Bar */}
96
+ <div className="grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-6 gap-3 mt-4">
97
+ <StatCard
98
+ icon={<Activity className="w-4 h-4" />}
99
+ label="Total Changes"
100
+ value={comparison.statistics.totalChanges}
101
+ color="blue"
102
+ />
103
+ <StatCard
104
+ icon={<Link className="w-4 h-4" />}
105
+ label="URLs Modified"
106
+ value={comparison.statistics.urlsChanged}
107
+ color="purple"
108
+ />
109
+ <StatCard
110
+ icon={<Type className="w-4 h-4" />}
111
+ label="Texts Updated"
112
+ value={comparison.statistics.displayTextsChanged}
113
+ color="green"
114
+ />
115
+ <StatCard
116
+ icon={<Palette className="w-4 h-4" />}
117
+ label="Styles Applied"
118
+ value={comparison.statistics.stylesApplied}
119
+ color="orange"
120
+ />
121
+ <StatCard
122
+ icon={<CheckCircle className="w-4 h-4" />}
123
+ label="Content IDs"
124
+ value={comparison.statistics.contentIdsAppended}
125
+ color="teal"
126
+ />
127
+ <StatCard
128
+ icon={<Clock className="w-4 h-4" />}
129
+ label="Processing Time"
130
+ value={formattedTime}
131
+ color="gray"
132
+ />
133
+ </div>
134
+
135
+ {/* Filter Tabs */}
136
+ <div className="flex gap-2 mt-4">
137
+ {(['all', 'urls', 'texts', 'styles'] as const).map((tab) => (
138
+ <button
139
+ key={tab}
140
+ onClick={() => setFilter(tab)}
141
+ className={cn(
142
+ 'px-4 py-2 rounded-lg text-sm font-medium transition-colors',
143
+ filter === tab
144
+ ? 'bg-blue-500 text-white'
145
+ : 'bg-gray-100 dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600'
146
+ )}
147
+ >
148
+ {tab.charAt(0).toUpperCase() + tab.slice(1)}
149
+ {tab === 'all' && ` (${comparison.statistics.totalChanges})`}
150
+ {tab === 'urls' && ` (${comparison.statistics.urlsChanged})`}
151
+ {tab === 'texts' && ` (${comparison.statistics.displayTextsChanged})`}
152
+ {tab === 'styles' && ` (${comparison.statistics.stylesApplied})`}
153
+ </button>
154
+ ))}
155
+ </div>
156
+ </div>
157
+ </div>
158
+
159
+ {/* Main Content */}
160
+ <div className="max-w-7xl mx-auto px-6 py-6">
161
+ {/* Hyperlink Changes Section */}
162
+ {(filter === 'all' || filter === 'urls' || filter === 'texts') &&
163
+ filteredHyperlinkChanges.length > 0 && (
164
+ <Section
165
+ title="Hyperlink Changes"
166
+ icon={<Link className="w-5 h-5" />}
167
+ count={filteredHyperlinkChanges.length}
168
+ expanded={expandedSections.has('hyperlinks')}
169
+ onToggle={() => toggleSection('hyperlinks')}
170
+ >
171
+ <div className="space-y-3">
172
+ {filteredHyperlinkChanges.map((change, index) => (
173
+ <HyperlinkChangeCard key={index} change={change} />
174
+ ))}
175
+ </div>
176
+ </Section>
177
+ )}
178
+
179
+ {/* Style Changes Section */}
180
+ {(filter === 'all' || filter === 'styles') && comparison.styleChanges.length > 0 && (
181
+ <Section
182
+ title="Style Changes"
183
+ icon={<Palette className="w-5 h-5" />}
184
+ count={comparison.styleChanges.length}
185
+ expanded={expandedSections.has('styles')}
186
+ onToggle={() => toggleSection('styles')}
187
+ >
188
+ <div className="space-y-3">
189
+ {comparison.styleChanges.map((change, index) => (
190
+ <StyleChangeCard key={index} change={change} />
191
+ ))}
192
+ </div>
193
+ </Section>
194
+ )}
195
+
196
+ {/* Empty State */}
197
+ {filteredHyperlinkChanges.length === 0 &&
198
+ (filter === 'styles' ? comparison.styleChanges.length === 0 : true) && (
199
+ <div className="text-center py-12">
200
+ <AlertCircle className="w-12 h-12 text-gray-400 mx-auto mb-4" />
201
+ <p className="text-gray-500 dark:text-gray-400">
202
+ No changes found for the selected filter
203
+ </p>
204
+ </div>
205
+ )}
206
+ </div>
207
+ </div>
208
+ );
209
+ };
210
+
211
+ // Stat Card Component
212
+ const StatCard: React.FC<{
213
+ icon: React.ReactNode;
214
+ label: string;
215
+ value: string | number;
216
+ color: 'blue' | 'purple' | 'green' | 'orange' | 'teal' | 'gray';
217
+ }> = ({ icon, label, value, color }) => {
218
+ const colorClasses = {
219
+ blue: 'bg-blue-50 dark:bg-blue-900/20 text-blue-600 dark:text-blue-400',
220
+ purple: 'bg-purple-50 dark:bg-purple-900/20 text-purple-600 dark:text-purple-400',
221
+ green: 'bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400',
222
+ orange: 'bg-orange-50 dark:bg-orange-900/20 text-orange-600 dark:text-orange-400',
223
+ teal: 'bg-teal-50 dark:bg-teal-900/20 text-teal-600 dark:text-teal-400',
224
+ gray: 'bg-gray-50 dark:bg-gray-900/20 text-gray-600 dark:text-gray-400',
225
+ };
226
+
227
+ return (
228
+ <div className={cn('p-3 rounded-lg', colorClasses[color])}>
229
+ <div className="flex items-center gap-2 mb-1">
230
+ {icon}
231
+ <span className="text-xs font-medium opacity-80">{label}</span>
232
+ </div>
233
+ <div className="text-xl font-bold">{value}</div>
234
+ </div>
235
+ );
236
+ };
237
+
238
+ // Section Component
239
+ const Section: React.FC<{
240
+ title: string;
241
+ icon: React.ReactNode;
242
+ count: number;
243
+ expanded: boolean;
244
+ onToggle: () => void;
245
+ children: React.ReactNode;
246
+ }> = ({ title, icon, count, expanded, onToggle, children }) => {
247
+ return (
248
+ <motion.div initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} className="mb-6">
249
+ <button
250
+ onClick={onToggle}
251
+ className="w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow"
252
+ >
253
+ <div className="px-6 py-4 flex items-center justify-between">
254
+ <div className="flex items-center gap-3">
255
+ {icon}
256
+ <h2 className="text-lg font-semibold text-gray-900 dark:text-white">{title}</h2>
257
+ <span className="px-2.5 py-1 bg-gray-100 dark:bg-gray-700 text-gray-600 dark:text-gray-300 text-sm rounded-full">
258
+ {count}
259
+ </span>
260
+ </div>
261
+ {expanded ? (
262
+ <ChevronUp className="w-5 h-5 text-gray-400" />
263
+ ) : (
264
+ <ChevronDown className="w-5 h-5 text-gray-400" />
265
+ )}
266
+ </div>
267
+ </button>
268
+
269
+ <AnimatePresence>
270
+ {expanded && (
271
+ <motion.div
272
+ initial={{ height: 0, opacity: 0 }}
273
+ animate={{ height: 'auto', opacity: 1 }}
274
+ exit={{ height: 0, opacity: 0 }}
275
+ transition={{ duration: 0.2 }}
276
+ className="overflow-hidden"
277
+ >
278
+ <div className="pt-4">{children}</div>
279
+ </motion.div>
280
+ )}
281
+ </AnimatePresence>
282
+ </motion.div>
283
+ );
284
+ };
285
+
286
+ // Hyperlink Change Card
287
+ const HyperlinkChangeCard: React.FC<{ change: HyperlinkChange }> = ({ change }) => {
288
+ const urlChanged = change.originalUrl !== change.modifiedUrl;
289
+ const textChanged = change.originalText !== change.modifiedText;
290
+
291
+ return (
292
+ <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
293
+ <div className="flex items-start justify-between mb-3">
294
+ <div className="text-sm text-gray-500 dark:text-gray-400">
295
+ Paragraph {change.paragraphIndex + 1}, Hyperlink {change.hyperlinkIndex + 1}
296
+ </div>
297
+ <div className="text-xs text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20 px-2 py-1 rounded">
298
+ {change.changeReason}
299
+ </div>
300
+ </div>
301
+
302
+ {urlChanged && (
303
+ <div className="mb-3">
304
+ <div className="text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
305
+ URL Changed:
306
+ </div>
307
+ <div className="space-y-1">
308
+ <div className="flex items-start gap-2">
309
+ <span className="text-red-500">−</span>
310
+ <code className="text-xs bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 p-1.5 rounded flex-1 break-all">
311
+ {change.originalUrl}
312
+ </code>
313
+ </div>
314
+ <div className="flex items-start gap-2">
315
+ <span className="text-green-500">+</span>
316
+ <code className="text-xs bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400 p-1.5 rounded flex-1 break-all">
317
+ {change.modifiedUrl}
318
+ </code>
319
+ </div>
320
+ </div>
321
+ </div>
322
+ )}
323
+
324
+ {textChanged && (
325
+ <div>
326
+ <div className="text-xs font-medium text-gray-600 dark:text-gray-400 mb-1">
327
+ Display Text Changed:
328
+ </div>
329
+ <div className="space-y-1">
330
+ <div className="flex items-start gap-2">
331
+ <span className="text-red-500">−</span>
332
+ <div className="text-sm bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 p-1.5 rounded flex-1">
333
+ {change.originalText}
334
+ </div>
335
+ </div>
336
+ <div className="flex items-start gap-2">
337
+ <span className="text-green-500">+</span>
338
+ <div className="text-sm bg-green-50 dark:bg-green-900/20 text-green-600 dark:text-green-400 p-1.5 rounded flex-1">
339
+ {change.modifiedText}
340
+ </div>
341
+ </div>
342
+ </div>
343
+ </div>
344
+ )}
345
+ </div>
346
+ );
347
+ };
348
+
349
+ // Style Change Card
350
+ const StyleChangeCard: React.FC<{ change: StyleChange }> = ({ change }) => {
351
+ return (
352
+ <div className="bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-700 p-4">
353
+ <div className="flex items-start justify-between mb-3">
354
+ <div className="text-sm text-gray-500 dark:text-gray-400">
355
+ Paragraph {change.paragraphIndex + 1}
356
+ </div>
357
+ <div className="text-xs text-purple-600 dark:text-purple-400 bg-purple-50 dark:bg-purple-900/20 px-2 py-1 rounded">
358
+ {change.styleName}
359
+ </div>
360
+ </div>
361
+
362
+ <div className="space-y-1">
363
+ {Object.entries(change.properties).map(([key, value]) => (
364
+ <div key={key} className="flex items-center gap-2 text-sm">
365
+ <span className="text-gray-500 dark:text-gray-400">{key}:</span>
366
+ <span className="text-gray-900 dark:text-white font-medium">{String(value)}</span>
367
+ </div>
368
+ ))}
369
+ </div>
370
+ </div>
371
+ );
372
+ };
373
+
374
+ export default ComparisonWindow;