UNPKG

@hhgtech/hhg-components

Version:
251 lines (230 loc) • 9.02 kB
import { _ as __rest } from './tslib.es6-ea4dfe68.js'; import React__default, { useState, useCallback, useEffect } from 'react'; import throttle from 'lodash/throttle'; import styled from '@emotion/styled'; import { theme } from './miscTheme.js'; const StyledSlider = styled.div ` position: relative; width: 100%; & div[role='slider'] { -webkit-text-size-adjust: none; -webkit-user-select: none; &:focus { outline: none; } } `; const StyledStep = styled.div ` position: absolute; top: 19px; width: 24px; height: 24px; color: ${theme.colors.white}; border: 2px solid ${theme.colors.white}; border-radius: 50%; transform: translateY(-50%) translateX(-50%); display: flex; align-items: center; justify-content: center; cursor: pointer; background-color: ${theme.colors.white}; color: ${theme.colors.gray300}; border: 1px solid ${theme.colors.gray300}; &[data-is-active='true'] { background-color: ${theme.colors.primaryBase}; color: ${theme.colors.white}; border: none; } `; const StyledTrackContainer = styled.div ` display: flex; width: 100%; height: 36px; &[data-track-type='detail'] { margin-top: 0; } &[data-track-type='detail'][data-step-passed='true'] > div { border: 1px solid ${theme.colors.primaryBase}; height: 0px; } &[data-track-type='detail'] > div { border: 1px solid ${theme.colors.gray200}; height: 0px; } `; const StyledTrack = styled.div ` width: 100%; height: 5px; align-self: center; border-radius: 4px; background-color: ${theme.colors.gray200}; `; const StyledStepLabel = styled.div ` position: absolute; top: 32px; min-width: 100px; text-align: center; color: ${theme.colors.gray500}; font-size: ${theme.sizes.fsCaption2}; font-weight: ${theme.sizes.fwBold}; &[data-step-passed='true'] { color: ${theme.colors.gray800}; } `; const StyledBreadcrumbContainer = styled.div ` display: flex; align-items: center; `; const StyledBreadcrumbWrapper = styled.div ` display: flex; align-items: center; font-size: ${theme.sizes.fsCaption2}; font-weight: ${theme.sizes.fwBold}; color: ${theme.colors.gray500}; cursor: pointer; & > svg { height: 10px; width: 10px; margin: 0 14px; } & > svg > path { stroke: ${theme.colors.gray500}; } &[data-selected='true'] { color: ${theme.colors.primaryBase}; } `; const StyledDetailStep = styled.div ` position: absolute; left: 0; top: 19px; height: 24px; cursor: pointer; transform: translateY(-50%); display: flex; align-items: center; padding: 8px; background-color: ${theme.colors.white}; `; const StyledDetailStepIndicator = styled.div ` min-width: 24px; height: 24px; border: 2px solid ${theme.colors.white}; border-radius: 50%; margin-right: 8px; display: flex; align-items: center; justify-content: center; cursor: pointer; background-color: ${theme.colors.white}; color: ${theme.colors.gray300}; border: 1px solid ${theme.colors.gray300}; &[data-is-active='true'] { border: none; background-color: ${theme.colors.primaryBase}; color: ${theme.colors.white}; } `; const StyledDetailStepIndicatorExternal = styled.div ` display: flex; align-items: center; justify-content: center; & > svg { height: 20px; width: 20px; margin-right: 8px; & > path { stroke: ${theme.colors.gray500}; } } `; const StyledDetailStepLabel = styled.div ` color: ${theme.colors.gray400}; font-size: ${theme.sizes.fsCaption2}; font-weight: ${theme.sizes.fwBold}; margin-right: 8px; flex: 0 0 auto; &[data-step-passed='true'] { color: ${theme.colors.gray800}; } `; const StyledDetailStepDescription = styled.div ` position: absolute; top: 32px; font-weight: ${theme.sizes.fwRegular}; color: ${theme.colors.gray400}; padding-right: 16px; `; const ProgressBar = ({ type, numberOfStep, activeStep, labelPrefix, detailSteps, className, onChange, }) => { const [trackLength, setTrackLength] = useState(0); const Track = (_a) => { var { trackClassName } = _a, props = __rest(_a, ["trackClassName"]); return (React__default.createElement(StyledTrackContainer, Object.assign({}, props, { className: trackClassName }), React__default.createElement(StyledTrack, null))); }; // step track const Steps = ({ trackLength, activeStep, labelPrefix = 'Step', onChange, }) => { return (React__default.createElement(React__default.Fragment, null, Array.from({ length: numberOfStep }, (v, i) => i).map((_, step) => (React__default.createElement(StyledStep, { "data-is-active": step === activeStep, "data-label": step, style: { left: (step * trackLength) / (numberOfStep - 1) }, onClick: () => { onChange && onChange(step); }, key: step }, step + 1, React__default.createElement(StyledStepLabel, { "data-step-passed": step <= activeStep }, labelPrefix + ' ' + (step + 1))))))); }; const stepTrack = (React__default.createElement(StyledSlider, { className: className + ' progress-bar' }, React__default.createElement(Track, null), React__default.createElement(Steps, { trackLength: trackLength, activeStep: activeStep, labelPrefix: labelPrefix, onChange: onChange }))); // breadcrumb const breadcrumbIcon = (React__default.createElement("svg", { "data-name": "Layer 1", viewBox: "0 0 5.5 9.5" }, React__default.createElement("title", null, 'chevron-right'), React__default.createElement("path", { d: "M.75 8.75l4-4-4-4", fill: "none", // stroke="#000" strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5 }))); const breadcrumb = (React__default.createElement(StyledBreadcrumbContainer, null, detailSteps && Array.from({ length: detailSteps.length }, (v, i) => i).map((_, step_index) => { var _a; return (React__default.createElement(StyledBreadcrumbWrapper, { key: step_index, "data-selected": step_index === activeStep, onClick: () => { onChange && onChange(step_index); } }, (_a = detailSteps[step_index]) === null || _a === void 0 ? void 0 : _a.text, ' ', step_index < detailSteps.length - 1 && breadcrumbIcon)); }))); // detail track const DetailStepsGroup = ({ detailSteps, activeStep, onChange, }) => { return (React__default.createElement(React__default.Fragment, null, Array.from({ length: detailSteps.length }, (v, i) => i).map((step, step_index) => (React__default.createElement(StyledDetailStep, { key: step_index, style: { left: (100 / detailSteps.length) * step_index + '%', width: 100 / detailSteps.length + '%', }, onClick: () => { onChange && onChange(step_index); } }, detailSteps[step_index].icon ? (React__default.createElement(StyledDetailStepIndicatorExternal, { onClick: () => { onChange && onChange(step_index); } }, detailSteps[step_index].icon)) : (React__default.createElement(StyledDetailStepIndicator, { "data-is-active": step_index === activeStep, "data-label": step, onClick: () => { onChange && onChange(step_index); }, key: step_index }, step_index + 1)), React__default.createElement(StyledDetailStepLabel, { "data-step-passed": step_index < activeStep + 1 }, detailSteps[step_index].text, React__default.createElement(StyledDetailStepDescription, null, detailSteps[step_index].description)), step_index < detailSteps.length - 1 && (React__default.createElement(Track, { "data-step-passed": step_index < activeStep, trackClassName: 'progress-track', "data-track-type": "detail" }))))))); }; const detailTrack = (React__default.createElement(StyledSlider, { className: className + ' progress-bar' }, React__default.createElement(DetailStepsGroup, { activeStep: activeStep, detailSteps: detailSteps, onChange: onChange }))); const resizeTrack = useCallback(throttle(() => { const progressTrack = document.querySelector('.progress-bar'); progressTrack && setTrackLength(progressTrack.offsetWidth); }, 1000), []); useEffect(() => { const track = document.querySelector('.progress-bar'); setTrackLength(track === null || track === void 0 ? void 0 : track.offsetWidth); window.addEventListener('resize', resizeTrack, { passive: true, }); return () => { window.removeEventListener('resize', resizeTrack); }; }, []); return ((type === 'step-track' && stepTrack) || (type === 'breadcrumb' && breadcrumb) || (type === 'detail-track' && detailTrack)); }; export { ProgressBar };