pdf-viewer-controls-toolbar.tsx 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. import { memo, useCallback, useState } from 'react'
  2. import { createPortal } from 'react-dom'
  3. import PdfPageNumberControl from './pdf-page-number-control'
  4. import PdfZoomButtons from './pdf-zoom-buttons'
  5. import PdfZoomDropdown from './pdf-zoom-dropdown'
  6. import { useResizeObserver } from '@/shared/hooks/use-resize-observer'
  7. import PdfViewerControlsMenuButton from './pdf-viewer-controls-menu-button'
  8. import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
  9. import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
  10. import { useTranslation } from 'react-i18next'
  11. import { useLayoutContext } from '@/shared/context/layout-context'
  12. type PdfViewerControlsToolbarProps = {
  13. requestPresentationMode: () => void
  14. setZoom: (zoom: string) => void
  15. rawScale: number
  16. setPage: (page: number) => void
  17. page: number
  18. totalPages: number
  19. pdfContainer?: HTMLDivElement
  20. }
  21. function PdfViewerControlsToolbar({
  22. requestPresentationMode,
  23. setZoom,
  24. rawScale,
  25. setPage,
  26. page,
  27. totalPages,
  28. pdfContainer,
  29. }: PdfViewerControlsToolbarProps) {
  30. const { t } = useTranslation()
  31. const { showLogs } = useCompileContext()
  32. const toolbarControlsElement = document.querySelector('#toolbar-pdf-controls')
  33. const [availableWidth, setAvailableWidth] = useState<number>(1000)
  34. const handleResize = useCallback(
  35. (element: Element) => {
  36. setAvailableWidth((element as HTMLElement).offsetWidth)
  37. },
  38. [setAvailableWidth]
  39. )
  40. const { elementRef: pdfControlsRef } = useResizeObserver(handleResize)
  41. const { view: ideView, pdfLayout } = useLayoutContext()
  42. const editorOnly = ideView !== 'pdf' && pdfLayout === 'flat'
  43. useCommandProvider(() => {
  44. if (editorOnly) {
  45. return
  46. }
  47. return [
  48. {
  49. id: 'view-pdf-presentation-mode',
  50. label: t('presentation_mode'),
  51. handler: requestPresentationMode,
  52. },
  53. {
  54. id: 'view-pdf-zoom-in',
  55. label: t('zoom_in'),
  56. handler: () => setZoom('zoom-in'),
  57. },
  58. {
  59. id: 'view-pdf-zoom-out',
  60. label: t('zoom_out'),
  61. handler: () => setZoom('zoom-out'),
  62. },
  63. {
  64. id: 'view-pdf-fit-width',
  65. label: t('fit_to_width'),
  66. handler: () => setZoom('page-width'),
  67. },
  68. {
  69. id: 'view-pdf-fit-height',
  70. label: t('fit_to_height'),
  71. handler: () => setZoom('page-height'),
  72. },
  73. ]
  74. }, [t, requestPresentationMode, setZoom, editorOnly])
  75. if (!toolbarControlsElement) {
  76. return null
  77. }
  78. if (showLogs) {
  79. return null
  80. }
  81. const InnerControlsComponent =
  82. availableWidth >= 300
  83. ? PdfViewerControlsToolbarFull
  84. : PdfViewerControlsToolbarSmall
  85. return createPortal(
  86. <div className="pdfjs-viewer-controls" ref={pdfControlsRef}>
  87. <InnerControlsComponent
  88. requestPresentationMode={requestPresentationMode}
  89. setZoom={setZoom}
  90. rawScale={rawScale}
  91. setPage={setPage}
  92. page={page}
  93. totalPages={totalPages}
  94. pdfContainer={pdfContainer}
  95. />
  96. </div>,
  97. toolbarControlsElement
  98. )
  99. }
  100. type InnerControlsProps = {
  101. requestPresentationMode: () => void
  102. setZoom: (zoom: string) => void
  103. rawScale: number
  104. setPage: (page: number) => void
  105. page: number
  106. totalPages: number
  107. // eslint-disable-next-line react/no-unused-prop-types
  108. pdfContainer?: HTMLDivElement
  109. }
  110. function PdfViewerControlsToolbarFull({
  111. requestPresentationMode,
  112. setZoom,
  113. rawScale,
  114. setPage,
  115. page,
  116. totalPages,
  117. }: InnerControlsProps) {
  118. return (
  119. <>
  120. <PdfPageNumberControl
  121. setPage={setPage}
  122. page={page}
  123. totalPages={totalPages}
  124. />
  125. <div className="pdfjs-zoom-controls">
  126. <PdfZoomButtons setZoom={setZoom} />
  127. <PdfZoomDropdown
  128. requestPresentationMode={requestPresentationMode}
  129. rawScale={rawScale}
  130. setZoom={setZoom}
  131. />
  132. </div>
  133. </>
  134. )
  135. }
  136. function PdfViewerControlsToolbarSmall({
  137. requestPresentationMode,
  138. setZoom,
  139. rawScale,
  140. setPage,
  141. page,
  142. totalPages,
  143. pdfContainer,
  144. }: InnerControlsProps) {
  145. return (
  146. <div className="pdfjs-viewer-controls-small">
  147. <PdfZoomDropdown
  148. requestPresentationMode={requestPresentationMode}
  149. rawScale={rawScale}
  150. setZoom={setZoom}
  151. />
  152. <PdfViewerControlsMenuButton
  153. setZoom={setZoom}
  154. setPage={setPage}
  155. page={page}
  156. totalPages={totalPages}
  157. pdfContainer={pdfContainer}
  158. />
  159. </div>
  160. )
  161. }
  162. export default memo(PdfViewerControlsToolbar)