@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,112 @@
1
+ import { resolve } from 'node:path'
2
+ import { existsSync } from 'node:fs'
3
+ import { loadConfiguration } from '../../utils/loadConfiguration.js'
4
+ import { VitePluginRadar } from 'vite-plugin-radar'
5
+ import Vue from '@vitejs/plugin-vue'
6
+ import Markdown from 'unplugin-vue-markdown/vite'
7
+ import markdownAnchor from 'markdown-it-anchor'
8
+ import Pages from 'vite-plugin-pages'
9
+ import tailwindcss from 'tailwindcss'
10
+ import autoprefixer from 'autoprefixer'
11
+ import {
12
+ relativeToRouterPlugin,
13
+ variableReplacementPlugin
14
+ } from '../../plugins/markdown/index.js'
15
+ import { ViteRestart, projectStylesPlugin } from '../../plugins/vite/index.js'
16
+
17
+ /**
18
+ * Build the full Vite configuration, resolving paths correctly
19
+ * for both the installed package and the user's project directory.
20
+ *
21
+ * @param {object} options
22
+ * @param {string} options.packageRoot - Absolute path to the taxonpages package
23
+ * @param {string} options.projectRoot - Absolute path to the user's project (CWD)
24
+ */
25
+ export function getViteConfig({ packageRoot, projectRoot }) {
26
+ const configuration = loadConfiguration(projectRoot)
27
+
28
+ // Use user's index.html if it exists, otherwise fall back to the package's
29
+ const root = existsSync(resolve(projectRoot, 'index.html'))
30
+ ? projectRoot
31
+ : packageRoot
32
+
33
+ return {
34
+ root,
35
+ base: configuration.base_url,
36
+
37
+ resolve: {
38
+ alias: {
39
+ '@': resolve(packageRoot, 'src'),
40
+ '~': projectRoot
41
+ }
42
+ },
43
+
44
+ css: {
45
+ postcss: {
46
+ plugins: [
47
+ tailwindcss({
48
+ config: getTailwindConfigPath(packageRoot, projectRoot)
49
+ }),
50
+ autoprefixer()
51
+ ]
52
+ },
53
+ preprocessorOptions: {
54
+ scss: {
55
+ api: 'modern-compiler'
56
+ }
57
+ }
58
+ },
59
+
60
+ plugins: [
61
+ projectStylesPlugin(projectRoot),
62
+
63
+ ViteRestart({ dir: [resolve(projectRoot, 'config/**/*.yml')], projectRoot }),
64
+
65
+ Vue({
66
+ include: [/\.vue$/, /\.md$/]
67
+ }),
68
+
69
+ Markdown({
70
+ wrapperComponent: 'markdown-layout',
71
+ markdownItSetup(md) {
72
+ md.use(markdownAnchor)
73
+ md.use(variableReplacementPlugin, {
74
+ variables: { ...configuration }
75
+ })
76
+ md.use(relativeToRouterPlugin, configuration)
77
+ }
78
+ }),
79
+
80
+ Pages({
81
+ dirs: resolve(projectRoot, 'pages'),
82
+ exclude: ['**/components/*.vue', 'components/**/*.vue'],
83
+ extensions: ['vue', 'md'],
84
+ extendRoute(route) {
85
+ if (route.path === '/home') {
86
+ route.alias = '/home'
87
+ route.path = '/'
88
+ return route
89
+ }
90
+ }
91
+ }),
92
+
93
+ VitePluginRadar({
94
+ ...configuration?.analytics_services
95
+ })
96
+ ]
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Resolve the Tailwind config file path.
102
+ * Prefers user's custom config at config/vendor/tailwind.config.cjs,
103
+ * falls back to the package's default tailwind.config.cjs.
104
+ */
105
+
106
+ function getTailwindConfigPath(packageRoot, projectRoot) {
107
+ const userConfig = resolve(projectRoot, 'config/vendor/tailwind.config.cjs')
108
+ if (existsSync(userConfig)) {
109
+ return userConfig
110
+ }
111
+ return resolve(packageRoot, 'tailwind.config.cjs')
112
+ }
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <button
3
+ type="button"
4
+ class="text-secondary-color cursor-pointer whitespace-nowrap inline bg-transparent border-0 p-0 font-inherit text-inherit"
5
+ aria-label="Send email"
6
+ @click="openClient"
7
+ >
8
+ <span v-html="data.username" />
9
+ <template v-for="(item, index) in data.host">
10
+ <svg
11
+ v-if="index === 0"
12
+ class="h-4 inline"
13
+ xmlns="http://www.w3.org/2000/svg"
14
+ fill="none"
15
+ viewBox="0 0 24 24"
16
+ stroke-width="1.5"
17
+ stroke="currentColor"
18
+ aria-hidden="true"
19
+ >
20
+ <path
21
+ stroke-linecap="round"
22
+ d="M16.5 12a4.5 4.5 0 11-9 0 4.5 4.5 0 019 0zm0 0c0 1.657 1.007 3 2.25 3S21 13.657 21 12a9 9 0 10-2.636 6.364M16.5 12V8.25"
23
+ />
24
+ </svg>
25
+
26
+ <svg
27
+ class="inline h-4 w-1"
28
+ aria-hidden="true"
29
+ v-else
30
+ >
31
+ <circle
32
+ cy="calc(100% - 5px)"
33
+ cx="2.5"
34
+ r="1"
35
+ fill="currentColor"
36
+ />
37
+ </svg>
38
+ <span v-html="item" />
39
+ </template>
40
+ </button>
41
+ </template>
42
+
43
+ <script setup>
44
+ import { computed } from 'vue'
45
+
46
+ const props = defineProps({
47
+ items: {
48
+ type: Array,
49
+ required: true
50
+ }
51
+ })
52
+
53
+ const data = computed(() => {
54
+ const [username, ...rest] = props.items
55
+
56
+ return {
57
+ username,
58
+ host: rest
59
+ }
60
+ })
61
+
62
+ function openClient() {
63
+ const [username, ...rest] = props.items
64
+
65
+ document.location.href = `mailto:${username}@${rest.join('.')}`
66
+ }
67
+ </script>
@@ -0,0 +1,12 @@
1
+ <template>
2
+ <transition
3
+ enter-active-class="duration-500 ease-out origin-top"
4
+ enter-from-class="transform opacity-0 scale-y-0"
5
+ enter-to-class="opacity-100 scale-y-100"
6
+ leave-active-class="duration-200 ease-in origin-top"
7
+ leave-from-class="opacity-100 scale-y-100"
8
+ leave-to-class="transform opacity-0 scale-y-0"
9
+ >
10
+ <slot />
11
+ </transition>
12
+ </template>
@@ -0,0 +1,223 @@
1
+ <template>
2
+ <div class="tp-autocomplete md:block relative w-fit">
3
+ <div
4
+ class="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none"
5
+ >
6
+ <IconSearch
7
+ class="w-4 h-4 text-gray-500"
8
+ aria-hidden="true"
9
+ />
10
+ </div>
11
+ <InputText
12
+ ref="inputElement"
13
+ v-model="typed"
14
+ type="text"
15
+ role="combobox"
16
+ :autofocus="autofocus"
17
+ autocomplete="off"
18
+ aria-autocomplete="list"
19
+ :aria-expanded="list.length > 0"
20
+ aria-controls="autocomplete-listbox"
21
+ :aria-activedescendant="activeDescendant"
22
+ class="tp-autocomplete__input block box-border w-full p-1.5 pl-10"
23
+ :placeholder="placeholder"
24
+ @input="trigger"
25
+ @keydown="handleKeydown"
26
+ />
27
+ <AutocompleteSpinner
28
+ v-if="isSearching"
29
+ class="tp-autocomplete__spinner hidden absolute top-1/2 -translate-y-1/2 right-2 h-5 w-5"
30
+ />
31
+
32
+ <ul
33
+ v-if="list.length"
34
+ id="autocomplete-listbox"
35
+ class="tp-autocomplete__list list absolute z-[500] max-h-52 w-full overflow-y-auto border bg-base-foreground border-base-border !m-0 shadow-md"
36
+ role="listbox"
37
+ >
38
+ <li
39
+ v-for="(item, index) in list"
40
+ :id="`autocomplete-option-${index}`"
41
+ :key="item.id"
42
+ class="tp-autocomplete__item px-3 py-2 border-b text-xs text-base-content cursor-pointer hover:bg-secondary-color hover:bg-opacity-5 border-base-border truncate"
43
+ :class="{ 'bg-secondary-color bg-opacity-10': index === activeIndex }"
44
+ role="option"
45
+ :aria-selected="index === activeIndex"
46
+ @mousedown.prevent="selectItem(item)"
47
+ >
48
+ <span v-html="label ? item[label] : item" />
49
+ </li>
50
+ </ul>
51
+ </div>
52
+ </template>
53
+
54
+ <script setup>
55
+ import { ref, computed, watch } from 'vue'
56
+ import { makeAPIRequest } from '@/utils/request'
57
+ import AutocompleteSpinner from './AutocompleteSpinner.vue'
58
+
59
+ const props = defineProps({
60
+ autofocus: {
61
+ type: Boolean,
62
+ default: false
63
+ },
64
+
65
+ placeholder: {
66
+ type: String,
67
+ default: 'Search...'
68
+ },
69
+
70
+ url: {
71
+ type: String,
72
+ required: true
73
+ },
74
+
75
+ queryParam: {
76
+ type: String,
77
+ default: 'term'
78
+ },
79
+
80
+ params: {
81
+ type: Object,
82
+ default: () => ({})
83
+ },
84
+
85
+ label: {
86
+ type: String,
87
+ default: undefined
88
+ },
89
+
90
+ retainInput: {
91
+ type: Boolean,
92
+ default: false
93
+ }
94
+ })
95
+
96
+ const typed = defineModel('input', {
97
+ type: String,
98
+ default: ''
99
+ })
100
+
101
+ const emit = defineEmits(['select'])
102
+ const list = ref([])
103
+ const isSearching = ref(false)
104
+ const inputElement = ref(null)
105
+ const activeIndex = ref(-1)
106
+
107
+ const activeDescendant = computed(() =>
108
+ activeIndex.value >= 0
109
+ ? `autocomplete-option-${activeIndex.value}`
110
+ : undefined
111
+ )
112
+
113
+ watch(list, () => {
114
+ activeIndex.value = -1
115
+ })
116
+
117
+ const delay = 500
118
+ let timeout
119
+
120
+ function trigger(e) {
121
+ clearTimeout(timeout)
122
+
123
+ if (e.target.value.length) {
124
+ timeout = setTimeout(() => {
125
+ list.value = []
126
+ isSearching.value = true
127
+
128
+ makeAPIRequest
129
+ .get(props.url, {
130
+ params: {
131
+ ...props.params,
132
+ [props.queryParam]: typed.value
133
+ }
134
+ })
135
+ .then(({ data }) => {
136
+ list.value = data
137
+ })
138
+ .catch(() => {})
139
+ .finally(() => {
140
+ isSearching.value = false
141
+ })
142
+ }, delay)
143
+ } else {
144
+ list.value = []
145
+ }
146
+ }
147
+
148
+ function highlightItem() {
149
+ const el = document.querySelector(`#${activeDescendant.value}`)
150
+
151
+ el?.scrollIntoView({
152
+ block: 'nearest',
153
+ behavior: 'auto'
154
+ })
155
+ }
156
+
157
+ function handleKeydown(e) {
158
+ if (!list.value.length) return
159
+
160
+ switch (e.key) {
161
+ case 'ArrowDown':
162
+ e.preventDefault()
163
+ activeIndex.value = (activeIndex.value + 1) % list.value.length
164
+ break
165
+ case 'ArrowUp':
166
+ e.preventDefault()
167
+ activeIndex.value =
168
+ activeIndex.value <= 0 ? list.value.length - 1 : activeIndex.value - 1
169
+ break
170
+ case 'Enter':
171
+ if (activeIndex.value >= 0) {
172
+ e.preventDefault()
173
+ selectItem(list.value[activeIndex.value])
174
+ }
175
+ break
176
+ }
177
+
178
+ highlightItem()
179
+ }
180
+
181
+ const selectItem = (item) => {
182
+ emit('select', item)
183
+
184
+ if (props.retainInput) {
185
+ typed.value = props.label ? item[props.label] : item
186
+ } else {
187
+ typed.value = ''
188
+ }
189
+
190
+ list.value = []
191
+ activeIndex.value = -1
192
+ inputElement.value.inputRef.blur()
193
+ }
194
+
195
+ function setFocus() {
196
+ inputElement.value.inputRef.focus()
197
+ }
198
+
199
+ defineExpose({
200
+ setFocus
201
+ })
202
+ </script>
203
+
204
+ <style lang="scss" scoped>
205
+ .tp-autocomplete {
206
+ &__list {
207
+ display: none;
208
+ padding: 0px;
209
+ }
210
+
211
+ &__item {
212
+ margin: 0px;
213
+ }
214
+
215
+ &__input:focus ~ &__list {
216
+ display: block;
217
+ }
218
+
219
+ &__input:focus ~ &__spinner {
220
+ display: block;
221
+ }
222
+ }
223
+ </style>
@@ -0,0 +1,33 @@
1
+ <template>
2
+ <Autocomplete
3
+ url="/otus/autocomplete"
4
+ query-param="term"
5
+ label="label_html"
6
+ :autofocus="autofocus"
7
+ :params="{ having_taxon_name_only: true }"
8
+ @select="loadOtu"
9
+ />
10
+ </template>
11
+
12
+ <script setup>
13
+ import { useRouter } from 'vue-router'
14
+ import Autocomplete from '@/components/Autocomplete/Autocomplete.global.vue'
15
+
16
+ const router = useRouter()
17
+
18
+ const props = defineProps({
19
+ autofocus: {
20
+ type: Boolean,
21
+ default: false
22
+ }
23
+ })
24
+
25
+ const loadOtu = ({ id, otu_valid_id }) => {
26
+ router.push({
27
+ name: 'otus-id-overview',
28
+ params: {
29
+ id: otu_valid_id || id
30
+ }
31
+ })
32
+ }
33
+ </script>
@@ -0,0 +1,36 @@
1
+ <template>
2
+ <svg
3
+ viewBox="0 0 38 38"
4
+ xmlns="http://www.w3.org/2000/svg"
5
+ stroke="green"
6
+ >
7
+ <g
8
+ fill="none"
9
+ fill-rule="evenodd"
10
+ >
11
+ <g
12
+ transform="translate(1 1)"
13
+ stroke-width="2"
14
+ >
15
+ <circle
16
+ stroke-opacity=".5"
17
+ cx="18"
18
+ cy="18"
19
+ r="18"
20
+ />
21
+ <path d="M36 18c0-9.94-8.06-18-18-18">
22
+ <animateTransform
23
+ attributeName="transform"
24
+ type="rotate"
25
+ from="0 18 18"
26
+ to="360 18 18"
27
+ dur="1s"
28
+ repeatCount="indefinite"
29
+ />
30
+ </path>
31
+ </g>
32
+ </g>
33
+ </svg>
34
+ </template>
35
+
36
+ <script></script>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <button
3
+ type="button"
4
+ :title="isExpanded ? 'Close' : 'Expand'"
5
+ class="button-expand bg-base-foreground text-secondary-color w-5 h-5"
6
+ @click="isExpanded = !isExpanded"
7
+ >
8
+ <IconMinusCircle
9
+ v-if="isExpanded"
10
+ class="w-5 h-5"
11
+ />
12
+ <IconPlusCircle
13
+ v-else
14
+ class="w-5 h-5"
15
+ />
16
+ </button>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { computed } from 'vue'
21
+
22
+ const props = defineProps({
23
+ modelValue: {
24
+ type: Boolean,
25
+ required: true
26
+ }
27
+ })
28
+
29
+ const emit = defineEmits(['update:modelValue'])
30
+
31
+ const isExpanded = computed({
32
+ get() {
33
+ return props.modelValue
34
+ },
35
+
36
+ set(value) {
37
+ emit('update:modelValue', value)
38
+ }
39
+ })
40
+ </script>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <button
3
+ type="button"
4
+ :class="[
5
+ 'tp-button',
6
+ 'px-3',
7
+ 'py-1',
8
+ circle ? 'rounded-full ' : 'rounded-md',
9
+ 'hover:bg-opacity-80',
10
+ {
11
+ 'bg-primary-color': primary,
12
+ 'bg-secondary-color': secondary,
13
+ 'text-primary-content': primary,
14
+ 'text-secondary-content': secondary
15
+ }
16
+ ]"
17
+ >
18
+ <slot />
19
+ </button>
20
+ </template>
21
+
22
+ <script setup>
23
+ const props = defineProps({
24
+ primary: {
25
+ type: Boolean,
26
+ default: false
27
+ },
28
+
29
+ secondary: {
30
+ type: Boolean,
31
+ default: false
32
+ },
33
+
34
+ circle: {
35
+ type: Boolean,
36
+ default: false
37
+ }
38
+ })
39
+ </script>
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div
3
+ class="border-1 tp-card border-base-muted bg-base-foreground print:shadow-none print:border-0 rounded"
4
+ >
5
+ <slot />
6
+ </div>
7
+ </template>
8
+
9
+ <style>
10
+ .tp-card {
11
+ box-shadow: rgba(30, 41, 59, 0.04) 0 2px 4px 0;
12
+ border: 1px solid rgba(98, 105, 118, 0.16);
13
+ transition:
14
+ transform 0.3s ease-out,
15
+ opacity 0.3s ease-out,
16
+ box-shadow 0.3s ease-out;
17
+ }
18
+ </style>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <div class="p-4 pl-5 pr-5 tp-card-content">
3
+ <slot />
4
+ </div>
5
+ </template>
@@ -0,0 +1,7 @@
1
+ <template>
2
+ <div
3
+ class="tp-card-header p-4 pl-5 pr-5 border-b font-medium border-base-muted"
4
+ >
5
+ <slot />
6
+ </div>
7
+ </template>
@@ -0,0 +1,50 @@
1
+ <template>
2
+ <VButton
3
+ class="px-2 py-2 rounded-full"
4
+ primary
5
+ :aria-label="isCopied ? 'Copied to clipboard' : 'Copy to clipboard'"
6
+ @click="copyText"
7
+ >
8
+ <IconCheck
9
+ v-if="isCopied"
10
+ class="w-4 h-4"
11
+ />
12
+ <IconClipboard
13
+ v-else
14
+ class="w-4 h-4"
15
+ />
16
+ </VButton>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { ref, onBeforeUnmount } from 'vue'
21
+
22
+ const props = defineProps({
23
+ text: {
24
+ type: String,
25
+ required: true
26
+ },
27
+
28
+ delay: {
29
+ type: Number,
30
+ default: 2000
31
+ }
32
+ })
33
+
34
+ const isCopied = ref(false)
35
+ let timeoutId
36
+
37
+ function copyText() {
38
+ navigator.clipboard.writeText(props.text).then(() => {
39
+ isCopied.value = true
40
+
41
+ timeoutId = setTimeout(() => {
42
+ isCopied.value = false
43
+ }, props.delay)
44
+ })
45
+ }
46
+
47
+ onBeforeUnmount(() => {
48
+ clearTimeout(timeoutId)
49
+ })
50
+ </script>