smarthr-ui 97.0.0 → 98.1.0

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 (293) hide show
  1. package/lib/components/AppHeader/components/common/AppLauncherFeatures.cjs +1 -1
  2. package/lib/components/AppHeader/components/common/AppLauncherFeatures.js +1 -1
  3. package/lib/components/AppHeader/components/common/AppLauncherSortDropdown.cjs +1 -1
  4. package/lib/components/AppHeader/components/common/AppLauncherSortDropdown.js +1 -1
  5. package/lib/components/AppHeader/components/desktop/AppLauncher.cjs +5 -5
  6. package/lib/components/AppHeader/components/desktop/AppLauncher.cjs.map +1 -1
  7. package/lib/components/AppHeader/components/desktop/AppLauncher.js +5 -5
  8. package/lib/components/AppHeader/components/desktop/AppLauncher.js.map +1 -1
  9. package/lib/components/AppHeader/components/desktop/DesktopHeader.cjs +1 -1
  10. package/lib/components/AppHeader/components/desktop/DesktopHeader.js +1 -1
  11. package/lib/components/AppHeader/components/desktop/ReleaseNotesDropdown.cjs +1 -1
  12. package/lib/components/AppHeader/components/desktop/ReleaseNotesDropdown.js +1 -1
  13. package/lib/components/AppHeader/components/desktop/UserInfo.cjs +1 -1
  14. package/lib/components/AppHeader/components/desktop/UserInfo.js +1 -1
  15. package/lib/components/AppHeader/components/mobile/AppLauncher.cjs +1 -1
  16. package/lib/components/AppHeader/components/mobile/AppLauncher.js +1 -1
  17. package/lib/components/AppHeader/components/mobile/AppLauncherFilterDropdown.cjs +1 -1
  18. package/lib/components/AppHeader/components/mobile/AppLauncherFilterDropdown.js +1 -1
  19. package/lib/components/AppHeader/components/mobile/Help.cjs +1 -1
  20. package/lib/components/AppHeader/components/mobile/Help.js +1 -1
  21. package/lib/components/AppHeader/components/mobile/LanguageSelector.cjs +1 -1
  22. package/lib/components/AppHeader/components/mobile/LanguageSelector.js +1 -1
  23. package/lib/components/AppHeader/components/mobile/Menu.cjs +1 -1
  24. package/lib/components/AppHeader/components/mobile/Menu.js +1 -1
  25. package/lib/components/AppHeader/components/mobile/MenuAccordion.cjs +1 -1
  26. package/lib/components/AppHeader/components/mobile/MenuAccordion.js +1 -1
  27. package/lib/components/AppHeader/components/mobile/MenuDialog.cjs +2 -2
  28. package/lib/components/AppHeader/components/mobile/MenuDialog.js +2 -2
  29. package/lib/components/AppHeader/components/mobile/MenuSubHeading.cjs +1 -1
  30. package/lib/components/AppHeader/components/mobile/MenuSubHeading.js +1 -1
  31. package/lib/components/AppHeader/components/mobile/ReleaseNote.cjs +1 -1
  32. package/lib/components/AppHeader/components/mobile/ReleaseNote.js +1 -1
  33. package/lib/components/AppHeader/components/mobile/UserInfo.cjs +2 -2
  34. package/lib/components/AppHeader/components/mobile/UserInfo.js +2 -2
  35. package/lib/components/Browser/Browser.cjs +11 -7
  36. package/lib/components/Browser/Browser.cjs.map +1 -1
  37. package/lib/components/Browser/Browser.js +12 -8
  38. package/lib/components/Browser/Browser.js.map +1 -1
  39. package/lib/components/Calendar/Calendar.cjs +1 -1
  40. package/lib/components/Calendar/Calendar.js +1 -1
  41. package/lib/components/Calendar/CalendarTable.cjs +1 -1
  42. package/lib/components/Calendar/CalendarTable.js +1 -1
  43. package/lib/components/Calendar/YearPicker.cjs +1 -1
  44. package/lib/components/Calendar/YearPicker.js +1 -1
  45. package/lib/components/Combobox/ItemButton.cjs +27 -26
  46. package/lib/components/Combobox/ItemButton.cjs.map +1 -1
  47. package/lib/components/Combobox/ItemButton.js +28 -27
  48. package/lib/components/Combobox/ItemButton.js.map +1 -1
  49. package/lib/components/Combobox/MultiCombobox/MultiCombobox.cjs +122 -134
  50. package/lib/components/Combobox/MultiCombobox/MultiCombobox.cjs.map +1 -1
  51. package/lib/components/Combobox/MultiCombobox/MultiCombobox.js +123 -135
  52. package/lib/components/Combobox/MultiCombobox/MultiCombobox.js.map +1 -1
  53. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.cjs +1 -1
  54. package/lib/components/Combobox/MultiCombobox/MultiSelectedItem.js +1 -1
  55. package/lib/components/Combobox/SingleCombobox/SingleCombobox.cjs +79 -46
  56. package/lib/components/Combobox/SingleCombobox/SingleCombobox.cjs.map +1 -1
  57. package/lib/components/Combobox/SingleCombobox/SingleCombobox.js +81 -48
  58. package/lib/components/Combobox/SingleCombobox/SingleCombobox.js.map +1 -1
  59. package/lib/components/Combobox/useListbox.cjs +1 -1
  60. package/lib/components/Combobox/useListbox.js +1 -1
  61. package/lib/components/Combobox/useOptions.cjs +3 -1
  62. package/lib/components/Combobox/useOptions.cjs.map +1 -1
  63. package/lib/components/Combobox/useOptions.js +4 -2
  64. package/lib/components/Combobox/useOptions.js.map +1 -1
  65. package/lib/components/Dialog/ControlledActionDialog/ActionDialogContentInner.cjs +3 -3
  66. package/lib/components/Dialog/ControlledActionDialog/ActionDialogContentInner.cjs.map +1 -1
  67. package/lib/components/Dialog/ControlledActionDialog/ActionDialogContentInner.js +3 -3
  68. package/lib/components/Dialog/ControlledActionDialog/ActionDialogContentInner.js.map +1 -1
  69. package/lib/components/Dialog/ControlledFormDialog/FormDialogContentInner.cjs +3 -3
  70. package/lib/components/Dialog/ControlledFormDialog/FormDialogContentInner.cjs.map +1 -1
  71. package/lib/components/Dialog/ControlledFormDialog/FormDialogContentInner.js +3 -3
  72. package/lib/components/Dialog/ControlledFormDialog/FormDialogContentInner.js.map +1 -1
  73. package/lib/components/Dialog/ControlledMessageDialog/MessageDialogContentInner.cjs +1 -1
  74. package/lib/components/Dialog/ControlledMessageDialog/MessageDialogContentInner.js +1 -1
  75. package/lib/components/Dialog/ControlledStepFormDialog/ControlledStepFormDialog.cjs +1 -1
  76. package/lib/components/Dialog/ControlledStepFormDialog/ControlledStepFormDialog.js +1 -1
  77. package/lib/components/Dialog/ControlledStepFormDialog/StepFormDialogContentInner.cjs +2 -2
  78. package/lib/components/Dialog/ControlledStepFormDialog/StepFormDialogContentInner.cjs.map +1 -1
  79. package/lib/components/Dialog/ControlledStepFormDialog/StepFormDialogContentInner.js +2 -2
  80. package/lib/components/Dialog/ControlledStepFormDialog/StepFormDialogContentInner.js.map +1 -1
  81. package/lib/components/Dialog/DialogContentResponseStatusMessage.cjs +3 -8
  82. package/lib/components/Dialog/DialogContentResponseStatusMessage.cjs.map +1 -1
  83. package/lib/components/Dialog/DialogContentResponseStatusMessage.d.ts +1 -1
  84. package/lib/components/Dialog/DialogContentResponseStatusMessage.js +3 -8
  85. package/lib/components/Dialog/DialogContentResponseStatusMessage.js.map +1 -1
  86. package/lib/components/Dialog/FocusTrap.cjs +4 -1
  87. package/lib/components/Dialog/FocusTrap.cjs.map +1 -1
  88. package/lib/components/Dialog/FocusTrap.js +4 -1
  89. package/lib/components/Dialog/FocusTrap.js.map +1 -1
  90. package/lib/components/Dialog/ModelessDialog/ModelessDialog.cjs +1 -1
  91. package/lib/components/Dialog/ModelessDialog/ModelessDialog.js +1 -1
  92. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs +9 -3
  93. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.cjs.map +1 -1
  94. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js +9 -3
  95. package/lib/components/Dialog/RemoteDialogTrigger/RemoteDialogTrigger.js.map +1 -1
  96. package/lib/components/Disclosure/DisclosureTrigger.cjs +8 -4
  97. package/lib/components/Disclosure/DisclosureTrigger.cjs.map +1 -1
  98. package/lib/components/Disclosure/DisclosureTrigger.js +8 -4
  99. package/lib/components/Disclosure/DisclosureTrigger.js.map +1 -1
  100. package/lib/components/DropZone/DropZone.cjs +1 -1
  101. package/lib/components/DropZone/DropZone.js +1 -1
  102. package/lib/components/Dropdown/Dropdown.cjs +36 -34
  103. package/lib/components/Dropdown/Dropdown.cjs.map +1 -1
  104. package/lib/components/Dropdown/Dropdown.js +37 -35
  105. package/lib/components/Dropdown/Dropdown.js.map +1 -1
  106. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.cjs +1 -1
  107. package/lib/components/Dropdown/DropdownMenuButton/DropdownMenuButton.js +1 -1
  108. package/lib/components/Dropdown/FilterDropdown/FilterDropdown.cjs +3 -5
  109. package/lib/components/Dropdown/FilterDropdown/FilterDropdown.cjs.map +1 -1
  110. package/lib/components/Dropdown/FilterDropdown/FilterDropdown.d.ts +1 -1
  111. package/lib/components/Dropdown/FilterDropdown/FilterDropdown.js +3 -5
  112. package/lib/components/Dropdown/FilterDropdown/FilterDropdown.js.map +1 -1
  113. package/lib/components/Dropdown/SortDropdown/useSortDropdown.cjs +1 -1
  114. package/lib/components/Dropdown/SortDropdown/useSortDropdown.js +1 -1
  115. package/lib/components/ErrorScreen/AuthErrorScreen.cjs +1 -1
  116. package/lib/components/ErrorScreen/AuthErrorScreen.js +1 -1
  117. package/lib/components/ErrorScreen/ForbiddenErrorScreen.cjs +1 -1
  118. package/lib/components/ErrorScreen/ForbiddenErrorScreen.js +1 -1
  119. package/lib/components/ErrorScreen/NotFoundErrorScreen.cjs +1 -1
  120. package/lib/components/ErrorScreen/NotFoundErrorScreen.js +1 -1
  121. package/lib/components/ErrorScreen/UnauthorizedErrorScreen.cjs +1 -1
  122. package/lib/components/ErrorScreen/UnauthorizedErrorScreen.js +1 -1
  123. package/lib/components/FileViewer/FileViewer.cjs +35 -2
  124. package/lib/components/FileViewer/FileViewer.cjs.map +1 -1
  125. package/lib/components/FileViewer/FileViewer.js +37 -4
  126. package/lib/components/FileViewer/FileViewer.js.map +1 -1
  127. package/lib/components/FileViewer/PDFViewer.cjs +59 -2
  128. package/lib/components/FileViewer/PDFViewer.cjs.map +1 -1
  129. package/lib/components/FileViewer/PDFViewer.d.ts +6 -1
  130. package/lib/components/FileViewer/PDFViewer.js +60 -3
  131. package/lib/components/FileViewer/PDFViewer.js.map +1 -1
  132. package/lib/components/FileViewer/SearchController.cjs +105 -0
  133. package/lib/components/FileViewer/SearchController.cjs.map +1 -0
  134. package/lib/components/FileViewer/SearchController.d.ts +7 -0
  135. package/lib/components/FileViewer/SearchController.js +103 -0
  136. package/lib/components/FileViewer/SearchController.js.map +1 -0
  137. package/lib/components/FileViewer/buildCustomTextRenderer.cjs +55 -0
  138. package/lib/components/FileViewer/buildCustomTextRenderer.cjs.map +1 -0
  139. package/lib/components/FileViewer/buildCustomTextRenderer.d.ts +9 -0
  140. package/lib/components/FileViewer/buildCustomTextRenderer.js +50 -0
  141. package/lib/components/FileViewer/buildCustomTextRenderer.js.map +1 -0
  142. package/lib/components/FileViewer/types.d.ts +7 -0
  143. package/lib/components/FileViewer/usePDFSearch.cjs +148 -0
  144. package/lib/components/FileViewer/usePDFSearch.cjs.map +1 -0
  145. package/lib/components/FileViewer/usePDFSearch.d.ts +19 -0
  146. package/lib/components/FileViewer/usePDFSearch.js +143 -0
  147. package/lib/components/FileViewer/usePDFSearch.js.map +1 -0
  148. package/lib/components/FormControl/FormControl.cjs +2 -22
  149. package/lib/components/FormControl/FormControl.cjs.map +1 -1
  150. package/lib/components/FormControl/FormControl.js +2 -22
  151. package/lib/components/FormControl/FormControl.js.map +1 -1
  152. package/lib/components/Header/AppLauncher/AppLauncher.cjs +1 -1
  153. package/lib/components/Header/AppLauncher/AppLauncher.js +1 -1
  154. package/lib/components/Header/LanguageSwitcher/LanguageSwitcher.cjs +1 -1
  155. package/lib/components/Header/LanguageSwitcher/LanguageSwitcher.js +1 -1
  156. package/lib/components/Icon/FaIcon.js +1 -1
  157. package/lib/components/Icon/OpenInNewTabIcon.cjs +1 -1
  158. package/lib/components/Icon/OpenInNewTabIcon.js +1 -1
  159. package/lib/components/InformationPanel/InformationPanel.cjs +1 -1
  160. package/lib/components/InformationPanel/InformationPanel.js +1 -1
  161. package/lib/components/Input/SearchInput/SearchInputIcon.cjs +1 -1
  162. package/lib/components/Input/SearchInput/SearchInputIcon.js +1 -1
  163. package/lib/components/InputFile/InputFileMultiplyAppendable.cjs +1 -1
  164. package/lib/components/InputFile/InputFileMultiplyAppendable.js +1 -1
  165. package/lib/components/InputFile/InputFileNative.cjs +1 -1
  166. package/lib/components/InputFile/InputFileNative.js +1 -1
  167. package/lib/components/Layout/Cluster/Cluster.cjs +0 -1
  168. package/lib/components/Layout/Cluster/Cluster.cjs.map +1 -1
  169. package/lib/components/Layout/Cluster/Cluster.js +0 -1
  170. package/lib/components/Layout/Cluster/Cluster.js.map +1 -1
  171. package/lib/components/Layout/Container/Container.cjs +1 -5
  172. package/lib/components/Layout/Container/Container.cjs.map +1 -1
  173. package/lib/components/Layout/Container/Container.js +1 -5
  174. package/lib/components/Layout/Container/Container.js.map +1 -1
  175. package/lib/components/Layout/Stack/Stack.cjs +22 -22
  176. package/lib/components/Layout/Stack/Stack.cjs.map +1 -1
  177. package/lib/components/Layout/Stack/Stack.js +22 -22
  178. package/lib/components/Layout/Stack/Stack.js.map +1 -1
  179. package/lib/components/Loader/LoaderSpinner.cjs +1 -1
  180. package/lib/components/Loader/LoaderSpinner.js +1 -1
  181. package/lib/components/Pagination/Pagination.cjs +1 -1
  182. package/lib/components/Pagination/Pagination.js +1 -1
  183. package/lib/components/Pagination/PaginationItemButton.cjs +1 -1
  184. package/lib/components/Pagination/PaginationItemButton.js +1 -1
  185. package/lib/components/SideNav/SideNav.cjs +3 -22
  186. package/lib/components/SideNav/SideNav.cjs.map +1 -1
  187. package/lib/components/SideNav/SideNav.d.ts +2 -9
  188. package/lib/components/SideNav/SideNav.js +4 -23
  189. package/lib/components/SideNav/SideNav.js.map +1 -1
  190. package/lib/components/SideNav/SideNavContext.cjs +11 -0
  191. package/lib/components/SideNav/SideNavContext.cjs.map +1 -0
  192. package/lib/components/SideNav/SideNavContext.d.ts +7 -0
  193. package/lib/components/SideNav/SideNavContext.js +8 -0
  194. package/lib/components/SideNav/SideNavContext.js.map +1 -0
  195. package/lib/components/SideNav/SideNavItemButton.cjs +12 -7
  196. package/lib/components/SideNav/SideNavItemButton.cjs.map +1 -1
  197. package/lib/components/SideNav/SideNavItemButton.d.ts +5 -11
  198. package/lib/components/SideNav/SideNavItemButton.js +12 -7
  199. package/lib/components/SideNav/SideNavItemButton.js.map +1 -1
  200. package/lib/components/Table/Th.cjs +2 -2
  201. package/lib/components/Table/Th.cjs.map +1 -1
  202. package/lib/components/Table/Th.d.ts +0 -2
  203. package/lib/components/Table/Th.js +2 -2
  204. package/lib/components/Table/Th.js.map +1 -1
  205. package/lib/components/Table/ThCheckbox.cjs +1 -1
  206. package/lib/components/Table/ThCheckbox.js +1 -1
  207. package/lib/components/Table/ThSortButton.cjs +5 -6
  208. package/lib/components/Table/ThSortButton.cjs.map +1 -1
  209. package/lib/components/Table/ThSortButton.d.ts +1 -6
  210. package/lib/components/Table/ThSortButton.js +5 -6
  211. package/lib/components/Table/ThSortButton.js.map +1 -1
  212. package/lib/components/WarekiPicker/WarekiPicker.cjs +1 -1
  213. package/lib/components/WarekiPicker/WarekiPicker.js +1 -1
  214. package/lib/hooks/useLatest.cjs +33 -0
  215. package/lib/hooks/useLatest.cjs.map +1 -0
  216. package/lib/hooks/useLatest.d.ts +19 -0
  217. package/lib/hooks/useLatest.js +31 -0
  218. package/lib/hooks/useLatest.js.map +1 -0
  219. package/lib/index.cjs +1 -6
  220. package/lib/index.cjs.map +1 -1
  221. package/lib/index.d.ts +0 -1
  222. package/lib/index.js +1 -4
  223. package/lib/index.js.map +1 -1
  224. package/lib/intl/Localizer.cjs +5 -1
  225. package/lib/intl/Localizer.cjs.map +1 -1
  226. package/lib/intl/Localizer.d.ts +1 -1
  227. package/lib/intl/Localizer.js +5 -1
  228. package/lib/intl/Localizer.js.map +1 -1
  229. package/lib/intl/locales/en_us.json.cjs +3 -0
  230. package/lib/intl/locales/en_us.json.cjs.map +1 -1
  231. package/lib/intl/locales/en_us.json.js +3 -0
  232. package/lib/intl/locales/en_us.json.js.map +1 -1
  233. package/lib/intl/locales/id_id.json.cjs +3 -0
  234. package/lib/intl/locales/id_id.json.cjs.map +1 -1
  235. package/lib/intl/locales/id_id.json.js +3 -0
  236. package/lib/intl/locales/id_id.json.js.map +1 -1
  237. package/lib/intl/locales/index.d.ts +27 -0
  238. package/lib/intl/locales/ja.cjs +3 -0
  239. package/lib/intl/locales/ja.cjs.map +1 -1
  240. package/lib/intl/locales/ja.d.ts +3 -0
  241. package/lib/intl/locales/ja.js +3 -0
  242. package/lib/intl/locales/ja.js.map +1 -1
  243. package/lib/intl/locales/ja.json.cjs +3 -0
  244. package/lib/intl/locales/ja.json.cjs.map +1 -1
  245. package/lib/intl/locales/ja.json.js +3 -0
  246. package/lib/intl/locales/ja.json.js.map +1 -1
  247. package/lib/intl/locales/ja_easy.json.cjs +3 -0
  248. package/lib/intl/locales/ja_easy.json.cjs.map +1 -1
  249. package/lib/intl/locales/ja_easy.json.js +3 -0
  250. package/lib/intl/locales/ja_easy.json.js.map +1 -1
  251. package/lib/intl/locales/ko_kr.json.cjs +3 -0
  252. package/lib/intl/locales/ko_kr.json.cjs.map +1 -1
  253. package/lib/intl/locales/ko_kr.json.js +3 -0
  254. package/lib/intl/locales/ko_kr.json.js.map +1 -1
  255. package/lib/intl/locales/pt_br.json.cjs +3 -0
  256. package/lib/intl/locales/pt_br.json.cjs.map +1 -1
  257. package/lib/intl/locales/pt_br.json.js +3 -0
  258. package/lib/intl/locales/pt_br.json.js.map +1 -1
  259. package/lib/intl/locales/vi_vn.json.cjs +3 -0
  260. package/lib/intl/locales/vi_vn.json.cjs.map +1 -1
  261. package/lib/intl/locales/vi_vn.json.js +3 -0
  262. package/lib/intl/locales/vi_vn.json.js.map +1 -1
  263. package/lib/intl/locales/zh_hans_cn.json.cjs +3 -0
  264. package/lib/intl/locales/zh_hans_cn.json.cjs.map +1 -1
  265. package/lib/intl/locales/zh_hans_cn.json.js +3 -0
  266. package/lib/intl/locales/zh_hans_cn.json.js.map +1 -1
  267. package/lib/intl/locales/zh_hant_tw.json.cjs +3 -0
  268. package/lib/intl/locales/zh_hant_tw.json.cjs.map +1 -1
  269. package/lib/intl/locales/zh_hant_tw.json.js +3 -0
  270. package/lib/intl/locales/zh_hant_tw.json.js.map +1 -1
  271. package/metadata.json +1 -1
  272. package/package.json +1 -1
  273. package/smarthr-ui.css +35 -98
  274. package/lib/hooks/useDecorators.cjs +0 -18
  275. package/lib/hooks/useDecorators.cjs.map +0 -1
  276. package/lib/hooks/useDecorators.d.ts +0 -6
  277. package/lib/hooks/useDecorators.js +0 -16
  278. package/lib/hooks/useDecorators.js.map +0 -1
  279. package/lib/hooks/useDevice/DeviceProvider.cjs +0 -37
  280. package/lib/hooks/useDevice/DeviceProvider.cjs.map +0 -1
  281. package/lib/hooks/useDevice/DeviceProvider.d.ts +0 -4
  282. package/lib/hooks/useDevice/DeviceProvider.js +0 -35
  283. package/lib/hooks/useDevice/DeviceProvider.js.map +0 -1
  284. package/lib/hooks/useDevice/index.cjs +0 -10
  285. package/lib/hooks/useDevice/index.cjs.map +0 -1
  286. package/lib/hooks/useDevice/index.d.ts +0 -2
  287. package/lib/hooks/useDevice/index.js +0 -3
  288. package/lib/hooks/useDevice/index.js.map +0 -1
  289. package/lib/hooks/useDevice/useDevice.cjs +0 -11
  290. package/lib/hooks/useDevice/useDevice.cjs.map +0 -1
  291. package/lib/hooks/useDevice/useDevice.d.ts +0 -4
  292. package/lib/hooks/useDevice/useDevice.js +0 -8
  293. package/lib/hooks/useDevice/useDevice.js.map +0 -1
@@ -1,7 +1,20 @@
1
1
  "use client";
2
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
3
3
  import { Decimal } from './../../vendor/.pnpm/decimal.js@10.6.0/vendor/decimal.js/decimal.js';
4
- import { memo, useRef, useState, useMemo, useCallback, useEffect } from 'react';
4
+ import { memo, useMemo, useCallback, useRef, useState, useEffect } from 'react';
5
+ import { tv as ce } from './../../vendor/.pnpm/tailwind-variants@0.3.1_tailwindcss@3.4.19_ts-node@10.9.2_@swc_core@1.15.17_@types_node@20.19.35_typescript@5.9.3__/vendor/tailwind-variants/dist/index.js';
6
+ import { useEnvironment } from '../../hooks/useEnvironment/useEnvironment.js';
7
+ import '../../themes/createSpacing.js';
8
+ import '../../_virtual/index.js';
9
+ import '../../_virtual/index2.js';
10
+ import '../../themes/createColor.js';
11
+ import '../../themes/createTextColor.js';
12
+ import 'styled-components';
13
+ import '../../themes/createShadow/defaultShadow.js';
14
+ import '../../themes/createWidth.js';
15
+ import '../../themes/createBackgroundColor.js';
16
+ import '../../themes/createBorder.js';
17
+ import '../../hooks/useTheme.js';
5
18
  import '../../intl/IntlProvider.js';
6
19
  import 'react-intl';
7
20
  import { Localizer } from '../../intl/Localizer.js';
@@ -32,6 +45,8 @@ import { Scroller } from '../Scroller/Scroller.js';
32
45
  import { VisuallyHiddenText } from '../VisuallyHiddenText/VisuallyHiddenText.js';
33
46
  import { ImageViewer } from './ImageViewer.js';
34
47
  import { PDFViewer } from './PDFViewer.js';
48
+ import { SearchController } from './SearchController.js';
49
+ import { usePDFSearch } from './usePDFSearch.js';
35
50
 
36
51
  const defaultScaleStep = new Decimal(0.2);
37
52
  const defaultScaleSteps = [0.2, 0.6, 1, 1.6, 2, 3];
@@ -41,6 +56,8 @@ const FileViewer = ({ file, scaleStep, scaleSteps, width: fixedWidth, onPassword
41
56
  const [loaded, setLoaded] = useState(false);
42
57
  const [rotation, setRotation] = useState(undefined);
43
58
  const [width, setWidth] = useState(fixedWidth ?? 0);
59
+ const isPDF = file.contentType === 'application/pdf';
60
+ const search = usePDFSearch(file.url);
44
61
  const internalScaleStep = useMemo(() => (scaleStep ? new Decimal(scaleStep) : defaultScaleStep), [scaleStep]);
45
62
  const scaleUp = useCallback(() => {
46
63
  setScale((currentScale) => new Decimal(currentScale).add(internalScaleStep).toNumber());
@@ -72,9 +89,25 @@ const FileViewer = ({ file, scaleStep, scaleSteps, width: fixedWidth, onPassword
72
89
  resizeObserver.disconnect();
73
90
  };
74
91
  }, [fixedWidth]);
75
- return (jsxs(Scroller, { direction: "both", className: "shr-flex shr-h-full shr-w-full shr-flex-col shr-gap-2 shr-bg-scrim shr-bg-[radial-gradient(theme(textColor.black)_1px,_transparent_0)] shr-bg-[length:16px_16px]", ref: ref, children: [jsx("div", { className: "shr-sticky shr-start-0 shr-top-0 shr-z-[1] shr-flex shr-w-full shr-flex-shrink-0 shr-gap-0.5", children: jsx(Controller, { scale: scale, setScale: setScale, scaleSteps: scaleSteps || defaultScaleSteps, onClickScaleUpButton: scaleUp, onClickScaleDownButton: scaleDown, onClickRotateButton: rotate }) }), jsxs("div", { className: "shr-z-[0] shr-mx-auto shr-my-0 shr-box-border shr-flex shr-w-fit shr-flex-shrink-0 shr-grow shr-items-center shr-justify-center shr-px-2 shr-pb-2", children: [!loaded && (jsx("div", { className: "shr-pointer-events-none shr-fixed shr-inset-0 shr-flex shr-h-full shr-w-full shr-items-center shr-justify-center", children: jsx(Loader, { type: "light", size: "M" }) })), jsx("div", { className: !loaded ? 'shr-invisible' : '', children: file.contentType === 'application/pdf' ? (jsx(PDFViewer, { scale: scale, rotation: rotation, file: file, width: width, onLoad: handleLoaded, onPDFLoaded: handlePDFLoaded, onPassword: onPassword, onLoadError: onLoadError })) : file.contentType.startsWith('image/') ? (jsx(ImageViewer, { scale: scale, rotation: rotation, file: file, width: width, onLoad: handleLoaded, onLoadError: onLoadError })) : (jsx(Localizer, { id: "smarthr-ui/FileViewer/unsupportedFileText", defaultText: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u5F62\u5F0F\u306E\u30D5\u30A1\u30A4\u30EB\u3067\u3059\u3002" })) })] })] }));
92
+ return (jsxs(Scroller, { direction: "both", className: "shr-flex shr-h-full shr-w-full shr-flex-col shr-gap-2 shr-bg-scrim shr-bg-[radial-gradient(theme(textColor.black)_1px,_transparent_0)] shr-bg-[length:16px_16px]", ref: ref, children: [jsx("div", { className: "shr-sticky shr-start-0 shr-top-0 shr-z-[1] shr-flex shr-w-full shr-flex-shrink-0 shr-gap-0.5", children: jsx(Controller, { scale: scale, setScale: setScale, scaleSteps: scaleSteps || defaultScaleSteps, onClickScaleUpButton: scaleUp, onClickScaleDownButton: scaleDown, onClickRotateButton: rotate, searchController: isPDF ? jsx(SearchController, { search: search }) : undefined }) }), jsxs("div", { className: "shr-z-[0] shr-mx-auto shr-my-0 shr-box-border shr-flex shr-w-fit shr-flex-shrink-0 shr-grow shr-items-center shr-justify-center shr-px-2 shr-pb-2", children: [!loaded && (jsx("div", { className: "shr-pointer-events-none shr-fixed shr-inset-0 shr-flex shr-h-full shr-w-full shr-items-center shr-justify-center", children: jsx(Loader, { type: "light", size: "M" }) })), jsx("div", { className: !loaded ? 'shr-invisible' : '', children: isPDF ? (jsx(PDFViewer, { scale: scale, rotation: rotation, file: file, width: width, onLoad: handleLoaded, onPDFLoaded: handlePDFLoaded, onPassword: onPassword, onLoadError: onLoadError, search: search })) : file.contentType.startsWith('image/') ? (jsx(ImageViewer, { scale: scale, rotation: rotation, file: file, width: width, onLoad: handleLoaded, onLoadError: onLoadError })) : (jsx(Localizer, { id: "smarthr-ui/FileViewer/unsupportedFileText", defaultText: "\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u5F62\u5F0F\u306E\u30D5\u30A1\u30A4\u30EB\u3067\u3059\u3002" })) })] })] }));
76
93
  };
77
- const Controller = memo(({ scale, setScale, scaleSteps, onClickScaleUpButton, onClickScaleDownButton, onClickRotateButton, }) => (jsx("div", { className: "shr-sticky shr-flex shr-w-full shr-items-center shr-justify-center shr-justify-items-center shr-gap-0.5 shr-bg-scrim shr-p-0.5 shr-shadow-layer-1", children: jsxs(Cluster, { gap: 0.5, children: [jsxs("div", { className: "shr-border-shorthand shr-flex shr-divide-x shr-divide-solid shr-overflow-hidden shr-rounded-m", children: [jsx(Button, { onClick: onClickScaleDownButton, disabled: scale <= scaleSteps[0], className: "shr-rounded-r-none shr-border-none", children: jsx(FaMagnifyingGlassMinusIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleDownAlt", defaultText: "\u7E2E\u5C0F" }) }) }), jsx(DropdownMenuButton, { trigger: jsxs(Fragment, { children: [jsx(VisuallyHiddenText, { children: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleRateLabel", defaultText: "\u62E1\u5927\u7387" }) }), `${(scale * 100).toFixed(0)}%`] }), className: "shr-border-y-0 shr-border-[theme(borderColor.default)] [&_.smarthr-ui-Button]:shr-rounded-none [&_.smarthr-ui-Button]:shr-border-[transparent]", children: scaleSteps.map((step) => (jsx(Button, { onClick: () => setScale(step), className: "shr-rounded-none shr-border-0", children: `${(step * 100).toFixed(0)}%` }, step.toString()))) }), jsx(Button, { onClick: onClickScaleUpButton, className: "shr-rounded-l-none shr-border-0", children: jsx(FaMagnifyingGlassPlusIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleUpAlt", defaultText: "\u62E1\u5927" }) }) })] }), jsx(Button, { onClick: onClickRotateButton, className: "shr-p-0.75", children: jsx(FaArrowRotateLeftIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/rotateAlt", defaultText: "\u5DE6\u56DE\u8EE2" }) }) })] }) })));
94
+ const controllerClassNameGenerator = ce({
95
+ base: 'shr-sticky shr-grid shr-w-full shr-items-center shr-bg-scrim shr-py-0.5 shr-shadow-layer-1',
96
+ variants: {
97
+ mobile: {
98
+ true: 'shr-gap-0.5 shr-px-1',
99
+ false: 'shr-grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] shr-gap-1.5 shr-px-2',
100
+ },
101
+ },
102
+ });
103
+ const Controller = memo(({ scale, setScale, scaleSteps, onClickScaleUpButton, onClickScaleDownButton, onClickRotateButton, searchController, }) => {
104
+ const { mobile } = useEnvironment();
105
+ const className = useMemo(() => controllerClassNameGenerator({ mobile }), [mobile]);
106
+ const onClickScaleStep = useCallback((e) => setScale(Number(e.currentTarget.value)), [setScale]);
107
+ return (jsxs("div", { className: className, children: [!mobile && jsx("div", { role: "presentation", "aria-hidden": "true" }), jsxs(Cluster, { gap: 0.5, className: "shr-justify-self-center", children: [jsxs("div", { className: "shr-border-shorthand shr-flex shr-divide-x shr-divide-solid shr-overflow-hidden shr-rounded-m", children: [jsx(Button, { onClick: onClickScaleDownButton, disabled: scale <= scaleSteps[0], className: "shr-rounded-r-none shr-border-none", children: jsx(FaMagnifyingGlassMinusIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleDownAlt", defaultText: "\u7E2E\u5C0F" }) }) }), jsx(DropdownMenuButton, { trigger: jsxs(Fragment, { children: [jsx(VisuallyHiddenText, { children: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleRateLabel", defaultText: "\u62E1\u5927\u7387" }) }), `${(scale * 100).toFixed(0)}%`] }), className: "shr-border-y-0 shr-border-[theme(borderColor.default)] [&_.smarthr-ui-Button]:shr-rounded-none [&_.smarthr-ui-Button]:shr-border-[transparent]", children: scaleSteps.map((step) => (jsx(Button, { value: step, onClick: onClickScaleStep, className: "shr-rounded-none shr-border-0", children: `${(step * 100).toFixed(0)}%` }, step.toString()))) }), jsx(Button, { onClick: onClickScaleUpButton, className: "shr-rounded-l-none shr-border-0", children: jsx(FaMagnifyingGlassPlusIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/scaleUpAlt", defaultText: "\u62E1\u5927" }) }) })] }), jsx(Button, { onClick: onClickRotateButton, className: "shr-p-0.75", children: jsx(FaArrowRotateLeftIcon, { alt: jsx(Localizer, { id: "smarthr-ui/FileViewer/rotateAlt", defaultText: "\u5DE6\u56DE\u8EE2" }) }) })] }), searchController ? (jsx("div", { className: "shr-min-w-0 shr-justify-self-stretch", children: searchController })) : (
108
+ /* PC 表示時のときに中央の操作ボタンたちを中央へ寄せるための空のスペーサー */
109
+ !mobile && jsx("div", { role: "presentation", "aria-hidden": "true" }))] }));
110
+ });
78
111
 
79
112
  export { FileViewer };
80
113
  //# sourceMappingURL=FileViewer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileViewer.js","sources":["../../../src/components/FileViewer/FileViewer.tsx"],"sourcesContent":["'use client'\n\nimport Decimal from 'decimal.js'\nimport {\n type ComponentProps,\n type FC,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\n\nimport { Localizer } from '../../intl'\nimport { Button } from '../Button'\nimport { DropdownMenuButton } from '../Dropdown'\nimport {\n FaArrowRotateLeftIcon,\n FaMagnifyingGlassMinusIcon,\n FaMagnifyingGlassPlusIcon,\n} from '../Icon'\nimport { Cluster } from '../Layout'\nimport { Loader } from '../Loader'\nimport { Scroller } from '../Scroller'\nimport { VisuallyHiddenText } from '../VisuallyHiddenText'\n\nimport { ImageViewer } from './ImageViewer'\nimport { PDFViewer } from './PDFViewer'\n\nimport type { FileForViewer } from './types'\n\nconst defaultScaleStep = new Decimal(0.2)\nconst defaultScaleSteps = [0.2, 0.6, 1, 1.6, 2, 3]\n\ntype Props = {\n file: FileForViewer\n width?: number\n\n /*\n * 拡大縮小率のステップを、100%を1とした配列で指定します。\n * */\n scaleSteps?: number[]\n\n scaleStep?: number\n onPassword?: ComponentProps<typeof PDFViewer>['onPassword']\n onLoadError?: () => void\n}\n\nexport const FileViewer: FC<Props> = ({\n file,\n scaleStep,\n scaleSteps,\n width: fixedWidth,\n onPassword,\n onLoadError,\n}) => {\n const ref = useRef<HTMLDivElement>(null)\n const [scale, setScale] = useState(1)\n const [loaded, setLoaded] = useState(false)\n const [rotation, setRotation] = useState<number | undefined>(undefined)\n const [width, setWidth] = useState(fixedWidth ?? 0)\n\n const internalScaleStep = useMemo(\n () => (scaleStep ? new Decimal(scaleStep) : defaultScaleStep),\n [scaleStep],\n )\n\n const scaleUp = useCallback(() => {\n setScale((currentScale) => new Decimal(currentScale).add(internalScaleStep).toNumber())\n }, [internalScaleStep])\n\n const scaleDown = useCallback(() => {\n setScale((currentScale) => new Decimal(currentScale).sub(internalScaleStep).toNumber())\n }, [internalScaleStep])\n\n const rotate = useCallback(() => {\n // HINT: react-pdf側のAnnotationLayer.cssではマイナスの回転に対応しておらず、また0, 90, 180, 270度のみ対応しているため、-90度の場合は+270度として扱う\n const currentRotation = rotation ?? 0\n const newRotation = currentRotation === 0 ? 270 : currentRotation - 90\n setRotation(newRotation)\n }, [rotation])\n\n const handleLoaded = useCallback(() => {\n setLoaded(true)\n }, [])\n\n const handlePDFLoaded = useCallback((defaultRotation: number) => {\n setRotation(defaultRotation)\n }, [])\n\n useEffect(() => {\n if (!ref.current || fixedWidth !== undefined) {\n return\n }\n\n const resizeObserver = new ResizeObserver(() => {\n setWidth((ref.current?.clientWidth ?? 0) - 64)\n })\n\n resizeObserver.observe(ref.current)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [fixedWidth])\n\n return (\n <Scroller\n direction=\"both\"\n className=\"shr-flex shr-h-full shr-w-full shr-flex-col shr-gap-2 shr-bg-scrim shr-bg-[radial-gradient(theme(textColor.black)_1px,_transparent_0)] shr-bg-[length:16px_16px]\"\n ref={ref}\n >\n <div className=\"shr-sticky shr-start-0 shr-top-0 shr-z-[1] shr-flex shr-w-full shr-flex-shrink-0 shr-gap-0.5\">\n <Controller\n scale={scale}\n setScale={setScale}\n scaleSteps={scaleSteps || defaultScaleSteps}\n onClickScaleUpButton={scaleUp}\n onClickScaleDownButton={scaleDown}\n onClickRotateButton={rotate}\n />\n </div>\n <div className=\"shr-z-[0] shr-mx-auto shr-my-0 shr-box-border shr-flex shr-w-fit shr-flex-shrink-0 shr-grow shr-items-center shr-justify-center shr-px-2 shr-pb-2\">\n {!loaded && (\n <div className=\"shr-pointer-events-none shr-fixed shr-inset-0 shr-flex shr-h-full shr-w-full shr-items-center shr-justify-center\">\n <Loader type=\"light\" size=\"M\" />\n </div>\n )}\n <div className={!loaded ? 'shr-invisible' : ''}>\n {file.contentType === 'application/pdf' ? (\n <PDFViewer\n scale={scale}\n rotation={rotation}\n file={file}\n width={width}\n onLoad={handleLoaded}\n onPDFLoaded={handlePDFLoaded}\n onPassword={onPassword}\n onLoadError={onLoadError}\n />\n ) : file.contentType.startsWith('image/') ? (\n <ImageViewer\n scale={scale}\n rotation={rotation}\n file={file}\n width={width}\n onLoad={handleLoaded}\n onLoadError={onLoadError}\n />\n ) : (\n <Localizer\n id=\"smarthr-ui/FileViewer/unsupportedFileText\"\n defaultText=\"サポートされていない形式のファイルです。\"\n />\n )}\n </div>\n </div>\n </Scroller>\n )\n}\n\ntype ControllerProps = {\n scale: number\n setScale: (scale: number) => void\n scaleSteps: number[]\n onClickScaleUpButton: () => void\n onClickScaleDownButton: () => void\n onClickRotateButton: () => void\n}\n\nconst Controller: FC<ControllerProps> = memo(\n ({\n scale,\n setScale,\n scaleSteps,\n onClickScaleUpButton,\n onClickScaleDownButton,\n onClickRotateButton,\n }) => (\n <div className=\"shr-sticky shr-flex shr-w-full shr-items-center shr-justify-center shr-justify-items-center shr-gap-0.5 shr-bg-scrim shr-p-0.5 shr-shadow-layer-1\">\n <Cluster gap={0.5}>\n <div className=\"shr-border-shorthand shr-flex shr-divide-x shr-divide-solid shr-overflow-hidden shr-rounded-m\">\n <Button\n onClick={onClickScaleDownButton}\n disabled={scale <= scaleSteps[0]}\n className=\"shr-rounded-r-none shr-border-none\"\n >\n <FaMagnifyingGlassMinusIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/scaleDownAlt\" defaultText=\"縮小\" />}\n />\n </Button>\n <DropdownMenuButton\n trigger={\n <>\n <VisuallyHiddenText>\n <Localizer id=\"smarthr-ui/FileViewer/scaleRateLabel\" defaultText=\"拡大率\" />\n </VisuallyHiddenText>\n {`${(scale * 100).toFixed(0)}%`}\n </>\n }\n className=\"shr-border-y-0 shr-border-[theme(borderColor.default)] [&_.smarthr-ui-Button]:shr-rounded-none [&_.smarthr-ui-Button]:shr-border-[transparent]\"\n >\n {scaleSteps.map((step) => (\n <Button\n key={step.toString()}\n onClick={() => setScale(step)}\n className=\"shr-rounded-none shr-border-0\"\n >\n {`${(step * 100).toFixed(0)}%`}\n </Button>\n ))}\n </DropdownMenuButton>\n <Button onClick={onClickScaleUpButton} className=\"shr-rounded-l-none shr-border-0\">\n <FaMagnifyingGlassPlusIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/scaleUpAlt\" defaultText=\"拡大\" />}\n />\n </Button>\n </div>\n <Button onClick={onClickRotateButton} className=\"shr-p-0.75\">\n <FaArrowRotateLeftIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/rotateAlt\" defaultText=\"左回転\" />}\n />\n </Button>\n </Cluster>\n </div>\n ),\n)\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCA;AACA;;AAwBE;;;;AAIA;;AAOA;;AAEA;AAEA;;AAEA;AAEA;;AAEE;AACA;;AAEF;AAEA;;;AAIA;;;;;;;AASE;AACE;AACF;AAEA;AAEA;;AAEA;AACF;;AAuDF;AAWA;;"}
1
+ {"version":3,"file":"FileViewer.js","sources":["../../../src/components/FileViewer/FileViewer.tsx"],"sourcesContent":["'use client'\n\nimport Decimal from 'decimal.js'\nimport {\n type ComponentProps,\n type FC,\n type MouseEvent,\n type ReactNode,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnvironment } from '../../hooks/useEnvironment'\nimport { Localizer } from '../../intl'\nimport { Button } from '../Button'\nimport { DropdownMenuButton } from '../Dropdown'\nimport {\n FaArrowRotateLeftIcon,\n FaMagnifyingGlassMinusIcon,\n FaMagnifyingGlassPlusIcon,\n} from '../Icon'\nimport { Cluster } from '../Layout'\nimport { Loader } from '../Loader'\nimport { Scroller } from '../Scroller'\nimport { VisuallyHiddenText } from '../VisuallyHiddenText'\n\nimport { ImageViewer } from './ImageViewer'\nimport { PDFViewer } from './PDFViewer'\nimport { SearchController } from './SearchController'\nimport { usePDFSearch } from './usePDFSearch'\n\nimport type { FileForViewer } from './types'\n\nconst defaultScaleStep = new Decimal(0.2)\nconst defaultScaleSteps = [0.2, 0.6, 1, 1.6, 2, 3]\n\ntype Props = {\n file: FileForViewer\n width?: number\n\n /*\n * 拡大縮小率のステップを、100%を1とした配列で指定します。\n * */\n scaleSteps?: number[]\n\n scaleStep?: number\n onPassword?: ComponentProps<typeof PDFViewer>['onPassword']\n onLoadError?: () => void\n}\n\nexport const FileViewer: FC<Props> = ({\n file,\n scaleStep,\n scaleSteps,\n width: fixedWidth,\n onPassword,\n onLoadError,\n}) => {\n const ref = useRef<HTMLDivElement>(null)\n const [scale, setScale] = useState(1)\n const [loaded, setLoaded] = useState(false)\n const [rotation, setRotation] = useState<number | undefined>(undefined)\n const [width, setWidth] = useState(fixedWidth ?? 0)\n const isPDF = file.contentType === 'application/pdf'\n\n const search = usePDFSearch(file.url)\n\n const internalScaleStep = useMemo(\n () => (scaleStep ? new Decimal(scaleStep) : defaultScaleStep),\n [scaleStep],\n )\n\n const scaleUp = useCallback(() => {\n setScale((currentScale) => new Decimal(currentScale).add(internalScaleStep).toNumber())\n }, [internalScaleStep])\n\n const scaleDown = useCallback(() => {\n setScale((currentScale) => new Decimal(currentScale).sub(internalScaleStep).toNumber())\n }, [internalScaleStep])\n\n const rotate = useCallback(() => {\n // HINT: react-pdf側のAnnotationLayer.cssではマイナスの回転に対応しておらず、また0, 90, 180, 270度のみ対応しているため、-90度の場合は+270度として扱う\n const currentRotation = rotation ?? 0\n const newRotation = currentRotation === 0 ? 270 : currentRotation - 90\n setRotation(newRotation)\n }, [rotation])\n\n const handleLoaded = useCallback(() => {\n setLoaded(true)\n }, [])\n\n const handlePDFLoaded = useCallback((defaultRotation: number) => {\n setRotation(defaultRotation)\n }, [])\n\n useEffect(() => {\n if (!ref.current || fixedWidth !== undefined) {\n return\n }\n\n const resizeObserver = new ResizeObserver(() => {\n setWidth((ref.current?.clientWidth ?? 0) - 64)\n })\n\n resizeObserver.observe(ref.current)\n\n return () => {\n resizeObserver.disconnect()\n }\n }, [fixedWidth])\n\n return (\n <Scroller\n direction=\"both\"\n className=\"shr-flex shr-h-full shr-w-full shr-flex-col shr-gap-2 shr-bg-scrim shr-bg-[radial-gradient(theme(textColor.black)_1px,_transparent_0)] shr-bg-[length:16px_16px]\"\n ref={ref}\n >\n <div className=\"shr-sticky shr-start-0 shr-top-0 shr-z-[1] shr-flex shr-w-full shr-flex-shrink-0 shr-gap-0.5\">\n <Controller\n scale={scale}\n setScale={setScale}\n scaleSteps={scaleSteps || defaultScaleSteps}\n onClickScaleUpButton={scaleUp}\n onClickScaleDownButton={scaleDown}\n onClickRotateButton={rotate}\n searchController={isPDF ? <SearchController search={search} /> : undefined}\n />\n </div>\n <div className=\"shr-z-[0] shr-mx-auto shr-my-0 shr-box-border shr-flex shr-w-fit shr-flex-shrink-0 shr-grow shr-items-center shr-justify-center shr-px-2 shr-pb-2\">\n {!loaded && (\n <div className=\"shr-pointer-events-none shr-fixed shr-inset-0 shr-flex shr-h-full shr-w-full shr-items-center shr-justify-center\">\n <Loader type=\"light\" size=\"M\" />\n </div>\n )}\n <div className={!loaded ? 'shr-invisible' : ''}>\n {isPDF ? (\n <PDFViewer\n scale={scale}\n rotation={rotation}\n file={file}\n width={width}\n onLoad={handleLoaded}\n onPDFLoaded={handlePDFLoaded}\n onPassword={onPassword}\n onLoadError={onLoadError}\n search={search}\n />\n ) : file.contentType.startsWith('image/') ? (\n <ImageViewer\n scale={scale}\n rotation={rotation}\n file={file}\n width={width}\n onLoad={handleLoaded}\n onLoadError={onLoadError}\n />\n ) : (\n <Localizer\n id=\"smarthr-ui/FileViewer/unsupportedFileText\"\n defaultText=\"サポートされていない形式のファイルです。\"\n />\n )}\n </div>\n </div>\n </Scroller>\n )\n}\n\ntype ControllerProps = {\n scale: number\n setScale: (scale: number) => void\n scaleSteps: number[]\n onClickScaleUpButton: () => void\n onClickScaleDownButton: () => void\n onClickRotateButton: () => void\n searchController?: ReactNode\n}\n\nconst controllerClassNameGenerator = tv({\n base: 'shr-sticky shr-grid shr-w-full shr-items-center shr-bg-scrim shr-py-0.5 shr-shadow-layer-1',\n variants: {\n mobile: {\n true: 'shr-gap-0.5 shr-px-1',\n false: 'shr-grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] shr-gap-1.5 shr-px-2',\n },\n },\n})\n\nconst Controller: FC<ControllerProps> = memo(\n ({\n scale,\n setScale,\n scaleSteps,\n onClickScaleUpButton,\n onClickScaleDownButton,\n onClickRotateButton,\n searchController,\n }) => {\n const { mobile } = useEnvironment()\n const className = useMemo(() => controllerClassNameGenerator({ mobile }), [mobile])\n\n const onClickScaleStep = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => setScale(Number(e.currentTarget.value)),\n [setScale],\n )\n\n return (\n <div className={className}>\n {/* PC 表示時のときに中央の操作ボタンたちを中央へ寄せるための空のスペーサー */}\n {!mobile && <div role=\"presentation\" aria-hidden=\"true\" />}\n <Cluster gap={0.5} className=\"shr-justify-self-center\">\n <div className=\"shr-border-shorthand shr-flex shr-divide-x shr-divide-solid shr-overflow-hidden shr-rounded-m\">\n <Button\n onClick={onClickScaleDownButton}\n disabled={scale <= scaleSteps[0]}\n className=\"shr-rounded-r-none shr-border-none\"\n >\n <FaMagnifyingGlassMinusIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/scaleDownAlt\" defaultText=\"縮小\" />}\n />\n </Button>\n <DropdownMenuButton\n trigger={\n <>\n <VisuallyHiddenText>\n <Localizer id=\"smarthr-ui/FileViewer/scaleRateLabel\" defaultText=\"拡大率\" />\n </VisuallyHiddenText>\n {`${(scale * 100).toFixed(0)}%`}\n </>\n }\n className=\"shr-border-y-0 shr-border-[theme(borderColor.default)] [&_.smarthr-ui-Button]:shr-rounded-none [&_.smarthr-ui-Button]:shr-border-[transparent]\"\n >\n {scaleSteps.map((step) => (\n <Button\n key={step.toString()}\n value={step}\n onClick={onClickScaleStep}\n className=\"shr-rounded-none shr-border-0\"\n >\n {`${(step * 100).toFixed(0)}%`}\n </Button>\n ))}\n </DropdownMenuButton>\n <Button onClick={onClickScaleUpButton} className=\"shr-rounded-l-none shr-border-0\">\n <FaMagnifyingGlassPlusIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/scaleUpAlt\" defaultText=\"拡大\" />}\n />\n </Button>\n </div>\n <Button onClick={onClickRotateButton} className=\"shr-p-0.75\">\n <FaArrowRotateLeftIcon\n alt={<Localizer id=\"smarthr-ui/FileViewer/rotateAlt\" defaultText=\"左回転\" />}\n />\n </Button>\n </Cluster>\n {searchController ? (\n <div className=\"shr-min-w-0 shr-justify-self-stretch\">{searchController}</div>\n ) : (\n /* PC 表示時のときに中央の操作ボタンたちを中央へ寄せるための空のスペーサー */\n !mobile && <div role=\"presentation\" aria-hidden=\"true\" />\n )}\n </div>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsCA;AACA;;AAwBE;;;;AAIA;AACA;;;AASA;;AAEA;AAEA;;AAEA;AAEA;;AAEE;AACA;;AAEF;AAEA;;;AAIA;;;;;;;AASE;AACE;AACF;AAEA;AAEA;;AAEA;AACF;;AAyDF;AAYA;AACE;AACA;AACE;AACE;AACA;AACD;AACF;AACF;AAED;AAUI;AACA;;;;AA4DM;AAIR;;"}
@@ -5,6 +5,7 @@ var jsxRuntime = require('react/jsx-runtime');
5
5
  var React = require('react');
6
6
  require('./../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/index.cjs');
7
7
  var components_Scroller_Scroller = require('../Scroller/Scroller.cjs');
8
+ var components_FileViewer_buildCustomTextRenderer = require('./buildCustomTextRenderer.cjs');
8
9
  var components_FileViewer_generatedReactPDFStyle = require('./generatedReactPDFStyle.cjs');
9
10
  var Document = require('./../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/Document.cjs');
10
11
  var Page = require('./../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/Page.cjs');
@@ -42,8 +43,22 @@ const options = {
42
43
  // cMapUrl: '/cmaps/',
43
44
  cMapUrl: `//unpkg.com/pdfjs-dist@${pdf.version}/cmaps/`,
44
45
  };
45
- const PDFViewer = React.memo(({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError }) => {
46
+ // pdfjs が用意している CSS 変数 (--highlight-bg-color / --highlight-selected-bg-color) .textLayer スコープで上書きし、検索ハイライト色を変更している。
47
+ const HighlightOverrideStyle = () => (jsxRuntime.jsx("style", { children: `
48
+ .textLayer {
49
+ --highlight-bg-color: rgba(255, 235, 0, 0.5);
50
+ --highlight-selected-bg-color: rgba(255, 140, 0, 0.6);
51
+ }
52
+ .textLayer mark.highlight {
53
+ color: transparent;
54
+ }
55
+ ` }));
56
+ const PDFViewer = React.memo(({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError, search }) => {
57
+ const matches = search?.matches;
58
+ const currentMatchIndex = search?.currentMatchIndex;
59
+ const onPageTextLoaded = search?.registerPageText;
46
60
  const [pdfNumPages, setPdfNumPages] = React.useState(1);
61
+ const rootRef = React.useRef(null);
47
62
  const onDocumentLoadSuccess = React.useCallback(({ numPages }) => {
48
63
  setPdfNumPages(numPages);
49
64
  }, []);
@@ -61,7 +76,49 @@ const PDFViewer = React.memo(({ scale, rotation, file, width, onLoad, onPDFLoade
61
76
  }
62
77
  };
63
78
  }, [onLoad, onPDFLoaded, pdfNumPages, rotation]);
64
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(components_FileViewer_generatedReactPDFStyle.ReactPDFStyle, {}), jsxRuntime.jsx(components_Scroller_Scroller.Scroller, { direction: "both", className: "shr-h-full", children: jsxRuntime.jsx(Document, { options: options, file: file.url, onLoadSuccess: onDocumentLoadSuccess, onLoadError: onLoadError, rotate: rotation, className: "shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1", externalLinkTarget: "_blank", loading: null, onPassword: onPassword, children: Array.from({ length: pdfNumPages }).map((_, i) => (jsxRuntime.jsx(Page, { pageNumber: i + 1, width: width, scale: scale, className: "shr-w-full", onLoadSuccess: onPageLoad, loading: null }, `page_${i}`))) }) })] }));
79
+ const customTextRenderer = React.useMemo(() => {
80
+ if (!matches || matches.length === 0) {
81
+ return undefined;
82
+ }
83
+ return components_FileViewer_buildCustomTextRenderer.buildCustomTextRenderer(matches);
84
+ }, [matches]);
85
+ const handleGetTextSuccess = React.useCallback((pageIndex) => (textContent) => {
86
+ if (!onPageTextLoaded)
87
+ return;
88
+ const texts = textContent.items.reduce((acc, item) => {
89
+ if ('str' in item) {
90
+ acc.push(item.str);
91
+ }
92
+ return acc;
93
+ }, []);
94
+ onPageTextLoaded(pageIndex, texts);
95
+ }, [onPageTextLoaded]);
96
+ React.useEffect(() => {
97
+ const root = rootRef.current;
98
+ if (!root)
99
+ return;
100
+ root
101
+ .querySelectorAll(`mark.highlight.${components_FileViewer_buildCustomTextRenderer.SELECTED_MATCH_CLASS}`)
102
+ .forEach((el) => el.classList.remove(components_FileViewer_buildCustomTextRenderer.SELECTED_MATCH_CLASS));
103
+ if (currentMatchIndex === undefined || currentMatchIndex < 0)
104
+ return;
105
+ const start = performance.now();
106
+ let id = 0;
107
+ const apply = () => {
108
+ const els = root.querySelectorAll(components_FileViewer_buildCustomTextRenderer.matchSelector(currentMatchIndex));
109
+ if (els.length > 0) {
110
+ els.forEach((el) => el.classList.add(components_FileViewer_buildCustomTextRenderer.SELECTED_MATCH_CLASS));
111
+ els[0].scrollIntoView({ block: 'center', behavior: 'smooth' });
112
+ return;
113
+ }
114
+ if (performance.now() - start < 1000) {
115
+ id = requestAnimationFrame(apply);
116
+ }
117
+ };
118
+ id = requestAnimationFrame(apply);
119
+ return () => cancelAnimationFrame(id);
120
+ }, [currentMatchIndex, matches]);
121
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(components_FileViewer_generatedReactPDFStyle.ReactPDFStyle, {}), jsxRuntime.jsx(HighlightOverrideStyle, {}), jsxRuntime.jsx(components_Scroller_Scroller.Scroller, { ref: rootRef, direction: "both", className: "shr-h-full", children: jsxRuntime.jsx(Document, { options: options, file: file.url, onLoadSuccess: onDocumentLoadSuccess, onLoadError: onLoadError, rotate: rotation, className: "shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1", externalLinkTarget: "_blank", loading: null, onPassword: onPassword, children: Array.from({ length: pdfNumPages }).map((_, i) => (jsxRuntime.jsx(Page, { pageNumber: i + 1, width: width, scale: scale, className: "shr-w-full", onLoadSuccess: onPageLoad, onGetTextSuccess: handleGetTextSuccess(i), customTextRenderer: customTextRenderer, loading: null }, `page_${i}`))) }) })] }));
65
122
  });
66
123
 
67
124
  exports.PDFViewer = PDFViewer;
@@ -1 +1 @@
1
- {"version":3,"file":"PDFViewer.cjs","sources":["../../../src/components/FileViewer/PDFViewer.tsx"],"sourcesContent":["'use client'\n\nimport { type ComponentProps, type FC, memo, useCallback, useMemo, useState } from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Scroller } from '../Scroller'\n\nimport { ReactPDFStyle } from './generatedReactPDFStyle'\n\nimport type { ViewerProps } from './types'\n\nif (typeof window !== 'undefined') {\n // iOS 17.3以下ではPromise.withResolversが未定義のため、polyfillを適用する\n // @ts-expect-error\n if (typeof window.Promise.withResolvers === 'undefined') {\n // @ts-expect-error\n window.Promise.withResolvers = function () {\n let resolve, reject\n const promise = new Promise((res, rej) => {\n resolve = res\n reject = rej\n })\n return { promise, resolve, reject }\n }\n // web workerもpolyfillされたものを読み込む\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`\n } else {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // pdfjs.GlobalWorkerOptions.workerSrc = new URL(\n // 'pdfjs-dist/build/pdf.worker.min.mjs',\n // import.meta.url,\n // ).toString()\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`\n }\n}\n\nconst options = {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // 非latin文字を読み込むためのオプション\n // 参考: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#support-for-non-latin-characters\n // cMapUrl: '/cmaps/',\n cMapUrl: `//unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n} satisfies ComponentProps<typeof Document>['options']\n\nexport const PDFViewer: FC<ViewerProps> = memo(\n ({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError }) => {\n const [pdfNumPages, setPdfNumPages] = useState(1)\n\n const onDocumentLoadSuccess = useCallback<\n NonNullable<ComponentProps<typeof Document>['onLoadSuccess']>\n >(({ numPages }) => {\n setPdfNumPages(numPages)\n }, [])\n\n const onPageLoad: ComponentProps<typeof Page>['onLoadSuccess'] = useMemo(() => {\n if (!onLoad && !onPDFLoaded) {\n return undefined\n }\n\n return (page) => {\n if (onPDFLoaded && rotation === undefined) {\n onPDFLoaded(page.rotate)\n }\n // DocumentのLoadだとページごとの読み込みが考慮されないため\n if (onLoad && page.pageNumber === pdfNumPages) {\n onLoad()\n }\n }\n }, [onLoad, onPDFLoaded, pdfNumPages, rotation])\n\n return (\n <>\n {/* TODO: 外部CSSをsmarthr-uiから読み込んでもらえるようにする機構ができたら消す */}\n <ReactPDFStyle />\n <Scroller direction=\"both\" className=\"shr-h-full\">\n <Document\n options={options}\n file={file.url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onLoadError}\n rotate={rotation}\n className=\"shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1\"\n externalLinkTarget=\"_blank\"\n loading={null}\n onPassword={onPassword}\n >\n {Array.from({ length: pdfNumPages }).map((_, i) => (\n <Page\n key={`page_${i}`}\n pageNumber={i + 1}\n width={width}\n scale={scale}\n className=\"shr-w-full\"\n onLoadSuccess={onPageLoad}\n loading={null}\n />\n ))}\n </Document>\n </Scroller>\n </>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;;;AAWA;;;;;AAKI;;;;;AAKE;AACA;AACF;;;;;;;;;;;;AAWJ;AAEA;;;;;AAKE;;AAGK;;;;;AAUH;AACE;AACE;;;AAIA;AACE;;;;AAIA;;AAEJ;;;AAkCJ;;"}
1
+ {"version":3,"file":"PDFViewer.cjs","sources":["../../../src/components/FileViewer/PDFViewer.tsx"],"sourcesContent":["'use client'\n\nimport {\n type ComponentProps,\n type FC,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Scroller } from '../Scroller'\n\nimport {\n SELECTED_MATCH_CLASS,\n buildCustomTextRenderer,\n matchSelector,\n} from './buildCustomTextRenderer'\nimport { ReactPDFStyle } from './generatedReactPDFStyle'\n\nimport type { ViewerProps } from './types'\nimport type { UsePDFSearch } from './usePDFSearch'\n\nif (typeof window !== 'undefined') {\n // iOS 17.3以下ではPromise.withResolversが未定義のため、polyfillを適用する\n // @ts-expect-error\n if (typeof window.Promise.withResolvers === 'undefined') {\n // @ts-expect-error\n window.Promise.withResolvers = function () {\n let resolve, reject\n const promise = new Promise((res, rej) => {\n resolve = res\n reject = rej\n })\n return { promise, resolve, reject }\n }\n // web workerもpolyfillされたものを読み込む\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`\n } else {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // pdfjs.GlobalWorkerOptions.workerSrc = new URL(\n // 'pdfjs-dist/build/pdf.worker.min.mjs',\n // import.meta.url,\n // ).toString()\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`\n }\n}\n\nconst options = {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // 非latin文字を読み込むためのオプション\n // 参考: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#support-for-non-latin-characters\n // cMapUrl: '/cmaps/',\n cMapUrl: `//unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n} satisfies ComponentProps<typeof Document>['options']\n\ntype CustomTextRenderer = NonNullable<ComponentProps<typeof Page>['customTextRenderer']>\ntype TextContent = Parameters<NonNullable<ComponentProps<typeof Page>['onGetTextSuccess']>>[number]\n\n// pdfjs が用意している CSS 変数 (--highlight-bg-color / --highlight-selected-bg-color)を .textLayer スコープで上書きし、検索ハイライト色を変更している。\nconst HighlightOverrideStyle = () => (\n <style>{`\n.textLayer {\n --highlight-bg-color: rgba(255, 235, 0, 0.5);\n --highlight-selected-bg-color: rgba(255, 140, 0, 0.6);\n}\n.textLayer mark.highlight {\n color: transparent;\n}\n`}</style>\n)\n\ntype Props = ViewerProps & {\n search?: UsePDFSearch\n}\n\nexport const PDFViewer: FC<Props> = memo(\n ({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError, search }) => {\n const matches = search?.matches\n const currentMatchIndex = search?.currentMatchIndex\n const onPageTextLoaded = search?.registerPageText\n const [pdfNumPages, setPdfNumPages] = useState(1)\n const rootRef = useRef<HTMLDivElement>(null)\n\n const onDocumentLoadSuccess = useCallback<\n NonNullable<ComponentProps<typeof Document>['onLoadSuccess']>\n >(({ numPages }) => {\n setPdfNumPages(numPages)\n }, [])\n\n const onPageLoad: ComponentProps<typeof Page>['onLoadSuccess'] = useMemo(() => {\n if (!onLoad && !onPDFLoaded) {\n return undefined\n }\n\n return (page) => {\n if (onPDFLoaded && rotation === undefined) {\n onPDFLoaded(page.rotate)\n }\n // DocumentのLoadだとページごとの読み込みが考慮されないため\n if (onLoad && page.pageNumber === pdfNumPages) {\n onLoad()\n }\n }\n }, [onLoad, onPDFLoaded, pdfNumPages, rotation])\n\n const customTextRenderer = useMemo<CustomTextRenderer | undefined>(() => {\n if (!matches || matches.length === 0) {\n return undefined\n }\n return buildCustomTextRenderer(matches)\n }, [matches])\n\n const handleGetTextSuccess = useCallback(\n (pageIndex: number) => (textContent: TextContent) => {\n if (!onPageTextLoaded) return\n const texts = textContent.items.reduce<string[]>((acc, item) => {\n if ('str' in item) {\n acc.push(item.str)\n }\n return acc\n }, [])\n onPageTextLoaded(pageIndex, texts)\n },\n [onPageTextLoaded],\n )\n\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n root\n .querySelectorAll(`mark.highlight.${SELECTED_MATCH_CLASS}`)\n .forEach((el) => el.classList.remove(SELECTED_MATCH_CLASS))\n\n if (currentMatchIndex === undefined || currentMatchIndex < 0) return\n\n const start = performance.now()\n let id = 0\n const apply = () => {\n const els = root.querySelectorAll(matchSelector(currentMatchIndex))\n if (els.length > 0) {\n els.forEach((el) => el.classList.add(SELECTED_MATCH_CLASS))\n els[0].scrollIntoView({ block: 'center', behavior: 'smooth' })\n return\n }\n if (performance.now() - start < 1000) {\n id = requestAnimationFrame(apply)\n }\n }\n id = requestAnimationFrame(apply)\n return () => cancelAnimationFrame(id)\n }, [currentMatchIndex, matches])\n\n return (\n <>\n {/* TODO: 外部CSSをsmarthr-uiから読み込んでもらえるようにする機構ができたら消す */}\n <ReactPDFStyle />\n <HighlightOverrideStyle />\n <Scroller ref={rootRef} direction=\"both\" className=\"shr-h-full\">\n <Document\n options={options}\n file={file.url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onLoadError}\n rotate={rotation}\n className=\"shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1\"\n externalLinkTarget=\"_blank\"\n loading={null}\n onPassword={onPassword}\n >\n {Array.from({ length: pdfNumPages }).map((_, i) => (\n <Page\n key={`page_${i}`}\n pageNumber={i + 1}\n width={width}\n scale={scale}\n className=\"shr-w-full\"\n onLoadSuccess={onPageLoad}\n onGetTextSuccess={handleGetTextSuccess(i)}\n customTextRenderer={customTextRenderer}\n loading={null}\n />\n ))}\n </Document>\n </Scroller>\n </>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;;;;AA0BA;;;;;AAKI;;;;;AAKE;AACA;AACF;;;;;;;;;;;;AAWJ;AAEA;;;;;AAKE;;AAMF;AACA;;;;;;;;AASC;AAOM;AAEH;AACA;AACA;;AAEA;;;;AAQA;AACE;AACE;;;AAIA;AACE;;;;AAIA;;AAEJ;;AAGF;;AAEI;;AAEF;AACF;AAEA;AAEI;;AACA;AACE;AACE;;AAEF;;AAEF;AACF;;AAKA;AACA;;;AAEG;AACA;AAEH;;AAEA;;;;AAIE;AACE;AACA;;;;AAIA;;AAEJ;AACA;AACA;AACF;AAEA;AAkCF;;"}
@@ -1,3 +1,8 @@
1
1
  import { type FC } from 'react';
2
2
  import type { ViewerProps } from './types';
3
- export declare const PDFViewer: FC<ViewerProps>;
3
+ import type { UsePDFSearch } from './usePDFSearch';
4
+ type Props = ViewerProps & {
5
+ search?: UsePDFSearch;
6
+ };
7
+ export declare const PDFViewer: FC<Props>;
8
+ export {};
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
3
- import { memo, useState, useCallback, useMemo } from 'react';
3
+ import { memo, useState, useRef, useCallback, useMemo, useEffect } from 'react';
4
4
  import './../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/index.js';
5
5
  import { Scroller } from '../Scroller/Scroller.js';
6
+ import { buildCustomTextRenderer, SELECTED_MATCH_CLASS, matchSelector } from './buildCustomTextRenderer.js';
6
7
  import { ReactPDFStyle } from './generatedReactPDFStyle.js';
7
8
  import Document from './../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/Document.js';
8
9
  import Page from './../../vendor/.pnpm/react-pdf@9.2.1_@types_react@18.3.28_react-dom@19.2.6_react@19.2.6__react@19.2.6/vendor/react-pdf/dist/esm/Page.js';
@@ -40,8 +41,22 @@ const options = {
40
41
  // cMapUrl: '/cmaps/',
41
42
  cMapUrl: `//unpkg.com/pdfjs-dist@${__webpack_exports__version}/cmaps/`,
42
43
  };
43
- const PDFViewer = memo(({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError }) => {
44
+ // pdfjs が用意している CSS 変数 (--highlight-bg-color / --highlight-selected-bg-color) .textLayer スコープで上書きし、検索ハイライト色を変更している。
45
+ const HighlightOverrideStyle = () => (jsx("style", { children: `
46
+ .textLayer {
47
+ --highlight-bg-color: rgba(255, 235, 0, 0.5);
48
+ --highlight-selected-bg-color: rgba(255, 140, 0, 0.6);
49
+ }
50
+ .textLayer mark.highlight {
51
+ color: transparent;
52
+ }
53
+ ` }));
54
+ const PDFViewer = memo(({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError, search }) => {
55
+ const matches = search?.matches;
56
+ const currentMatchIndex = search?.currentMatchIndex;
57
+ const onPageTextLoaded = search?.registerPageText;
44
58
  const [pdfNumPages, setPdfNumPages] = useState(1);
59
+ const rootRef = useRef(null);
45
60
  const onDocumentLoadSuccess = useCallback(({ numPages }) => {
46
61
  setPdfNumPages(numPages);
47
62
  }, []);
@@ -59,7 +74,49 @@ const PDFViewer = memo(({ scale, rotation, file, width, onLoad, onPDFLoaded, onP
59
74
  }
60
75
  };
61
76
  }, [onLoad, onPDFLoaded, pdfNumPages, rotation]);
62
- return (jsxs(Fragment, { children: [jsx(ReactPDFStyle, {}), jsx(Scroller, { direction: "both", className: "shr-h-full", children: jsx(Document, { options: options, file: file.url, onLoadSuccess: onDocumentLoadSuccess, onLoadError: onLoadError, rotate: rotation, className: "shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1", externalLinkTarget: "_blank", loading: null, onPassword: onPassword, children: Array.from({ length: pdfNumPages }).map((_, i) => (jsx(Page, { pageNumber: i + 1, width: width, scale: scale, className: "shr-w-full", onLoadSuccess: onPageLoad, loading: null }, `page_${i}`))) }) })] }));
77
+ const customTextRenderer = useMemo(() => {
78
+ if (!matches || matches.length === 0) {
79
+ return undefined;
80
+ }
81
+ return buildCustomTextRenderer(matches);
82
+ }, [matches]);
83
+ const handleGetTextSuccess = useCallback((pageIndex) => (textContent) => {
84
+ if (!onPageTextLoaded)
85
+ return;
86
+ const texts = textContent.items.reduce((acc, item) => {
87
+ if ('str' in item) {
88
+ acc.push(item.str);
89
+ }
90
+ return acc;
91
+ }, []);
92
+ onPageTextLoaded(pageIndex, texts);
93
+ }, [onPageTextLoaded]);
94
+ useEffect(() => {
95
+ const root = rootRef.current;
96
+ if (!root)
97
+ return;
98
+ root
99
+ .querySelectorAll(`mark.highlight.${SELECTED_MATCH_CLASS}`)
100
+ .forEach((el) => el.classList.remove(SELECTED_MATCH_CLASS));
101
+ if (currentMatchIndex === undefined || currentMatchIndex < 0)
102
+ return;
103
+ const start = performance.now();
104
+ let id = 0;
105
+ const apply = () => {
106
+ const els = root.querySelectorAll(matchSelector(currentMatchIndex));
107
+ if (els.length > 0) {
108
+ els.forEach((el) => el.classList.add(SELECTED_MATCH_CLASS));
109
+ els[0].scrollIntoView({ block: 'center', behavior: 'smooth' });
110
+ return;
111
+ }
112
+ if (performance.now() - start < 1000) {
113
+ id = requestAnimationFrame(apply);
114
+ }
115
+ };
116
+ id = requestAnimationFrame(apply);
117
+ return () => cancelAnimationFrame(id);
118
+ }, [currentMatchIndex, matches]);
119
+ return (jsxs(Fragment, { children: [jsx(ReactPDFStyle, {}), jsx(HighlightOverrideStyle, {}), jsx(Scroller, { ref: rootRef, direction: "both", className: "shr-h-full", children: jsx(Document, { options: options, file: file.url, onLoadSuccess: onDocumentLoadSuccess, onLoadError: onLoadError, rotate: rotation, className: "shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1", externalLinkTarget: "_blank", loading: null, onPassword: onPassword, children: Array.from({ length: pdfNumPages }).map((_, i) => (jsx(Page, { pageNumber: i + 1, width: width, scale: scale, className: "shr-w-full", onLoadSuccess: onPageLoad, onGetTextSuccess: handleGetTextSuccess(i), customTextRenderer: customTextRenderer, loading: null }, `page_${i}`))) }) })] }));
63
120
  });
64
121
 
65
122
  export { PDFViewer };
@@ -1 +1 @@
1
- {"version":3,"file":"PDFViewer.js","sources":["../../../src/components/FileViewer/PDFViewer.tsx"],"sourcesContent":["'use client'\n\nimport { type ComponentProps, type FC, memo, useCallback, useMemo, useState } from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Scroller } from '../Scroller'\n\nimport { ReactPDFStyle } from './generatedReactPDFStyle'\n\nimport type { ViewerProps } from './types'\n\nif (typeof window !== 'undefined') {\n // iOS 17.3以下ではPromise.withResolversが未定義のため、polyfillを適用する\n // @ts-expect-error\n if (typeof window.Promise.withResolvers === 'undefined') {\n // @ts-expect-error\n window.Promise.withResolvers = function () {\n let resolve, reject\n const promise = new Promise((res, rej) => {\n resolve = res\n reject = rej\n })\n return { promise, resolve, reject }\n }\n // web workerもpolyfillされたものを読み込む\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`\n } else {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // pdfjs.GlobalWorkerOptions.workerSrc = new URL(\n // 'pdfjs-dist/build/pdf.worker.min.mjs',\n // import.meta.url,\n // ).toString()\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`\n }\n}\n\nconst options = {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // 非latin文字を読み込むためのオプション\n // 参考: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#support-for-non-latin-characters\n // cMapUrl: '/cmaps/',\n cMapUrl: `//unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n} satisfies ComponentProps<typeof Document>['options']\n\nexport const PDFViewer: FC<ViewerProps> = memo(\n ({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError }) => {\n const [pdfNumPages, setPdfNumPages] = useState(1)\n\n const onDocumentLoadSuccess = useCallback<\n NonNullable<ComponentProps<typeof Document>['onLoadSuccess']>\n >(({ numPages }) => {\n setPdfNumPages(numPages)\n }, [])\n\n const onPageLoad: ComponentProps<typeof Page>['onLoadSuccess'] = useMemo(() => {\n if (!onLoad && !onPDFLoaded) {\n return undefined\n }\n\n return (page) => {\n if (onPDFLoaded && rotation === undefined) {\n onPDFLoaded(page.rotate)\n }\n // DocumentのLoadだとページごとの読み込みが考慮されないため\n if (onLoad && page.pageNumber === pdfNumPages) {\n onLoad()\n }\n }\n }, [onLoad, onPDFLoaded, pdfNumPages, rotation])\n\n return (\n <>\n {/* TODO: 外部CSSをsmarthr-uiから読み込んでもらえるようにする機構ができたら消す */}\n <ReactPDFStyle />\n <Scroller direction=\"both\" className=\"shr-h-full\">\n <Document\n options={options}\n file={file.url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onLoadError}\n rotate={rotation}\n className=\"shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1\"\n externalLinkTarget=\"_blank\"\n loading={null}\n onPassword={onPassword}\n >\n {Array.from({ length: pdfNumPages }).map((_, i) => (\n <Page\n key={`page_${i}`}\n pageNumber={i + 1}\n width={width}\n scale={scale}\n className=\"shr-w-full\"\n onLoadSuccess={onPageLoad}\n loading={null}\n />\n ))}\n </Document>\n </Scroller>\n </>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;AAWA;;;;;AAKI;;;;;AAKE;AACA;AACF;;;;;;;;;;;;AAWJ;AAEA;;;;;AAKE;;AAGK;;;;;AAUH;AACE;AACE;;;AAIA;AACE;;;;AAIA;;AAEJ;;;AAkCJ;;"}
1
+ {"version":3,"file":"PDFViewer.js","sources":["../../../src/components/FileViewer/PDFViewer.tsx"],"sourcesContent":["'use client'\n\nimport {\n type ComponentProps,\n type FC,\n memo,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react'\nimport { Document, Page, pdfjs } from 'react-pdf'\n\nimport { Scroller } from '../Scroller'\n\nimport {\n SELECTED_MATCH_CLASS,\n buildCustomTextRenderer,\n matchSelector,\n} from './buildCustomTextRenderer'\nimport { ReactPDFStyle } from './generatedReactPDFStyle'\n\nimport type { ViewerProps } from './types'\nimport type { UsePDFSearch } from './usePDFSearch'\n\nif (typeof window !== 'undefined') {\n // iOS 17.3以下ではPromise.withResolversが未定義のため、polyfillを適用する\n // @ts-expect-error\n if (typeof window.Promise.withResolvers === 'undefined') {\n // @ts-expect-error\n window.Promise.withResolvers = function () {\n let resolve, reject\n const promise = new Promise((res, rej) => {\n resolve = res\n reject = rej\n })\n return { promise, resolve, reject }\n }\n // web workerもpolyfillされたものを読み込む\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/legacy/build/pdf.worker.min.mjs`\n } else {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // pdfjs.GlobalWorkerOptions.workerSrc = new URL(\n // 'pdfjs-dist/build/pdf.worker.min.mjs',\n // import.meta.url,\n // ).toString()\n pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`\n }\n}\n\nconst options = {\n // TODO: バンドラの関係でCDNから読み込んでいるが、smarthr-uiから配信するようにしたい\n // 非latin文字を読み込むためのオプション\n // 参考: https://github.com/wojtekmaj/react-pdf?tab=readme-ov-file#support-for-non-latin-characters\n // cMapUrl: '/cmaps/',\n cMapUrl: `//unpkg.com/pdfjs-dist@${pdfjs.version}/cmaps/`,\n} satisfies ComponentProps<typeof Document>['options']\n\ntype CustomTextRenderer = NonNullable<ComponentProps<typeof Page>['customTextRenderer']>\ntype TextContent = Parameters<NonNullable<ComponentProps<typeof Page>['onGetTextSuccess']>>[number]\n\n// pdfjs が用意している CSS 変数 (--highlight-bg-color / --highlight-selected-bg-color)を .textLayer スコープで上書きし、検索ハイライト色を変更している。\nconst HighlightOverrideStyle = () => (\n <style>{`\n.textLayer {\n --highlight-bg-color: rgba(255, 235, 0, 0.5);\n --highlight-selected-bg-color: rgba(255, 140, 0, 0.6);\n}\n.textLayer mark.highlight {\n color: transparent;\n}\n`}</style>\n)\n\ntype Props = ViewerProps & {\n search?: UsePDFSearch\n}\n\nexport const PDFViewer: FC<Props> = memo(\n ({ scale, rotation, file, width, onLoad, onPDFLoaded, onPassword, onLoadError, search }) => {\n const matches = search?.matches\n const currentMatchIndex = search?.currentMatchIndex\n const onPageTextLoaded = search?.registerPageText\n const [pdfNumPages, setPdfNumPages] = useState(1)\n const rootRef = useRef<HTMLDivElement>(null)\n\n const onDocumentLoadSuccess = useCallback<\n NonNullable<ComponentProps<typeof Document>['onLoadSuccess']>\n >(({ numPages }) => {\n setPdfNumPages(numPages)\n }, [])\n\n const onPageLoad: ComponentProps<typeof Page>['onLoadSuccess'] = useMemo(() => {\n if (!onLoad && !onPDFLoaded) {\n return undefined\n }\n\n return (page) => {\n if (onPDFLoaded && rotation === undefined) {\n onPDFLoaded(page.rotate)\n }\n // DocumentのLoadだとページごとの読み込みが考慮されないため\n if (onLoad && page.pageNumber === pdfNumPages) {\n onLoad()\n }\n }\n }, [onLoad, onPDFLoaded, pdfNumPages, rotation])\n\n const customTextRenderer = useMemo<CustomTextRenderer | undefined>(() => {\n if (!matches || matches.length === 0) {\n return undefined\n }\n return buildCustomTextRenderer(matches)\n }, [matches])\n\n const handleGetTextSuccess = useCallback(\n (pageIndex: number) => (textContent: TextContent) => {\n if (!onPageTextLoaded) return\n const texts = textContent.items.reduce<string[]>((acc, item) => {\n if ('str' in item) {\n acc.push(item.str)\n }\n return acc\n }, [])\n onPageTextLoaded(pageIndex, texts)\n },\n [onPageTextLoaded],\n )\n\n useEffect(() => {\n const root = rootRef.current\n if (!root) return\n root\n .querySelectorAll(`mark.highlight.${SELECTED_MATCH_CLASS}`)\n .forEach((el) => el.classList.remove(SELECTED_MATCH_CLASS))\n\n if (currentMatchIndex === undefined || currentMatchIndex < 0) return\n\n const start = performance.now()\n let id = 0\n const apply = () => {\n const els = root.querySelectorAll(matchSelector(currentMatchIndex))\n if (els.length > 0) {\n els.forEach((el) => el.classList.add(SELECTED_MATCH_CLASS))\n els[0].scrollIntoView({ block: 'center', behavior: 'smooth' })\n return\n }\n if (performance.now() - start < 1000) {\n id = requestAnimationFrame(apply)\n }\n }\n id = requestAnimationFrame(apply)\n return () => cancelAnimationFrame(id)\n }, [currentMatchIndex, matches])\n\n return (\n <>\n {/* TODO: 外部CSSをsmarthr-uiから読み込んでもらえるようにする機構ができたら消す */}\n <ReactPDFStyle />\n <HighlightOverrideStyle />\n <Scroller ref={rootRef} direction=\"both\" className=\"shr-h-full\">\n <Document\n options={options}\n file={file.url}\n onLoadSuccess={onDocumentLoadSuccess}\n onLoadError={onLoadError}\n rotate={rotation}\n className=\"shr-flex shr-w-fit shr-flex-col shr-items-center shr-gap-1\"\n externalLinkTarget=\"_blank\"\n loading={null}\n onPassword={onPassword}\n >\n {Array.from({ length: pdfNumPages }).map((_, i) => (\n <Page\n key={`page_${i}`}\n pageNumber={i + 1}\n width={width}\n scale={scale}\n className=\"shr-w-full\"\n onLoadSuccess={onPageLoad}\n onGetTextSuccess={handleGetTextSuccess(i)}\n customTextRenderer={customTextRenderer}\n loading={null}\n />\n ))}\n </Document>\n </Scroller>\n </>\n )\n },\n)\n"],"names":[],"mappings":";;;;;;;;;;;AA0BA;;;;;AAKI;;;;;AAKE;AACA;AACF;;;;;;;;;;;;AAWJ;AAEA;;;;;AAKE;;AAMF;AACA;;;;;;;;AASC;AAOM;AAEH;AACA;AACA;;AAEA;;;;AAQA;AACE;AACE;;;AAIA;AACE;;;;AAIA;;AAEJ;;AAGF;;AAEI;;AAEF;AACF;AAEA;AAEI;;AACA;AACE;AACE;;AAEF;;AAEF;AACF;;AAKA;AACA;;;AAEG;AACA;AAEH;;AAEA;;;;AAIE;AACE;AACA;;;;AAIA;;AAEJ;AACA;AACA;AACF;AAEA;AAkCF;;"}
@@ -0,0 +1,105 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var React = require('react');
6
+ var index = require('./../../vendor/.pnpm/tailwind-variants@0.3.1_tailwindcss@3.4.19_ts-node@10.9.2_@swc_core@1.15.17_@types_node@20.19.35_typescript@5.9.3__/vendor/tailwind-variants/dist/index.cjs');
7
+ var hooks_useEnvironment_useEnvironment = require('../../hooks/useEnvironment/useEnvironment.cjs');
8
+ require('../../themes/createSpacing.cjs');
9
+ require('../../_virtual/index.cjs');
10
+ require('../../_virtual/index2.cjs');
11
+ require('../../themes/createColor.cjs');
12
+ require('../../themes/createTextColor.cjs');
13
+ require('styled-components');
14
+ require('../../themes/createShadow/defaultShadow.cjs');
15
+ require('../../themes/createWidth.cjs');
16
+ require('../../themes/createBackgroundColor.cjs');
17
+ require('../../themes/createBorder.cjs');
18
+ require('../../hooks/useTheme.cjs');
19
+ require('../../intl/IntlProvider.cjs');
20
+ var intl_useIntl = require('../../intl/useIntl.cjs');
21
+ require('../../intl/Localizer.cjs');
22
+ require('../../_virtual/dayjs.min.cjs');
23
+ require('../../intl/TimeFormatter.cjs');
24
+ var components_Button_Button = require('../Button/Button.cjs');
25
+ require('../Button/AnchorButton.cjs');
26
+ require('../Button/UnstyledButton.cjs');
27
+ var components_Icon_FaIcon = require('../Icon/FaIcon.cjs');
28
+ require('../Icon/generateIcon.cjs');
29
+ require('../Icon/OpenInNewTabIcon.cjs');
30
+ require('../Input/Input.cjs');
31
+ require('../Input/CurrencyInput/CurrencyInput.cjs');
32
+ var components_Input_SearchInput_SearchInput = require('../Input/SearchInput/SearchInput.cjs');
33
+ var components_Text_Text = require('../Text/Text.cjs');
34
+
35
+ const classNameGenerator = index.tv({
36
+ slots: {
37
+ wrapper: 'shr-flex shr-w-full',
38
+ inputArea: 'shr-min-w-0 shr-grow',
39
+ },
40
+ variants: {
41
+ mobile: {
42
+ true: {},
43
+ false: {
44
+ wrapper: 'shr-justify-end',
45
+ inputArea: 'shr-max-w-[15em]',
46
+ },
47
+ },
48
+ },
49
+ });
50
+ const SearchController = React.memo(({ search }) => {
51
+ const { query, setQuery, matchCount, currentMatchIndex, goNext: onClickNext, goPrev: onClickPrev, clear: onClickClear, } = search;
52
+ const { localize } = intl_useIntl.useIntl();
53
+ const { mobile } = hooks_useEnvironment_useEnvironment.useEnvironment();
54
+ const classNames = React.useMemo(() => {
55
+ const { wrapper, inputArea } = classNameGenerator({ mobile });
56
+ return { wrapper: wrapper(), inputArea: inputArea() };
57
+ }, [mobile]);
58
+ const translated = React.useMemo(() => ({
59
+ searchInputTooltipMessage: localize({
60
+ id: 'smarthr-ui/FileViewer/searchInputTooltipMessage',
61
+ defaultText: 'PDF内のテキストを検索',
62
+ }),
63
+ previousMatchAlt: localize({
64
+ id: 'smarthr-ui/FileViewer/previousMatchAlt',
65
+ defaultText: '前の検索結果へ',
66
+ }),
67
+ nextMatchAlt: localize({
68
+ id: 'smarthr-ui/FileViewer/nextMatchAlt',
69
+ defaultText: '次の検索結果へ',
70
+ }),
71
+ }), [localize]);
72
+ const hasMatches = matchCount > 0;
73
+ const displayedCurrent = hasMatches ? currentMatchIndex + 1 : 0;
74
+ const handleChange = React.useCallback((e) => {
75
+ setQuery(e.target.value);
76
+ }, [setQuery]);
77
+ const handleKeyDown = React.useCallback((e) => {
78
+ if (e.nativeEvent.isComposing) {
79
+ return;
80
+ }
81
+ switch (e.key) {
82
+ case 'Enter': {
83
+ e.preventDefault();
84
+ if (e.shiftKey) {
85
+ onClickPrev();
86
+ }
87
+ else {
88
+ onClickNext();
89
+ }
90
+ break;
91
+ }
92
+ case 'Escape': {
93
+ if (query !== '') {
94
+ e.preventDefault();
95
+ onClickClear();
96
+ }
97
+ break;
98
+ }
99
+ }
100
+ }, [onClickNext, onClickPrev, onClickClear, query]);
101
+ return (jsxRuntime.jsxs("div", { className: classNames.wrapper, children: [jsxRuntime.jsx("div", { className: classNames.inputArea, children: jsxRuntime.jsx(components_Input_SearchInput_SearchInput.SearchInput, { name: "file_viewer_search", tooltipMessage: translated.searchInputTooltipMessage, value: query, onChange: handleChange, onKeyDown: handleKeyDown, width: "100%", suffix: query !== '' ? (jsxRuntime.jsx(components_Text_Text.Text, { size: "S", "aria-live": "polite", className: "shr-tabular-nums", children: `${displayedCurrent}/${matchCount}` })) : undefined, className: "[&_.smarthr-ui-Input]:shr-rounded-e-none" }) }), jsxRuntime.jsx(components_Button_Button.Button, { onClick: onClickPrev, disabled: !hasMatches, className: "shr-rounded-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default", children: jsxRuntime.jsx(components_Icon_FaIcon.FaAngleUpIcon, { alt: translated.previousMatchAlt }) }), jsxRuntime.jsx(components_Button_Button.Button, { onClick: onClickNext, disabled: !hasMatches, className: "shr-rounded-s-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default", children: jsxRuntime.jsx(components_Icon_FaIcon.FaAngleDownIcon, { alt: translated.nextMatchAlt }) })] }));
102
+ });
103
+
104
+ exports.SearchController = SearchController;
105
+ //# sourceMappingURL=SearchController.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchController.cjs","sources":["../../../src/components/FileViewer/SearchController.tsx"],"sourcesContent":["'use client'\n\nimport { type ChangeEvent, type FC, type KeyboardEvent, memo, useCallback, useMemo } from 'react'\nimport { tv } from 'tailwind-variants'\n\nimport { useEnvironment } from '../../hooks/useEnvironment'\nimport { useIntl } from '../../intl'\nimport { Button } from '../Button'\nimport { FaAngleDownIcon, FaAngleUpIcon } from '../Icon'\nimport { SearchInput } from '../Input'\nimport { Text } from '../Text'\n\nimport type { UsePDFSearch } from './usePDFSearch'\n\ntype Props = {\n search: UsePDFSearch\n}\n\nconst classNameGenerator = tv({\n slots: {\n wrapper: 'shr-flex shr-w-full',\n inputArea: 'shr-min-w-0 shr-grow',\n },\n variants: {\n mobile: {\n true: {},\n false: {\n wrapper: 'shr-justify-end',\n inputArea: 'shr-max-w-[15em]',\n },\n },\n },\n})\n\nexport const SearchController: FC<Props> = memo(({ search }) => {\n const {\n query,\n setQuery,\n matchCount,\n currentMatchIndex,\n goNext: onClickNext,\n goPrev: onClickPrev,\n clear: onClickClear,\n } = search\n const { localize } = useIntl()\n const { mobile } = useEnvironment()\n const classNames = useMemo(() => {\n const { wrapper, inputArea } = classNameGenerator({ mobile })\n return { wrapper: wrapper(), inputArea: inputArea() }\n }, [mobile])\n const translated = useMemo(\n () => ({\n searchInputTooltipMessage: localize({\n id: 'smarthr-ui/FileViewer/searchInputTooltipMessage',\n defaultText: 'PDF内のテキストを検索',\n }),\n previousMatchAlt: localize({\n id: 'smarthr-ui/FileViewer/previousMatchAlt',\n defaultText: '前の検索結果へ',\n }),\n nextMatchAlt: localize({\n id: 'smarthr-ui/FileViewer/nextMatchAlt',\n defaultText: '次の検索結果へ',\n }),\n }),\n [localize],\n )\n\n const hasMatches = matchCount > 0\n const displayedCurrent = hasMatches ? currentMatchIndex + 1 : 0\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setQuery(e.target.value)\n },\n [setQuery],\n )\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.nativeEvent.isComposing) {\n return\n }\n switch (e.key) {\n case 'Enter': {\n e.preventDefault()\n if (e.shiftKey) {\n onClickPrev()\n } else {\n onClickNext()\n }\n break\n }\n case 'Escape': {\n if (query !== '') {\n e.preventDefault()\n onClickClear()\n }\n break\n }\n }\n },\n [onClickNext, onClickPrev, onClickClear, query],\n )\n\n return (\n <div className={classNames.wrapper}>\n <div className={classNames.inputArea}>\n <SearchInput\n name=\"file_viewer_search\"\n tooltipMessage={translated.searchInputTooltipMessage}\n value={query}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n width=\"100%\"\n suffix={\n query !== '' ? (\n <Text size=\"S\" aria-live=\"polite\" className=\"shr-tabular-nums\">\n {`${displayedCurrent}/${matchCount}`}\n </Text>\n ) : undefined\n }\n className=\"[&_.smarthr-ui-Input]:shr-rounded-e-none\"\n />\n </div>\n <Button\n onClick={onClickPrev}\n disabled={!hasMatches}\n className=\"shr-rounded-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default\"\n >\n <FaAngleUpIcon alt={translated.previousMatchAlt} />\n </Button>\n <Button\n onClick={onClickNext}\n disabled={!hasMatches}\n className=\"shr-rounded-s-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default\"\n >\n <FaAngleDownIcon alt={translated.nextMatchAlt} />\n </Button>\n </div>\n )\n})\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkBA;AACE;AACE;AACA;AACD;AACD;AACE;AACE;AACA;AACE;AACA;AACD;AACF;AACF;AACF;AAEM;;AAUL;AACA;AACA;AACE;;AAEF;AACA;;AAGM;AACA;;;AAGA;AACA;;;AAGA;AACA;;AAEH;AAIH;AACA;AAEA;AAEI;AACF;AAIF;AAEI;;;AAGA;;;AAGI;AACE;;;AAEA;;;;;AAKF;;AAEE;;;;;;AASV;AAoCF;;"}
@@ -0,0 +1,7 @@
1
+ import { type FC } from 'react';
2
+ import type { UsePDFSearch } from './usePDFSearch';
3
+ type Props = {
4
+ search: UsePDFSearch;
5
+ };
6
+ export declare const SearchController: FC<Props>;
7
+ export {};
@@ -0,0 +1,103 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { memo, useMemo, useCallback } from 'react';
4
+ import { tv as ce } from './../../vendor/.pnpm/tailwind-variants@0.3.1_tailwindcss@3.4.19_ts-node@10.9.2_@swc_core@1.15.17_@types_node@20.19.35_typescript@5.9.3__/vendor/tailwind-variants/dist/index.js';
5
+ import { useEnvironment } from '../../hooks/useEnvironment/useEnvironment.js';
6
+ import '../../themes/createSpacing.js';
7
+ import '../../_virtual/index.js';
8
+ import '../../_virtual/index2.js';
9
+ import '../../themes/createColor.js';
10
+ import '../../themes/createTextColor.js';
11
+ import 'styled-components';
12
+ import '../../themes/createShadow/defaultShadow.js';
13
+ import '../../themes/createWidth.js';
14
+ import '../../themes/createBackgroundColor.js';
15
+ import '../../themes/createBorder.js';
16
+ import '../../hooks/useTheme.js';
17
+ import '../../intl/IntlProvider.js';
18
+ import { useIntl } from '../../intl/useIntl.js';
19
+ import '../../intl/Localizer.js';
20
+ import '../../_virtual/dayjs.min.js';
21
+ import '../../intl/TimeFormatter.js';
22
+ import { Button } from '../Button/Button.js';
23
+ import '../Button/AnchorButton.js';
24
+ import '../Button/UnstyledButton.js';
25
+ import { FaAngleUpIcon, FaAngleDownIcon } from '../Icon/FaIcon.js';
26
+ import '../Icon/generateIcon.js';
27
+ import '../Icon/OpenInNewTabIcon.js';
28
+ import '../Input/Input.js';
29
+ import '../Input/CurrencyInput/CurrencyInput.js';
30
+ import { SearchInput } from '../Input/SearchInput/SearchInput.js';
31
+ import { Text } from '../Text/Text.js';
32
+
33
+ const classNameGenerator = ce({
34
+ slots: {
35
+ wrapper: 'shr-flex shr-w-full',
36
+ inputArea: 'shr-min-w-0 shr-grow',
37
+ },
38
+ variants: {
39
+ mobile: {
40
+ true: {},
41
+ false: {
42
+ wrapper: 'shr-justify-end',
43
+ inputArea: 'shr-max-w-[15em]',
44
+ },
45
+ },
46
+ },
47
+ });
48
+ const SearchController = memo(({ search }) => {
49
+ const { query, setQuery, matchCount, currentMatchIndex, goNext: onClickNext, goPrev: onClickPrev, clear: onClickClear, } = search;
50
+ const { localize } = useIntl();
51
+ const { mobile } = useEnvironment();
52
+ const classNames = useMemo(() => {
53
+ const { wrapper, inputArea } = classNameGenerator({ mobile });
54
+ return { wrapper: wrapper(), inputArea: inputArea() };
55
+ }, [mobile]);
56
+ const translated = useMemo(() => ({
57
+ searchInputTooltipMessage: localize({
58
+ id: 'smarthr-ui/FileViewer/searchInputTooltipMessage',
59
+ defaultText: 'PDF内のテキストを検索',
60
+ }),
61
+ previousMatchAlt: localize({
62
+ id: 'smarthr-ui/FileViewer/previousMatchAlt',
63
+ defaultText: '前の検索結果へ',
64
+ }),
65
+ nextMatchAlt: localize({
66
+ id: 'smarthr-ui/FileViewer/nextMatchAlt',
67
+ defaultText: '次の検索結果へ',
68
+ }),
69
+ }), [localize]);
70
+ const hasMatches = matchCount > 0;
71
+ const displayedCurrent = hasMatches ? currentMatchIndex + 1 : 0;
72
+ const handleChange = useCallback((e) => {
73
+ setQuery(e.target.value);
74
+ }, [setQuery]);
75
+ const handleKeyDown = useCallback((e) => {
76
+ if (e.nativeEvent.isComposing) {
77
+ return;
78
+ }
79
+ switch (e.key) {
80
+ case 'Enter': {
81
+ e.preventDefault();
82
+ if (e.shiftKey) {
83
+ onClickPrev();
84
+ }
85
+ else {
86
+ onClickNext();
87
+ }
88
+ break;
89
+ }
90
+ case 'Escape': {
91
+ if (query !== '') {
92
+ e.preventDefault();
93
+ onClickClear();
94
+ }
95
+ break;
96
+ }
97
+ }
98
+ }, [onClickNext, onClickPrev, onClickClear, query]);
99
+ return (jsxs("div", { className: classNames.wrapper, children: [jsx("div", { className: classNames.inputArea, children: jsx(SearchInput, { name: "file_viewer_search", tooltipMessage: translated.searchInputTooltipMessage, value: query, onChange: handleChange, onKeyDown: handleKeyDown, width: "100%", suffix: query !== '' ? (jsx(Text, { size: "S", "aria-live": "polite", className: "shr-tabular-nums", children: `${displayedCurrent}/${matchCount}` })) : undefined, className: "[&_.smarthr-ui-Input]:shr-rounded-e-none" }) }), jsx(Button, { onClick: onClickPrev, disabled: !hasMatches, className: "shr-rounded-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default", children: jsx(FaAngleUpIcon, { alt: translated.previousMatchAlt }) }), jsx(Button, { onClick: onClickNext, disabled: !hasMatches, className: "shr-rounded-s-none shr-border-s-0 shr-p-0.75 aria-disabled:!shr-border-default", children: jsx(FaAngleDownIcon, { alt: translated.nextMatchAlt }) })] }));
100
+ });
101
+
102
+ export { SearchController };
103
+ //# sourceMappingURL=SearchController.js.map