@sfgrp/taxonpages 0.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 (312) hide show
  1. package/README.markdown +432 -0
  2. package/bin/taxonpages.js +78 -0
  3. package/index.html +22 -0
  4. package/package.json +82 -0
  5. package/postcss.config.cjs +17 -0
  6. package/server.js +142 -0
  7. package/src/App.vue +31 -0
  8. package/src/assets/css/leaflet.css +24 -0
  9. package/src/assets/css/main.css +23 -0
  10. package/src/assets/css/tailwind.css +3 -0
  11. package/src/assets/css/vars.css +58 -0
  12. package/src/assets/css/webkit.css +19 -0
  13. package/src/assets/images/taxonworks_full_logo.svg +22 -0
  14. package/src/assets/images/taxonworks_logo.svg +7 -0
  15. package/src/cli/commands/build.js +60 -0
  16. package/src/cli/commands/dev.js +48 -0
  17. package/src/cli/commands/init.js +65 -0
  18. package/src/cli/commands/preview.js +27 -0
  19. package/src/cli/commands/serve.js +26 -0
  20. package/src/cli/utils/resolveConfig.js +112 -0
  21. package/src/components/AddressMaker.global.vue +67 -0
  22. package/src/components/Animation/AnimationOpacity.global.vue +12 -0
  23. package/src/components/Autocomplete/Autocomplete.global.vue +223 -0
  24. package/src/components/Autocomplete/AutocompleteOtu.global.vue +33 -0
  25. package/src/components/Autocomplete/AutocompleteSpinner.vue +36 -0
  26. package/src/components/Button/ButtonExpand.global.vue +40 -0
  27. package/src/components/Button/VButton.global.vue +39 -0
  28. package/src/components/Card/VCard.global.vue +18 -0
  29. package/src/components/Card/VCardContent.global.vue +5 -0
  30. package/src/components/Card/VCardHeader.global.vue +7 -0
  31. package/src/components/Clipboard/VClipboard.global.vue +50 -0
  32. package/src/components/Dropdown/Dropdown.global.vue +108 -0
  33. package/src/components/Footer/FooterAnalytics.vue +26 -0
  34. package/src/components/Footer/FooterCitation.vue +45 -0
  35. package/src/components/Footer/FooterCopyright.vue +20 -0
  36. package/src/components/Gallery/GalleryCarousel/GalleryCarousel.global.vue +138 -0
  37. package/src/components/Gallery/GalleryImage.global.vue +65 -0
  38. package/src/components/Gallery/GalleryMainImage.vue +63 -0
  39. package/src/components/Gallery/GalleryMosaic/GalleryMosaic.global.vue +75 -0
  40. package/src/components/Gallery/GalleryThumbnail.vue +26 -0
  41. package/src/components/Gallery/GalleryThumbnailList.vue +34 -0
  42. package/src/components/Gallery/useGallery.js +50 -0
  43. package/src/components/Icon/IconArrowDown.global.vue +19 -0
  44. package/src/components/Icon/IconArrowLeft.global.vue +20 -0
  45. package/src/components/Icon/IconArrowRight.global.vue +20 -0
  46. package/src/components/Icon/IconArrowUp.global.vue +16 -0
  47. package/src/components/Icon/IconCalendar.global.vue +25 -0
  48. package/src/components/Icon/IconCheck.global.vue +16 -0
  49. package/src/components/Icon/IconClipboard.global.vue +16 -0
  50. package/src/components/Icon/IconClose.global.vue +20 -0
  51. package/src/components/Icon/IconDocument.global.vue +20 -0
  52. package/src/components/Icon/IconDownload.global.vue +16 -0
  53. package/src/components/Icon/IconFiles.global.vue +23 -0
  54. package/src/components/Icon/IconGithub.global.vue +11 -0
  55. package/src/components/Icon/IconHamburger.global.vue +18 -0
  56. package/src/components/Icon/IconInformation.global.vue +16 -0
  57. package/src/components/Icon/IconJson.global.vue +14 -0
  58. package/src/components/Icon/IconMinusCircle.global.vue +19 -0
  59. package/src/components/Icon/IconPause.global.vue +16 -0
  60. package/src/components/Icon/IconPlay.global.vue +16 -0
  61. package/src/components/Icon/IconPlusCircle.global.vue +19 -0
  62. package/src/components/Icon/IconSearch.global.vue +19 -0
  63. package/src/components/Icon/IconSpeakerWave.global.vue +16 -0
  64. package/src/components/Icon/IconSpeakerX.global.vue +16 -0
  65. package/src/components/Icon/IconTrash.global.vue +16 -0
  66. package/src/components/Icon/IconWarning.global.vue +16 -0
  67. package/src/components/ImageViewer/ControlImageNext.vue +11 -0
  68. package/src/components/ImageViewer/ControlImagePrevious.vue +10 -0
  69. package/src/components/ImageViewer/ImageAttribution.vue +15 -0
  70. package/src/components/ImageViewer/ImageDepictions.vue +21 -0
  71. package/src/components/ImageViewer/ImageSource.vue +15 -0
  72. package/src/components/ImageViewer/ImageToolbar.vue +14 -0
  73. package/src/components/ImageViewer/ImageViewer.global.vue +197 -0
  74. package/src/components/ImageViewer/ImageViewerClose.vue +12 -0
  75. package/src/components/ImageViewer/ImageViewerCounter.vue +16 -0
  76. package/src/components/Input/InputText.global.vue +30 -0
  77. package/src/components/Input/SelectInput.global.vue +31 -0
  78. package/src/components/Layout/LayoutFooter.vue +67 -0
  79. package/src/components/Layout/LayoutHeader.vue +62 -0
  80. package/src/components/Map/VMap.client.vue +365 -0
  81. package/src/components/Map/constants/disableLayerOptions.js +7 -0
  82. package/src/components/Map/constants/index.js +1 -0
  83. package/src/components/Map/icons/AssertedDistribution.js +5 -0
  84. package/src/components/Map/icons/CollectionObject.js +5 -0
  85. package/src/components/Map/icons/FieldOccurrence.js +5 -0
  86. package/src/components/Map/icons/Georeference.js +5 -0
  87. package/src/components/Map/icons/TypeMaterial.js +5 -0
  88. package/src/components/Map/icons/index.js +5 -0
  89. package/src/components/Map/shapes/Absent.js +8 -0
  90. package/src/components/Map/shapes/Aggregate.js +7 -0
  91. package/src/components/Map/shapes/AssertedDistribution.js +7 -0
  92. package/src/components/Map/shapes/CollectionObject.js +5 -0
  93. package/src/components/Map/shapes/FieldOccurrence.js +5 -0
  94. package/src/components/Map/shapes/TypeMaterial.js +5 -0
  95. package/src/components/Map/shapes/index.js +6 -0
  96. package/src/components/Map/utils/addPatternToMap.js +45 -0
  97. package/src/components/Map/utils/geojsonOptions.js +62 -0
  98. package/src/components/Map/utils/makeTileFromConfiguration.js +31 -0
  99. package/src/components/Markdown/MarkdownLayout.global.vue +36 -0
  100. package/src/components/Modal/VModal.global.vue +107 -0
  101. package/src/components/Navbar/NavbarMenu.vue +36 -0
  102. package/src/components/Navbar/NavbarMobile.vue +93 -0
  103. package/src/components/Navbar/NavbarSubmenu.vue +112 -0
  104. package/src/components/Pagination/VPagination.global.vue +139 -0
  105. package/src/components/Pagination/VPaginationInfo.global.vue +36 -0
  106. package/src/components/ProjectStats.global.vue +69 -0
  107. package/src/components/Ssr/ClientOnly.global.vue +14 -0
  108. package/src/components/SwitchTheme.vue +86 -0
  109. package/src/components/Tab/TabItem.global.vue +20 -0
  110. package/src/components/Tab/TabMenu.global.vue +7 -0
  111. package/src/components/Table/VTable.global.vue +7 -0
  112. package/src/components/Table/VTableBody.global.vue +7 -0
  113. package/src/components/Table/VTableBodyCell.global.vue +7 -0
  114. package/src/components/Table/VTableBodyRow.global.vue +5 -0
  115. package/src/components/Table/VTableHeader.global.vue +7 -0
  116. package/src/components/Table/VTableHeaderCell.global.vue +7 -0
  117. package/src/components/Table/VTableHeaderRow.global.vue +5 -0
  118. package/src/components/TrackerReport.global.vue +92 -0
  119. package/src/components/VSkeleton.global.vue +48 -0
  120. package/src/components/VSpinner.global.vue +219 -0
  121. package/src/components/clientComponents.js +28 -0
  122. package/src/components/globalComponents.js +29 -0
  123. package/src/constants/configPaths.cjs +4 -0
  124. package/src/constants/defaultConfig.js +7 -0
  125. package/src/constants/objectTypes.js +8 -0
  126. package/src/entry-client.js +39 -0
  127. package/src/entry-server.js +114 -0
  128. package/src/layout/Application.vue +21 -0
  129. package/src/main.js +20 -0
  130. package/src/modules/DwCFilter/components/DropdownMenu.vue +79 -0
  131. package/src/modules/DwCFilter/components/Facet/FacetDistribution.vue +47 -0
  132. package/src/modules/DwCFilter/components/Facet/FacetInstitutionCode.vue +17 -0
  133. package/src/modules/DwCFilter/components/Facet/FacetOrder.vue +38 -0
  134. package/src/modules/DwCFilter/components/Facet/FacetTypeStatus.vue +35 -0
  135. package/src/modules/DwCFilter/components/FilterBar.vue +123 -0
  136. package/src/modules/DwCFilter/components/OtuModal/OtuModal.vue +177 -0
  137. package/src/modules/DwCFilter/components/OtuModal/RecordItems.vue +89 -0
  138. package/src/modules/DwCFilter/components/OtuModal/TabList.vue +32 -0
  139. package/src/modules/DwCFilter/router/index.js +7 -0
  140. package/src/modules/DwCFilter/utils/flattenParameters.js +20 -0
  141. package/src/modules/DwCFilter/views/index.vue +183 -0
  142. package/src/modules/ImageMatrix/components/ListImages.vue +54 -0
  143. package/src/modules/ImageMatrix/router/index.js +7 -0
  144. package/src/modules/ImageMatrix/services/Keys.js +9 -0
  145. package/src/modules/ImageMatrix/utils/makeImageObject.js +15 -0
  146. package/src/modules/ImageMatrix/views/id.vue +133 -0
  147. package/src/modules/bibliography/components/DropdownMenu.vue +53 -0
  148. package/src/modules/bibliography/components/Facet/FacetFullCitation.vue +0 -0
  149. package/src/modules/bibliography/components/OtuModal.vue +129 -0
  150. package/src/modules/bibliography/components/VSlider.vue +154 -0
  151. package/src/modules/bibliography/components/YearPicker.vue +40 -0
  152. package/src/modules/bibliography/router/index.js +7 -0
  153. package/src/modules/bibliography/utils/getPagination.js +7 -0
  154. package/src/modules/bibliography/views/index.vue +225 -0
  155. package/src/modules/home/router/index.js +8 -0
  156. package/src/modules/home/views/index.vue +11 -0
  157. package/src/modules/httpErrorPages/router/index.js +18 -0
  158. package/src/modules/httpErrorPages/view/404.vue +10 -0
  159. package/src/modules/httpErrorPages/view/500.vue +11 -0
  160. package/src/modules/interactiveKeys/router/index.js +7 -0
  161. package/src/modules/interactiveKeys/views/InteractiveKey.vue +108 -0
  162. package/src/modules/keys/components/MetadataModal.vue +53 -0
  163. package/src/modules/keys/router/index.js +7 -0
  164. package/src/modules/keys/views/keyId.vue +161 -0
  165. package/src/modules/news/adapters/makeNews.js +21 -0
  166. package/src/modules/news/components/NewsCard.vue +35 -0
  167. package/src/modules/news/components/NewsCategories.vue +31 -0
  168. package/src/modules/news/components/PinnedNews.vue +70 -0
  169. package/src/modules/news/components/WidgetNews.global.vue +53 -0
  170. package/src/modules/news/router/index.js +12 -0
  171. package/src/modules/news/services/News.js +11 -0
  172. package/src/modules/news/store/news.js +50 -0
  173. package/src/modules/news/utils/getPagination.js +7 -0
  174. package/src/modules/news/views/id.vue +77 -0
  175. package/src/modules/news/views/index.vue +69 -0
  176. package/src/modules/otus/components/Breadcrumb/Breadcrumb.vue +40 -0
  177. package/src/modules/otus/components/Breadcrumb/BreadcrumbDropdown.vue +57 -0
  178. package/src/modules/otus/components/CommonNames.vue +14 -0
  179. package/src/modules/otus/components/DWCDownload.vue +33 -0
  180. package/src/modules/otus/components/DataMap.vue +57 -0
  181. package/src/modules/otus/components/Export.vue +1 -0
  182. package/src/modules/otus/components/ExternalResources.vue +11 -0
  183. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/PanelBiologicalAssociations.vue +184 -0
  184. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/main.js +6 -0
  185. package/src/modules/otus/components/Panel/PanelBiologicalAssociations/utils/makeBiologicalAssociation.js +30 -0
  186. package/src/modules/otus/components/Panel/PanelContent/PanelContent.vue +58 -0
  187. package/src/modules/otus/components/Panel/PanelContent/PanelContentTopic.vue +42 -0
  188. package/src/modules/otus/components/Panel/PanelContent/main.js +6 -0
  189. package/src/modules/otus/components/Panel/PanelDescendants/DescendantsSynonymList.vue +21 -0
  190. package/src/modules/otus/components/Panel/PanelDescendants/DescendantsTree.vue +122 -0
  191. package/src/modules/otus/components/Panel/PanelDescendants/PanelDescendants.vue +82 -0
  192. package/src/modules/otus/components/Panel/PanelDescendants/main.js +6 -0
  193. package/src/modules/otus/components/Panel/PanelDropdown.vue +63 -0
  194. package/src/modules/otus/components/Panel/PanelGallery/PanelGallery.vue +42 -0
  195. package/src/modules/otus/components/Panel/PanelGallery/main.js +7 -0
  196. package/src/modules/otus/components/Panel/PanelKeys/PanelKeys.vue +103 -0
  197. package/src/modules/otus/components/Panel/PanelKeys/main.js +6 -0
  198. package/src/modules/otus/components/Panel/PanelMap/PanelMap.vue +124 -0
  199. package/src/modules/otus/components/Panel/PanelMap/clusters/Mixed.js +50 -0
  200. package/src/modules/otus/components/Panel/PanelMap/clusters/index.js +2 -0
  201. package/src/modules/otus/components/Panel/PanelMap/clusters/makeClusterIconFor.js +10 -0
  202. package/src/modules/otus/components/Panel/PanelMap/components/CachedMap.vue +118 -0
  203. package/src/modules/otus/components/Panel/PanelMap/components/DwcTable.vue +64 -0
  204. package/src/modules/otus/components/Panel/PanelMap/components/MapPopup.vue +34 -0
  205. package/src/modules/otus/components/Panel/PanelMap/components/Search/ListResults.vue +51 -0
  206. package/src/modules/otus/components/Panel/PanelMap/components/Search/OtuSearch.vue +167 -0
  207. package/src/modules/otus/components/Panel/PanelMap/components/Search/SearchBar.vue +27 -0
  208. package/src/modules/otus/components/Panel/PanelMap/composables/useGeojsonOptions.js +36 -0
  209. package/src/modules/otus/components/Panel/PanelMap/constants/index.js +1 -0
  210. package/src/modules/otus/components/Panel/PanelMap/constants/legend.js +30 -0
  211. package/src/modules/otus/components/Panel/PanelMap/main.js +6 -0
  212. package/src/modules/otus/components/Panel/PanelMap/store/useDistributionStore.js +130 -0
  213. package/src/modules/otus/components/Panel/PanelMap/utils/index.js +4 -0
  214. package/src/modules/otus/components/Panel/PanelMap/utils/isRankGroup.js +5 -0
  215. package/src/modules/otus/components/Panel/PanelMap/utils/makeGeoJSONFeature.js +13 -0
  216. package/src/modules/otus/components/Panel/PanelMap/utils/makeSegmentedCircle.js +37 -0
  217. package/src/modules/otus/components/Panel/PanelMap/utils/removeDuplicateShapes.js +40 -0
  218. package/src/modules/otus/components/Panel/PanelNomenclature/PanelCitationRow.vue +25 -0
  219. package/src/modules/otus/components/Panel/PanelNomenclature/PanelNomenclature.vue +97 -0
  220. package/src/modules/otus/components/Panel/PanelNomenclature/PanelNomenclatureShowMore.vue +22 -0
  221. package/src/modules/otus/components/Panel/PanelNomenclature/main.js +6 -0
  222. package/src/modules/otus/components/Panel/PanelNomenclature/splitList.js +14 -0
  223. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/PanelNomenclatureReferences.vue +72 -0
  224. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/PanelReferenceRow.vue +20 -0
  225. package/src/modules/otus/components/Panel/PanelNomenclatureReferences/main.js +6 -0
  226. package/src/modules/otus/components/Panel/PanelSounds/PanelSounds.vue +42 -0
  227. package/src/modules/otus/components/Panel/PanelSounds/components/AudioPlayer.vue +275 -0
  228. package/src/modules/otus/components/Panel/PanelSounds/components/PanelSoundRow.vue +21 -0
  229. package/src/modules/otus/components/Panel/PanelSounds/components/SoundObservations.vue +73 -0
  230. package/src/modules/otus/components/Panel/PanelSounds/components/TableObservations.vue +31 -0
  231. package/src/modules/otus/components/Panel/PanelSounds/constants/observationTypes.js +15 -0
  232. package/src/modules/otus/components/Panel/PanelSounds/main.js +7 -0
  233. package/src/modules/otus/components/Panel/PanelSounds/utils/index.js +5 -0
  234. package/src/modules/otus/components/Panel/PanelSounds/utils/makeContinuousObservation.js +5 -0
  235. package/src/modules/otus/components/Panel/PanelSounds/utils/makeMediaObservation.js +5 -0
  236. package/src/modules/otus/components/Panel/PanelSounds/utils/makeObservation.js +40 -0
  237. package/src/modules/otus/components/Panel/PanelSounds/utils/makePresenceAbsenceObservation.js +5 -0
  238. package/src/modules/otus/components/Panel/PanelSounds/utils/makeQualitativeObservation.js +5 -0
  239. package/src/modules/otus/components/Panel/PanelSounds/utils/makeSampleObservation.js +29 -0
  240. package/src/modules/otus/components/Panel/PanelSounds/utils/makeWorkingObservation.js +5 -0
  241. package/src/modules/otus/components/Panel/PanelStats/PanelStats.vue +160 -0
  242. package/src/modules/otus/components/Panel/PanelStats/main.js +6 -0
  243. package/src/modules/otus/components/Panel/PanelTypeDesignation/PanelTypeDesignation.vue +37 -0
  244. package/src/modules/otus/components/Panel/PanelTypeDesignation/main.js +8 -0
  245. package/src/modules/otus/components/Panel/PanelTypeSpecimen/PanelTypeSpecimen.vue +52 -0
  246. package/src/modules/otus/components/Panel/PanelTypeSpecimen/main.js +8 -0
  247. package/src/modules/otus/components/TaxaInfo.vue +38 -0
  248. package/src/modules/otus/composables/index.js +2 -0
  249. package/src/modules/otus/composables/useChildrenRoutes.js +32 -0
  250. package/src/modules/otus/composables/useUserLifeCycleHooks.js +24 -0
  251. package/src/modules/otus/constants/index.js +3 -0
  252. package/src/modules/otus/constants/layouts/index.js +1 -0
  253. package/src/modules/otus/constants/layouts/overview.js +23 -0
  254. package/src/modules/otus/constants/layouts.js +43 -0
  255. package/src/modules/otus/constants/rankGroups.js +5 -0
  256. package/src/modules/otus/constants/responseError.js +3 -0
  257. package/src/modules/otus/constants/typeOrder.js +11 -0
  258. package/src/modules/otus/helpers/useOtuPageRequest.js +19 -0
  259. package/src/modules/otus/router/index.js +28 -0
  260. package/src/modules/otus/services/TaxonWorks.js +77 -0
  261. package/src/modules/otus/store/request.js +34 -0
  262. package/src/modules/otus/store/store.js +92 -0
  263. package/src/modules/otus/store/useImageStore.js +57 -0
  264. package/src/modules/otus/utils/index.js +2 -0
  265. package/src/modules/otus/utils/isAvailableForRank.js +6 -0
  266. package/src/modules/otus/utils/stripHtml.js +5 -0
  267. package/src/modules/otus/views/Index.vue +218 -0
  268. package/src/modules/otus/views/PageLayout.vue +78 -0
  269. package/src/modules/setup/views/Index.vue +66 -0
  270. package/src/plugins/markdown/index.js +2 -0
  271. package/src/plugins/markdown/relativeToRouter.js +51 -0
  272. package/src/plugins/markdown/variableReplacement.js +14 -0
  273. package/src/plugins/schemaOrg/composables/index.js +28 -0
  274. package/src/plugins/schemaOrg/index.js +31 -0
  275. package/src/plugins/schemaOrg/loadResolver.js +10 -0
  276. package/src/plugins/schemaOrg/nodes/Taxon.js +82 -0
  277. package/src/plugins/schemaOrg/nodes/index.js +1 -0
  278. package/src/plugins/vite/index.js +2 -0
  279. package/src/plugins/vite/projectStyle.js +29 -0
  280. package/src/plugins/vite/restart.js +30 -0
  281. package/src/router/index.js +46 -0
  282. package/src/ssr/utils/generateConsoleMessage.js +16 -0
  283. package/src/ssr/utils/registerFakeClientComponents.js +20 -0
  284. package/src/ssr/utils/taxonPagesMark.txt +9 -0
  285. package/src/store/index.js +1 -0
  286. package/src/store/useFooterStore.js +13 -0
  287. package/src/utils/color.js +9 -0
  288. package/src/utils/files.js +21 -0
  289. package/src/utils/globalVars.js +7 -0
  290. package/src/utils/index.js +5 -0
  291. package/src/utils/loadConfiguration.js +34 -0
  292. package/src/utils/loadLayouts.js +21 -0
  293. package/src/utils/parseEnvConfig.js +0 -0
  294. package/src/utils/request.js +18 -0
  295. package/src/utils/strings.js +12 -0
  296. package/src/utils/url.js +8 -0
  297. package/tailwind.config.cjs +92 -0
  298. package/templates/config/analytics.yml.example +22 -0
  299. package/templates/config/api.yml +5 -0
  300. package/templates/config/copyright.yml +5 -0
  301. package/templates/config/header.yml +17 -0
  302. package/templates/config/maps.yml +16 -0
  303. package/templates/config/metadata.yml +10 -0
  304. package/templates/config/news.yml.example +15 -0
  305. package/templates/config/project.yml +6 -0
  306. package/templates/config/router.yml.example +4 -0
  307. package/templates/config/style/theme.css +48 -0
  308. package/templates/config/taxa_page.yml.example +22 -0
  309. package/templates/config/tracker.yml.example +8 -0
  310. package/templates/pages/about.md +44 -0
  311. package/templates/pages/home.md +26 -0
  312. package/vite.config.js +92 -0
@@ -0,0 +1,197 @@
1
+ <template>
2
+ <div
3
+ ref="viewerRef"
4
+ role="dialog"
5
+ aria-modal="true"
6
+ aria-label="Image viewer"
7
+ class="fixed z-[10000] h-full overflow-y-hidden overflow-x-hidden w-full top-0 left-0 flex flex-col items-center justify-center backdrop-blur-md bg-base-foreground"
8
+ >
9
+ <div
10
+ class="min-w-96 dark:bg-slate-900 rounded-lg shadow-sm mb-24"
11
+ @click.stop
12
+ >
13
+ <div
14
+ class="absolute rounded-t-lg w-auto max-h-full h-auto top-12 bottom-44 left-0 right-0 flex justify-center align-middle"
15
+ >
16
+ <VSpinner v-if="isLoading" />
17
+ <div
18
+ class="flex flex-col justify-center"
19
+ v-if="errorMessage"
20
+ v-text="errorMessage"
21
+ />
22
+ <img
23
+ v-show="!errorMessage"
24
+ ref="imageElement"
25
+ class="mx-auto cursor-zoom-out w-auto max-w-full max-h-full h-auto my-auto"
26
+ :alt="image?.depictions?.map((d) => d.label).join(';')"
27
+ :src="image.original"
28
+ @click="emit('close')"
29
+ />
30
+
31
+ <ControlNextImage
32
+ v-if="next"
33
+ class="right-0 absolute my-auto top-1/2 -translate-y-1/2"
34
+ @click="emit('next')"
35
+ />
36
+ <ControlPreviousImage
37
+ v-if="previous"
38
+ class="left-0 absolute my-auto top-1/2 -translate-y-1/2"
39
+ @click="emit('previous')"
40
+ />
41
+ </div>
42
+ </div>
43
+ <div class="bottom-0 fixed max-w-full w-full">
44
+ <div
45
+ class="text-base-content text-sm attributions p-6 align-middle flex justify-between flex-col text-center"
46
+ >
47
+ <ImageDepictions
48
+ class="my-auto"
49
+ :depictions="image.depictions"
50
+ />
51
+ <ImageAttribution
52
+ class="my-auto"
53
+ :attribution="image.attribution"
54
+ />
55
+ <ImageSource
56
+ class="my-auto"
57
+ :source="image.source"
58
+ />
59
+ </div>
60
+ <div class="flex justify-center">
61
+ <GalleryThumbnailList
62
+ class="pb-2"
63
+ :current="index"
64
+ :images="images"
65
+ @select-index="emit('selectIndex', $event)"
66
+ @click.stop
67
+ />
68
+ </div>
69
+ </div>
70
+ <ImageToolbar class="w-full absolute top-0 h-12 left-0 items-center">
71
+ <ImageViewerCounter
72
+ :current-image="index"
73
+ :total-images="images.length"
74
+ />
75
+ <template #right>
76
+ <ImageViewerClose @click="emit('close')" />
77
+ </template>
78
+ </ImageToolbar>
79
+ </div>
80
+ </template>
81
+
82
+ <script setup>
83
+ import { onMounted, onUnmounted, ref, watch, computed } from 'vue'
84
+ import ImageAttribution from './ImageAttribution.vue'
85
+ import ImageDepictions from './ImageDepictions.vue'
86
+ import ImageSource from './ImageSource.vue'
87
+ import ImageViewerCounter from './ImageViewerCounter.vue'
88
+ import ControlNextImage from './ControlImageNext.vue'
89
+ import ControlPreviousImage from './ControlImagePrevious.vue'
90
+ import GalleryThumbnailList from '@/components/Gallery/GalleryThumbnailList.vue'
91
+ import ImageToolbar from './ImageToolbar.vue'
92
+ import ImageViewerClose from './ImageViewerClose.vue'
93
+
94
+ const props = defineProps({
95
+ index: {
96
+ type: Number,
97
+ required: true
98
+ },
99
+
100
+ images: {
101
+ type: Array,
102
+ default: () => []
103
+ },
104
+
105
+ next: {
106
+ type: Boolean,
107
+ default: false
108
+ },
109
+
110
+ previous: {
111
+ type: Boolean,
112
+ default: false
113
+ }
114
+ })
115
+
116
+ const emit = defineEmits(['close', 'previous', 'next', 'selectIndex'])
117
+
118
+ let previouslyFocusedElement = null
119
+ const viewerRef = ref(null)
120
+
121
+ const handleKeyboard = (e) => {
122
+ switch (e.key) {
123
+ case 'ArrowLeft':
124
+ if (props.previous) {
125
+ emit('previous')
126
+ }
127
+ break
128
+ case 'ArrowRight':
129
+ if (props.next) {
130
+ emit('next')
131
+ }
132
+ break
133
+ case 'Escape':
134
+ emit('close')
135
+ break
136
+ case 'Tab':
137
+ trapFocus(e)
138
+ break
139
+ }
140
+ }
141
+
142
+ function trapFocus(e) {
143
+ const focusable = viewerRef.value?.querySelectorAll(
144
+ 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])'
145
+ )
146
+
147
+ if (!focusable?.length) return
148
+
149
+ const first = focusable[0]
150
+ const last = focusable[focusable.length - 1]
151
+
152
+ if (e.shiftKey && document.activeElement === first) {
153
+ e.preventDefault()
154
+ last.focus()
155
+ } else if (!e.shiftKey && document.activeElement === last) {
156
+ e.preventDefault()
157
+ first.focus()
158
+ }
159
+ }
160
+
161
+ const imageElement = ref(null)
162
+ const isLoading = ref(false)
163
+ const errorMessage = ref(null)
164
+ const image = computed(() => props.images[props.index])
165
+
166
+ previouslyFocusedElement = document.activeElement
167
+ document.addEventListener('keyup', handleKeyboard)
168
+
169
+ function handleError() {
170
+ isLoading.value = false
171
+ errorMessage.value = 'Image was not found or format is not supported'
172
+ }
173
+
174
+ function handleLoad() {
175
+ isLoading.value = false
176
+ }
177
+
178
+ onMounted(() => {
179
+ imageElement.value.addEventListener('load', handleLoad)
180
+ imageElement.value.addEventListener('error', handleError)
181
+ document.body.classList.add('overflow-hidden')
182
+ })
183
+
184
+ onUnmounted(() => {
185
+ document.removeEventListener('keyup', handleKeyboard)
186
+ document.body.classList.remove('overflow-hidden')
187
+ previouslyFocusedElement?.focus()
188
+ })
189
+
190
+ watch(
191
+ () => props.index,
192
+ () => {
193
+ errorMessage.value = null
194
+ isLoading.value = true
195
+ }
196
+ )
197
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <button
3
+ type="button"
4
+ aria-label="Close image viewer"
5
+ class="p-2 cursor-pointer opacity-50 text-base-content"
6
+ >
7
+ <IconClose />
8
+ </button>
9
+ </template>
10
+
11
+ <script setup>
12
+ </script>
@@ -0,0 +1,16 @@
1
+ <template>
2
+ <span class="p-2 text-black dark:text-white opacity-50">{{ currentImage + 1 }}/{{ totalImages }}</span>
3
+ </template>
4
+
5
+ <script setup>
6
+ defineProps({
7
+ currentImage: {
8
+ type: Number,
9
+ required: true
10
+ },
11
+ totalImages: {
12
+ type: Number,
13
+ required: true
14
+ }
15
+ })
16
+ </script>
@@ -0,0 +1,30 @@
1
+ <template>
2
+ <input
3
+ ref="input"
4
+ type="text"
5
+ class="box-border p-1.5 px-2 text-base-content rounded border sm:text-sm placeholder:text-sm border-base-border focus:ring-primary-500 focus:border-primary-500"
6
+ :value="props.modelValue ?? props.value"
7
+ @input="onInput"
8
+ />
9
+ </template>
10
+
11
+ <script setup>
12
+ import { useTemplateRef } from 'vue'
13
+
14
+ const props = defineProps({
15
+ modelValue: [String, Number],
16
+ value: [String, Number]
17
+ })
18
+
19
+ const emit = defineEmits(['update:modelValue'])
20
+
21
+ const inputRef = useTemplateRef('input')
22
+
23
+ const onInput = (event) => {
24
+ emit('update:modelValue', event.target.value)
25
+ }
26
+
27
+ defineExpose({
28
+ inputRef
29
+ })
30
+ </script>
@@ -0,0 +1,31 @@
1
+ <template>
2
+ <select
3
+ ref="input"
4
+ class="box-border p-1.5 px-2 text-base-content rounded border sm:text-sm placeholder:text-sm border-base-border focus:ring-primary-500 focus:border-primary-500"
5
+ :value="props.modelValue ?? props.value"
6
+ @change="onInput"
7
+ >
8
+ <slot />
9
+ </select>
10
+ </template>
11
+
12
+ <script setup>
13
+ import { useTemplateRef } from 'vue'
14
+
15
+ const props = defineProps({
16
+ modelValue: [String, Number],
17
+ value: [String, Number]
18
+ })
19
+
20
+ const emit = defineEmits(['update:modelValue'])
21
+
22
+ const inputRef = useTemplateRef('input')
23
+
24
+ function onInput(e) {
25
+ emit('update:modelValue', e.target.value)
26
+ }
27
+
28
+ defineExpose({
29
+ inputRef
30
+ })
31
+ </script>
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <footer
3
+ class="footer text-white bottom-0 border-gray-200 bg-zinc-800 pl-4 pr-4"
4
+ >
5
+ <div class="container mx-auto text-sm pt-2 pb-4">
6
+ <FooterCitation />
7
+ <FooterCopyright />
8
+
9
+ <hr class="mt-3 mb-3 border-gray-500" />
10
+
11
+ <div class="flex flex-col sm:flex-row justify-between gap-4">
12
+ <div
13
+ class="[&>*:not(:last-child)]:after:content-['|'] [&>*:not(:last-child)]:after:mx-1"
14
+ >
15
+ <span>
16
+ Data provided by
17
+ <a
18
+ class="text-slate-400 hover:text-slate-500 dark:hover:text-slate-300 font-medium"
19
+ target="_blank"
20
+ rel="noopener"
21
+ href="https://taxonworks.org/"
22
+ >
23
+ TaxonWorks
24
+ <span class="sr-only">(opens in new window)</span>
25
+ </a>
26
+ </span>
27
+ <span>
28
+ Pages by
29
+ <a
30
+ class="text-slate-400 hover:text-slate-500 dark:hover:text-slate-300 font-medium"
31
+ target="_blank"
32
+ rel="noopener"
33
+ href="https://github.com/SpeciesFileGroup/taxonpages"
34
+ >
35
+ TaxonPages
36
+ <span class="sr-only">(opens in new window)</span>
37
+ </a>
38
+ </span>
39
+ <span>
40
+ Support (Services) by
41
+ <a
42
+ class="text-slate-400 hover:text-slate-500 dark:hover:text-slate-300 font-medium"
43
+ target="_blank"
44
+ rel="noopener"
45
+ href="https://speciesfilegroup.org"
46
+ >
47
+ Species File Group
48
+ <span class="sr-only">(opens in new window)</span>
49
+ </a>
50
+ </span>
51
+ <FooterAnalytics class="italic" />
52
+ </div>
53
+ <TrackerReport
54
+ icon
55
+ label="Report a problem"
56
+ button-class="flex gap-2 items-center pl-0 pr-0 pt-0 pb-0 self-end"
57
+ />
58
+ </div>
59
+ </div>
60
+ </footer>
61
+ </template>
62
+
63
+ <script setup>
64
+ import FooterCitation from '@/components/Footer/FooterCitation.vue'
65
+ import FooterCopyright from '@/components/Footer/FooterCopyright.vue'
66
+ import FooterAnalytics from '@/components/Footer/FooterAnalytics.vue'
67
+ </script>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <header
3
+ class="tp-header relative bg-header px-2 sm:px-4 py-2.5 shadow-sm shadow-base-muted pl-4 pr-4 h-9 align-middle flex items-center bg-primary-color"
4
+ >
5
+ <div
6
+ class="container flex flex-wrap justify-between items-center mx-auto font-medium text-secondary-content"
7
+ >
8
+ <RouterLink
9
+ to="/"
10
+ class="flex items-center text-primary-content"
11
+ >
12
+ <img
13
+ v-if="header_logo_url"
14
+ class="mr-3 h-10"
15
+ :src="logoUrl"
16
+ alt=""
17
+ />
18
+ <span>
19
+ {{ header_logo_text || project_name }}
20
+ </span>
21
+ </RouterLink>
22
+
23
+ <NavbarMobile />
24
+
25
+ <div class="relative hidden md:flex items-center ml-auto">
26
+ <NavbarMenu :menu="header_links" />
27
+ <div
28
+ class="flex items-center border-l ml-6 pl-6 border-base-muted border-opacity-50"
29
+ >
30
+ <ClientOnly>
31
+ <SwitchTheme class="text-primary-content" />
32
+ </ClientOnly>
33
+ </div>
34
+ <div class="flex items-center ml-2 border-base-muted">
35
+ <TrackerReport
36
+ icon
37
+ button-class="text-primary-content"
38
+ />
39
+ </div>
40
+ </div>
41
+ </div>
42
+ </header>
43
+ </template>
44
+
45
+ <script setup>
46
+ import SwitchTheme from '../SwitchTheme.vue'
47
+ import NavbarMenu from '../Navbar/NavbarMenu.vue'
48
+ import NavbarMobile from '../Navbar/NavbarMobile.vue'
49
+ import { isValidUrl } from '@/utils/url'
50
+
51
+ const {
52
+ header_links,
53
+ header_logo_text,
54
+ header_logo_url,
55
+ base_url,
56
+ project_name
57
+ } = __APP_ENV__
58
+
59
+ const logoUrl = isValidUrl(header_logo_url)
60
+ ? header_logo_url
61
+ : (base_url + header_logo_url).replace('//', '/')
62
+ </script>