@@ -261,10 +262,12 @@ type HoveredFeatureProps = {
hover: [number, number][][] | undefined;
hoverCode: string | undefined;
featureProps: FeatureProps;
+ isKeyboardActive?: boolean;
};
const HoveredFeature = memo((props: HoveredFeatureProps) => {
- const { hoveredRef, hover, hoverCode, featureProps } = props;
+ const { hoveredRef, hover, hoverCode, featureProps, isKeyboardActive } =
+ props;
if (!isDefined(hoverCode) || !isDefined(hover)) {
return null;
@@ -282,7 +285,11 @@ const HoveredFeature = memo((props: HoveredFeatureProps) => {
points={x.flat()}
strokeWidth={featureProps.hover.strokeWidth(hoverCode, true)}
closed
- stroke={featureProps.hover.stroke(hoverCode, true)}
+ stroke={featureProps.hover.stroke(
+ hoverCode,
+ true,
+ isKeyboardActive
+ )}
/>
))}
@@ -395,6 +402,11 @@ type AreaMapProps = {
width: number;
};
+type GeoInfoGroup = {
+ code: string;
+ coordinatesList: [number, number][][];
+};
+
function AreaMap(props: AreaMapProps) {
const {
isTabInteractive,
@@ -409,6 +421,27 @@ function AreaMap(props: AreaMapProps) {
width,
} = props;
+ const geoInfoGroups: GeoInfoGroup[] = geoInfo
+ .reduce((geoInfoGroups, geoItem) => {
+ const index = geoInfoGroups.findIndex(
+ (geoInfoGroup) => geoInfoGroup.code === geoItem.code
+ );
+ if (index === -1) {
+ geoInfoGroups.push({
+ code: geoItem.code,
+ coordinatesList: [geoItem.coordinates],
+ });
+ } else {
+ geoInfoGroups[index].coordinatesList.push(geoItem.coordinates);
+ }
+ return geoInfoGroups;
+ }, [] as GeoInfoGroup[])
+ .sort((geoInfoGroupA, geoInfoGroupB) => {
+ return getFeatureName(geoInfoGroupA.code).localeCompare(
+ getFeatureName(geoInfoGroupB.code)
+ );
+ });
+
const isTouch = useIsTouchDevice();
return (
@@ -417,28 +450,34 @@ function AreaMap(props: AreaMapProps) {
tabIndex={isTabInteractive ? 0 : -1}
onMouseMove={!isTouch || isIOSDevice() ? handleMouseOver : undefined}
>
- {geoInfo.map((x, i) => (
-
{
- anchorEventHandlers.onFocus(event);
- selectFeature(x.code as CodeProp, true);
- }}
- onBlur={(event) => {
- anchorEventHandlers.onBlur(event);
- selectFeature(undefined, true);
- }}
- />
- ))}
+ {geoInfoGroups.map((geoInfoGroup) =>
+ geoInfoGroup.coordinatesList.map((geoInfoCoordinates, index) => (
+
{
+ anchorEventHandlers.onFocus(event);
+ selectFeature(geoInfoGroup.code as CodeProp, true);
+ }}
+ onBlur={(event) => {
+ anchorEventHandlers.onBlur(event);
+ selectFeature(undefined, true);
+ }}
+ />
+ ))
+ )}
= (code: string) => T;
type GetHoverFeatureProp
= (
code: string,
- isActivated?: boolean
+ isActivated?: boolean,
+ isKeyboardActive?: boolean
) => T;
export type FeatureProps = {
@@ -86,9 +87,16 @@ export function getFeatureProps(
isHover ? dataConfig.hoverFill : 'none',
stroke:
!dataOptions.highlightSelection || !dataOptions.selectedCode
- ? (_code: string, isActivated?: boolean) => {
- return isActivated ? dataConfig.hoverStroke : 'none';
- }
+ ? (
+ _code: string,
+ isActivated?: boolean,
+ isKeyboardActive?: boolean
+ ) =>
+ isActivated
+ ? isKeyboardActive
+ ? dataConfig.highlightStroke
+ : dataConfig.hoverStroke
+ : 'none'
: (code: string, isActivated?: boolean) =>
code === dataOptions.selectedCode
? isActivated
@@ -126,8 +134,16 @@ export function getFeatureProps(
},
hover: {
fill: () => 'none',
- stroke: (_code: string, isActivated?: boolean) =>
- isActivated ? dataConfig.hoverStroke : 'none',
+ stroke: (
+ _code: string,
+ isActivated?: boolean,
+ isKeyboardActive?: boolean
+ ) =>
+ isActivated
+ ? isKeyboardActive
+ ? dataConfig.highlightStroke
+ : dataConfig.hoverStroke
+ : 'none',
strokeWidth: (_code: string, isActivated?: boolean) =>
isActivated ? dataConfig.hoverStrokeWidth : 0,
},
diff --git a/packages/app/src/components/cms/rich-content.tsx b/packages/app/src/components/cms/rich-content.tsx
index ddf11f0ee8..264b91c7ed 100644
--- a/packages/app/src/components/cms/rich-content.tsx
+++ b/packages/app/src/components/cms/rich-content.tsx
@@ -38,6 +38,11 @@ import { InlineChoropleth } from './inline-choropleth';
import { InlineDonutChart } from './inline-donut-chart';
import { InlineKpi } from './inline-kpi';
import { InlineTimeSeriesCharts } from './inline-time-series-charts';
+import {
+ ChevronRight,
+ Download,
+ External as ExternalLinkIcon,
+} from '@corona-dashboard/icons';
interface RichContentProps {
blocks: PortableTextEntry[];
@@ -56,7 +61,11 @@ interface AgeDemographicConfigNode {
title: string;
startDate?: string;
endDate?: string;
- config: AgeDemographicConfiguration, AccessibilityDefinition['key']>;
+ config: AgeDemographicConfiguration<
+ DataScopeKey,
+ MetricKeys,
+ AccessibilityDefinition['key']
+ >;
}
interface ChoroplethConfigNode {
@@ -295,8 +304,12 @@ function InlineAttachmentMark(props: {
if (!props.mark.asset) return <>{props.children}>;
return (
-
- {props.children}
+
+ {props.children}
);
}
@@ -309,10 +322,18 @@ function InlineLinkMark(props: { children: ReactNode; mark: InlineLink }) {
if (!mark.href) return <>{children}>;
return isAbsoluteUrl(mark.href) ? (
- {children}
+
+ {children}
+
+
) : (
- {children}
+
+ {children}
+
);
}
diff --git a/packages/app/src/components/combo-box/combo-box.tsx b/packages/app/src/components/combo-box/combo-box.tsx
index 288d392a79..c7f5798ca6 100644
--- a/packages/app/src/components/combo-box/combo-box.tsx
+++ b/packages/app/src/components/combo-box/combo-box.tsx
@@ -26,7 +26,6 @@ type TProps