@eka-care/medical-records-ui 1.0.28 → 1.0.32

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 (94) hide show
  1. package/dist/{DocumentViewer-NMFEAQUY.js → DocumentViewer-D7OJVVZM.js} +2 -2
  2. package/dist/{DocumentViewer-NMFEAQUY.js.map → DocumentViewer-D7OJVVZM.js.map} +1 -1
  3. package/dist/{DocumentViewer-JTKMSJ3V.mjs → DocumentViewer-OM6D4CSI.mjs} +2 -2
  4. package/dist/{DocumentViewer-JTKMSJ3V.mjs.map → DocumentViewer-OM6D4CSI.mjs.map} +1 -1
  5. package/dist/OriginalRecordPanel-A22BG3QL.js +504 -0
  6. package/dist/OriginalRecordPanel-A22BG3QL.js.map +1 -0
  7. package/dist/OriginalRecordPanel-LMKGQHTO.mjs +504 -0
  8. package/dist/OriginalRecordPanel-LMKGQHTO.mjs.map +1 -0
  9. package/dist/SmartUploadModal-3RRNSNWK.mjs +9 -0
  10. package/dist/SmartUploadModal-OD6BX2QW.js +9 -0
  11. package/dist/SmartUploadModal-OD6BX2QW.js.map +1 -0
  12. package/dist/VitalHistoryPanel-RR7PLR2G.mjs +10 -0
  13. package/dist/VitalHistoryPanel-RR7PLR2G.mjs.map +1 -0
  14. package/dist/VitalHistoryPanel-Z7ZB4W46.js +10 -0
  15. package/dist/VitalHistoryPanel-Z7ZB4W46.js.map +1 -0
  16. package/dist/{chunk-WZDXWCEU.js → chunk-4Y2ERGKG.js} +19 -55
  17. package/dist/chunk-4Y2ERGKG.js.map +1 -0
  18. package/dist/{SmartUploadModal-NMAUZ4QO.mjs → chunk-4YPFI2TD.mjs} +10 -16
  19. package/dist/chunk-4YPFI2TD.mjs.map +1 -0
  20. package/dist/chunk-AI54RJVT.mjs +490 -0
  21. package/dist/chunk-AI54RJVT.mjs.map +1 -0
  22. package/dist/chunk-AJ3HP2ZE.js +158 -0
  23. package/dist/chunk-AJ3HP2ZE.js.map +1 -0
  24. package/dist/chunk-DK66MUOK.mjs +158 -0
  25. package/dist/chunk-DK66MUOK.mjs.map +1 -0
  26. package/dist/chunk-INY7LTUM.js +490 -0
  27. package/dist/chunk-INY7LTUM.js.map +1 -0
  28. package/dist/chunk-JFLECNMK.js +2794 -0
  29. package/dist/chunk-JFLECNMK.js.map +1 -0
  30. package/dist/chunk-SXNVBIGI.mjs +2794 -0
  31. package/dist/chunk-SXNVBIGI.mjs.map +1 -0
  32. package/dist/{chunk-B2IT4PAR.mjs → chunk-TXH2CZMG.mjs} +17 -53
  33. package/dist/chunk-TXH2CZMG.mjs.map +1 -0
  34. package/dist/{SmartUploadModal-XLI6UAGJ.js → chunk-ZJUTZJMZ.js} +25 -31
  35. package/dist/chunk-ZJUTZJMZ.js.map +1 -0
  36. package/dist/index.css +2942 -3463
  37. package/dist/index.css.map +1 -1
  38. package/dist/index.d.mts +14 -103
  39. package/dist/index.d.ts +14 -103
  40. package/dist/index.js +1668 -6249
  41. package/dist/index.js.map +1 -1
  42. package/dist/index.mjs +1739 -6320
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/styles.css +2942 -3463
  45. package/dist/styles.css.map +1 -1
  46. package/dist/widgets-4ZOUXM33.js +43 -0
  47. package/dist/widgets-4ZOUXM33.js.map +1 -0
  48. package/dist/widgets-AXVBGZWJ.mjs +43 -0
  49. package/dist/widgets-AXVBGZWJ.mjs.map +1 -0
  50. package/package.json +5 -1
  51. package/dist/DeleteConfirmModal-6ACJAAPQ.mjs +0 -8
  52. package/dist/DeleteConfirmModal-S3PQB23U.js +0 -8
  53. package/dist/DeleteConfirmModal-S3PQB23U.js.map +0 -1
  54. package/dist/OriginalRecordPanel-F2XBYCYK.mjs +0 -84
  55. package/dist/OriginalRecordPanel-F2XBYCYK.mjs.map +0 -1
  56. package/dist/OriginalRecordPanel-S6P6CZ7T.js +0 -84
  57. package/dist/OriginalRecordPanel-S6P6CZ7T.js.map +0 -1
  58. package/dist/SidebarSelectPanel-43VXOOJI.js +0 -155
  59. package/dist/SidebarSelectPanel-43VXOOJI.js.map +0 -1
  60. package/dist/SidebarSelectPanel-UH7ESKRL.mjs +0 -155
  61. package/dist/SidebarSelectPanel-UH7ESKRL.mjs.map +0 -1
  62. package/dist/SmartUploadModal-NMAUZ4QO.mjs.map +0 -1
  63. package/dist/SmartUploadModal-XLI6UAGJ.js.map +0 -1
  64. package/dist/VitalHistoryPanel-NWZ5FW3O.mjs +0 -332
  65. package/dist/VitalHistoryPanel-NWZ5FW3O.mjs.map +0 -1
  66. package/dist/VitalHistoryPanel-TBSJHHZD.js +0 -332
  67. package/dist/VitalHistoryPanel-TBSJHHZD.js.map +0 -1
  68. package/dist/chunk-3OOMRNC7.mjs +0 -44
  69. package/dist/chunk-3OOMRNC7.mjs.map +0 -1
  70. package/dist/chunk-4WP3ODNC.mjs +0 -115
  71. package/dist/chunk-4WP3ODNC.mjs.map +0 -1
  72. package/dist/chunk-76KQYC25.mjs +0 -556
  73. package/dist/chunk-76KQYC25.mjs.map +0 -1
  74. package/dist/chunk-774IDII7.js +0 -44
  75. package/dist/chunk-774IDII7.js.map +0 -1
  76. package/dist/chunk-7SDNFBY6.js +0 -27
  77. package/dist/chunk-7SDNFBY6.js.map +0 -1
  78. package/dist/chunk-B2IT4PAR.mjs.map +0 -1
  79. package/dist/chunk-CY7UDRH4.mjs +0 -27
  80. package/dist/chunk-CY7UDRH4.mjs.map +0 -1
  81. package/dist/chunk-GDFENXWT.mjs +0 -17
  82. package/dist/chunk-GDFENXWT.mjs.map +0 -1
  83. package/dist/chunk-KT35Z3A3.js +0 -80
  84. package/dist/chunk-KT35Z3A3.js.map +0 -1
  85. package/dist/chunk-NDOJKAQS.js +0 -556
  86. package/dist/chunk-NDOJKAQS.js.map +0 -1
  87. package/dist/chunk-P6HKALWC.mjs +0 -80
  88. package/dist/chunk-P6HKALWC.mjs.map +0 -1
  89. package/dist/chunk-VWIMLKZP.js +0 -115
  90. package/dist/chunk-VWIMLKZP.js.map +0 -1
  91. package/dist/chunk-WU4E4CWK.js +0 -17
  92. package/dist/chunk-WU4E4CWK.js.map +0 -1
  93. package/dist/chunk-WZDXWCEU.js.map +0 -1
  94. /package/dist/{DeleteConfirmModal-6ACJAAPQ.mjs.map → SmartUploadModal-3RRNSNWK.mjs.map} +0 -0
@@ -44,7 +44,7 @@ function TextViewer({ url }) {
44
44
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "Couldn't load this document." });
45
45
  }
46
46
  if (!state.text.trim()) {
47
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "This file appears to be empty." });
47
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "This record appears to be empty." });
48
48
  }
49
49
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
50
50
  "iframe",
@@ -195,4 +195,4 @@ function DocumentViewer({ files, title, isHtml }) {
195
195
 
196
196
 
197
197
  exports.DocumentViewer = DocumentViewer;
198
- //# sourceMappingURL=DocumentViewer-NMFEAQUY.js.map
198
+ //# sourceMappingURL=DocumentViewer-D7OJVVZM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/DocumentViewer-NMFEAQUY.js","../src/views/RecordPreview/DocumentViewer.tsx","../src/views/RecordPreview/TextViewer.tsx"],"names":["jsx"],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/DocumentViewer-NMFEAQUY.js","sourcesContent":[null,"import { lazy, Suspense, useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ChevronLeft,\n ChevronRight,\n Minus,\n Plus,\n Download,\n Maximize,\n Minimize,\n Globe,\n} from 'lucide-react';\nimport { TextViewer } from './TextViewer';\nimport type { PreviewFile } from '../../connection';\n\nconst PdfViewer = lazy(() => import('./PdfViewer').then((m) => ({ default: m.PdfViewer })));\n\nexport interface DocumentViewerProps {\n files: PreviewFile[];\n title: string;\n isHtml?: boolean;\n}\n\nconst PAGE_WIDTH = 595; \nconst ZOOM_STEP = 0.25;\nconst ZOOM_MIN = 0.5;\nconst ZOOM_MAX = 3;\n\nexport function DocumentViewer({ files, title, isHtml }: DocumentViewerProps) {\n const [zoom, setZoom] = useState(1);\n const [pageInfo, setPageInfo] = useState({ current: 1, total: 0 });\n const [scrollToPage, setScrollToPage] = useState(1);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const onChange = () => setIsFullscreen(document.fullscreenElement === rootRef.current);\n document.addEventListener('fullscreenchange', onChange);\n return () => document.removeEventListener('fullscreenchange', onChange);\n }, []);\n\n const toggleFullscreen = () => {\n if (document.fullscreenElement) void document.exitFullscreen();\n else void rootRef.current?.requestFullscreen?.();\n };\n\n const primary = files[0] ?? null;\n const isPdf = primary?.kind === 'pdf';\n const images = files.filter((f) => f.kind === 'image');\n const isZoomable = isPdf || images.length > 0;\n\n const zoomOut = () => setZoom((z) => Math.max(ZOOM_MIN, +(z - ZOOM_STEP).toFixed(2)));\n const zoomIn = () => setZoom((z) => Math.min(ZOOM_MAX, +(z + ZOOM_STEP).toFixed(2)));\n\n const prevPage = () => setScrollToPage(Math.max(1, pageInfo.current - 1));\n const nextPage = () => setScrollToPage(Math.min(pageInfo.total, pageInfo.current + 1));\n\n // Download / print fetch the file into a blob URL rather than re-opening the\n // signed URL directly, so it works even when the document is already loaded.\n const withBlobUrl = useCallback(async (fn: (objUrl: string) => void) => {\n if (!primary) return;\n try {\n const res = await fetch(primary.url);\n const blob = await res.blob();\n const objUrl = URL.createObjectURL(blob);\n fn(objUrl);\n // Revoke after the consumer has had a chance to use it.\n setTimeout(() => URL.revokeObjectURL(objUrl), 120_000);\n } catch {\n // Fall back to opening the original URL.\n fn(primary.url);\n }\n }, [primary]);\n\n const handleDownload = () =>\n withBlobUrl((objUrl) => {\n const a = document.createElement('a');\n a.href = objUrl;\n a.download = title || 'document';\n a.click();\n });\n\n return (\n <div className={`mr-doc-viewer${isHtml ? ' mr-doc-viewer--html' : ''}`} ref={rootRef}>\n {!isHtml && <div className=\"mr-doc-viewer__toolbar\">\n <span className=\"mr-doc-viewer__filename\">{title}</span>\n {isPdf && (\n <div className=\"mr-doc-viewer__pages\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n onClick={prevPage}\n disabled={pageInfo.current <= 1}\n >\n <ChevronLeft size={18} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__page-badge\">{pageInfo.current}</span>\n <span>/</span>\n <span>{pageInfo.total || '—'}</span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n onClick={nextPage}\n disabled={pageInfo.current >= pageInfo.total}\n >\n <ChevronRight size={18} aria-hidden />\n </button>\n </div>\n )}\n {isZoomable && (\n <div className=\"mr-doc-viewer__zoom\">\n <button type=\"button\" aria-label=\"Zoom out\" onClick={zoomOut} disabled={zoom <= ZOOM_MIN}>\n <Minus size={20} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__zoom-badge\">{Math.round(zoom * 100)}%</span>\n <button type=\"button\" aria-label=\"Zoom in\" onClick={zoomIn} disabled={zoom >= ZOOM_MAX}>\n <Plus size={20} aria-hidden />\n </button>\n </div>\n )}\n <div className=\"mr-doc-viewer__actions\">\n <button type=\"button\" aria-label=\"Download\" onClick={handleDownload} disabled={!primary}>\n <Download size={20} aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label={isFullscreen ? 'Exit full screen' : 'Full screen'}\n onClick={toggleFullscreen}\n >\n {isFullscreen ? <Minimize size={20} aria-hidden /> : <Maximize size={20} aria-hidden />}\n </button>\n </div>\n </div>}\n\n {isHtml && (\n <div className=\"mr-doc-viewer__html-bar\">\n <div className=\"mr-doc-viewer__html-bar-left\">\n <Globe size={12} aria-hidden />\n <span>Previewing HTML file – you can copy to a note and edit this file. The original record that you are viewing now will not be affected.</span>\n </div>\n <button\n type=\"button\"\n className=\"mr-doc-viewer__html-download\"\n aria-label=\"Download\"\n onClick={handleDownload}\n disabled={!primary}\n >\n <Download size={16} aria-hidden />\n </button>\n </div>\n )}\n\n <div className=\"mr-doc-viewer__canvas\">\n {!primary ? (\n <div className=\"mr-doc-viewer__status\">No preview available for this record.</div>\n ) : isPdf ? (\n <Suspense fallback={<div className=\"mr-doc-viewer__status\">Loading viewer…</div>}>\n <PdfViewer\n url={primary.url}\n baseWidth={PAGE_WIDTH}\n scale={zoom}\n scrollToPage={scrollToPage}\n onPageInfo={setPageInfo}\n />\n </Suspense>\n ) : images.length > 0 ? (\n images.map((img, i) => (\n <img\n key={i}\n className=\"mr-doc-viewer__image\"\n src={img.url}\n alt={`${title} ${i + 1}`}\n style={{ transform: `scale(${zoom})`, transformOrigin: 'top center' }}\n />\n ))\n ) : (\n <TextViewer url={primary.url} />\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\nexport interface TextViewerProps {\n url: string;\n}\n\nexport function TextViewer({ url }: TextViewerProps) {\n const [state, setState] = useState<{ status: 'loading' | 'loaded' | 'error'; text: string }>({\n status: 'loading',\n text: '',\n });\n\n useEffect(() => {\n let cancelled = false;\n setState({ status: 'loading', text: '' });\n (async () => {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`fetch ${res.status}`);\n const text = await res.text();\n if (text.trimStart().startsWith('%PDF')) throw new Error('binary');\n if (!cancelled) setState({ status: 'loaded', text });\n } catch {\n if (!cancelled) setState({ status: 'error', text: '' });\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [url]);\n\n if (state.status === 'loading') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Loading document...</div>;\n }\n if (state.status === 'error') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Couldn't load this document.</div>;\n }\n if (!state.text.trim()) {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>This file appears to be empty.</div>;\n }\n return (\n <iframe\n className=\"mr-doc-viewer__html-frame\"\n srcDoc={state.text}\n sandbox=\"allow-same-origin\"\n title=\"HTML preview\"\n />\n );\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/medical-records-ui/medical-records-ui/dist/DocumentViewer-D7OJVVZM.js","../src/views/RecordPreview/DocumentViewer.tsx","../src/views/RecordPreview/TextViewer.tsx"],"names":["jsx"],"mappings":"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","file":"/home/runner/work/medical-records-ui/medical-records-ui/dist/DocumentViewer-D7OJVVZM.js","sourcesContent":[null,"import { lazy, Suspense, useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ChevronLeft,\n ChevronRight,\n Minus,\n Plus,\n Download,\n Maximize,\n Minimize,\n Globe,\n} from 'lucide-react';\nimport { TextViewer } from './TextViewer';\nimport type { PreviewFile } from '../../connection';\n\nconst PdfViewer = lazy(() => import('./PdfViewer').then((m) => ({ default: m.PdfViewer })));\n\nexport interface DocumentViewerProps {\n files: PreviewFile[];\n title: string;\n isHtml?: boolean;\n}\n\nconst PAGE_WIDTH = 595; \nconst ZOOM_STEP = 0.25;\nconst ZOOM_MIN = 0.5;\nconst ZOOM_MAX = 3;\n\nexport function DocumentViewer({ files, title, isHtml }: DocumentViewerProps) {\n const [zoom, setZoom] = useState(1);\n const [pageInfo, setPageInfo] = useState({ current: 1, total: 0 });\n const [scrollToPage, setScrollToPage] = useState(1);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const onChange = () => setIsFullscreen(document.fullscreenElement === rootRef.current);\n document.addEventListener('fullscreenchange', onChange);\n return () => document.removeEventListener('fullscreenchange', onChange);\n }, []);\n\n const toggleFullscreen = () => {\n if (document.fullscreenElement) void document.exitFullscreen();\n else void rootRef.current?.requestFullscreen?.();\n };\n\n const primary = files[0] ?? null;\n const isPdf = primary?.kind === 'pdf';\n const images = files.filter((f) => f.kind === 'image');\n const isZoomable = isPdf || images.length > 0;\n\n const zoomOut = () => setZoom((z) => Math.max(ZOOM_MIN, +(z - ZOOM_STEP).toFixed(2)));\n const zoomIn = () => setZoom((z) => Math.min(ZOOM_MAX, +(z + ZOOM_STEP).toFixed(2)));\n\n const prevPage = () => setScrollToPage(Math.max(1, pageInfo.current - 1));\n const nextPage = () => setScrollToPage(Math.min(pageInfo.total, pageInfo.current + 1));\n\n // Download / print fetch the file into a blob URL rather than re-opening the\n // signed URL directly, so it works even when the document is already loaded.\n const withBlobUrl = useCallback(async (fn: (objUrl: string) => void) => {\n if (!primary) return;\n try {\n const res = await fetch(primary.url);\n const blob = await res.blob();\n const objUrl = URL.createObjectURL(blob);\n fn(objUrl);\n // Revoke after the consumer has had a chance to use it.\n setTimeout(() => URL.revokeObjectURL(objUrl), 120_000);\n } catch {\n // Fall back to opening the original URL.\n fn(primary.url);\n }\n }, [primary]);\n\n const handleDownload = () =>\n withBlobUrl((objUrl) => {\n const a = document.createElement('a');\n a.href = objUrl;\n a.download = title || 'document';\n a.click();\n });\n\n return (\n <div className={`mr-doc-viewer${isHtml ? ' mr-doc-viewer--html' : ''}`} ref={rootRef}>\n {!isHtml && <div className=\"mr-doc-viewer__toolbar\">\n <span className=\"mr-doc-viewer__filename\">{title}</span>\n {isPdf && (\n <div className=\"mr-doc-viewer__pages\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n onClick={prevPage}\n disabled={pageInfo.current <= 1}\n >\n <ChevronLeft size={18} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__page-badge\">{pageInfo.current}</span>\n <span>/</span>\n <span>{pageInfo.total || '—'}</span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n onClick={nextPage}\n disabled={pageInfo.current >= pageInfo.total}\n >\n <ChevronRight size={18} aria-hidden />\n </button>\n </div>\n )}\n {isZoomable && (\n <div className=\"mr-doc-viewer__zoom\">\n <button type=\"button\" aria-label=\"Zoom out\" onClick={zoomOut} disabled={zoom <= ZOOM_MIN}>\n <Minus size={20} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__zoom-badge\">{Math.round(zoom * 100)}%</span>\n <button type=\"button\" aria-label=\"Zoom in\" onClick={zoomIn} disabled={zoom >= ZOOM_MAX}>\n <Plus size={20} aria-hidden />\n </button>\n </div>\n )}\n <div className=\"mr-doc-viewer__actions\">\n <button type=\"button\" aria-label=\"Download\" onClick={handleDownload} disabled={!primary}>\n <Download size={20} aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label={isFullscreen ? 'Exit full screen' : 'Full screen'}\n onClick={toggleFullscreen}\n >\n {isFullscreen ? <Minimize size={20} aria-hidden /> : <Maximize size={20} aria-hidden />}\n </button>\n </div>\n </div>}\n\n {isHtml && (\n <div className=\"mr-doc-viewer__html-bar\">\n <div className=\"mr-doc-viewer__html-bar-left\">\n <Globe size={12} aria-hidden />\n <span>Previewing HTML file – you can copy to a note and edit this file. The original record that you are viewing now will not be affected.</span>\n </div>\n <button\n type=\"button\"\n className=\"mr-doc-viewer__html-download\"\n aria-label=\"Download\"\n onClick={handleDownload}\n disabled={!primary}\n >\n <Download size={16} aria-hidden />\n </button>\n </div>\n )}\n\n <div className=\"mr-doc-viewer__canvas\">\n {!primary ? (\n <div className=\"mr-doc-viewer__status\">No preview available for this record.</div>\n ) : isPdf ? (\n <Suspense fallback={<div className=\"mr-doc-viewer__status\">Loading viewer…</div>}>\n <PdfViewer\n url={primary.url}\n baseWidth={PAGE_WIDTH}\n scale={zoom}\n scrollToPage={scrollToPage}\n onPageInfo={setPageInfo}\n />\n </Suspense>\n ) : images.length > 0 ? (\n images.map((img, i) => (\n <img\n key={i}\n className=\"mr-doc-viewer__image\"\n src={img.url}\n alt={`${title} ${i + 1}`}\n style={{ transform: `scale(${zoom})`, transformOrigin: 'top center' }}\n />\n ))\n ) : (\n <TextViewer url={primary.url} />\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\nexport interface TextViewerProps {\n url: string;\n}\n\nexport function TextViewer({ url }: TextViewerProps) {\n const [state, setState] = useState<{ status: 'loading' | 'loaded' | 'error'; text: string }>({\n status: 'loading',\n text: '',\n });\n\n useEffect(() => {\n let cancelled = false;\n setState({ status: 'loading', text: '' });\n (async () => {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`fetch ${res.status}`);\n const text = await res.text();\n if (text.trimStart().startsWith('%PDF')) throw new Error('binary');\n if (!cancelled) setState({ status: 'loaded', text });\n } catch {\n if (!cancelled) setState({ status: 'error', text: '' });\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [url]);\n\n if (state.status === 'loading') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Loading document...</div>;\n }\n if (state.status === 'error') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Couldn't load this document.</div>;\n }\n if (!state.text.trim()) {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>This record appears to be empty.</div>;\n }\n return (\n <iframe\n className=\"mr-doc-viewer__html-frame\"\n srcDoc={state.text}\n sandbox=\"allow-same-origin\"\n title=\"HTML preview\"\n />\n );\n}\n"]}
@@ -44,7 +44,7 @@ function TextViewer({ url }) {
44
44
  return /* @__PURE__ */ jsx("div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "Couldn't load this document." });
45
45
  }
46
46
  if (!state.text.trim()) {
47
- return /* @__PURE__ */ jsx("div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "This file appears to be empty." });
47
+ return /* @__PURE__ */ jsx("div", { className: "mr-doc-viewer__status", style: { color: "var(--mr-muted-foreground)" }, children: "This record appears to be empty." });
48
48
  }
49
49
  return /* @__PURE__ */ jsx(
50
50
  "iframe",
@@ -195,4 +195,4 @@ function DocumentViewer({ files, title, isHtml }) {
195
195
  export {
196
196
  DocumentViewer
197
197
  };
198
- //# sourceMappingURL=DocumentViewer-JTKMSJ3V.mjs.map
198
+ //# sourceMappingURL=DocumentViewer-OM6D4CSI.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/views/RecordPreview/DocumentViewer.tsx","../src/views/RecordPreview/TextViewer.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ChevronLeft,\n ChevronRight,\n Minus,\n Plus,\n Download,\n Maximize,\n Minimize,\n Globe,\n} from 'lucide-react';\nimport { TextViewer } from './TextViewer';\nimport type { PreviewFile } from '../../connection';\n\nconst PdfViewer = lazy(() => import('./PdfViewer').then((m) => ({ default: m.PdfViewer })));\n\nexport interface DocumentViewerProps {\n files: PreviewFile[];\n title: string;\n isHtml?: boolean;\n}\n\nconst PAGE_WIDTH = 595; \nconst ZOOM_STEP = 0.25;\nconst ZOOM_MIN = 0.5;\nconst ZOOM_MAX = 3;\n\nexport function DocumentViewer({ files, title, isHtml }: DocumentViewerProps) {\n const [zoom, setZoom] = useState(1);\n const [pageInfo, setPageInfo] = useState({ current: 1, total: 0 });\n const [scrollToPage, setScrollToPage] = useState(1);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const onChange = () => setIsFullscreen(document.fullscreenElement === rootRef.current);\n document.addEventListener('fullscreenchange', onChange);\n return () => document.removeEventListener('fullscreenchange', onChange);\n }, []);\n\n const toggleFullscreen = () => {\n if (document.fullscreenElement) void document.exitFullscreen();\n else void rootRef.current?.requestFullscreen?.();\n };\n\n const primary = files[0] ?? null;\n const isPdf = primary?.kind === 'pdf';\n const images = files.filter((f) => f.kind === 'image');\n const isZoomable = isPdf || images.length > 0;\n\n const zoomOut = () => setZoom((z) => Math.max(ZOOM_MIN, +(z - ZOOM_STEP).toFixed(2)));\n const zoomIn = () => setZoom((z) => Math.min(ZOOM_MAX, +(z + ZOOM_STEP).toFixed(2)));\n\n const prevPage = () => setScrollToPage(Math.max(1, pageInfo.current - 1));\n const nextPage = () => setScrollToPage(Math.min(pageInfo.total, pageInfo.current + 1));\n\n // Download / print fetch the file into a blob URL rather than re-opening the\n // signed URL directly, so it works even when the document is already loaded.\n const withBlobUrl = useCallback(async (fn: (objUrl: string) => void) => {\n if (!primary) return;\n try {\n const res = await fetch(primary.url);\n const blob = await res.blob();\n const objUrl = URL.createObjectURL(blob);\n fn(objUrl);\n // Revoke after the consumer has had a chance to use it.\n setTimeout(() => URL.revokeObjectURL(objUrl), 120_000);\n } catch {\n // Fall back to opening the original URL.\n fn(primary.url);\n }\n }, [primary]);\n\n const handleDownload = () =>\n withBlobUrl((objUrl) => {\n const a = document.createElement('a');\n a.href = objUrl;\n a.download = title || 'document';\n a.click();\n });\n\n return (\n <div className={`mr-doc-viewer${isHtml ? ' mr-doc-viewer--html' : ''}`} ref={rootRef}>\n {!isHtml && <div className=\"mr-doc-viewer__toolbar\">\n <span className=\"mr-doc-viewer__filename\">{title}</span>\n {isPdf && (\n <div className=\"mr-doc-viewer__pages\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n onClick={prevPage}\n disabled={pageInfo.current <= 1}\n >\n <ChevronLeft size={18} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__page-badge\">{pageInfo.current}</span>\n <span>/</span>\n <span>{pageInfo.total || '—'}</span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n onClick={nextPage}\n disabled={pageInfo.current >= pageInfo.total}\n >\n <ChevronRight size={18} aria-hidden />\n </button>\n </div>\n )}\n {isZoomable && (\n <div className=\"mr-doc-viewer__zoom\">\n <button type=\"button\" aria-label=\"Zoom out\" onClick={zoomOut} disabled={zoom <= ZOOM_MIN}>\n <Minus size={20} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__zoom-badge\">{Math.round(zoom * 100)}%</span>\n <button type=\"button\" aria-label=\"Zoom in\" onClick={zoomIn} disabled={zoom >= ZOOM_MAX}>\n <Plus size={20} aria-hidden />\n </button>\n </div>\n )}\n <div className=\"mr-doc-viewer__actions\">\n <button type=\"button\" aria-label=\"Download\" onClick={handleDownload} disabled={!primary}>\n <Download size={20} aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label={isFullscreen ? 'Exit full screen' : 'Full screen'}\n onClick={toggleFullscreen}\n >\n {isFullscreen ? <Minimize size={20} aria-hidden /> : <Maximize size={20} aria-hidden />}\n </button>\n </div>\n </div>}\n\n {isHtml && (\n <div className=\"mr-doc-viewer__html-bar\">\n <div className=\"mr-doc-viewer__html-bar-left\">\n <Globe size={12} aria-hidden />\n <span>Previewing HTML file – you can copy to a note and edit this file. The original record that you are viewing now will not be affected.</span>\n </div>\n <button\n type=\"button\"\n className=\"mr-doc-viewer__html-download\"\n aria-label=\"Download\"\n onClick={handleDownload}\n disabled={!primary}\n >\n <Download size={16} aria-hidden />\n </button>\n </div>\n )}\n\n <div className=\"mr-doc-viewer__canvas\">\n {!primary ? (\n <div className=\"mr-doc-viewer__status\">No preview available for this record.</div>\n ) : isPdf ? (\n <Suspense fallback={<div className=\"mr-doc-viewer__status\">Loading viewer…</div>}>\n <PdfViewer\n url={primary.url}\n baseWidth={PAGE_WIDTH}\n scale={zoom}\n scrollToPage={scrollToPage}\n onPageInfo={setPageInfo}\n />\n </Suspense>\n ) : images.length > 0 ? (\n images.map((img, i) => (\n <img\n key={i}\n className=\"mr-doc-viewer__image\"\n src={img.url}\n alt={`${title} ${i + 1}`}\n style={{ transform: `scale(${zoom})`, transformOrigin: 'top center' }}\n />\n ))\n ) : (\n <TextViewer url={primary.url} />\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\nexport interface TextViewerProps {\n url: string;\n}\n\nexport function TextViewer({ url }: TextViewerProps) {\n const [state, setState] = useState<{ status: 'loading' | 'loaded' | 'error'; text: string }>({\n status: 'loading',\n text: '',\n });\n\n useEffect(() => {\n let cancelled = false;\n setState({ status: 'loading', text: '' });\n (async () => {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`fetch ${res.status}`);\n const text = await res.text();\n if (text.trimStart().startsWith('%PDF')) throw new Error('binary');\n if (!cancelled) setState({ status: 'loaded', text });\n } catch {\n if (!cancelled) setState({ status: 'error', text: '' });\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [url]);\n\n if (state.status === 'loading') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Loading document...</div>;\n }\n if (state.status === 'error') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Couldn't load this document.</div>;\n }\n if (!state.text.trim()) {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>This file appears to be empty.</div>;\n }\n return (\n <iframe\n className=\"mr-doc-viewer__html-frame\"\n srcDoc={state.text}\n sandbox=\"allow-same-origin\"\n title=\"HTML preview\"\n />\n );\n}\n"],"mappings":"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","names":["useEffect","useState","jsx","useState","useEffect"]}
1
+ {"version":3,"sources":["../src/views/RecordPreview/DocumentViewer.tsx","../src/views/RecordPreview/TextViewer.tsx"],"sourcesContent":["import { lazy, Suspense, useCallback, useEffect, useRef, useState } from 'react';\nimport {\n ChevronLeft,\n ChevronRight,\n Minus,\n Plus,\n Download,\n Maximize,\n Minimize,\n Globe,\n} from 'lucide-react';\nimport { TextViewer } from './TextViewer';\nimport type { PreviewFile } from '../../connection';\n\nconst PdfViewer = lazy(() => import('./PdfViewer').then((m) => ({ default: m.PdfViewer })));\n\nexport interface DocumentViewerProps {\n files: PreviewFile[];\n title: string;\n isHtml?: boolean;\n}\n\nconst PAGE_WIDTH = 595; \nconst ZOOM_STEP = 0.25;\nconst ZOOM_MIN = 0.5;\nconst ZOOM_MAX = 3;\n\nexport function DocumentViewer({ files, title, isHtml }: DocumentViewerProps) {\n const [zoom, setZoom] = useState(1);\n const [pageInfo, setPageInfo] = useState({ current: 1, total: 0 });\n const [scrollToPage, setScrollToPage] = useState(1);\n const [isFullscreen, setIsFullscreen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const onChange = () => setIsFullscreen(document.fullscreenElement === rootRef.current);\n document.addEventListener('fullscreenchange', onChange);\n return () => document.removeEventListener('fullscreenchange', onChange);\n }, []);\n\n const toggleFullscreen = () => {\n if (document.fullscreenElement) void document.exitFullscreen();\n else void rootRef.current?.requestFullscreen?.();\n };\n\n const primary = files[0] ?? null;\n const isPdf = primary?.kind === 'pdf';\n const images = files.filter((f) => f.kind === 'image');\n const isZoomable = isPdf || images.length > 0;\n\n const zoomOut = () => setZoom((z) => Math.max(ZOOM_MIN, +(z - ZOOM_STEP).toFixed(2)));\n const zoomIn = () => setZoom((z) => Math.min(ZOOM_MAX, +(z + ZOOM_STEP).toFixed(2)));\n\n const prevPage = () => setScrollToPage(Math.max(1, pageInfo.current - 1));\n const nextPage = () => setScrollToPage(Math.min(pageInfo.total, pageInfo.current + 1));\n\n // Download / print fetch the file into a blob URL rather than re-opening the\n // signed URL directly, so it works even when the document is already loaded.\n const withBlobUrl = useCallback(async (fn: (objUrl: string) => void) => {\n if (!primary) return;\n try {\n const res = await fetch(primary.url);\n const blob = await res.blob();\n const objUrl = URL.createObjectURL(blob);\n fn(objUrl);\n // Revoke after the consumer has had a chance to use it.\n setTimeout(() => URL.revokeObjectURL(objUrl), 120_000);\n } catch {\n // Fall back to opening the original URL.\n fn(primary.url);\n }\n }, [primary]);\n\n const handleDownload = () =>\n withBlobUrl((objUrl) => {\n const a = document.createElement('a');\n a.href = objUrl;\n a.download = title || 'document';\n a.click();\n });\n\n return (\n <div className={`mr-doc-viewer${isHtml ? ' mr-doc-viewer--html' : ''}`} ref={rootRef}>\n {!isHtml && <div className=\"mr-doc-viewer__toolbar\">\n <span className=\"mr-doc-viewer__filename\">{title}</span>\n {isPdf && (\n <div className=\"mr-doc-viewer__pages\">\n <button\n type=\"button\"\n aria-label=\"Previous page\"\n onClick={prevPage}\n disabled={pageInfo.current <= 1}\n >\n <ChevronLeft size={18} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__page-badge\">{pageInfo.current}</span>\n <span>/</span>\n <span>{pageInfo.total || '—'}</span>\n <button\n type=\"button\"\n aria-label=\"Next page\"\n onClick={nextPage}\n disabled={pageInfo.current >= pageInfo.total}\n >\n <ChevronRight size={18} aria-hidden />\n </button>\n </div>\n )}\n {isZoomable && (\n <div className=\"mr-doc-viewer__zoom\">\n <button type=\"button\" aria-label=\"Zoom out\" onClick={zoomOut} disabled={zoom <= ZOOM_MIN}>\n <Minus size={20} aria-hidden />\n </button>\n <span className=\"mr-doc-viewer__zoom-badge\">{Math.round(zoom * 100)}%</span>\n <button type=\"button\" aria-label=\"Zoom in\" onClick={zoomIn} disabled={zoom >= ZOOM_MAX}>\n <Plus size={20} aria-hidden />\n </button>\n </div>\n )}\n <div className=\"mr-doc-viewer__actions\">\n <button type=\"button\" aria-label=\"Download\" onClick={handleDownload} disabled={!primary}>\n <Download size={20} aria-hidden />\n </button>\n <button\n type=\"button\"\n aria-label={isFullscreen ? 'Exit full screen' : 'Full screen'}\n onClick={toggleFullscreen}\n >\n {isFullscreen ? <Minimize size={20} aria-hidden /> : <Maximize size={20} aria-hidden />}\n </button>\n </div>\n </div>}\n\n {isHtml && (\n <div className=\"mr-doc-viewer__html-bar\">\n <div className=\"mr-doc-viewer__html-bar-left\">\n <Globe size={12} aria-hidden />\n <span>Previewing HTML file – you can copy to a note and edit this file. The original record that you are viewing now will not be affected.</span>\n </div>\n <button\n type=\"button\"\n className=\"mr-doc-viewer__html-download\"\n aria-label=\"Download\"\n onClick={handleDownload}\n disabled={!primary}\n >\n <Download size={16} aria-hidden />\n </button>\n </div>\n )}\n\n <div className=\"mr-doc-viewer__canvas\">\n {!primary ? (\n <div className=\"mr-doc-viewer__status\">No preview available for this record.</div>\n ) : isPdf ? (\n <Suspense fallback={<div className=\"mr-doc-viewer__status\">Loading viewer…</div>}>\n <PdfViewer\n url={primary.url}\n baseWidth={PAGE_WIDTH}\n scale={zoom}\n scrollToPage={scrollToPage}\n onPageInfo={setPageInfo}\n />\n </Suspense>\n ) : images.length > 0 ? (\n images.map((img, i) => (\n <img\n key={i}\n className=\"mr-doc-viewer__image\"\n src={img.url}\n alt={`${title} ${i + 1}`}\n style={{ transform: `scale(${zoom})`, transformOrigin: 'top center' }}\n />\n ))\n ) : (\n <TextViewer url={primary.url} />\n )}\n </div>\n </div>\n );\n}\n","import { useEffect, useState } from 'react';\n\nexport interface TextViewerProps {\n url: string;\n}\n\nexport function TextViewer({ url }: TextViewerProps) {\n const [state, setState] = useState<{ status: 'loading' | 'loaded' | 'error'; text: string }>({\n status: 'loading',\n text: '',\n });\n\n useEffect(() => {\n let cancelled = false;\n setState({ status: 'loading', text: '' });\n (async () => {\n try {\n const res = await fetch(url);\n if (!res.ok) throw new Error(`fetch ${res.status}`);\n const text = await res.text();\n if (text.trimStart().startsWith('%PDF')) throw new Error('binary');\n if (!cancelled) setState({ status: 'loaded', text });\n } catch {\n if (!cancelled) setState({ status: 'error', text: '' });\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [url]);\n\n if (state.status === 'loading') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Loading document...</div>;\n }\n if (state.status === 'error') {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>Couldn't load this document.</div>;\n }\n if (!state.text.trim()) {\n return <div className=\"mr-doc-viewer__status\" style={{ color: 'var(--mr-muted-foreground)' }}>This record appears to be empty.</div>;\n }\n return (\n <iframe\n className=\"mr-doc-viewer__html-frame\"\n srcDoc={state.text}\n sandbox=\"allow-same-origin\"\n title=\"HTML preview\"\n />\n );\n}\n"],"mappings":"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","names":["useEffect","useState","jsx","useState","useEffect"]}