diff --git a/apps/climatemappedafrica/src/components/Hero/Hero.js b/apps/climatemappedafrica/src/components/Hero/Hero.js
index 6085bc944..91239fb64 100644
--- a/apps/climatemappedafrica/src/components/Hero/Hero.js
+++ b/apps/climatemappedafrica/src/components/Hero/Hero.js
@@ -4,6 +4,8 @@ import dynamic from "next/dynamic";
import PropTypes from "prop-types";
import React, { useState } from "react";
+import Legend from "./Legend";
+
import heroBg from "@/climatemappedafrica/assets/images/bg-map-white.jpg";
import DropdownSearch from "@/climatemappedafrica/components/DropdownSearch";
import Image from "@/climatemappedafrica/components/Image";
@@ -23,6 +25,8 @@ function Hero({
properties,
level,
explorePageSlug,
+ averageTemperature,
+ legend,
...props
}) {
const isUpLg = useMediaQuery((theme) => theme.breakpoints.up("lg"));
@@ -99,45 +103,44 @@ function Hero({
{/* Since map is dynamic-ally loaded, no need for implementation="css" */}
-
-
- {center ? (
-
- ) : null}
-
-
- {hoverGeo}
-
-
-
-
+
+
+ {center ? (
+
+ ) : null}
+
+
+
+ {hoverGeo}
+
+
+
@@ -153,6 +156,8 @@ Hero.propTypes = {
featuredLocations: PropTypes.arrayOf(PropTypes.shape({})),
properties: PropTypes.shape({}),
level: PropTypes.string,
+ explorePageSlug: PropTypes.string,
+ averageTemperature: PropTypes.string,
};
export default Hero;
diff --git a/apps/climatemappedafrica/src/components/Hero/Hero.snap.js b/apps/climatemappedafrica/src/components/Hero/Hero.snap.js
index 6b4302a5f..a0e855047 100644
--- a/apps/climatemappedafrica/src/components/Hero/Hero.snap.js
+++ b/apps/climatemappedafrica/src/components/Hero/Hero.snap.js
@@ -90,14 +90,40 @@ exports[` renders unchanged 1`] = `
+ class="MuiBox-root css-0"
+ >
+
+
diff --git a/apps/climatemappedafrica/src/components/Hero/Hero.test.js b/apps/climatemappedafrica/src/components/Hero/Hero.test.js
index ec342ec4f..2f50687e7 100644
--- a/apps/climatemappedafrica/src/components/Hero/Hero.test.js
+++ b/apps/climatemappedafrica/src/components/Hero/Hero.test.js
@@ -48,6 +48,15 @@ const defaultProps = {
},
variant: "explore",
icon: null,
+ legend: [
+ { min: 10, max: 13, color: "#021AFE" },
+ { min: 13, max: 16, color: "#5455FF" },
+ { min: 16, max: 19, color: "#928EFD" },
+ { min: 19, max: 22, color: "#B494DF" },
+ { min: 22, max: 25, color: "#FA9B9B" },
+ { min: 25, max: 28, color: "#F96264" },
+ { min: 28, max: 31, color: "#F80701" },
+ ],
};
describe("", () => {
diff --git a/apps/climatemappedafrica/src/components/Hero/Legend.js b/apps/climatemappedafrica/src/components/Hero/Legend.js
new file mode 100644
index 000000000..77877f2a5
--- /dev/null
+++ b/apps/climatemappedafrica/src/components/Hero/Legend.js
@@ -0,0 +1,59 @@
+import { RichTypography } from "@commons-ui/legacy";
+import { Box } from "@mui/material";
+import PropTypes from "prop-types";
+import React, { useState, forwardRef } from "react";
+
+const Legend = forwardRef(function Legend({ data, title }, ref) {
+ const [hoveredValue, setHoveredValue] = useState(null);
+
+ const handleMouseEnter = (value) => {
+ setHoveredValue(value);
+ };
+
+ const handleMouseLeave = () => {
+ setHoveredValue(null);
+ };
+
+ return (
+
+
+ {title}
+
+
+ {data.map((item) => (
+ handleMouseEnter(`${item.min} - ${item.max}`)}
+ onMouseLeave={handleMouseLeave}
+ sx={{
+ backgroundColor: item.color,
+ height: 24,
+ minWidth: 24,
+ cursor: "pointer",
+ }}
+ />
+ ))}
+ {hoveredValue && (
+
+ {hoveredValue}
+
+ )}
+
+
+ );
+});
+
+Legend.propTypes = {
+ data: PropTypes.arrayOf(
+ PropTypes.shape({
+ min: PropTypes.number.isRequired,
+ max: PropTypes.number.isRequired,
+ color: PropTypes.string.isRequired,
+ }),
+ ).isRequired,
+};
+
+export default Legend;
diff --git a/apps/climatemappedafrica/src/components/Hero/Map.js b/apps/climatemappedafrica/src/components/Hero/Map.js
index bd8f60512..c89c1c8a4 100644
--- a/apps/climatemappedafrica/src/components/Hero/Map.js
+++ b/apps/climatemappedafrica/src/components/Hero/Map.js
@@ -17,82 +17,85 @@ function Map({
geoJSONStyles = {
color: "#2A2A2C",
weight: 1,
- opacity: 1,
dashArray: "2",
},
onLayerMouseOver,
featuredLocations,
explorePageSlug,
+ choropleth,
}) {
const router = useRouter();
- const countyCodes = featuredLocations?.map(({ code }) => code);
-
+ const regionCodes = featuredLocations?.map(({ code }) => code);
const theme = useTheme();
const onEachFeature = (feature, layer) => {
+ const choroplethColor = choropleth?.find?.(
+ (c) => c.code.toLowerCase() === feature.properties.code.toLowerCase(),
+ );
layer.setStyle({
fillColor: theme.palette.background.default,
+ ...choroplethColor,
fillOpacity: 1,
});
- if (countyCodes.includes(feature.properties.code?.toLowerCase())) {
- layer.setStyle({
- weight: 1.5,
- dashArray: 0,
- });
+ if (regionCodes.includes(feature.properties.code?.toLowerCase())) {
+ layer.setStyle(geoJSONStyles);
layer.on("mouseover", () => {
onLayerMouseOver(feature.properties.name.toLowerCase());
- layer.setStyle({
- fillColor: theme.palette.primary.main,
- fillOpacity: 0.5,
- });
+ if (explorePageSlug) {
+ layer.setStyle({
+ fillColor: choroplethColor?.fillColor,
+ fillOpacity: 0.4,
+ });
+ }
});
layer.on("mouseout", () => {
onLayerMouseOver(null);
- layer.setStyle({
- fillOpacity: 1,
- fillColor: theme.palette.background.default,
- });
+ layer.setStyle({ ...choroplethColor, fillOpacity: 1, weight: 1 });
});
layer.on("click", () => {
- router.push(
- `/${explorePageSlug}/${feature.properties.code.toLowerCase()}`,
- );
+ if (explorePageSlug) {
+ router.push(
+ `/${explorePageSlug}/${feature.properties.code.toLowerCase()}`,
+ );
+ }
});
}
};
return (
-
-
+
-
-
+
+
+
+
);
}
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js
index 8377f338e..2f2179445 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/explore-page.js
@@ -1,13 +1,19 @@
import { fetchProfileGeography } from "@/climatemappedafrica/lib/hurumap";
-async function explorePage({ block: { slugs }, hurumap, hurumapProfile }) {
+/**
+ * This function will be called only when HURUmap is enabled.
+ * @see @/climatemappedafrica/lib/data/common/index.js
+ */
+async function explorePage(block, _api, _context, { hurumap }) {
const {
- rootGeography,
- labels: { dataNotAvailable, scrollToTop: scrollToTopLabel },
items: panelItems,
- page: { value },
+ labels: { dataNotAvailable, scrollToTop: scrollToTopLabel },
+ profile: hurumapProfile,
+ profilePage,
+ rootGeography,
} = hurumap;
const { code: name } = rootGeography;
+ const { slugs } = block;
const code = slugs.length ? slugs[0] : name;
const { locations, preferredChildren, mapType, choropleth } = hurumapProfile;
@@ -41,7 +47,7 @@ async function explorePage({ block: { slugs }, hurumap, hurumapProfile }) {
blockType: "explore-page",
choropleth,
rootGeography,
- explorePagePath: value.slug,
+ explorePagePath: profilePage.slug,
locations,
mapType,
panel,
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/hero.js b/apps/climatemappedafrica/src/lib/data/blockify/hero.js
index 66b91a3e0..f225159d4 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/hero.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/hero.js
@@ -1,15 +1,21 @@
+import { generateChoropleth } from "@hurumap/next";
+
import {
fetchProfile,
fetchProfileGeography,
} from "@/climatemappedafrica/lib/hurumap";
-export default async function hero({ block, hurumap }) {
+/**
+ * This function will be called even when HURUmap is disabled.
+ * @see @/climatemappedafrica/lib/data/common/index.js
+ *
+ */
+export default async function hero(block, _api, _context, { hurumap }) {
const {
- rootGeography: { center, code, rootGeographyHasData: pinRootGeography },
- page: {
- value: { slug: explorePageSlug },
- },
- } = hurumap;
+ profilePage,
+ rootGeography: { center, code, hasData: pinRootGeography },
+ profile: hurumapProfile,
+ } = hurumap ?? { rootGeography: {} };
const { geometries } = await fetchProfileGeography(code.toLowerCase());
const { level } = geometries.boundary?.properties ?? {};
const childLevelMaps = {
@@ -18,6 +24,12 @@ export default async function hero({ block, hurumap }) {
};
const childLevel = childLevelMaps[level];
const { locations, preferredChildren } = await fetchProfile();
+ const chloropleth = hurumapProfile?.choropleth ?? null;
+ const { choropleth, legend } = generateChoropleth(
+ chloropleth,
+ locations,
+ "choropleth",
+ );
const preferredChildrenPerLevel = preferredChildren[level];
const { children } = geometries;
const preferredLevel =
@@ -26,15 +38,18 @@ export default async function hero({ block, hurumap }) {
(location) => location.level === childLevel,
);
const boundary = children[preferredLevel];
+
return {
...block,
- center,
- slug: "hero",
boundary,
+ center,
+ explorePageSlug: profilePage?.slug || null,
featuredLocations,
level,
- properties: geometries.boundary?.properties,
pinRootGeography,
- explorePageSlug,
+ properties: geometries.boundary?.properties,
+ slug: "hero",
+ choropleth,
+ legend,
};
}
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/index.js b/apps/climatemappedafrica/src/lib/data/blockify/index.js
index b89ee1313..40d3247ef 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/index.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/index.js
@@ -12,14 +12,13 @@ const propsifyBlockBySlug = {
tutorial,
};
-export const blockify = async (blocks, api, context, settings) => {
- const { hurumap, hurumapProfile } = settings;
+export const blockify = async ({ blocks }, api, context, settings) => {
const promises = blocks?.map(async (block) => {
const slug = block.blockType;
const propsifyBlock = propsifyBlockBySlug[slug];
if (propsifyBlock) {
- return propsifyBlock({ block, api, context, hurumap, hurumapProfile });
+ return propsifyBlock(block, api, context, settings);
}
return {
...block,
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js b/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js
index 1be4c04a4..0a732a785 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/page-hero.js
@@ -1,6 +1,6 @@
import { imageFromMedia } from "@/climatemappedafrica/lib/data/utils";
-async function pageHero({ block }) {
+async function pageHero(block) {
const { background: media, ...others } = block;
let background = null;
if (media) {
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/team.js b/apps/climatemappedafrica/src/lib/data/blockify/team.js
index 74c51abf6..ccc51693e 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/team.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/team.js
@@ -8,7 +8,7 @@ import { equalsIgnoreCase } from "@/climatemappedafrica/utils";
const getCountryFromCode = (alpha3) =>
countries.find((c) => equalsIgnoreCase(c.alpha3, alpha3)) ?? null;
-async function team({ block, api, context }) {
+async function team(block, api, context) {
const { query } = context;
const data = await getMembers(api, query);
let members = null;
diff --git a/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js
index c1ba44590..6e8c39fb3 100644
--- a/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js
+++ b/apps/climatemappedafrica/src/lib/data/blockify/tutorial.js
@@ -1,18 +1,19 @@
-async function tutorial({ hurumap }) {
- const {
- panel: { steps },
- enabled,
- } = hurumap;
+/**
+ * This function will be called only when HURUmap tutorial is enabled.
+ * @see @/climatemappedafrica/lib/data/common/index.js
+ */
+async function tutorial(block, _api, _context, { hurumap }) {
+ const { steps, enabled } = hurumap.tutorial;
const items = steps.map((step) => ({
...step,
selector: `#${step.selector}`,
}));
return {
- blockType: "tutorial",
- id: "tutorial",
+ ...block,
enabled,
items,
+ slug: block.blockType,
};
}
diff --git a/apps/climatemappedafrica/src/lib/data/common/index.js b/apps/climatemappedafrica/src/lib/data/common/index.js
index 33104d6b4..b784c3552 100644
--- a/apps/climatemappedafrica/src/lib/data/common/index.js
+++ b/apps/climatemappedafrica/src/lib/data/common/index.js
@@ -10,7 +10,7 @@ export function imageFromMedia(alt, url) {
return { alt, src: url };
}
-function getFooter(siteSettings, variant) {
+function getFooter(variant, settings) {
const {
connect,
footerNavigation,
@@ -19,10 +19,8 @@ function getFooter(siteSettings, variant) {
secondaryLogo,
description,
title,
- } = siteSettings;
-
+ } = settings.site;
const { menus: footerMenus, ...footerProps } = footerNavigation;
-
const media = secondaryLogo || primaryLogo;
const footerLogoUrl = typeof media === "string" ? null : media.url;
@@ -40,37 +38,46 @@ function getFooter(siteSettings, variant) {
};
}
-async function getNavBar(siteSettings, variant, { slug }, hurumapProfile) {
- const { locations } = hurumapProfile;
+async function getNavBar(variant, settings) {
+ const { hurumap, site } = settings;
const {
connect: { links = [] },
- primaryNavigation: { menus = [], connect = [] },
- primaryLogo,
drawerLogo,
+ primaryLogo,
+ primaryNavigation: { menus = [], connect = [] },
title,
- } = siteSettings;
+ } = site;
const socialLinks = links?.filter((link) => connect.includes(link.platform));
+ let explorePagePath = null;
+ let locations = null;
+ if (hurumap?.enabled) {
+ explorePagePath = hurumap.profilePage.slug;
+ if (hurumap.profile) {
+ locations = hurumap.profile.locations;
+ }
+ }
return {
- logo: imageFromMedia(title, primaryLogo.url),
drawerLogo: imageFromMedia(title, drawerLogo.url),
- explorePagePath: slug,
+ explorePagePath,
+ locations,
+ logo: imageFromMedia(title, primaryLogo.url),
menus,
socialLinks,
variant,
- locations,
};
}
export async function getPagePaths(api) {
const hurumapSettings = await api.findGlobal("settings-hurumap");
+ let profilePage;
+ if (hurumapSettings?.enabled) {
+ profilePage = hurumapSettings.page.value;
+ }
const { docs: pages } = await api.getCollection("pages");
- const {
- page: { value: explorePage },
- } = hurumapSettings;
const paths = pages.flatMap(({ slug }) => {
// TODO(kilemensi): Handle parent > child page relation e.g. /insights/news
- if (slug !== explorePage?.slug) {
+ if (slug !== profilePage?.slug) {
return {
params: {
slugs: [slug === "index" ? "" : slug],
@@ -80,7 +87,7 @@ export async function getPagePaths(api) {
// HURUmap profile page
return GEOGRAPHIES.map((code) => ({
params: {
- slugs: [explorePage.slug, code],
+ slugs: [profilePage.slug, code],
},
}));
});
@@ -98,53 +105,45 @@ export async function getPageProps(api, context) {
const { draftMode = false } = context;
const options = { draft: draftMode };
- const hurumapProfile = await fetchProfile();
-
const {
docs: [page],
} = await api.findPage(slug, options);
-
if (!page) {
return null;
}
- const hurumap = await api.findGlobal("settings-hurumap");
- const {
- page: { value: explorePage },
- } = hurumap;
- const siteSettings = await api.findGlobal("settings-site");
-
- const settings = {
- hurumap,
- hurumapProfile,
- siteSettings,
- };
-
- let blocks = await blockify(page.blocks, api, context, settings);
- const variant = page.slug === explorePage.slug ? "explore" : "default";
-
- const footer = getFooter(siteSettings, variant);
- const menus = await getNavBar(
- siteSettings,
- variant,
- explorePage,
- hurumapProfile,
- );
-
- if (slug === explorePage.slug) {
- // The explore page is a special case. The only block we need to render is map and tutorial.
- const explorePageBlocks = [
- {
+ let variant = "default";
+ const settings = {};
+ settings.site = (await api.findGlobal("settings-site")) || null;
+ const hurumapSettings = await api.findGlobal("settings-hurumap");
+ if (hurumapSettings?.enabled) {
+ // TODO(koech): Handle cases when fetching profile fails?
+ const profile = await fetchProfile();
+ const { page: hurumapPage, ...otherHurumapSettings } = hurumapSettings;
+ const { value: profilePage } = hurumapPage;
+ if (slug === profilePage.slug) {
+ variant = "explore";
+ const explorePageBlock = {
blockType: "explore-page",
slugs: slugs.slice(1),
- },
- {
- blockType: "tutorial",
- },
- ];
- blocks = await blockify(explorePageBlocks, api, context, settings);
+ };
+ page.blocks.push(explorePageBlock);
+ if (hurumapSettings.tutorial?.enabled) {
+ const tutorialBlock = { blockType: "tutorial" };
+ page.blocks.push(tutorialBlock);
+ }
+ }
+ settings.hurumap = {
+ ...otherHurumapSettings,
+ profile,
+ profilePage,
+ };
}
+ const blocks = await blockify(page, api, context, settings);
+ const footer = getFooter(variant, settings);
+ const menus = await getNavBar(variant, settings);
+
return {
blocks,
footer,
diff --git a/apps/climatemappedafrica/src/payload/blocks/Hero.js b/apps/climatemappedafrica/src/payload/blocks/Hero.js
index 674343824..6c2b6c23c 100644
--- a/apps/climatemappedafrica/src/payload/blocks/Hero.js
+++ b/apps/climatemappedafrica/src/payload/blocks/Hero.js
@@ -52,6 +52,13 @@ const Hero = {
label: "Comment",
localized: true,
},
+ {
+ name: "averageTemperature",
+ type: "text",
+ label: "Average Temperature",
+ defaultValue: "Average Temperature",
+ localized: true,
+ },
],
};
diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/PanelOptions.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/DataPanels.js
similarity index 93%
rename from apps/climatemappedafrica/src/payload/globals/HURUMap/PanelOptions.js
rename to apps/climatemappedafrica/src/payload/globals/HURUMap/DataPanels.js
index f47e0e99f..cf60493c5 100644
--- a/apps/climatemappedafrica/src/payload/globals/HURUMap/PanelOptions.js
+++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/DataPanels.js
@@ -1,12 +1,13 @@
import image from "../../fields/image";
-const PanelOptions = {
- label: "Panel Options",
+const DataPanels = {
+ label: "Data Panels",
fields: [
{
name: "items",
type: "array",
label: "Panel Items",
+ required: true,
fields: [
{
type: "select",
@@ -61,4 +62,4 @@ const PanelOptions = {
],
};
-export default PanelOptions;
+export default DataPanels;
diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/Profile.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/Profile.js
index 85f337a4a..7f33ea355 100644
--- a/apps/climatemappedafrica/src/payload/globals/HURUMap/Profile.js
+++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/Profile.js
@@ -12,7 +12,7 @@ const Profile = {
maxDepth: 1,
required: true,
admin: {
- description: "The page to show the interactive map on.",
+ description: "The page to show the HURUmap profile on.",
},
},
],
diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/RootGeography.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/RootGeography.js
index 34ef7c658..d0b44ae0f 100644
--- a/apps/climatemappedafrica/src/payload/globals/HURUMap/RootGeography.js
+++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/RootGeography.js
@@ -9,7 +9,6 @@ const RootGeography = {
en: "Root Geography",
},
type: "group",
- localized: true,
fields: [
{
name: "code",
@@ -17,7 +16,6 @@ const RootGeography = {
label: {
en: "Location Code",
},
- localized: true,
required: true,
hasMany: false,
defaultValue: "af",
@@ -35,9 +33,8 @@ const RootGeography = {
defaultValue: [20.0, 4.25],
},
{
- name: "rootGeographyHasData",
+ name: "hasData",
type: "checkbox",
- localized: true,
label: {
en: "Root geography has data",
},
diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/Tutorial.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/Tutorial.js
index 9e6852f0e..5aea722b9 100644
--- a/apps/climatemappedafrica/src/payload/globals/HURUMap/Tutorial.js
+++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/Tutorial.js
@@ -26,25 +26,17 @@ const Tutorial = {
label: "Tutorial",
fields: [
{
- name: "enabled",
- label: {
- en: "Enable Tutorial",
- },
- type: "checkbox",
- defaultValue: true,
- localized: true,
- },
- {
- name: "panel",
- label: {
- en: "Tutorial Panel",
- },
+ name: "tutorial",
type: "group",
- localized: true,
- admin: {
- condition: (_, siblingData) => !!siblingData?.enabled,
- },
fields: [
+ {
+ name: "enabled",
+ label: {
+ en: "Enable HURUmap Tutorial",
+ },
+ type: "checkbox",
+ defaultValue: true,
+ },
{
name: "steps",
label: {
@@ -60,6 +52,7 @@ const Tutorial = {
return data?.title || `Step ${String(index).padStart(2, "0")}`;
},
},
+ condition: (_, siblingData) => !!siblingData?.enabled,
},
fields: [
{
diff --git a/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js b/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js
index 047dd2ce7..b91ebb6a1 100644
--- a/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js
+++ b/apps/climatemappedafrica/src/payload/globals/HURUMap/index.js
@@ -1,4 +1,4 @@
-import PanelOptions from "./PanelOptions";
+import DataPanels from "./DataPanels";
import Profile from "./Profile";
import RootGeography from "./RootGeography";
import Tutorial from "./Tutorial";
@@ -23,7 +23,7 @@ const HURUMap = {
},
{
type: "tabs",
- tabs: [Profile, RootGeography, Tutorial, PanelOptions],
+ tabs: [Profile, DataPanels, RootGeography, Tutorial],
admin: {
condition: (_, siblingData) => !!siblingData?.enableHURUMap,
},
diff --git a/packages/hurumap-next/src/index.js b/packages/hurumap-next/src/index.js
index 52d900496..9a9fc3d0e 100644
--- a/packages/hurumap-next/src/index.js
+++ b/packages/hurumap-next/src/index.js
@@ -1,2 +1,3 @@
export { default as Source } from "./Source";
export { default as Map } from "./Map";
+export { generateChoropleth } from "./Map/utils";