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,153 @@
1
+ import * as React from 'react';
2
+ import * as Dialog from '@radix-ui/react-dialog';
3
+ import { Button } from './Button';
4
+ import { AlertCircle, X } from 'lucide-react';
5
+ import { cn } from '@/utils/cn';
6
+
7
+ export interface ErrorDetailsDialogProps {
8
+ open: boolean;
9
+ onOpenChange: (open: boolean) => void;
10
+ documentName: string;
11
+ errors: string[];
12
+ errorType?: 'file_locked' | 'api_timeout' | 'word_compatibility' | 'general';
13
+ processedAt?: Date;
14
+ }
15
+
16
+ export function ErrorDetailsDialog({
17
+ open,
18
+ onOpenChange,
19
+ documentName,
20
+ errors,
21
+ errorType,
22
+ processedAt,
23
+ }: ErrorDetailsDialogProps) {
24
+ return (
25
+ <Dialog.Root open={open} onOpenChange={onOpenChange}>
26
+ <Dialog.Portal>
27
+ <Dialog.Overlay className="fixed inset-0 bg-black/50 backdrop-blur-xs data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 z-50" />
28
+ <Dialog.Content
29
+ className={cn(
30
+ 'fixed left-[50%] top-[50%] z-50 translate-x-[-50%] translate-y-[-50%]',
31
+ 'w-full max-w-lg rounded-lg border border-border bg-card p-6 shadow-lg',
32
+ 'data-[state=open]:animate-in data-[state=closed]:animate-out',
33
+ 'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
34
+ 'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
35
+ 'data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]',
36
+ 'data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]'
37
+ )}
38
+ >
39
+ {/* Header */}
40
+ <div className="flex items-start justify-between mb-4">
41
+ <div className="flex items-center gap-2">
42
+ <AlertCircle className="w-5 h-5 text-red-500" />
43
+ <Dialog.Title className="text-lg font-semibold text-foreground">
44
+ Processing Error
45
+ </Dialog.Title>
46
+ </div>
47
+ <Dialog.Close className="rounded-xs opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
48
+ <X className="h-4 w-4" />
49
+ <span className="sr-only">Close</span>
50
+ </Dialog.Close>
51
+ </div>
52
+
53
+ {/* Document Info */}
54
+ <div className="mb-4">
55
+ <p className="font-medium text-foreground">{documentName}</p>
56
+ {processedAt && (
57
+ <p className="text-xs text-muted-foreground mt-1">
58
+ {new Date(processedAt).toLocaleString()}
59
+ </p>
60
+ )}
61
+ </div>
62
+
63
+ {/* Error Type Badge */}
64
+ <div className="mb-4">
65
+ {errorType === 'file_locked' ? (
66
+ <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900/30 dark:text-yellow-400">
67
+ File Locked
68
+ </span>
69
+ ) : errorType === 'api_timeout' ? (
70
+ <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-400">
71
+ API Timeout
72
+ </span>
73
+ ) : errorType === 'word_compatibility' ? (
74
+ <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400">
75
+ Compatibility Mode
76
+ </span>
77
+ ) : (
78
+ <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-400">
79
+ Error
80
+ </span>
81
+ )}
82
+ </div>
83
+
84
+ {/* Error Messages */}
85
+ <div className="mb-4">
86
+ <p className="text-sm font-medium text-foreground mb-2">Error Details:</p>
87
+ <div className="max-h-48 overflow-y-auto rounded-md bg-muted/50 p-3 space-y-2">
88
+ {errors.length > 0 ? (
89
+ errors.map((error, index) => (
90
+ <p key={index} className="text-sm text-red-600 dark:text-red-400">
91
+ {error}
92
+ </p>
93
+ ))
94
+ ) : (
95
+ <p className="text-sm text-muted-foreground">No error details available.</p>
96
+ )}
97
+ </div>
98
+ </div>
99
+
100
+ {/* Helpful Tip for File Locked */}
101
+ {errorType === 'file_locked' && (
102
+ <div className="mb-4 p-3 rounded-md bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800">
103
+ <p className="text-sm text-yellow-800 dark:text-yellow-200">
104
+ <strong>Tip:</strong> Please close the document in Microsoft Word and try processing again.
105
+ </p>
106
+ </div>
107
+ )}
108
+
109
+ {/* Helpful Tip for API Timeout */}
110
+ {errorType === 'api_timeout' && (
111
+ <div className="mb-4 p-3 rounded-md bg-orange-50 dark:bg-orange-900/20 border border-orange-200 dark:border-orange-800">
112
+ <p className="text-sm text-orange-800 dark:text-orange-200">
113
+ <strong>Tip:</strong> The Power Automate service timed out. Please wait a moment and try again.
114
+ </p>
115
+ </div>
116
+ )}
117
+
118
+ {/* Helpful Tip for Word Compatibility Mode */}
119
+ {errorType === 'word_compatibility' && (
120
+ <div className="mb-4 p-3 rounded-md bg-purple-50 dark:bg-purple-900/20 border border-purple-200 dark:border-purple-800">
121
+ <p className="text-sm text-purple-800 dark:text-purple-200 mb-2">
122
+ <strong>How to Convert Your Document:</strong>
123
+ </p>
124
+ <p className="text-sm text-purple-700 dark:text-purple-300 mb-2">
125
+ It appears the Word document you are trying to process was using outdated functions
126
+ from an old Word version. Please convert the file by following these steps:
127
+ </p>
128
+ <ol className="text-sm text-purple-700 dark:text-purple-300 list-decimal list-inside space-y-1">
129
+ <li>Open the document in Microsoft Word</li>
130
+ <li>Click on the word <strong>&quot;Compatibility&quot;</strong> in the Title Bar</li>
131
+ <li>Click <strong>&quot;Convert&quot;</strong></li>
132
+ <li>Save and close the document</li>
133
+ <li>Return here and click <strong>Retry</strong></li>
134
+ </ol>
135
+ <p className="text-xs text-purple-600 dark:text-purple-400 mt-3 italic">
136
+ Be cautious: Even Word&apos;s own conversion methods aren&apos;t always accurate, so some
137
+ odd formatting may occur as a result. Thoroughly compare the original to the
138
+ processed file to ensure everything aligns with our Documentation Standards.
139
+ </p>
140
+ </div>
141
+ )}
142
+
143
+ {/* Actions */}
144
+ <div className="flex justify-end">
145
+ <Button variant="outline" onClick={() => onOpenChange(false)}>
146
+ Close
147
+ </Button>
148
+ </div>
149
+ </Dialog.Content>
150
+ </Dialog.Portal>
151
+ </Dialog.Root>
152
+ );
153
+ }
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Error Fallback UI Component
3
+ *
4
+ * Displays when an error is caught by the ErrorBoundary.
5
+ * Provides error details and recovery options.
6
+ */
7
+
8
+ import React, { ErrorInfo } from 'react';
9
+ import { AlertTriangle, RefreshCw, Home, Bug } from 'lucide-react';
10
+ import { Button } from './Button';
11
+ import logger from '@/utils/logger';
12
+
13
+ interface ErrorFallbackProps {
14
+ error: Error | null;
15
+ errorInfo: ErrorInfo | null;
16
+ onReset?: () => void;
17
+ }
18
+
19
+ export function ErrorFallback({ error, errorInfo, onReset }: ErrorFallbackProps) {
20
+ const handleReload = () => {
21
+ window.location.reload();
22
+ };
23
+
24
+ const handleGoHome = () => {
25
+ // HASH ROUTER FIX: Use hash-based navigation for Electron app
26
+ // window.location.href = '/' doesn't work with createHashRouter
27
+ window.location.hash = '#/';
28
+ window.location.reload();
29
+ };
30
+
31
+ const handleReportBug = () => {
32
+ // In production, this could open a bug report dialog or navigate to a support page
33
+ const errorDetails = {
34
+ error: error?.toString(),
35
+ stack: error?.stack,
36
+ componentStack: errorInfo?.componentStack,
37
+ };
38
+
39
+ logger.debug('Bug Report Details:', errorDetails);
40
+ // You could integrate with your bug tracking system here
41
+ };
42
+
43
+ return (
44
+ <div className="flex min-h-screen items-center justify-center bg-background p-4">
45
+ <div className="w-full max-w-2xl rounded-lg border border-destructive/20 bg-card p-8 shadow-lg">
46
+ {/* Header */}
47
+ <div className="mb-6 flex items-start gap-4">
48
+ <div className="rounded-full bg-destructive/10 p-3">
49
+ <AlertTriangle className="h-8 w-8 text-destructive" />
50
+ </div>
51
+ <div className="flex-1">
52
+ <h1 className="text-2xl font-bold text-foreground">Oops! Something went wrong</h1>
53
+ <p className="mt-2 text-muted-foreground">
54
+ The application encountered an unexpected error. Don't worry, your data is safe.
55
+ </p>
56
+ </div>
57
+ </div>
58
+
59
+ {/* Error Details (collapsible) */}
60
+ {error && (
61
+ <details className="mb-6 rounded-md border border-border bg-muted/30 p-4">
62
+ <summary className="cursor-pointer font-medium text-foreground">Error Details</summary>
63
+ <div className="mt-3 space-y-2">
64
+ <div className="rounded bg-destructive/5 p-3">
65
+ <p className="text-sm font-mono text-destructive">{error.toString()}</p>
66
+ </div>
67
+ {error.stack && (
68
+ <div className="max-h-48 overflow-y-auto rounded bg-muted p-3">
69
+ <pre className="text-xs text-muted-foreground">{error.stack}</pre>
70
+ </div>
71
+ )}
72
+ {errorInfo?.componentStack && (
73
+ <div className="max-h-48 overflow-y-auto rounded bg-muted p-3">
74
+ <p className="mb-2 text-xs font-semibold text-foreground">Component Stack:</p>
75
+ <pre className="text-xs text-muted-foreground">{errorInfo.componentStack}</pre>
76
+ </div>
77
+ )}
78
+ </div>
79
+ </details>
80
+ )}
81
+
82
+ {/* Recovery Actions */}
83
+ <div className="space-y-3">
84
+ <p className="text-sm text-muted-foreground">What would you like to do?</p>
85
+
86
+ <div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
87
+ {onReset && (
88
+ <Button onClick={onReset} variant="outline" className="w-full">
89
+ <RefreshCw className="mr-2 h-4 w-4" />
90
+ Try Again
91
+ </Button>
92
+ )}
93
+
94
+ <Button onClick={handleReload} variant="default" className="w-full">
95
+ <RefreshCw className="mr-2 h-4 w-4" />
96
+ Reload Application
97
+ </Button>
98
+
99
+ <Button onClick={handleGoHome} variant="outline" className="w-full">
100
+ <Home className="mr-2 h-4 w-4" />
101
+ Go to Dashboard
102
+ </Button>
103
+
104
+ <Button onClick={handleReportBug} variant="outline" className="w-full">
105
+ <Bug className="mr-2 h-4 w-4" />
106
+ Report Issue
107
+ </Button>
108
+ </div>
109
+ </div>
110
+
111
+ {/* Additional Help */}
112
+ <div className="mt-6 rounded-md bg-muted/50 p-4">
113
+ <p className="text-sm text-muted-foreground">
114
+ <strong>Tip:</strong> If this error persists, try restarting the application or clearing
115
+ your browser cache. Your session data is automatically saved.
116
+ </p>
117
+ </div>
118
+ </div>
119
+ </div>
120
+ );
121
+ }
122
+
123
+ /**
124
+ * Context-specific Error Fallback
125
+ *
126
+ * A simplified error fallback for context provider errors.
127
+ * Shows which context failed and provides recovery options.
128
+ */
129
+ interface ContextErrorFallbackProps {
130
+ context: 'theme' | 'settings' | 'stats' | 'session';
131
+ error?: Error | null;
132
+ }
133
+
134
+ const contextInfo: Record<string, { name: string; description: string }> = {
135
+ theme: {
136
+ name: 'Theme System',
137
+ description: 'Unable to load theme settings. The application will use default styling.',
138
+ },
139
+ settings: {
140
+ name: 'User Settings',
141
+ description: 'Unable to load your preferences. Default settings will be used.',
142
+ },
143
+ stats: {
144
+ name: 'Statistics',
145
+ description: 'Unable to load statistics data. Your session data is still safe.',
146
+ },
147
+ session: {
148
+ name: 'Session Manager',
149
+ description: 'Unable to load session data. Please try reloading the application.',
150
+ },
151
+ };
152
+
153
+ export function ContextErrorFallback({ context, error }: ContextErrorFallbackProps) {
154
+ const info = contextInfo[context] || { name: 'Unknown', description: 'An error occurred.' };
155
+
156
+ const handleReload = () => {
157
+ window.location.reload();
158
+ };
159
+
160
+ const handleClearAndReload = () => {
161
+ // Clear potentially corrupted data for this context
162
+ if (context === 'theme') {
163
+ localStorage.removeItem('theme');
164
+ localStorage.removeItem('density');
165
+ localStorage.removeItem('accentColor');
166
+ } else if (context === 'settings') {
167
+ localStorage.removeItem('userSettings');
168
+ } else if (context === 'stats') {
169
+ // Stats are in IndexedDB, just reload
170
+ } else if (context === 'session') {
171
+ localStorage.removeItem('sessions-emergency-backup');
172
+ }
173
+ window.location.reload();
174
+ };
175
+
176
+ return (
177
+ <div className="flex min-h-screen items-center justify-center bg-gray-100 dark:bg-gray-900 p-4">
178
+ <div className="w-full max-w-md rounded-lg border border-red-200 dark:border-red-800 bg-white dark:bg-gray-800 p-6 shadow-lg">
179
+ <div className="flex items-center gap-3 mb-4">
180
+ <AlertTriangle className="h-6 w-6 text-red-500" />
181
+ <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
182
+ {info.name} Error
183
+ </h2>
184
+ </div>
185
+
186
+ <p className="text-sm text-gray-600 dark:text-gray-300 mb-4">{info.description}</p>
187
+
188
+ {error && (
189
+ <details className="mb-4 rounded border border-gray-200 dark:border-gray-700 p-2">
190
+ <summary className="cursor-pointer text-sm text-gray-500 dark:text-gray-400">
191
+ Technical Details
192
+ </summary>
193
+ <pre className="mt-2 text-xs text-red-600 dark:text-red-400 overflow-auto max-h-32">
194
+ {error.message}
195
+ </pre>
196
+ </details>
197
+ )}
198
+
199
+ <div className="flex gap-2">
200
+ <button
201
+ onClick={handleReload}
202
+ className="flex-1 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 text-sm font-medium"
203
+ >
204
+ Reload App
205
+ </button>
206
+ <button
207
+ onClick={handleClearAndReload}
208
+ className="flex-1 px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-200 rounded hover:bg-gray-300 dark:hover:bg-gray-600 text-sm font-medium"
209
+ >
210
+ Reset & Reload
211
+ </button>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ );
216
+ }
217
+
218
+ export default ErrorFallback;
@@ -0,0 +1,109 @@
1
+ import { forwardRef, useId, useState } from 'react';
2
+ import { cn } from '@/utils/cn';
3
+ import { Eye, EyeOff, Search, X } from 'lucide-react';
4
+
5
+ export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
6
+ label?: string;
7
+ error?: string;
8
+ helperText?: string;
9
+ leftIcon?: React.ReactNode;
10
+ rightIcon?: React.ReactNode;
11
+ onClear?: () => void;
12
+ }
13
+
14
+ const Input = forwardRef<HTMLInputElement, InputProps>(
15
+ (
16
+ { className, type = 'text', label, error, helperText, leftIcon, rightIcon, onClear, id, ...props },
17
+ ref
18
+ ) => {
19
+ const [showPassword, setShowPassword] = useState(false);
20
+ const generatedId = useId();
21
+ const inputId = id || generatedId;
22
+ const isPassword = type === 'password';
23
+ const isSearch = type === 'search';
24
+
25
+ return (
26
+ <div className="w-full">
27
+ {label && (
28
+ <label htmlFor={inputId} className="block text-sm font-medium text-foreground mb-1.5">
29
+ {label}
30
+ {props.required && <span className="text-destructive ml-1">*</span>}
31
+ </label>
32
+ )}
33
+
34
+ <div className="relative">
35
+ {leftIcon && (
36
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground">
37
+ {leftIcon}
38
+ </div>
39
+ )}
40
+
41
+ {isSearch && (
42
+ <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
43
+ )}
44
+
45
+ <input
46
+ id={inputId}
47
+ type={isPassword && showPassword ? 'text' : type}
48
+ className={cn(
49
+ 'flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm',
50
+ 'ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium',
51
+ 'placeholder:text-muted-foreground',
52
+ 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
53
+ 'disabled:cursor-not-allowed disabled:opacity-50',
54
+ 'transition-colors duration-200',
55
+ error && 'border-destructive focus-visible:ring-destructive',
56
+ (leftIcon || isSearch) && 'pl-10',
57
+ (rightIcon || isPassword || (onClear && props.value)) && 'pr-10',
58
+ className
59
+ )}
60
+ ref={ref}
61
+ {...props}
62
+ />
63
+
64
+ {isPassword && (
65
+ <button
66
+ type="button"
67
+ onClick={() => setShowPassword(!showPassword)}
68
+ className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
69
+ tabIndex={-1}
70
+ >
71
+ {showPassword ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
72
+ </button>
73
+ )}
74
+
75
+ {onClear && props.value && !isPassword && (
76
+ <button
77
+ type="button"
78
+ onClick={onClear}
79
+ className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground transition-colors"
80
+ tabIndex={-1}
81
+ >
82
+ <X className="w-4 h-4" />
83
+ </button>
84
+ )}
85
+
86
+ {rightIcon && !isPassword && !onClear && (
87
+ <div className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground">
88
+ {rightIcon}
89
+ </div>
90
+ )}
91
+ </div>
92
+
93
+ {error && (
94
+ <p className="mt-1.5 text-sm text-destructive" role="alert">
95
+ {error}
96
+ </p>
97
+ )}
98
+
99
+ {helperText && !error && (
100
+ <p className="mt-1.5 text-sm text-muted-foreground">{helperText}</p>
101
+ )}
102
+ </div>
103
+ );
104
+ }
105
+ );
106
+
107
+ Input.displayName = 'Input';
108
+
109
+ export { Input };
@@ -0,0 +1,184 @@
1
+ import { cn } from '@/utils/cn';
2
+
3
+ interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
4
+ variant?: 'default' | 'circle' | 'text' | 'card';
5
+ }
6
+
7
+ export function Skeleton({ className, variant = 'default', ...props }: SkeletonProps) {
8
+ const variants = {
9
+ default: '',
10
+ circle: 'rounded-full',
11
+ text: 'h-4 rounded',
12
+ card: 'h-32 rounded-lg',
13
+ };
14
+
15
+ return (
16
+ <div
17
+ className={cn('skeleton', 'bg-muted animate-pulse', variants[variant], className)}
18
+ {...props}
19
+ />
20
+ );
21
+ }
22
+
23
+ export function SkeletonCard() {
24
+ return (
25
+ <div className="rounded-lg border border-border p-6 space-y-4">
26
+ <div className="space-y-2">
27
+ <Skeleton variant="text" className="w-3/4" />
28
+ <Skeleton variant="text" className="w-1/2" />
29
+ </div>
30
+ <Skeleton className="h-20" />
31
+ <div className="flex gap-2">
32
+ <Skeleton className="h-9 w-20" />
33
+ <Skeleton className="h-9 w-20" />
34
+ </div>
35
+ </div>
36
+ );
37
+ }
38
+
39
+ export function SkeletonList({ count = 3 }: { count?: number }) {
40
+ return (
41
+ <div className="space-y-3">
42
+ {Array.from({ length: count }).map((_, i) => (
43
+ <div key={i} className="flex items-center gap-3">
44
+ <Skeleton variant="circle" className="w-10 h-10" />
45
+ <div className="space-y-2 flex-1">
46
+ <Skeleton variant="text" className="w-1/3" />
47
+ <Skeleton variant="text" className="w-2/3" />
48
+ </div>
49
+ </div>
50
+ ))}
51
+ </div>
52
+ );
53
+ }
54
+
55
+ // Document row skeleton for document lists
56
+ export function SkeletonDocumentRow() {
57
+ return (
58
+ <div className="flex items-center justify-between p-3 rounded-lg border border-border">
59
+ <div className="flex items-center gap-3">
60
+ <Skeleton className="w-8 h-8 rounded" />
61
+ <div className="space-y-1.5">
62
+ <Skeleton variant="text" className="w-40" />
63
+ <Skeleton variant="text" className="w-24 h-3" />
64
+ </div>
65
+ </div>
66
+ <div className="flex items-center gap-2">
67
+ <Skeleton className="w-16 h-6 rounded-full" />
68
+ <Skeleton className="w-8 h-8 rounded" />
69
+ </div>
70
+ </div>
71
+ );
72
+ }
73
+
74
+ // Session card skeleton
75
+ export function SkeletonSessionCard() {
76
+ return (
77
+ <div className="rounded-xl border border-border p-5 space-y-4">
78
+ <div className="flex items-start justify-between">
79
+ <div className="space-y-2 flex-1">
80
+ <Skeleton variant="text" className="w-2/3 h-5" />
81
+ <Skeleton variant="text" className="w-1/3 h-3" />
82
+ </div>
83
+ <Skeleton className="w-20 h-6 rounded-full" />
84
+ </div>
85
+ <div className="grid grid-cols-3 gap-3">
86
+ <Skeleton className="h-16 rounded-lg" />
87
+ <Skeleton className="h-16 rounded-lg" />
88
+ <Skeleton className="h-16 rounded-lg" />
89
+ </div>
90
+ <div className="flex gap-2">
91
+ <Skeleton className="h-9 flex-1 rounded-lg" />
92
+ <Skeleton className="h-9 w-9 rounded-lg" />
93
+ </div>
94
+ </div>
95
+ );
96
+ }
97
+
98
+ // Chart skeleton for analytics
99
+ export function SkeletonChart({ height = 200 }: { height?: number }) {
100
+ return (
101
+ <div className="rounded-xl border border-border p-5 space-y-4">
102
+ <div className="flex items-center justify-between">
103
+ <Skeleton variant="text" className="w-32 h-5" />
104
+ <Skeleton className="w-24 h-8 rounded-lg" />
105
+ </div>
106
+ <div
107
+ className="relative bg-muted/30 rounded-lg overflow-hidden"
108
+ style={{ height }}
109
+ >
110
+ {/* Fake bar chart skeleton */}
111
+ <div className="absolute bottom-0 left-0 right-0 flex items-end justify-around gap-2 p-4">
112
+ {[60, 80, 45, 90, 70, 55, 85].map((h, i) => (
113
+ <Skeleton
114
+ key={i}
115
+ className="flex-1 rounded-t"
116
+ style={{ height: `${h}%` }}
117
+ />
118
+ ))}
119
+ </div>
120
+ </div>
121
+ </div>
122
+ );
123
+ }
124
+
125
+ // Settings section skeleton
126
+ export function SkeletonSettingsSection() {
127
+ return (
128
+ <div className="space-y-4">
129
+ <div className="flex items-center gap-3 mb-6">
130
+ <Skeleton className="w-10 h-10 rounded-lg" />
131
+ <div className="space-y-1.5">
132
+ <Skeleton variant="text" className="w-32 h-5" />
133
+ <Skeleton variant="text" className="w-48 h-3" />
134
+ </div>
135
+ </div>
136
+ <div className="space-y-3">
137
+ {Array.from({ length: 4 }).map((_, i) => (
138
+ <div key={i} className="flex items-center justify-between py-3">
139
+ <div className="flex items-center gap-3">
140
+ <Skeleton className="w-8 h-8 rounded-lg" />
141
+ <div className="space-y-1.5">
142
+ <Skeleton variant="text" className="w-28" />
143
+ <Skeleton variant="text" className="w-40 h-3" />
144
+ </div>
145
+ </div>
146
+ <Skeleton className="w-10 h-5 rounded-full" />
147
+ </div>
148
+ ))}
149
+ </div>
150
+ </div>
151
+ );
152
+ }
153
+
154
+ // Table skeleton
155
+ export function SkeletonTable({ rows = 5, columns = 4 }: { rows?: number; columns?: number }) {
156
+ return (
157
+ <div className="rounded-lg border border-border overflow-hidden">
158
+ {/* Header */}
159
+ <div className="bg-muted/50 px-4 py-3 flex gap-4">
160
+ {Array.from({ length: columns }).map((_, i) => (
161
+ <Skeleton key={i} variant="text" className="flex-1 h-4" />
162
+ ))}
163
+ </div>
164
+ {/* Rows */}
165
+ <div className="divide-y divide-border">
166
+ {Array.from({ length: rows }).map((_, rowIndex) => (
167
+ <div key={rowIndex} className="px-4 py-3 flex gap-4 items-center">
168
+ {Array.from({ length: columns }).map((_, colIndex) => (
169
+ <Skeleton
170
+ key={colIndex}
171
+ variant="text"
172
+ className={cn(
173
+ 'flex-1',
174
+ colIndex === 0 && 'w-1/4',
175
+ colIndex === columns - 1 && 'w-20'
176
+ )}
177
+ />
178
+ ))}
179
+ </div>
180
+ ))}
181
+ </div>
182
+ </div>
183
+ );
184
+ }