@awsui/components-react
Version:
AWS UI is a collection of [React](https://reactjs.org/) components that help create intuitive, responsive, and accessible user experiences for web applications. It is developed by Amazon Web Services (AWS). This work is available under the terms of the [A
174 lines (173 loc) • 8.83 kB
JavaScript
import { __assign, __rest } from "tslib";
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { OpenAnnotation } from './annotation/open-annotation';
import { ClosedAnnotation } from './annotation/closed-annotation';
import { hotspotContext } from './context';
import { fireNonCancelableEvent } from '../internal/events';
import { useTelemetry } from '../internal/hooks/use-telemetry';
export function getStepInfo(annotations, index) {
if (index >= 0) {
var taskIndex = 0;
for (var _i = 0, annotations_1 = annotations; _i < annotations_1.length; _i++) {
var task = annotations_1[_i];
if (task.steps.length <= index) {
index -= task.steps.length;
taskIndex++;
continue;
}
return { task: task, step: task.steps[index], localIndex: index, taskIndex: taskIndex };
}
}
return { task: undefined, step: undefined, localIndex: 0, taskIndex: 0 };
}
export default function AnnotationContext(_a) {
var _b, _c, _d, _e;
var currentTutorial = _a.currentTutorial, children = _a.children, onStepChange = _a.onStepChange, onFinishHandler = _a.onFinish, onStartTutorial = _a.onStartTutorial, onExitTutorial = _a.onExitTutorial, announcementPopoverHeader = _a.announcementPopoverHeader, announcementPopoverBody = _a.announcementPopoverBody, onDismissAnnouncementPopover = _a.onDismissAnnouncementPopover, i18nStrings = _a.i18nStrings;
useTelemetry('AnnotationContext');
var _f = useState(true), open = _f[0], setOpen = _f[1];
var _g = useState(0), currentStepIndex = _g[0], setCurrentStepIndex = _g[1];
useEffect(function () {
setCurrentStepIndex(0);
setOpen(true);
}, [currentTutorial, setOpen]);
var _h = useState({}), availableHotspots = _h[0], setAvailableHotspots = _h[1];
var annotations = currentTutorial ? currentTutorial.tasks : [];
var _j = getStepInfo(annotations, currentStepIndex), task = _j.task, step = _j.step, localIndex = _j.localIndex, taskIndex = _j.taskIndex;
var currentId = step === null || step === void 0 ? void 0 : step.hotspotId;
var totalStepCount = annotations.map(function (a) { return a.steps.length; }).reduce(function (a, b) { return a + b; }, 0);
var id2index = useMemo(function () {
var mapping = {};
var counter = 0;
for (var _i = 0, annotations_2 = annotations; _i < annotations_2.length; _i++) {
var annotation = annotations_2[_i];
for (var _a = 0, _b = annotation.steps; _a < _b.length; _a++) {
var step_1 = _b[_a];
mapping[step_1.hotspotId] = counter;
counter++;
}
}
return mapping;
}, [annotations]);
var openNextStep = useCallback(function () {
var newStepIndex = Math.min(currentStepIndex + 1, totalStepCount);
setCurrentStepIndex(newStepIndex);
fireNonCancelableEvent(onStepChange, { step: newStepIndex, reason: 'next' });
}, [currentStepIndex, onStepChange, totalStepCount]);
var openPreviousStep = useCallback(function () {
var newStepIndex = Math.max(currentStepIndex - 1, 0);
setCurrentStepIndex(newStepIndex);
fireNonCancelableEvent(onStepChange, { step: newStepIndex, reason: 'previous' });
}, [onStepChange, currentStepIndex]);
var onFinish = useCallback(function () { return fireNonCancelableEvent(onFinishHandler); }, [onFinishHandler]);
useEffect(function () {
if (!currentId || availableHotspots[currentId]) {
return;
}
var findNearestHotspot = function () {
var nearestHotspot = undefined;
var nearestDistance = Infinity;
for (var _i = 0, _a = Object.keys(availableHotspots); _i < _a.length; _i++) {
var hotspotId = _a[_i];
var distanceFromCurrentHotspot = Math.abs(id2index[hotspotId] - currentStepIndex);
if (distanceFromCurrentHotspot < nearestDistance) {
nearestDistance = distanceFromCurrentHotspot;
nearestHotspot = hotspotId;
}
}
return nearestHotspot;
};
var nearestHotspot = findNearestHotspot();
if (nearestHotspot) {
var newStepIndex = id2index[nearestHotspot];
setCurrentStepIndex(newStepIndex);
fireNonCancelableEvent(onStepChange, { step: newStepIndex, reason: 'auto-fallback' });
}
}, [annotations, availableHotspots, currentId, currentStepIndex, id2index, onStepChange]);
var onDismiss = useCallback(function () {
setOpen(false);
}, [setOpen]);
var onOpen = useCallback(function (stepIndex) {
setCurrentStepIndex(stepIndex);
fireNonCancelableEvent(onStepChange, { step: stepIndex, reason: 'open' });
setOpen(true);
}, [onStepChange, setOpen]);
var idOfPreviousHotspot = (_b = getStepInfo(annotations, currentStepIndex - 1).step) === null || _b === void 0 ? void 0 : _b.hotspotId;
var idOfNextHotspot = (_c = getStepInfo(annotations, currentStepIndex + 1).step) === null || _c === void 0 ? void 0 : _c.hotspotId;
var previousHotspotIsAvailable = (_d = (idOfPreviousHotspot !== undefined && availableHotspots[idOfPreviousHotspot])) !== null && _d !== void 0 ? _d : false;
var nextHotspotIsAvailable = (_e = (idOfNextHotspot !== undefined && availableHotspots[idOfNextHotspot])) !== null && _e !== void 0 ? _e : false;
var getContentForId = useCallback(function (id, direction) {
if (currentTutorial === null || currentTutorial === void 0 ? void 0 : currentTutorial.completed) {
return null;
}
var globalStepIndex = id2index[id];
if (globalStepIndex === undefined) {
return null;
}
if (!task || !step || !open || id !== currentId) {
return (React.createElement(ClosedAnnotation, { globalStepIndex: globalStepIndex, i18nStrings: i18nStrings, onOpen: onOpen, focusOnRender: id === currentId }));
}
return (React.createElement(OpenAnnotation, { i18nStrings: i18nStrings, direction: direction, title: i18nStrings.taskTitle(taskIndex, task.title), content: step.content, alert: step.warningAlert, showFinishButton: globalStepIndex + 1 === totalStepCount, taskLocalStepIndex: localIndex, totalLocalSteps: task.steps.length, nextButtonEnabled: nextHotspotIsAvailable, onNextButtonClick: openNextStep, onFinish: onFinish, previousButtonEnabled: previousHotspotIsAvailable, onPreviousButtonClick: openPreviousStep, onDismiss: onDismiss }));
}, [
id2index,
currentTutorial,
task,
step,
open,
currentId,
i18nStrings,
taskIndex,
localIndex,
totalStepCount,
nextHotspotIsAvailable,
openNextStep,
onFinish,
previousHotspotIsAvailable,
openPreviousStep,
onDismiss,
onOpen
]);
var registerHotspot = useCallback(function (id) {
if (!id2index || id2index[id] === undefined) {
return;
}
if (availableHotspots[id]) {
return;
}
setAvailableHotspots(function (availableHotspots) {
var _a;
if (availableHotspots[id]) {
return availableHotspots;
}
return __assign(__assign({}, availableHotspots), (_a = {}, _a[id] = true, _a));
});
}, [id2index, availableHotspots]);
var unregisterHotspot = useCallback(function (id) {
if (!availableHotspots[id]) {
return;
}
setAvailableHotspots(function (availableHotspots) {
if (!availableHotspots[id]) {
return availableHotspots;
}
var removeKey = function (key, _a) {
var _b = key, _ = _a[_b], remainingObject = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
return remainingObject;
};
return removeKey(id, availableHotspots);
});
}, [availableHotspots]);
var context = {
getContentForId: getContentForId,
registerHotspot: registerHotspot,
unregisterHotspot: unregisterHotspot,
onStartTutorial: onStartTutorial,
onExitTutorial: onExitTutorial,
currentStepIndex: currentStepIndex,
currentTutorial: currentTutorial,
announcementPopoverHeader: announcementPopoverHeader,
announcementPopoverBody: announcementPopoverBody,
onDismissAnnouncementPopover: onDismissAnnouncementPopover,
labelDismissAnnouncementPopover: i18nStrings.labelDismissAnnouncementPopover
};
return React.createElement(hotspotContext.Provider, { value: context }, children);
}