@axa-fr/design-system-apollo-react 2.0.1 → 2.0.2-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,13 @@ import { ProgressBar } from "../ProgressBar/ProgressBarCommon";
3
3
  export type ProgressBarGroupProps = {
4
4
  currentStepProgress?: number;
5
5
  currentStep: number;
6
+ /**
7
+ * @deprecated Use `stepsCount` instead.
8
+ */
6
9
  nbSteps?: 2 | 3 | 4 | 5 | 6 | 7 | 8;
7
- label?: string;
10
+ stepsCount?: 2 | 3 | 4 | 5 | 6 | 7 | 8;
11
+ max?: number;
8
12
  className?: string;
9
13
  ProgressBarComponent: ComponentType<ComponentProps<typeof ProgressBar>>;
10
- };
11
- export declare const ProgressBarGroup: ({ currentStepProgress, nbSteps, currentStep, label, className, ProgressBarComponent, }: ProgressBarGroupProps) => import("react/jsx-runtime").JSX.Element;
14
+ } & Omit<ComponentProps<"ol">, "children" | "className">;
15
+ export declare const ProgressBarGroup: ({ currentStepProgress, max, nbSteps, stepsCount, currentStep, className, ProgressBarComponent, ...props }: ProgressBarGroupProps) => import("react/jsx-runtime").JSX.Element;
@@ -1,18 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import classNames from "classnames";
3
3
  import { useId } from "react";
4
- const INITIAL_STEPPER_PROGRESS = 10;
5
- const MAX_STEPPER_PROGRESS = 100;
6
- export const ProgressBarGroup = ({ currentStepProgress = INITIAL_STEPPER_PROGRESS, nbSteps = 4, currentStep, label, className, ProgressBarComponent, }) => {
4
+ import { useSequentialProgress } from "./useSequentialProgress";
5
+ export const ProgressBarGroup = ({ currentStepProgress = 0, max = 100, nbSteps = 4, stepsCount = nbSteps, currentStep, className, ProgressBarComponent, ...props }) => {
7
6
  const stepperId = useId();
8
- const getCurrentProgress = (index) => {
9
- if (index < currentStep) {
10
- return MAX_STEPPER_PROGRESS;
11
- }
12
- if (index === currentStep) {
13
- return currentStepProgress || INITIAL_STEPPER_PROGRESS;
14
- }
15
- return 0;
16
- };
17
- return (_jsx("div", { id: stepperId, role: "group", "aria-label": label, className: classNames("af-progress-bar-group", className), children: [...Array(nbSteps).keys()].map((index) => (_jsx(ProgressBarComponent, { value: getCurrentProgress(index), max: MAX_STEPPER_PROGRESS, "aria-current": index === currentStep ? true : undefined }, `${stepperId}-${index}`))) }));
7
+ const progressValues = useSequentialProgress(currentStepProgress / max, currentStep, stepsCount);
8
+ return (_jsx("ol", { className: classNames("af-progress-bar-group", className), ...props, children: progressValues.map((value, index) => (_jsx("li", { className: "af-progress-bar-group__item", children: _jsx(ProgressBarComponent, { value: value, "aria-hidden": true }) }, `af-progress-bar-group__item--${stepperId}-${index}`))) }));
18
9
  };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * useSequentialProgress
3
+ *
4
+ * A custom React hook to manage the animated progress values for a multi-step progress bar (stepper).
5
+ *
6
+ * This hook returns an array of numbers (between 0 and 1) representing the fill percentage of each progress bar step.
7
+ * It animates the transition between steps, smoothly updating the progress values when the current step or percentage changes.
8
+ *
9
+ * @param stepPercentage - The completion percentage (between 0 and 1) of the current step.
10
+ * @param currentStepIndex - The index (starting from 0) of the current step.
11
+ * @param steps - The total number of steps in the progress bar.
12
+ * @param duration - (Optional) Animation duration in milliseconds for each update (default: 750ms).
13
+ *
14
+ * @returns number[] - An array of progress values for each step (0 = empty, 1 = full, value between 0 and 1 = partial).
15
+ *
16
+ * Example usage:
17
+ * const progressValues = useSequentialProgress(0.5, 1, 3);
18
+ * // progressValues might be: [1, 0.5, 0]
19
+ */
20
+ export declare const useSequentialProgress: (stepPercentage: number, currentStepIndex: number, steps: number, duration?: number) => number[];
@@ -0,0 +1,80 @@
1
+ import { useCallback, useEffect, useRef, useState } from "react";
2
+ const getProgressValues = (currentStepIndex, stepPercentage, steps) => {
3
+ const values = Array(steps).fill(0);
4
+ for (let i = 0; i < steps; i++) {
5
+ if (i < currentStepIndex) {
6
+ values[i] = 1;
7
+ }
8
+ else if (i === currentStepIndex) {
9
+ values[i] = stepPercentage;
10
+ break;
11
+ }
12
+ }
13
+ return values;
14
+ };
15
+ /**
16
+ * useSequentialProgress
17
+ *
18
+ * A custom React hook to manage the animated progress values for a multi-step progress bar (stepper).
19
+ *
20
+ * This hook returns an array of numbers (between 0 and 1) representing the fill percentage of each progress bar step.
21
+ * It animates the transition between steps, smoothly updating the progress values when the current step or percentage changes.
22
+ *
23
+ * @param stepPercentage - The completion percentage (between 0 and 1) of the current step.
24
+ * @param currentStepIndex - The index (starting from 0) of the current step.
25
+ * @param steps - The total number of steps in the progress bar.
26
+ * @param duration - (Optional) Animation duration in milliseconds for each update (default: 750ms).
27
+ *
28
+ * @returns number[] - An array of progress values for each step (0 = empty, 1 = full, value between 0 and 1 = partial).
29
+ *
30
+ * Example usage:
31
+ * const progressValues = useSequentialProgress(0.5, 1, 3);
32
+ * // progressValues might be: [1, 0.5, 0]
33
+ */
34
+ export const useSequentialProgress = (stepPercentage, currentStepIndex, steps, duration = 750) => {
35
+ const [progressValues, setProgressValues] = useState(getProgressValues(currentStepIndex, stepPercentage, steps));
36
+ const currentAnimationStep = useRef(currentStepIndex + stepPercentage);
37
+ const timeoutRef = useRef(null);
38
+ const animate = useCallback(() => {
39
+ const targetStep = currentStepIndex + stepPercentage;
40
+ if (currentAnimationStep.current === targetStep) {
41
+ return;
42
+ }
43
+ const diff = targetStep - currentAnimationStep.current;
44
+ if (!Number.isInteger(currentAnimationStep.current) &&
45
+ Math.floor(currentAnimationStep.current) !== currentStepIndex) {
46
+ currentAnimationStep.current =
47
+ diff > 0
48
+ ? Math.ceil(currentAnimationStep.current)
49
+ : Math.floor(currentAnimationStep.current);
50
+ }
51
+ else if (Math.abs(diff) > 1) {
52
+ currentAnimationStep.current += Number(Math.sign(diff)) * 1;
53
+ }
54
+ else if (Math.abs(diff) > 0) {
55
+ currentAnimationStep.current = targetStep;
56
+ }
57
+ setProgressValues(getProgressValues(Math.floor(currentAnimationStep.current), currentAnimationStep.current - Math.floor(currentAnimationStep.current), steps));
58
+ timeoutRef.current = setTimeout(animate, duration);
59
+ }, [currentStepIndex, duration, stepPercentage, steps]);
60
+ // Reset the array and animation if the number of steps changes
61
+ useEffect(() => {
62
+ if (timeoutRef.current) {
63
+ clearTimeout(timeoutRef.current);
64
+ timeoutRef.current = null;
65
+ }
66
+ setProgressValues(getProgressValues(currentStepIndex, stepPercentage, steps));
67
+ // eslint-disable-next-line react-hooks/exhaustive-deps
68
+ }, [steps]);
69
+ // Animate only when currentStepIndex or stepPercentage changes
70
+ useEffect(() => {
71
+ animate();
72
+ return () => {
73
+ if (timeoutRef.current) {
74
+ clearTimeout(timeoutRef.current);
75
+ }
76
+ };
77
+ // eslint-disable-next-line react-hooks/exhaustive-deps
78
+ }, [stepPercentage, currentStepIndex]);
79
+ return progressValues;
80
+ };
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useId, } from "react";
3
3
  import { ItemMessage, } from "../Form/ItemMessage/ItemMessageCommon";
4
4
  export const Stepper = ({ currentStepProgress, currentTitle, nbSteps, currentStep, currentSubtitle, className, ProgressBarGroupComponent, helper, message, messageType = "success", titleLevel = 2, ...props }) => {
5
- const stepperId = useId();
5
+ const titleId = useId();
6
6
  const Title = `h${titleLevel}`;
7
- return (_jsxs("div", { className: "af-stepper", ...props, children: [_jsxs("div", { className: "af-stepper__header", children: [_jsx(Title, { className: "af-stepper__title", "aria-describedby": stepperId, children: currentTitle }), Boolean(currentSubtitle) && (_jsx("p", { className: "af-stepper__subtitle", children: currentSubtitle }))] }), _jsx(ProgressBarGroupComponent, { label: currentTitle, className: className, currentStep: currentStep, nbSteps: nbSteps, currentStepProgress: currentStepProgress }), Boolean(helper) && _jsx("span", { className: "af-stepper__helper", children: helper }), _jsx(ItemMessage, { message: message, messageType: messageType })] }));
7
+ return (_jsxs("div", { className: "af-stepper", ...props, tabIndex: undefined, children: [_jsxs("div", { className: "af-stepper__header", children: [_jsx(Title, { id: titleId, className: "af-stepper__title", children: currentTitle }), Boolean(currentSubtitle) && (_jsx("p", { className: "af-stepper__subtitle", children: currentSubtitle }))] }), _jsx(ProgressBarGroupComponent, { className: className, currentStep: currentStep, stepsCount: nbSteps, currentStepProgress: currentStepProgress, "aria-labelledby": titleId }), Boolean(helper) && _jsx("span", { className: "af-stepper__helper", children: helper }), _jsx(ItemMessage, { message: message, messageType: messageType })] }));
8
8
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axa-fr/design-system-apollo-react",
3
- "version": "2.0.1",
3
+ "version": "2.0.2-alpha.1",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -46,8 +46,8 @@
46
46
  },
47
47
  "homepage": "https://github.com/AxaFrance/design-system#readme",
48
48
  "peerDependencies": {
49
- "@axa-fr/design-system-apollo-css": "2.0.1",
50
- "@axa-fr/design-system-look-and-feel-css": "2.0.1",
49
+ "@axa-fr/design-system-apollo-css": "2.0.2-alpha.1",
50
+ "@axa-fr/design-system-look-and-feel-css": "2.0.2-alpha.1",
51
51
  "@material-symbols/svg-400": ">= 0.19.0",
52
52
  "react": ">= 18"
53
53
  },