@awsui/components-react
Version:
On July 19th, 2022, we launched [Cloudscape Design System](https://cloudscape.design). Cloudscape is an evolution of AWS-UI. It consists of user interface guidelines, front-end components, design resources, and development tools for building intuitive, en
112 lines • 7.88 kB
JavaScript
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
import React, { useRef } from 'react';
import clsx from 'clsx';
import { useMergeRefs, warnOnce } from '@awsui/component-toolkit/internal';
import { getAnalyticsMetadataAttribute } from '@awsui/component-toolkit/internal/analytics-metadata';
import { useInternalI18n } from '../i18n/context';
import { FunnelMetrics } from '../internal/analytics';
import { useFunnel } from '../internal/analytics/hooks/use-funnel';
import { DATA_ATTR_FUNNEL_KEY, FUNNEL_KEY_FUNNEL_NAME, FUNNEL_KEY_STEP_NAME, getSubStepAllSelector, getTextFromSelector, } from '../internal/analytics/selectors';
import { getBaseProps } from '../internal/base-component';
import { fireNonCancelableEvent } from '../internal/events';
import { useContainerBreakpoints } from '../internal/hooks/container-queries';
import { useControllable } from '../internal/hooks/use-controllable';
import { useVisualRefresh } from '../internal/hooks/use-visual-mode';
import { useFunnelChangeEvent } from './analytics';
import WizardForm, { STEP_NAME_SELECTOR } from './wizard-form';
import WizardNavigation from './wizard-navigation';
import analyticsSelectors from './analytics-metadata/styles.css.js';
import styles from './styles.css.js';
export default function InternalWizard({ steps, activeStepIndex: controlledActiveStepIndex, submitButtonText, isLoadingNextStep = false, allowSkipTo = false, customPrimaryActions, secondaryActions, onCancel, onSubmit, onNavigate, __internalRootRef, __injectAnalyticsComponentMetadata = false, ...rest }) {
var _a, _b, _c, _d, _e, _f, _g, _h;
const baseProps = getBaseProps(rest);
const [breakpoint, breakpointsRef] = useContainerBreakpoints(['xs']);
const ref = useMergeRefs(breakpointsRef, __internalRootRef);
const smallContainer = breakpoint === 'default';
const [activeStepIndex, setActiveStepIndex] = useControllable(controlledActiveStepIndex, onNavigate, 0, {
componentName: 'Wizard',
controlledProp: 'activeStepIndex',
changeHandler: 'onNavigate',
});
const { funnelIdentifier, funnelInteractionId, funnelSubmit, funnelCancel, funnelProps, funnelNextOrSubmitAttempt } = useFunnel();
const actualActiveStepIndex = activeStepIndex ? Math.min(activeStepIndex, steps.length - 1) : 0;
const farthestStepIndex = useRef(actualActiveStepIndex);
farthestStepIndex.current = Math.max(farthestStepIndex.current, actualActiveStepIndex);
const isVisualRefresh = useVisualRefresh();
const isLastStep = actualActiveStepIndex >= steps.length - 1;
const navigationEvent = (requestedStepIndex, reason) => {
if (funnelInteractionId) {
const stepName = getTextFromSelector(STEP_NAME_SELECTOR);
FunnelMetrics.funnelStepNavigation({
navigationType: reason,
funnelInteractionId,
stepNumber: actualActiveStepIndex + 1,
stepName,
stepNameSelector: STEP_NAME_SELECTOR,
destinationStepNumber: requestedStepIndex + 1,
subStepAllSelector: getSubStepAllSelector(),
});
}
setActiveStepIndex(requestedStepIndex);
fireNonCancelableEvent(onNavigate, { requestedStepIndex, reason });
};
const onStepClick = (stepIndex) => navigationEvent(stepIndex, 'step');
const onSkipToClick = (stepIndex) => navigationEvent(stepIndex, 'skip');
const onCancelClick = () => {
funnelCancel();
fireNonCancelableEvent(onCancel);
};
const onPreviousClick = () => navigationEvent(actualActiveStepIndex - 1, 'previous');
const onPrimaryClick = () => {
funnelNextOrSubmitAttempt();
if (isLastStep) {
funnelSubmit();
fireNonCancelableEvent(onSubmit);
}
else {
navigationEvent(actualActiveStepIndex + 1, 'next');
}
};
useFunnelChangeEvent(funnelInteractionId, funnelIdentifier, steps);
const i18n = useInternalI18n('wizard');
const skipToButtonLabel = i18n('i18nStrings.skipToButtonLabel', (_a = rest.i18nStrings) === null || _a === void 0 ? void 0 : _a.skipToButtonLabel, format => task => format({ task__title: task.title }));
const i18nStrings = {
...rest.i18nStrings,
skipToButtonLabel,
stepNumberLabel: i18n('i18nStrings.stepNumberLabel', (_b = rest.i18nStrings) === null || _b === void 0 ? void 0 : _b.stepNumberLabel, format => stepNumber => format({ stepNumber })),
collapsedStepsLabel: i18n('i18nStrings.collapsedStepsLabel', (_c = rest.i18nStrings) === null || _c === void 0 ? void 0 : _c.collapsedStepsLabel, format => (stepNumber, stepsCount) => format({ stepNumber, stepsCount })),
navigationAriaLabel: i18n('i18nStrings.navigationAriaLabel', (_d = rest.i18nStrings) === null || _d === void 0 ? void 0 : _d.navigationAriaLabel),
cancelButton: i18n('i18nStrings.cancelButton', (_e = rest.i18nStrings) === null || _e === void 0 ? void 0 : _e.cancelButton),
previousButton: i18n('i18nStrings.previousButton', (_f = rest.i18nStrings) === null || _f === void 0 ? void 0 : _f.previousButton),
nextButton: i18n('i18nStrings.nextButton', (_g = rest.i18nStrings) === null || _g === void 0 ? void 0 : _g.nextButton),
optional: i18n('i18nStrings.optional', (_h = rest.i18nStrings) === null || _h === void 0 ? void 0 : _h.optional),
};
if (activeStepIndex && activeStepIndex >= steps.length) {
warnOnce('Wizard', `You have set \`activeStepIndex\` to ${activeStepIndex} but you have provided only ${steps.length} steps. Its value is ignored and the component uses ${steps.length - 1} instead.`);
}
if (allowSkipTo && !skipToButtonLabel) {
warnOnce('Wizard', `You have set \`allowSkipTo\` but you have not provided \`i18nStrings.skipToButtonLabel\`. The skip-to button will not be rendered.`);
}
const componentAnalyticsMetadata = {
name: 'awsui.Wizard',
label: {
root: 'body',
selector: `[${DATA_ATTR_FUNNEL_KEY}="${FUNNEL_KEY_FUNNEL_NAME}"]`,
},
properties: {
stepsCount: `${(steps || []).length}`,
activeStepIndex: `${activeStepIndex}`,
activeStepLabel: `[${DATA_ATTR_FUNNEL_KEY}="${FUNNEL_KEY_STEP_NAME}"]`,
...(rest.analyticsMetadata || {}),
},
};
return (React.createElement("div", { ...baseProps, ...funnelProps, ref: ref, className: clsx(styles.root, analyticsSelectors.root, baseProps.className), ...(__injectAnalyticsComponentMetadata
? getAnalyticsMetadataAttribute({ component: componentAnalyticsMetadata })
: {}) },
React.createElement("div", { className: clsx(styles.wizard, isVisualRefresh && styles.refresh, smallContainer && styles['small-container']) },
React.createElement(WizardNavigation, { activeStepIndex: actualActiveStepIndex, farthestStepIndex: farthestStepIndex.current, allowSkipTo: allowSkipTo, hidden: smallContainer, i18nStrings: i18nStrings, isLoadingNextStep: isLoadingNextStep, onStepClick: onStepClick, onSkipToClick: onSkipToClick, steps: steps }),
React.createElement("div", { className: clsx(styles.form, isVisualRefresh && styles.refresh, smallContainer && styles['small-container']) },
React.createElement(WizardForm, { steps: steps, showCollapsedSteps: smallContainer, i18nStrings: i18nStrings, submitButtonText: submitButtonText, activeStepIndex: actualActiveStepIndex, isPrimaryLoading: isLoadingNextStep, allowSkipTo: allowSkipTo, customPrimaryActions: customPrimaryActions, secondaryActions: secondaryActions, onCancelClick: onCancelClick, onPreviousClick: onPreviousClick, onSkipToClick: onSkipToClick, onPrimaryClick: onPrimaryClick })))));
}
//# sourceMappingURL=internal.js.map