col-browser 2.3.9 → 2.4.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.
- package/README.md +29 -0
- package/es/bibtex.js +2 -2
- package/es/chunks/{BibTex-CPaVr-5w.js → BibTex-79CCKAOK.js} +2 -2
- package/es/chunks/{BibTex-CPaVr-5w.js.map → BibTex-79CCKAOK.js.map} +1 -1
- package/es/chunks/{DatasetCitation-JpNSTWz-.js → DatasetCitation-BXtAmjdZ.js} +2 -2
- package/es/chunks/{DatasetCitation-JpNSTWz-.js.map → DatasetCitation-BXtAmjdZ.js.map} +1 -1
- package/es/chunks/{DatasetlogoWithFallback-BhWvpgDn.js → DatasetlogoWithFallback-Dava2uqZ.js} +2 -2
- package/es/chunks/{DatasetlogoWithFallback-BhWvpgDn.js.map → DatasetlogoWithFallback-Dava2uqZ.js.map} +1 -1
- package/es/chunks/{Distributions-CKn1-Qze.js → Distributions-Bd4hFYdS.js} +3 -3
- package/es/chunks/{Distributions-CKn1-Qze.js.map → Distributions-Bd4hFYdS.js.map} +1 -1
- package/es/chunks/{MergedDataBadge-DK4XUXsL.js → MergedDataBadge-C1CgoRFz.js} +2 -2
- package/es/chunks/{MergedDataBadge-DK4XUXsL.js.map → MergedDataBadge-C1CgoRFz.js.map} +1 -1
- package/es/chunks/{TaxonBreakdown-BYRnP8bH.js → TaxonBreakdown-DeWamLu_.js} +2 -2
- package/es/chunks/{TaxonBreakdown-BYRnP8bH.js.map → TaxonBreakdown-DeWamLu_.js.map} +1 -1
- package/es/chunks/{XrGutter-CORP2r5Y.js → XrGutter-CU7_QPAp.js} +2 -2
- package/es/chunks/{XrGutter-CORP2r5Y.js.map → XrGutter-CU7_QPAp.js.map} +1 -1
- package/es/chunks/config-D1NH4DTr.js +22 -0
- package/es/chunks/config-D1NH4DTr.js.map +1 -0
- package/es/chunks/{dataset-BuF063rn.js → dataset-BL6g4w0G.js} +2 -2
- package/es/chunks/{dataset-BuF063rn.js.map → dataset-BL6g4w0G.js.map} +1 -1
- package/es/chunks/{enumeration-CC8SblcI.js → enumeration-DM8Hb36g.js} +2 -2
- package/es/chunks/{enumeration-CC8SblcI.js.map → enumeration-DM8Hb36g.js.map} +1 -1
- package/es/chunks/{sector-Behb-WCC.js → sector-Qeo1zPxr.js} +2 -2
- package/es/chunks/{sector-Behb-WCC.js.map → sector-Qeo1zPxr.js.map} +1 -1
- package/es/chunks/withTheme-Dh6PRuII.js +17 -0
- package/es/chunks/withTheme-Dh6PRuII.js.map +1 -0
- package/es/config.js +5 -0
- package/es/config.js.map +1 -0
- package/es/index.js +4 -2
- package/es/index.js.map +1 -1
- package/es/search.js +14 -13
- package/es/search.js.map +1 -1
- package/es/sourceDataset.js +7 -6
- package/es/sourceDataset.js.map +1 -1
- package/es/sourceDatasetList.js +16 -15
- package/es/sourceDatasetList.js.map +1 -1
- package/es/taxon.js +215 -214
- package/es/taxon.js.map +1 -1
- package/es/taxonBreakdown.js +23 -22
- package/es/taxonBreakdown.js.map +1 -1
- package/es/taxonDistribution.js +20 -19
- package/es/taxonDistribution.js.map +1 -1
- package/es/tree.js +422 -411
- package/es/tree.js.map +1 -1
- package/package.json +5 -1
- package/types/config.d.ts +1 -0
- package/types/index.d.ts +21 -0
- package/umd/col-browser.js +42 -16
- package/umd/col-browser.js.map +1 -1
- package/umd/col-browser.min.js +4 -4
- package/umd/col-browser.min.js.map +1 -1
- package/es/chunks/config-B2Z9BaEd.js +0 -30
- package/es/chunks/config-B2Z9BaEd.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TaxonBreakdown-BYRnP8bH.js","sources":["../../src/Taxon/TaxonBreakdown.js"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport config from \"../config\";\nimport client from \"../api/client\";\nimport Highcharts from \"highcharts\";\nimport \"highcharts/modules/exporting\";\nimport HighchartsReact from \"highcharts-react-official\";\nimport { get, keyBy } from \"lodash-es\";\nimport { Spin, Row, Col, Switch } from \"antd\";\nimport { useNavigateTo } from \"../router\";\nimport { readSetting, writeSetting } from \"../storage\";\n\nconst BREAKDOWN_LEVEL_KEY = \"breakdown-level\";\n\nconst MAX_SLICES_PER_RING = 100;\nconst canonicalRanks = [\n \"kingdom\",\n \"phylum\",\n \"class\",\n \"order\",\n \"family\",\n \"genus\",\n \"species\",\n];\n\nconst notAssignedLabel = (rk) => (rk ? `Not assigned ${rk}` : \"Not assigned\");\n\nconst sortAndClip = (nodes) => {\n if (!nodes || nodes.length === 0) return [];\n const sorted = [...nodes].sort((a, b) => (b.species || 0) - (a.species || 0));\n return sorted.length <= MAX_SLICES_PER_RING\n ? sorted\n : sorted.slice(0, MAX_SLICES_PER_RING);\n};\n\n// Append a \"Not assigned <rank>\" slice for the difference between a parent's\n// total species count and the sum of its visible children. Covers two cases:\n// 1. species that sit directly under the parent without an intermediate rank\n// 2. species under children that were clipped out by sortAndClip\nconst padNotAssigned = (kids, parentSpecies) => {\n const sorted = sortAndClip(kids || []);\n const sum = sorted.reduce((a, n) => a + (n.species || 0), 0);\n if (sum >= parentSpecies) return sorted;\n return [\n ...sorted,\n {\n name: notAssignedLabel(get(sorted, \"[0].rank\", \"\")),\n species: parentSpecies - sum,\n children: [],\n },\n ];\n};\n\nconst TaxonBreakdown = ({\n taxon,\n datasetKey,\n rank = [],\n dataset,\n level = 1,\n showLevelSwitch = false,\n darkMode,\n}) => {\n const navigateToTaxon = useNavigateTo(\"taxon\");\n const [options, setOptions] = useState(null);\n const [loading, setLoading] = useState(false);\n const [invalid, setInvalid] = useState(false);\n // The chart's effective level is controlled internally when the switch\n // is enabled, so toggling can refetch + re-render the chart. Otherwise\n // the prop drives directly.\n const [activeLevel, setActiveLevel] = useState(() =>\n showLevelSwitch ? readSetting(BREAKDOWN_LEVEL_KEY, level) : level\n );\n useEffect(() => {\n // When the 1/2 switch is shown the remembered choice owns the level, so a\n // (usually static) `level` prop must not clobber it; otherwise the prop\n // drives directly.\n if (!showLevelSwitch) setActiveLevel(level);\n }, [level, showLevelSwitch]);\n useEffect(() => {\n if (showLevelSwitch) writeSetting(BREAKDOWN_LEVEL_KEY, activeLevel);\n }, [activeLevel, showLevelSwitch]);\n useEffect(() => {\n if (taxon?.id && datasetKey) {\n getData();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [taxon, datasetKey, activeLevel]);\n\n const getOverView = async () => {\n const res = await client(\n `${\n config.dataApi\n }dataset/${datasetKey}/nameusage/search?TAXON_ID=${encodeURIComponent(\n taxon.id\n )}&facet=rank&status=accepted&status=provisionally%20accepted&limit=0`\n );\n return keyBy(get(res, \"data.facets.rank\", []), \"value\");\n };\n\n const getData = async () => {\n setLoading(true);\n try {\n const counts = await getOverView();\n\n // confirm the focal taxon has at least one child rank with content\n const ranks = canonicalRanks;\n let taxonRankIdx = ranks.indexOf(get(taxon, \"name.rank\"));\n if (taxonRankIdx === -1) {\n let rankIndex = rank.indexOf(get(taxon, \"name.rank\")) + 1;\n while (taxonRankIdx === -1 && rankIndex < rank.length - 1) {\n const canonicalRankIndex = ranks.indexOf(rank[rankIndex]);\n if (canonicalRankIndex > -1) {\n taxonRankIdx = canonicalRankIndex - 1;\n }\n rankIndex++;\n }\n }\n let childRank;\n let childRankIndex = taxonRankIdx + 1;\n while (!childRank && childRankIndex < ranks.length) {\n const nextRank = get(ranks, `[${childRankIndex}]`);\n if (nextRank && get(counts, `${nextRank}.count`, 0) > 0) {\n childRank = nextRank;\n } else {\n childRankIndex++;\n }\n }\n if (!childRank) {\n setInvalid(true);\n setLoading(false);\n return;\n }\n\n const res = await client(\n `${config.dataApi}dataset/${datasetKey}/taxon/${taxon.id}/breakdown?level=${activeLevel}`\n );\n const children = res.data || [];\n const totalSpecies = get(counts, \"species.count\", 0);\n\n setLoading(false);\n buildChart(children, totalSpecies);\n } catch (err) {\n setLoading(false);\n }\n };\n\n const buildChart = (children, totalSpecies) => {\n const DOI = dataset.doi ? \"https://doi.org/\" + dataset.doi : null;\n const baseColors = Highcharts.getOptions().colors;\n // Colour used for outer-ring \"gap\" slices: match the page background so\n // the wedge reads as empty space rather than overlapping the inner pie.\n // Follows the explicit `darkMode` prop if given, otherwise prefers-color-scheme.\n const prefersDark =\n typeof darkMode === \"boolean\"\n ? darkMode\n : typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n const gapColor = prefersDark ? \"#1f1f1f\" : \"#ffffff\";\n const taxonClickHandler = {\n click: (e) => {\n if (e.point._id) {\n navigateToTaxon(e.point._id);\n }\n },\n };\n\n // Inner pie: direct children of the focal taxon. Pad with a single\n // \"Not assigned <rank>\" slice if focal-taxon species don't fully sum up.\n const innerNodes = padNotAssigned(children, totalSpecies);\n const innerData = innerNodes.map((n, i) => ({\n name: n.name,\n y: n.species,\n _id: n.id,\n color: baseColors[i % baseColors.length],\n _kids: n.children,\n }));\n\n // Outer ring: children of each inner slice (grandchildren of focal),\n // coloured as a monochrome brightness shift of the parent so each\n // family of arcs reads as one hue group. Only rendered when level >= 2\n // AND the response actually carries that depth. With level=1 we draw\n // a single-ring pie even if the API returned nested children.\n const outerData = [];\n const hasOuterData =\n activeLevel >= 2 && innerData.some((s) => s._kids && s._kids.length > 0);\n if (hasOuterData) {\n innerData.forEach((slice) => {\n const sorted = sortAndClip(slice._kids || []);\n const sum = sorted.reduce((a, n) => a + (n.species || 0), 0);\n sorted.forEach((g, j) => {\n const t = sorted.length > 1 ? j / (sorted.length - 1) : 0;\n const shift = -0.1 + t * 0.4;\n outerData.push({\n name: g.name,\n y: g.species,\n _id: g.id,\n color: Highcharts.color(slice.color).brighten(shift).get(),\n });\n });\n // Where children don't fully account for the inner slice, add a\n // transparent gap slice so the outer ring stays angularly aligned\n // with the inner pie but the missing portion reads as empty space\n // (rather than a labelled \"Not assigned\" wedge).\n if (sum < slice.y) {\n outerData.push({\n name: notAssignedLabel(get(sorted, \"[0].rank\", \"\")),\n y: slice.y - sum,\n color: gapColor,\n borderColor: gapColor,\n borderWidth: 0,\n dataLabels: { enabled: false },\n });\n }\n });\n }\n\n const clean = (rows) => rows.map(({ _kids, ...rest }) => rest);\n const grandTotal = totalSpecies || innerData.reduce((a, s) => a + s.y, 0);\n\n const innerLabelStyle = {\n color: \"contrast\",\n textOutline: \"1px contrast\",\n fontWeight: \"bold\",\n };\n\n // Inner-ring data labels: only positioned inside the ring when there's\n // an outer ring fighting for the external label gutter. With just one\n // ring (level=1) the labels live outside the chart, same as the outer\n // ring at level=2, with the slice name + species count.\n const innerDataLabels = hasOuterData\n ? {\n formatter: function () {\n return this.y > grandTotal / 10 ? this.point.name : null;\n },\n distance: -30,\n style: innerLabelStyle,\n }\n : {\n formatter: function () {\n return this.y > 1\n ? \"<b>\" +\n this.point.name +\n \":</b> \" +\n this.y.toLocaleString(\"en-GB\")\n : null;\n },\n };\n\n const series = [\n {\n name: \"Species\",\n data: clean(innerData),\n size: hasOuterData ? \"60%\" : \"85%\",\n dataLabels: innerDataLabels,\n point: { events: taxonClickHandler },\n },\n ];\n if (hasOuterData) {\n series.push({\n name: \"Species\",\n data: outerData,\n size: \"85%\",\n innerSize: \"60%\",\n dataLabels: {\n formatter: function () {\n return this.y > 1\n ? \"<b>\" +\n this.point.name +\n \":</b> \" +\n this.y.toLocaleString(\"en-GB\")\n : null;\n },\n },\n point: { events: taxonClickHandler },\n });\n }\n\n setOptions({\n chart: { type: \"pie\" },\n credits: {\n text: `${taxon.name.scientificName} in ${dataset.title}${\n dataset.version ? \" (\" + dataset.version + \")\" : \"\"\n }. ${(dataset.doi ? \"DOI:\" + dataset.doi : null) || dataset.url || \"\"}`,\n href: DOI || dataset.url || \"\",\n },\n title: { text: \"\" },\n plotOptions: { pie: { shadow: false, center: [\"50%\", \"50%\"] } },\n tooltip: {},\n series,\n responsive: {\n rules: [\n {\n condition: { maxWidth: 400 },\n chartOptions: {\n series: hasOuterData\n ? [{}, { dataLabels: { enabled: false } }]\n : [{}],\n },\n },\n ],\n },\n exporting: {\n chartOptions: {\n plotOptions: { series: { dataLabels: { enabled: true } } },\n },\n fallbackToExportServer: false,\n },\n });\n };\n\n if (invalid) return null;\n\n // Place the level toggle inside the chart's top-right area, just left of\n // the Highcharts context-menu (≡) icon, so it doesn't consume an extra\n // row. Colourless switch with lvl1 / lvl2 labels.\n const levelSwitch = showLevelSwitch ? (\n <Switch\n size=\"small\"\n checked={activeLevel === 2}\n onChange={(checked) => setActiveLevel(checked ? 2 : 1)}\n checkedChildren=\"lvl2\"\n unCheckedChildren=\"lvl1\"\n style={{\n position: \"absolute\",\n top: 11,\n right: 44,\n zIndex: 2,\n background: activeLevel === 2 ? \"#8c8c8c\" : \"#bfbfbf\",\n }}\n />\n ) : null;\n\n return (\n <div style={{ position: \"relative\" }}>\n {levelSwitch}\n {loading || !options ? (\n <Row style={{ padding: \"48px\" }}>\n <Col flex=\"auto\"></Col>\n <Col>\n <Spin size=\"large\" />\n </Col>\n <Col flex=\"auto\"></Col>\n </Row>\n ) : (\n <HighchartsReact highcharts={Highcharts} options={options} />\n )}\n </div>\n );\n};\n\nexport default TaxonBreakdown;\n"],"names":["BREAKDOWN_LEVEL_KEY","MAX_SLICES_PER_RING","canonicalRanks","notAssignedLabel","rk","sortAndClip","nodes","sorted","a","b","padNotAssigned","kids","parentSpecies","sum","n","get","TaxonBreakdown","taxon","datasetKey","rank","dataset","level","showLevelSwitch","darkMode","navigateToTaxon","useNavigateTo","options","setOptions","useState","loading","setLoading","invalid","setInvalid","activeLevel","setActiveLevel","readSetting","useEffect","writeSetting","getData","getOverView","res","client","config","keyBy","counts","ranks","taxonRankIdx","rankIndex","canonicalRankIndex","childRank","childRankIndex","nextRank","children","totalSpecies","buildChart","DOI","baseColors","Highcharts","gapColor","taxonClickHandler","innerData","i","outerData","hasOuterData","s","slice","g","j","shift","clean","rows","_kids","rest","grandTotal","innerDataLabels","series","levelSwitch","jsx","Switch","checked","jsxs","Row","Col","Spin","HighchartsReact"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TaxonBreakdown-DeWamLu_.js","sources":["../../src/Taxon/TaxonBreakdown.js"],"sourcesContent":["import React, { useState, useEffect } from \"react\";\nimport config from \"../config\";\nimport client from \"../api/client\";\nimport Highcharts from \"highcharts\";\nimport \"highcharts/modules/exporting\";\nimport HighchartsReact from \"highcharts-react-official\";\nimport { get, keyBy } from \"lodash-es\";\nimport { Spin, Row, Col, Switch } from \"antd\";\nimport { useNavigateTo } from \"../router\";\nimport { readSetting, writeSetting } from \"../storage\";\n\nconst BREAKDOWN_LEVEL_KEY = \"breakdown-level\";\n\nconst MAX_SLICES_PER_RING = 100;\nconst canonicalRanks = [\n \"kingdom\",\n \"phylum\",\n \"class\",\n \"order\",\n \"family\",\n \"genus\",\n \"species\",\n];\n\nconst notAssignedLabel = (rk) => (rk ? `Not assigned ${rk}` : \"Not assigned\");\n\nconst sortAndClip = (nodes) => {\n if (!nodes || nodes.length === 0) return [];\n const sorted = [...nodes].sort((a, b) => (b.species || 0) - (a.species || 0));\n return sorted.length <= MAX_SLICES_PER_RING\n ? sorted\n : sorted.slice(0, MAX_SLICES_PER_RING);\n};\n\n// Append a \"Not assigned <rank>\" slice for the difference between a parent's\n// total species count and the sum of its visible children. Covers two cases:\n// 1. species that sit directly under the parent without an intermediate rank\n// 2. species under children that were clipped out by sortAndClip\nconst padNotAssigned = (kids, parentSpecies) => {\n const sorted = sortAndClip(kids || []);\n const sum = sorted.reduce((a, n) => a + (n.species || 0), 0);\n if (sum >= parentSpecies) return sorted;\n return [\n ...sorted,\n {\n name: notAssignedLabel(get(sorted, \"[0].rank\", \"\")),\n species: parentSpecies - sum,\n children: [],\n },\n ];\n};\n\nconst TaxonBreakdown = ({\n taxon,\n datasetKey,\n rank = [],\n dataset,\n level = 1,\n showLevelSwitch = false,\n darkMode,\n}) => {\n const navigateToTaxon = useNavigateTo(\"taxon\");\n const [options, setOptions] = useState(null);\n const [loading, setLoading] = useState(false);\n const [invalid, setInvalid] = useState(false);\n // The chart's effective level is controlled internally when the switch\n // is enabled, so toggling can refetch + re-render the chart. Otherwise\n // the prop drives directly.\n const [activeLevel, setActiveLevel] = useState(() =>\n showLevelSwitch ? readSetting(BREAKDOWN_LEVEL_KEY, level) : level\n );\n useEffect(() => {\n // When the 1/2 switch is shown the remembered choice owns the level, so a\n // (usually static) `level` prop must not clobber it; otherwise the prop\n // drives directly.\n if (!showLevelSwitch) setActiveLevel(level);\n }, [level, showLevelSwitch]);\n useEffect(() => {\n if (showLevelSwitch) writeSetting(BREAKDOWN_LEVEL_KEY, activeLevel);\n }, [activeLevel, showLevelSwitch]);\n useEffect(() => {\n if (taxon?.id && datasetKey) {\n getData();\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [taxon, datasetKey, activeLevel]);\n\n const getOverView = async () => {\n const res = await client(\n `${\n config.dataApi\n }dataset/${datasetKey}/nameusage/search?TAXON_ID=${encodeURIComponent(\n taxon.id\n )}&facet=rank&status=accepted&status=provisionally%20accepted&limit=0`\n );\n return keyBy(get(res, \"data.facets.rank\", []), \"value\");\n };\n\n const getData = async () => {\n setLoading(true);\n try {\n const counts = await getOverView();\n\n // confirm the focal taxon has at least one child rank with content\n const ranks = canonicalRanks;\n let taxonRankIdx = ranks.indexOf(get(taxon, \"name.rank\"));\n if (taxonRankIdx === -1) {\n let rankIndex = rank.indexOf(get(taxon, \"name.rank\")) + 1;\n while (taxonRankIdx === -1 && rankIndex < rank.length - 1) {\n const canonicalRankIndex = ranks.indexOf(rank[rankIndex]);\n if (canonicalRankIndex > -1) {\n taxonRankIdx = canonicalRankIndex - 1;\n }\n rankIndex++;\n }\n }\n let childRank;\n let childRankIndex = taxonRankIdx + 1;\n while (!childRank && childRankIndex < ranks.length) {\n const nextRank = get(ranks, `[${childRankIndex}]`);\n if (nextRank && get(counts, `${nextRank}.count`, 0) > 0) {\n childRank = nextRank;\n } else {\n childRankIndex++;\n }\n }\n if (!childRank) {\n setInvalid(true);\n setLoading(false);\n return;\n }\n\n const res = await client(\n `${config.dataApi}dataset/${datasetKey}/taxon/${taxon.id}/breakdown?level=${activeLevel}`\n );\n const children = res.data || [];\n const totalSpecies = get(counts, \"species.count\", 0);\n\n setLoading(false);\n buildChart(children, totalSpecies);\n } catch (err) {\n setLoading(false);\n }\n };\n\n const buildChart = (children, totalSpecies) => {\n const DOI = dataset.doi ? \"https://doi.org/\" + dataset.doi : null;\n const baseColors = Highcharts.getOptions().colors;\n // Colour used for outer-ring \"gap\" slices: match the page background so\n // the wedge reads as empty space rather than overlapping the inner pie.\n // Follows the explicit `darkMode` prop if given, otherwise prefers-color-scheme.\n const prefersDark =\n typeof darkMode === \"boolean\"\n ? darkMode\n : typeof window !== \"undefined\" &&\n typeof window.matchMedia === \"function\" &&\n window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n const gapColor = prefersDark ? \"#1f1f1f\" : \"#ffffff\";\n const taxonClickHandler = {\n click: (e) => {\n if (e.point._id) {\n navigateToTaxon(e.point._id);\n }\n },\n };\n\n // Inner pie: direct children of the focal taxon. Pad with a single\n // \"Not assigned <rank>\" slice if focal-taxon species don't fully sum up.\n const innerNodes = padNotAssigned(children, totalSpecies);\n const innerData = innerNodes.map((n, i) => ({\n name: n.name,\n y: n.species,\n _id: n.id,\n color: baseColors[i % baseColors.length],\n _kids: n.children,\n }));\n\n // Outer ring: children of each inner slice (grandchildren of focal),\n // coloured as a monochrome brightness shift of the parent so each\n // family of arcs reads as one hue group. Only rendered when level >= 2\n // AND the response actually carries that depth. With level=1 we draw\n // a single-ring pie even if the API returned nested children.\n const outerData = [];\n const hasOuterData =\n activeLevel >= 2 && innerData.some((s) => s._kids && s._kids.length > 0);\n if (hasOuterData) {\n innerData.forEach((slice) => {\n const sorted = sortAndClip(slice._kids || []);\n const sum = sorted.reduce((a, n) => a + (n.species || 0), 0);\n sorted.forEach((g, j) => {\n const t = sorted.length > 1 ? j / (sorted.length - 1) : 0;\n const shift = -0.1 + t * 0.4;\n outerData.push({\n name: g.name,\n y: g.species,\n _id: g.id,\n color: Highcharts.color(slice.color).brighten(shift).get(),\n });\n });\n // Where children don't fully account for the inner slice, add a\n // transparent gap slice so the outer ring stays angularly aligned\n // with the inner pie but the missing portion reads as empty space\n // (rather than a labelled \"Not assigned\" wedge).\n if (sum < slice.y) {\n outerData.push({\n name: notAssignedLabel(get(sorted, \"[0].rank\", \"\")),\n y: slice.y - sum,\n color: gapColor,\n borderColor: gapColor,\n borderWidth: 0,\n dataLabels: { enabled: false },\n });\n }\n });\n }\n\n const clean = (rows) => rows.map(({ _kids, ...rest }) => rest);\n const grandTotal = totalSpecies || innerData.reduce((a, s) => a + s.y, 0);\n\n const innerLabelStyle = {\n color: \"contrast\",\n textOutline: \"1px contrast\",\n fontWeight: \"bold\",\n };\n\n // Inner-ring data labels: only positioned inside the ring when there's\n // an outer ring fighting for the external label gutter. With just one\n // ring (level=1) the labels live outside the chart, same as the outer\n // ring at level=2, with the slice name + species count.\n const innerDataLabels = hasOuterData\n ? {\n formatter: function () {\n return this.y > grandTotal / 10 ? this.point.name : null;\n },\n distance: -30,\n style: innerLabelStyle,\n }\n : {\n formatter: function () {\n return this.y > 1\n ? \"<b>\" +\n this.point.name +\n \":</b> \" +\n this.y.toLocaleString(\"en-GB\")\n : null;\n },\n };\n\n const series = [\n {\n name: \"Species\",\n data: clean(innerData),\n size: hasOuterData ? \"60%\" : \"85%\",\n dataLabels: innerDataLabels,\n point: { events: taxonClickHandler },\n },\n ];\n if (hasOuterData) {\n series.push({\n name: \"Species\",\n data: outerData,\n size: \"85%\",\n innerSize: \"60%\",\n dataLabels: {\n formatter: function () {\n return this.y > 1\n ? \"<b>\" +\n this.point.name +\n \":</b> \" +\n this.y.toLocaleString(\"en-GB\")\n : null;\n },\n },\n point: { events: taxonClickHandler },\n });\n }\n\n setOptions({\n chart: { type: \"pie\" },\n credits: {\n text: `${taxon.name.scientificName} in ${dataset.title}${\n dataset.version ? \" (\" + dataset.version + \")\" : \"\"\n }. ${(dataset.doi ? \"DOI:\" + dataset.doi : null) || dataset.url || \"\"}`,\n href: DOI || dataset.url || \"\",\n },\n title: { text: \"\" },\n plotOptions: { pie: { shadow: false, center: [\"50%\", \"50%\"] } },\n tooltip: {},\n series,\n responsive: {\n rules: [\n {\n condition: { maxWidth: 400 },\n chartOptions: {\n series: hasOuterData\n ? [{}, { dataLabels: { enabled: false } }]\n : [{}],\n },\n },\n ],\n },\n exporting: {\n chartOptions: {\n plotOptions: { series: { dataLabels: { enabled: true } } },\n },\n fallbackToExportServer: false,\n },\n });\n };\n\n if (invalid) return null;\n\n // Place the level toggle inside the chart's top-right area, just left of\n // the Highcharts context-menu (≡) icon, so it doesn't consume an extra\n // row. Colourless switch with lvl1 / lvl2 labels.\n const levelSwitch = showLevelSwitch ? (\n <Switch\n size=\"small\"\n checked={activeLevel === 2}\n onChange={(checked) => setActiveLevel(checked ? 2 : 1)}\n checkedChildren=\"lvl2\"\n unCheckedChildren=\"lvl1\"\n style={{\n position: \"absolute\",\n top: 11,\n right: 44,\n zIndex: 2,\n background: activeLevel === 2 ? \"#8c8c8c\" : \"#bfbfbf\",\n }}\n />\n ) : null;\n\n return (\n <div style={{ position: \"relative\" }}>\n {levelSwitch}\n {loading || !options ? (\n <Row style={{ padding: \"48px\" }}>\n <Col flex=\"auto\"></Col>\n <Col>\n <Spin size=\"large\" />\n </Col>\n <Col flex=\"auto\"></Col>\n </Row>\n ) : (\n <HighchartsReact highcharts={Highcharts} options={options} />\n )}\n </div>\n );\n};\n\nexport default TaxonBreakdown;\n"],"names":["BREAKDOWN_LEVEL_KEY","MAX_SLICES_PER_RING","canonicalRanks","notAssignedLabel","rk","sortAndClip","nodes","sorted","a","b","padNotAssigned","kids","parentSpecies","sum","n","get","TaxonBreakdown","taxon","datasetKey","rank","dataset","level","showLevelSwitch","darkMode","navigateToTaxon","useNavigateTo","options","setOptions","useState","loading","setLoading","invalid","setInvalid","activeLevel","setActiveLevel","readSetting","useEffect","writeSetting","getData","getOverView","res","client","config","keyBy","counts","ranks","taxonRankIdx","rankIndex","canonicalRankIndex","childRank","childRankIndex","nextRank","children","totalSpecies","buildChart","DOI","baseColors","Highcharts","gapColor","taxonClickHandler","innerData","i","outerData","hasOuterData","s","slice","g","j","shift","clean","rows","_kids","rest","grandTotal","innerDataLabels","series","levelSwitch","jsx","Switch","checked","jsxs","Row","Col","Spin","HighchartsReact"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as t } from "./jsx-runtime-BzflLqGi.js";
|
|
2
2
|
import "react";
|
|
3
|
-
import { M as i } from "./MergedDataBadge-
|
|
3
|
+
import { M as i } from "./MergedDataBadge-C1CgoRFz.js";
|
|
4
4
|
const m = ({ merged: r, style: o, children: s, ...a }) => r ? /* @__PURE__ */ t.jsxs("span", { style: { position: "relative", display: "inline-block", ...o }, children: [
|
|
5
5
|
/* @__PURE__ */ t.jsx(
|
|
6
6
|
i,
|
|
@@ -20,4 +20,4 @@ const m = ({ merged: r, style: o, children: s, ...a }) => r ? /* @__PURE__ */ t.
|
|
|
20
20
|
export {
|
|
21
21
|
m as X
|
|
22
22
|
};
|
|
23
|
-
//# sourceMappingURL=XrGutter-
|
|
23
|
+
//# sourceMappingURL=XrGutter-CU7_QPAp.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"XrGutter-
|
|
1
|
+
{"version":3,"file":"XrGutter-CU7_QPAp.js","sources":["../../src/components/XrGutter.js"],"sourcesContent":["import React from \"react\";\nimport MergedDataBadge from \"./MergedDataBadge\";\n\n// Renders the XR (merged-data) badge in the left gutter of a line or table\n// cell. The badge is absolutely positioned just left of the content, so it\n// takes no flow width — the content stays at the same position whether or not\n// the badge is shown. This keeps list/table rows aligned (mirroring how the\n// taxon title places its XR badge) instead of appending the badge after the\n// name or wedging it mid-line.\n//\n// When `merged` is falsy the children render unchanged (no wrapper). Any extra\n// props are forwarded to MergedDataBadge (datasetKey, verbatimSourceKey,\n// sourceDatasetKey, sourceId, createdBy, …).\nconst XrGutter = ({ merged, style, children, ...badgeProps }) =>\n merged ? (\n <span style={{ position: \"relative\", display: \"inline-block\", ...style }}>\n <MergedDataBadge\n {...badgeProps}\n style={{\n position: \"absolute\",\n right: \"100%\",\n top: \"50%\",\n transform: \"translateY(-50%)\",\n marginRight: \"4px\",\n }}\n />\n {children}\n </span>\n ) : (\n <>{children}</>\n );\n\nexport default XrGutter;\n"],"names":["XrGutter","merged","style","children","badgeProps","jsx","MergedDataBadge"],"mappings":";;;AAaA,MAAMA,IAAW,CAAC,EAAE,QAAAC,GAAQ,OAAAC,GAAO,UAAAC,GAAU,GAAGC,QAC9CH,2BACG,QAAA,EAAK,OAAO,EAAE,UAAU,YAAY,SAAS,gBAAgB,GAAGC,KAC/D,UAAA;AAAA,EAAAG,gBAAAA,EAAAA;AAAAA,IAACC;AAAA,IAAA;AAAA,MACE,GAAGF;AAAA,MACJ,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,KAAK;AAAA,QACL,WAAW;AAAA,QACX,aAAa;AAAA,MAAA;AAAA,IACf;AAAA,EAAA;AAAA,EAEDD;AAAA,EAAA,CACH,wCAEG,UAAAA,EAAA,CAAS;"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const o = {
|
|
2
|
+
dataApi: "https://api.checklistbank.org/",
|
|
3
|
+
// Human-facing ChecklistBank portal. Used for outbound links to
|
|
4
|
+
// dataset / publisher pages we don't host ourselves.
|
|
5
|
+
clbPortal: "https://www.checklistbank.org",
|
|
6
|
+
// GBIF API base (no trailing slash). Used for the occurrence count and
|
|
7
|
+
// the v2 map tile endpoint.
|
|
8
|
+
gbifApi: "https://api.gbif.org",
|
|
9
|
+
// GBIF human-facing portal where the attribution link points. The
|
|
10
|
+
// multitaxonomy occurrence search now ships on the production portal.
|
|
11
|
+
gbifPortal: "https://www.gbif.org"
|
|
12
|
+
}, r = /* @__PURE__ */ new Set(["dataApi"]), a = (i, t) => r.has(i) ? t.replace(/\/*$/, "/") : t.replace(/\/+$/, "");
|
|
13
|
+
function n(i = {}) {
|
|
14
|
+
return Object.entries(i).forEach(([t, c]) => {
|
|
15
|
+
o[t] = typeof c == "string" ? a(t, c) : c;
|
|
16
|
+
}), o;
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
n as a,
|
|
20
|
+
o as c
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=config-D1NH4DTr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-D1NH4DTr.js","sources":["../../src/config.js"],"sourcesContent":["const config = {\n dataApi: \"https://api.checklistbank.org/\",\n // Human-facing ChecklistBank portal. Used for outbound links to\n // dataset / publisher pages we don't host ourselves.\n clbPortal: \"https://www.checklistbank.org\",\n // GBIF API base (no trailing slash). Used for the occurrence count and\n // the v2 map tile endpoint.\n gbifApi: \"https://api.gbif.org\",\n // GBIF human-facing portal where the attribution link points. The\n // multitaxonomy occurrence search now ships on the production portal.\n gbifPortal: \"https://www.gbif.org\",\n};\n\n// `dataApi` is concatenated with bare paths (`${dataApi}dataset/…`) so it must\n// end with a slash; the others are concatenated with paths that carry their own\n// leading slash, so they must not. Normalising here means callers can pass\n// either form without breaking every URL the components build.\nconst SLASH_TERMINATED = new Set([\"dataApi\"]);\n\nconst normalize = (key, value) =>\n SLASH_TERMINATED.has(key)\n ? value.replace(/\\/*$/, \"/\")\n : value.replace(/\\/+$/, \"\");\n\n/**\n * Override the base URLs the components talk to, e.g. to point them at the\n * ChecklistBank dev API. Merges into the shared config, so keys left out keep\n * their current value. Call once before rendering.\n *\n * configure({ dataApi: \"https://api.dev.checklistbank.org/\" })\n */\nexport function configure(overrides = {}) {\n Object.entries(overrides).forEach(([key, value]) => {\n config[key] = typeof value === \"string\" ? normalize(key, value) : value;\n });\n return config;\n}\n\nexport default config;\n"],"names":["config","SLASH_TERMINATED","normalize","key","value","configure","overrides"],"mappings":"AAAA,MAAMA,IAAS;AAAA,EACX,SAAS;AAAA;AAAA;AAAA,EAGT,WAAW;AAAA;AAAA;AAAA,EAGX,SAAS;AAAA;AAAA;AAAA,EAGT,YAAY;AAChB,GAMMC,IAAmB,oBAAI,IAAI,CAAC,SAAS,CAAC,GAEtCC,IAAY,CAACC,GAAKC,MACpBH,EAAiB,IAAIE,CAAG,IAClBC,EAAM,QAAQ,QAAQ,GAAG,IACzBA,EAAM,QAAQ,QAAQ,EAAE;AAS3B,SAASC,EAAUC,IAAY,IAAI;AACtC,gBAAO,QAAQA,CAAS,EAAE,QAAQ,CAAC,CAACH,GAAKC,CAAK,MAAM;AAChD,IAAAJ,EAAOG,CAAG,IAAI,OAAOC,KAAU,WAAWF,EAAUC,GAAKC,CAAK,IAAIA;AAAA,EACtE,CAAC,GACMJ;AACX;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c } from "./router-CssZk5qZ.js";
|
|
2
|
-
import { c as s } from "./config-
|
|
2
|
+
import { c as s } from "./config-D1NH4DTr.js";
|
|
3
3
|
const p = (t) => t.then(
|
|
4
4
|
(e) => e.data,
|
|
5
5
|
(e) => null
|
|
@@ -27,4 +27,4 @@ export {
|
|
|
27
27
|
h as c,
|
|
28
28
|
g
|
|
29
29
|
};
|
|
30
|
-
//# sourceMappingURL=dataset-
|
|
30
|
+
//# sourceMappingURL=dataset-BL6g4w0G.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset-
|
|
1
|
+
{"version":3,"file":"dataset-BL6g4w0G.js","sources":["../../src/api/dataset.js"],"sourcesContent":["import client from \"./client\";\nimport config from \"../config\";\n\nconst reflect = (p) =>\n p.then(\n (v) => v.data,\n (e) => null\n );\n\n// Bulk lookup using the API's `/source/simple?id=…&id=…` endpoint. One\n// HTTP request resolves all ids in the batch. The endpoint returns a\n// lightweight dataset object per id; results may come back in any order,\n// so we reorder by `key` to match what DataLoader expects (same length\n// and same order as the requested ids).\n//\n// Tolerates any failure mode (404, network error, malformed response, …)\n// by resolving every id in the failing batch to null. Returning the\n// expected-length array is critical — DataLoader rejects every pending\n// load() if the batch function rejects or returns the wrong length, and\n// the per-id load() rejections would in turn reject the Promise.all in\n// TaxonSources and leave the popover spinner stuck.\nexport const getDatasetsBatch = (ids, datasetKey) => {\n if (!ids?.length) return Promise.resolve([]);\n const nullsForAll = () => ids.map(() => null);\n const params = ids.map((id) => `id=${encodeURIComponent(id)}`).join(\"&\");\n return client(`${config.dataApi}dataset/${datasetKey}/source/simple?${params}`)\n .then((res) => {\n try {\n const byKey = new Map();\n const arr = Array.isArray(res?.data) ? res.data : [];\n arr.forEach((d) => {\n if (d && d.key != null) byKey.set(d.key, d);\n });\n return ids.map((id) => byKey.get(id) ?? byKey.get(Number(id)) ?? null);\n } catch (parseErr) {\n return nullsForAll();\n }\n })\n .catch(() => nullsForAll());\n};\n\nexport const getPublishersBatch = (ids, datasetKey) => {\n return Promise.all(\n ids.map((i) =>\n reflect(client(`${config.dataApi}dataset/${datasetKey}/sector/publisher/${i}`))\n )\n );\n};\n\nexport const getCatalogues = () => {\n return client(`${config.dataApi}dataset/catalogues`).then(({ data }) =>\n getDatasetsBatch(data)\n );\n};\n\nexport const getDataset = (datasetKey) =>\n client(`${config.dataApi}dataset/${datasetKey}`);\n\n// Lightweight dataset descriptor — includes `origin`, `title`, `version`,\n// `key`, etc. Used by Search to gate filter UI on the dataset's origin.\n// TODO: switch to `/dataset/{key}/simple` once that endpoint deploys.\n// The full /dataset/{key} response is a superset, so it works today.\nexport const getDatasetSimple = (datasetKey) =>\n client(`${config.dataApi}dataset/${datasetKey}`);\n"],"names":["reflect","p","v","getDatasetsBatch","ids","datasetKey","nullsForAll","params","id","client","config","res","byKey","d","getPublishersBatch","i","getDataset","getDatasetSimple"],"mappings":";;AAGA,MAAMA,IAAU,CAACC,MACfA,EAAE;AAAA,EACA,CAACC,MAAMA,EAAE;AAAA,EACT,CAAC,MAAM;AACT,GAcWC,IAAmB,CAACC,GAAKC,MAAe;AACnD,MAAI,EAACD,KAAA,QAAAA,EAAK,gBAAe,QAAQ,QAAQ,CAAA,CAAE;AAC3C,QAAME,IAAc,MAAMF,EAAI,IAAI,MAAM,IAAI,GACtCG,IAASH,EAAI,IAAI,CAACI,MAAO,MAAM,mBAAmBA,CAAE,CAAC,EAAE,EAAE,KAAK,GAAG;AACvE,SAAOC,EAAO,GAAGC,EAAO,OAAO,WAAWL,CAAU,kBAAkBE,CAAM,EAAE,EAC3E,KAAK,CAACI,MAAQ;AACb,QAAI;AACF,YAAMC,wBAAY,IAAA;AAElB,cADY,MAAM,QAAQD,KAAA,gBAAAA,EAAK,IAAI,IAAIA,EAAI,OAAO,CAAA,GAC9C,QAAQ,CAACE,MAAM;AACjB,QAAIA,KAAKA,EAAE,OAAO,UAAY,IAAIA,EAAE,KAAKA,CAAC;AAAA,MAC5C,CAAC,GACMT,EAAI,IAAI,CAACI,MAAOI,EAAM,IAAIJ,CAAE,KAAKI,EAAM,IAAI,OAAOJ,CAAE,CAAC,KAAK,IAAI;AAAA,IACvE,QAAmB;AACjB,aAAOF,EAAA;AAAA,IACT;AAAA,EACF,CAAC,EACA,MAAM,MAAMA,GAAa;AAC9B,GAEaQ,IAAqB,CAACV,GAAKC,MAC/B,QAAQ;AAAA,EACbD,EAAI;AAAA,IAAI,CAACW,MACPf,EAAQS,EAAO,GAAGC,EAAO,OAAO,WAAWL,CAAU,qBAAqBU,CAAC,EAAE,CAAC;AAAA,EAAA;AAChF,GAUSC,IAAa,CAACX,MACzBI,EAAO,GAAGC,EAAO,OAAO,WAAWL,CAAU,EAAE,GAMpCY,IAAmB,CAACZ,MAC/BI,EAAO,GAAGC,EAAO,OAAO,WAAWL,CAAU,EAAE;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { c as a } from "./router-CssZk5qZ.js";
|
|
2
|
-
import { c as o } from "./config-
|
|
2
|
+
import { c as o } from "./config-D1NH4DTr.js";
|
|
3
3
|
const c = () => a(`${o.dataApi}vocab/country`).then(
|
|
4
4
|
(t) => t.data
|
|
5
5
|
), e = () => a(`${o.dataApi}vocab/taxgroup`).then(
|
|
@@ -9,4 +9,4 @@ export {
|
|
|
9
9
|
e as a,
|
|
10
10
|
c as g
|
|
11
11
|
};
|
|
12
|
-
//# sourceMappingURL=enumeration-
|
|
12
|
+
//# sourceMappingURL=enumeration-DM8Hb36g.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"enumeration-
|
|
1
|
+
{"version":3,"file":"enumeration-DM8Hb36g.js","sources":["../../src/api/enumeration.js"],"sourcesContent":["// import axiosInstance from './util/axiosInstance';\nimport client from \"./client\";\nimport config from \"../config\";\n\nexport const getFrequency = () => {\n return client(`${config.dataApi}vocab/frequency`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getDatasetType = () => {\n return client(`${config.dataApi}vocab/datasettype`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getDataFormatType = () => {\n return client(`${config.dataApi}vocab/dataformat`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getDatasetOrigin = () => {\n return client(`${config.dataApi}vocab/datasetorigin`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getRank = () => {\n return client(`${config.dataApi}vocab/rank`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getTaxonomicStatus = () => {\n return client(`${config.dataApi}vocab/taxonomicstatus`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getIssue = () => {\n return client(`${config.dataApi}vocab/issue`).then(res =>\n res.data\n );\n};\n\nexport const getNameType = () => {\n return client(`${config.dataApi}vocab/nametype`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getNameField = () => {\n return client(`${config.dataApi}vocab/namefield`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getNomStatus = () => {\n return client(`${config.dataApi}vocab/nomstatus`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getLicense = () => {\n return client(`${config.dataApi}vocab/license`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getNomCode = () => {\n return client(`${config.dataApi}vocab/nomcode`).then(res =>\n res.data\n );\n};\n\nexport const getImportState = () => {\n return client(`${config.dataApi}vocab/importstate`).then(res =>\n res.data\n );\n};\n\nexport const getLifezones = () => {\n return client(`${config.dataApi}vocab/lifezone`).then(res =>\n res.data\n );\n};\n\nexport const getSectorImportState = () => {\n return client(`${config.dataApi}vocab/sectorimport$state`).then(res =>\n res.data.map(e => e.name)\n );\n};\n\nexport const getCountries = () => {\n return client(`${config.dataApi}vocab/country`).then(res =>\n res.data\n );\n};\n\nexport const getTaxGroup = () => {\n return client(`${config.dataApi}vocab/taxgroup`).then(res =>\n res.data\n );\n};\n\n\n\n\n"],"names":["getCountries","client","config","res","getTaxGroup"],"mappings":";;AA8FO,MAAMA,IAAe,MACnBC,EAAO,GAAGC,EAAO,OAAO,eAAe,EAAE;AAAA,EAAK,OACnDC,EAAI;AAAA,GAIKC,IAAc,MAClBH,EAAO,GAAGC,EAAO,OAAO,gBAAgB,EAAE;AAAA,EAAK,OACpDC,EAAI;AAAA;"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { c as o } from "./router-CssZk5qZ.js";
|
|
2
|
-
import { c as r } from "./config-
|
|
2
|
+
import { c as r } from "./config-D1NH4DTr.js";
|
|
3
3
|
const c = (a) => a.then((t) => t.data, (t) => null), i = (a, t) => Promise.all(
|
|
4
4
|
a.map((e) => c(o(`${r.dataApi}dataset/${t}/sector/${e}`)))
|
|
5
5
|
);
|
|
6
6
|
export {
|
|
7
7
|
i as g
|
|
8
8
|
};
|
|
9
|
-
//# sourceMappingURL=sector-
|
|
9
|
+
//# sourceMappingURL=sector-Qeo1zPxr.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sector-
|
|
1
|
+
{"version":3,"file":"sector-Qeo1zPxr.js","sources":["../../src/api/sector.js"],"sourcesContent":["import client from \"./client\";\nimport config from \"../config\";\n\nconst reflect = p => p.then(v => v.data, e => null);\n\nexport const getSectorsBatch = (ids, datasetKey) => {\n return Promise.all(\n ids.map(i => reflect(client(`${config.dataApi}dataset/${datasetKey}/sector/${i}`)))\n );\n};\n"],"names":["reflect","p","v","getSectorsBatch","ids","datasetKey","i","client","config"],"mappings":";;AAGA,MAAMA,IAAU,OAAKC,EAAE,KAAK,OAAKC,EAAE,MAAM,OAAK,IAAI,GAErCC,IAAkB,CAACC,GAAKC,MAC5B,QAAQ;AAAA,EACbD,EAAI,IAAI,CAAAE,MAAKN,EAAQO,EAAO,GAAGC,EAAO,OAAO,WAAWH,CAAU,WAAWC,CAAC,EAAE,CAAC,CAAC;AAAA;"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { j as i } from "./jsx-runtime-BzflLqGi.js";
|
|
2
|
+
import "react";
|
|
3
|
+
import { theme as h, ConfigProvider as d } from "antd";
|
|
4
|
+
function l(e) {
|
|
5
|
+
const m = (a) => {
|
|
6
|
+
const { theme: o, darkMode: r, ...s } = a;
|
|
7
|
+
if (!o && !r)
|
|
8
|
+
return /* @__PURE__ */ i.jsx(e, { ...s });
|
|
9
|
+
const t = { ...o || {} };
|
|
10
|
+
return r && !t.algorithm && (t.algorithm = h.darkAlgorithm), /* @__PURE__ */ i.jsx(d, { theme: t, children: /* @__PURE__ */ i.jsx(e, { darkMode: r, ...s }) });
|
|
11
|
+
};
|
|
12
|
+
return m.displayName = `withTheme(${e.displayName || e.name || "Component"})`, m;
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
l as w
|
|
16
|
+
};
|
|
17
|
+
//# sourceMappingURL=withTheme-Dh6PRuII.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"withTheme-Dh6PRuII.js","sources":["../../src/withTheme.js"],"sourcesContent":["import React from \"react\";\nimport { ConfigProvider, theme as antdTheme } from \"antd\";\n\n// Optional antd theming. Embedders can pass:\n// - `theme`: a full antd ThemeConfig (token / algorithm / components),\n// forwarded straight to ConfigProvider.\n// - `darkMode`: convenience boolean. When true and theme.algorithm is not\n// set, antd's darkAlgorithm is applied.\n// When neither prop is provided we render the wrapped component directly,\n// without a ConfigProvider, so the library's defaults are untouched.\nexport function withTheme(Component) {\n const Wrapped = (props) => {\n const { theme, darkMode, ...rest } = props;\n\n if (!theme && !darkMode) {\n return <Component {...rest} />;\n }\n\n const merged = { ...(theme || {}) };\n if (darkMode && !merged.algorithm) {\n merged.algorithm = antdTheme.darkAlgorithm;\n }\n\n return (\n <ConfigProvider theme={merged}>\n <Component darkMode={darkMode} {...rest} />\n </ConfigProvider>\n );\n };\n Wrapped.displayName = `withTheme(${\n Component.displayName || Component.name || \"Component\"\n })`;\n return Wrapped;\n}\n\nexport default withTheme;\n"],"names":["withTheme","Component","Wrapped","props","theme","darkMode","rest","jsx","merged","antdTheme","ConfigProvider"],"mappings":";;;AAUO,SAASA,EAAUC,GAAW;AACnC,QAAMC,IAAU,CAACC,MAAU;AACzB,UAAM,EAAA,OAAEC,GAAO,UAAAC,GAAU,GAAGC,MAASH;AAErC,QAAI,CAACC,KAAS,CAACC;AACb,aAAOE,gBAAAA,MAACN,GAAA,EAAW,GAAGK,EAAA,CAAM;AAG9B,UAAME,IAAS,EAAE,GAAIJ,KAAS,GAAC;AAC/B,WAAIC,KAAY,CAACG,EAAO,cACtBA,EAAO,YAAYC,EAAU,gBAI7BF,gBAAAA,EAAAA,IAACG,KAAe,OAAOF,GACrB,gCAACP,GAAA,EAAU,UAAAI,GAAqB,GAAGC,EAAA,CAAM,EAAA,CAC3C;AAAA,EAEJ;AACA,SAAAJ,EAAQ,cAAc,aACpBD,EAAU,eAAeA,EAAU,QAAQ,WAC7C,KACOC;AACT;"}
|
package/es/config.js
ADDED
package/es/config.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
package/es/index.js
CHANGED
|
@@ -3,12 +3,13 @@ import { Search as x } from "./search.js";
|
|
|
3
3
|
import { Taxon as f } from "./taxon.js";
|
|
4
4
|
import { SourceDataset as p } from "./sourceDataset.js";
|
|
5
5
|
import { SourceDatasetList as n } from "./sourceDatasetList.js";
|
|
6
|
-
import { BibTex as
|
|
6
|
+
import { BibTex as u } from "./bibtex.js";
|
|
7
7
|
import { TaxonBreakdown as c } from "./taxonBreakdown.js";
|
|
8
8
|
import { TaxonDistribution as D } from "./taxonDistribution.js";
|
|
9
9
|
import { w as b } from "./chunks/index-BmhRLlZh.js";
|
|
10
|
+
import { a as h } from "./chunks/config-D1NH4DTr.js";
|
|
10
11
|
export {
|
|
11
|
-
|
|
12
|
+
u as BibTex,
|
|
12
13
|
x as Search,
|
|
13
14
|
p as SourceDataset,
|
|
14
15
|
n as SourceDatasetList,
|
|
@@ -16,6 +17,7 @@ export {
|
|
|
16
17
|
c as TaxonBreakdown,
|
|
17
18
|
D as TaxonDistribution,
|
|
18
19
|
e as Tree,
|
|
20
|
+
h as configure,
|
|
19
21
|
b as withRouting
|
|
20
22
|
};
|
|
21
23
|
//# sourceMappingURL=index.js.map
|
package/es/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;"}
|
package/es/search.js
CHANGED
|
@@ -2,21 +2,22 @@ var ut = Object.defineProperty;
|
|
|
2
2
|
var ct = (r, i, a) => i in r ? ut(r, i, { enumerable: !0, configurable: !0, writable: !0, value: a }) : r[i] = a;
|
|
3
3
|
var c = (r, i, a) => ct(r, typeof i != "symbol" ? i + "" : i, a);
|
|
4
4
|
import { a as ht } from "./chunks/withDatasetKey-BgMY05XE.js";
|
|
5
|
-
import {
|
|
5
|
+
import { w as dt } from "./chunks/withTheme-Dh6PRuII.js";
|
|
6
6
|
import { j as s } from "./chunks/jsx-runtime-BzflLqGi.js";
|
|
7
7
|
import * as C from "react";
|
|
8
8
|
import f from "react";
|
|
9
|
-
import { L as S, c as
|
|
10
|
-
import { a as ft } from "./chunks/dataset-
|
|
11
|
-
import { a as xt } from "./chunks/enumeration-
|
|
9
|
+
import { L as S, c as j, s as pt, R as mt, b as gt } from "./chunks/router-CssZk5qZ.js";
|
|
10
|
+
import { a as ft } from "./chunks/dataset-BL6g4w0G.js";
|
|
11
|
+
import { a as xt } from "./chunks/enumeration-DM8Hb36g.js";
|
|
12
12
|
import { r as St, w as vt } from "./chunks/storage-BgdCo9fV.js";
|
|
13
13
|
import { Input as G, Form as R, Select as k, Row as x, Col as g, AutoComplete as K, Radio as yt, Alert as jt, Button as I, Table as bt } from "antd";
|
|
14
|
+
import { c as b } from "./chunks/config-D1NH4DTr.js";
|
|
14
15
|
import Ct from "query-string";
|
|
15
16
|
import { isArray as O, startCase as m, snakeCase as M, get as u, initial as z, debounce as At, isEqual as Dt, isEmpty as Tt, merge as $t, forEach as Et } from "lodash-es";
|
|
16
17
|
import { E as Ot } from "./chunks/ErrorMsg-K8k5PPTp.js";
|
|
17
|
-
import { C as F, N as wt } from "./chunks/DatasetCitation-
|
|
18
|
+
import { C as F, N as wt } from "./chunks/DatasetCitation-BXtAmjdZ.js";
|
|
18
19
|
import Nt from "react-highlight-words";
|
|
19
|
-
import { X as Rt } from "./chunks/XrGutter-
|
|
20
|
+
import { X as Rt } from "./chunks/XrGutter-CU7_QPAp.js";
|
|
20
21
|
import { I as P } from "./chunks/AntdIcon-B1nMlqyh.js";
|
|
21
22
|
var kt = { icon: { tag: "svg", attrs: { viewBox: "64 64 896 896", focusable: "false" }, children: [{ tag: "path", attrs: { d: "M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z" } }] }, name: "down", theme: "outlined" };
|
|
22
23
|
function w() {
|
|
@@ -218,13 +219,13 @@ class Kt extends f.Component {
|
|
|
218
219
|
e && e !== a.defaultDatasetKey ? this.setDefaultValue(e) : a.defaultDatasetKey && !e && this.setState({ value: "" });
|
|
219
220
|
});
|
|
220
221
|
c(this, "setDefaultValue", (a) => {
|
|
221
|
-
|
|
222
|
+
j(`${b.dataApi}dataset/${a}`).then((e) => {
|
|
222
223
|
this.setState({ value: u(e, "data.title") || "" }), this.props.onSelectDataset(e.data);
|
|
223
224
|
});
|
|
224
225
|
});
|
|
225
226
|
c(this, "getDatasets", (a) => {
|
|
226
227
|
const { contributesTo: e } = this.props;
|
|
227
|
-
|
|
228
|
+
j(`${b.dataApi}dataset?q=${a}&limit=30${e ? "&contributesTo=" + e : ""}`).then((n) => {
|
|
228
229
|
this.setState({ datasets: n.data.result });
|
|
229
230
|
}).catch((n) => {
|
|
230
231
|
this.setState({ datasets: [], err: n });
|
|
@@ -385,7 +386,7 @@ class Ut extends f.Component {
|
|
|
385
386
|
Dt(a.filters, this.props.filters) || this.parseParamsAndGetData();
|
|
386
387
|
});
|
|
387
388
|
c(this, "getRank", () => {
|
|
388
|
-
|
|
389
|
+
j(`${b.dataApi}vocab/rank`).then(
|
|
389
390
|
(a) => this.setState({ rank: a.data.map((e) => e.name) })
|
|
390
391
|
);
|
|
391
392
|
});
|
|
@@ -417,8 +418,8 @@ class Ut extends f.Component {
|
|
|
417
418
|
c(this, "getData", () => {
|
|
418
419
|
const { params: a } = this.state;
|
|
419
420
|
this.setState({ loading: !0 });
|
|
420
|
-
const { datasetKey: e } = this.props, n = `${
|
|
421
|
-
|
|
421
|
+
const { datasetKey: e } = this.props, n = `${b.dataApi}dataset/${e}/nameusage/search`, o = u(a, "status") ? a : { ...a, status: "_NOT_NULL" };
|
|
422
|
+
j(`${n}?${Ct.stringify(o)}`).then((l) => {
|
|
422
423
|
const h = { ...this.state.pagination };
|
|
423
424
|
h.total = l.data.total, this.setState({
|
|
424
425
|
loading: !1,
|
|
@@ -794,8 +795,8 @@ function Yt({
|
|
|
794
795
|
}
|
|
795
796
|
) });
|
|
796
797
|
}
|
|
797
|
-
const
|
|
798
|
+
const de = dt(ht(Yt));
|
|
798
799
|
export {
|
|
799
|
-
|
|
800
|
+
de as Search
|
|
800
801
|
};
|
|
801
802
|
//# sourceMappingURL=search.js.map
|