react-restyle-components 0.4.49 → 0.4.50

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.
Files changed (23) hide show
  1. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/ProgressBar.d.ts +3 -0
  2. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/ProgressBar.js +237 -0
  3. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/index.d.ts +2 -0
  4. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/index.js +1 -0
  5. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/types.d.ts +29 -0
  6. package/lib/src/core-components/src/components/ProgressStepper/ProgressBar/types.js +1 -0
  7. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/ProgressStepper.d.ts +3 -0
  8. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/ProgressStepper.js +42 -0
  9. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/StepItem.d.ts +3 -0
  10. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/StepItem.js +349 -0
  11. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/index.d.ts +2 -0
  12. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/index.js +1 -0
  13. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/types.d.ts +75 -0
  14. package/lib/src/core-components/src/components/ProgressStepper/ProgressStepper/types.js +1 -0
  15. package/lib/src/core-components/src/components/ProgressStepper/index.d.ts +4 -0
  16. package/lib/src/core-components/src/components/ProgressStepper/index.js +2 -0
  17. package/lib/src/core-components/src/components/Table/Table.js +9 -7
  18. package/lib/src/core-components/src/components/Table/types.d.ts +3 -1
  19. package/lib/src/core-components/src/components/index.d.ts +1 -0
  20. package/lib/src/core-components/src/components/index.js +1 -0
  21. package/lib/src/core-components/src/tc.global.css +1 -269
  22. package/lib/src/core-components/src/tc.module.css +1 -3
  23. package/package.json +1 -1
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { ProgressBarProps } from './types';
3
+ export declare const ProgressBar: React.ForwardRefExoticComponent<ProgressBarProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,237 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useMemo, useEffect } from 'react';
4
+ // Inject keyframes animation styles
5
+ const injectAnimationStyles = () => {
6
+ const styleId = 'progress-bar-animations';
7
+ if (typeof document !== 'undefined' && !document.getElementById(styleId)) {
8
+ const styleSheet = document.createElement('style');
9
+ styleSheet.id = styleId;
10
+ styleSheet.textContent = `
11
+ @keyframes progressBarShimmer {
12
+ 0% {
13
+ transform: translateX(-100%);
14
+ }
15
+ 100% {
16
+ transform: translateX(100%);
17
+ }
18
+ }
19
+ @keyframes progressBarIndeterminate {
20
+ 0% {
21
+ left: -25%;
22
+ }
23
+ 100% {
24
+ left: 100%;
25
+ }
26
+ }
27
+ @keyframes progressBarPulse {
28
+ 0%, 100% {
29
+ opacity: 1;
30
+ }
31
+ 50% {
32
+ opacity: 0.7;
33
+ }
34
+ }
35
+ @keyframes progressBarStripe {
36
+ 0% {
37
+ background-position: 0 0;
38
+ }
39
+ 100% {
40
+ background-position: 40px 0;
41
+ }
42
+ }
43
+ @keyframes progressBarGlow {
44
+ 0%, 100% {
45
+ box-shadow: 0 0 4px currentColor, inset 0 0 4px rgba(255,255,255,0.2);
46
+ }
47
+ 50% {
48
+ box-shadow: 0 0 12px currentColor, inset 0 0 8px rgba(255,255,255,0.3);
49
+ }
50
+ }
51
+ @keyframes progressBarSegmentPulse {
52
+ 0%, 100% {
53
+ transform: scale(1);
54
+ opacity: 1;
55
+ }
56
+ 50% {
57
+ transform: scale(1.02);
58
+ opacity: 0.9;
59
+ }
60
+ }
61
+ `;
62
+ document.head.appendChild(styleSheet);
63
+ }
64
+ };
65
+ // Color constants
66
+ const colors = {
67
+ primary: '#8B5CF6',
68
+ track: '#E5E7EB',
69
+ text: '#374151',
70
+ supportText: '#6B7280',
71
+ };
72
+ // Size configurations
73
+ const sizeConfig = {
74
+ small: {
75
+ height: '4px',
76
+ borderRadius: '2px',
77
+ labelSize: '0.75rem',
78
+ supportSize: '0.625rem',
79
+ },
80
+ medium: {
81
+ height: '6px',
82
+ borderRadius: '3px',
83
+ labelSize: '0.875rem',
84
+ supportSize: '0.75rem',
85
+ },
86
+ large: {
87
+ height: '8px',
88
+ borderRadius: '4px',
89
+ labelSize: '1rem',
90
+ supportSize: '0.875rem',
91
+ },
92
+ };
93
+ export const ProgressBar = forwardRef(({ label, supportText, value, max = 100, size = 'medium', variant = 'continuous', segments = 4, color, trackColor, showValue = false, isIndeterminate = false, showAnimation = true, className, style, ...rest }, ref) => {
94
+ // Inject animation styles on mount
95
+ useEffect(() => {
96
+ injectAnimationStyles();
97
+ }, []);
98
+ const percentage = useMemo(() => {
99
+ const clampedValue = Math.max(0, Math.min(value, max));
100
+ return (clampedValue / max) * 100;
101
+ }, [value, max]);
102
+ // Check if progress is active (not 0 and not 100)
103
+ const isActive = percentage > 0 && percentage < 100;
104
+ const activeSegments = useMemo(() => {
105
+ if (variant !== 'segmented')
106
+ return 0;
107
+ return Math.ceil((percentage / 100) * segments);
108
+ }, [percentage, segments, variant]);
109
+ const ariaLabel = useMemo(() => {
110
+ if (isIndeterminate)
111
+ return 'Loading...';
112
+ return `${Math.round(percentage)}% complete`;
113
+ }, [percentage, isIndeterminate]);
114
+ const config = sizeConfig[size];
115
+ const containerStyle = {
116
+ display: 'flex',
117
+ flexDirection: 'column',
118
+ gap: '0.5rem',
119
+ width: '100%',
120
+ };
121
+ const labelStyle = {
122
+ fontSize: config.labelSize,
123
+ fontWeight: 600,
124
+ color: colors.text,
125
+ lineHeight: 1.4,
126
+ };
127
+ const supportTextStyle = {
128
+ fontSize: config.supportSize,
129
+ fontWeight: 400,
130
+ color: colors.supportText,
131
+ lineHeight: 1.4,
132
+ };
133
+ const trackStyle = {
134
+ width: '100%',
135
+ height: config.height,
136
+ backgroundColor: trackColor || colors.track,
137
+ borderRadius: config.borderRadius,
138
+ overflow: 'hidden',
139
+ position: 'relative',
140
+ };
141
+ const fillColor = color || colors.primary;
142
+ const fillStyle = {
143
+ height: '100%',
144
+ backgroundColor: fillColor,
145
+ borderRadius: config.borderRadius,
146
+ transition: 'width 0.5s ease-out',
147
+ width: isIndeterminate ? '30%' : `${percentage}%`,
148
+ position: 'relative',
149
+ overflow: 'hidden',
150
+ ...(isIndeterminate
151
+ ? {
152
+ position: 'absolute',
153
+ animation: 'progressBarIndeterminate 1.5s ease-in-out infinite',
154
+ }
155
+ : {}),
156
+ ...(showAnimation && isActive && !isIndeterminate
157
+ ? {
158
+ animation: 'progressBarPulse 2s ease-in-out infinite',
159
+ }
160
+ : {}),
161
+ };
162
+ // Shimmer overlay for the fill
163
+ const shimmerStyle = {
164
+ position: 'absolute',
165
+ top: 0,
166
+ left: 0,
167
+ right: 0,
168
+ bottom: 0,
169
+ background: `linear-gradient(
170
+ 90deg,
171
+ transparent 0%,
172
+ rgba(255, 255, 255, 0.4) 50%,
173
+ transparent 100%
174
+ )`,
175
+ animation: 'progressBarShimmer 1.5s ease-in-out infinite',
176
+ };
177
+ // Striped effect style (alternative animation)
178
+ const stripedStyle = {
179
+ position: 'absolute',
180
+ top: 0,
181
+ left: 0,
182
+ right: 0,
183
+ bottom: 0,
184
+ backgroundImage: `linear-gradient(
185
+ 45deg,
186
+ rgba(255, 255, 255, 0.15) 25%,
187
+ transparent 25%,
188
+ transparent 50%,
189
+ rgba(255, 255, 255, 0.15) 50%,
190
+ rgba(255, 255, 255, 0.15) 75%,
191
+ transparent 75%,
192
+ transparent
193
+ )`,
194
+ backgroundSize: '40px 40px',
195
+ animation: 'progressBarStripe 1s linear infinite',
196
+ };
197
+ const segmentedTrackStyle = {
198
+ display: 'flex',
199
+ gap: '0.25rem',
200
+ width: '100%',
201
+ height: config.height,
202
+ };
203
+ const getSegmentStyle = (isActiveSegment, segmentIndex) => {
204
+ const isLastActiveSegment = segmentIndex === activeSegments - 1 && activeSegments > 0;
205
+ return {
206
+ flex: 1,
207
+ height: '100%',
208
+ backgroundColor: isActiveSegment ? fillColor : trackColor || colors.track,
209
+ borderRadius: config.borderRadius,
210
+ transition: 'all 0.3s ease-in-out',
211
+ position: 'relative',
212
+ overflow: 'hidden',
213
+ ...(showAnimation && isLastActiveSegment && isActive
214
+ ? {
215
+ animation: 'progressBarSegmentPulse 1.5s ease-in-out infinite',
216
+ boxShadow: `0 0 8px ${fillColor}`,
217
+ }
218
+ : {}),
219
+ };
220
+ };
221
+ const valueContainerStyle = {
222
+ display: 'flex',
223
+ justifyContent: 'space-between',
224
+ alignItems: 'center',
225
+ };
226
+ const valueTextStyle = {
227
+ fontSize: config.supportSize,
228
+ fontWeight: 500,
229
+ color: colors.text,
230
+ };
231
+ return (_jsxs("div", { ref: ref, className: className, style: { ...containerStyle, ...style }, "data-aui": "progress-bar", ...rest, children: [(label || showValue) && (_jsxs("div", { style: valueContainerStyle, children: [label && _jsx("span", { style: labelStyle, children: label }), showValue && !isIndeterminate && (_jsxs("span", { style: valueTextStyle, children: [Math.round(percentage), "%"] }))] })), variant === 'continuous' ? (_jsx("div", { style: trackStyle, role: "progressbar", "aria-valuenow": isIndeterminate ? undefined : value, "aria-valuemin": 0, "aria-valuemax": max, "aria-label": ariaLabel, children: _jsxs("div", { style: fillStyle, children: [showAnimation && (isActive || isIndeterminate) && percentage > 0 && (_jsx("div", { style: shimmerStyle, "aria-hidden": "true" })), showAnimation && isIndeterminate && (_jsx("div", { style: stripedStyle, "aria-hidden": "true" }))] }) })) : (_jsx("div", { style: segmentedTrackStyle, role: "progressbar", "aria-valuenow": value, "aria-valuemin": 0, "aria-valuemax": max, "aria-label": ariaLabel, children: Array.from({ length: segments }).map((_, index) => {
232
+ const isActiveSegment = index < activeSegments;
233
+ const isLastActiveSegment = index === activeSegments - 1 && activeSegments > 0;
234
+ return (_jsx("div", { style: getSegmentStyle(isActiveSegment, index), children: showAnimation && isLastActiveSegment && isActive && (_jsx("div", { style: shimmerStyle, "aria-hidden": "true" })) }, index));
235
+ }) })), supportText && _jsx("span", { style: supportTextStyle, children: supportText })] }));
236
+ });
237
+ ProgressBar.displayName = 'ProgressBar';
@@ -0,0 +1,2 @@
1
+ export * from './ProgressBar';
2
+ export type { ProgressBarProps } from './types';
@@ -0,0 +1 @@
1
+ export * from './ProgressBar';
@@ -0,0 +1,29 @@
1
+ import React from 'react';
2
+ export interface ProgressBarProps extends React.HTMLAttributes<HTMLDivElement> {
3
+ /** Label text displayed above the progress bar */
4
+ label?: string;
5
+ /** Support text displayed below the progress bar */
6
+ supportText?: string;
7
+ /** Current progress value */
8
+ value: number;
9
+ /** Maximum value (default: 100) */
10
+ max?: number;
11
+ /** Size of the progress bar */
12
+ size?: 'small' | 'medium' | 'large';
13
+ /** Variant of the progress bar */
14
+ variant?: 'continuous' | 'segmented';
15
+ /** Number of segments (for segmented variant) */
16
+ segments?: number;
17
+ /** Custom color for the progress fill */
18
+ color?: string;
19
+ /** Custom color for the track */
20
+ trackColor?: string;
21
+ /** Whether to show the percentage value */
22
+ showValue?: boolean;
23
+ /** Whether the progress bar is in loading/indeterminate state */
24
+ isIndeterminate?: boolean;
25
+ /** Whether to show loading animations (shimmer, pulse effects). Default: true */
26
+ showAnimation?: boolean;
27
+ /** Custom class name */
28
+ className?: string;
29
+ }
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { ProgressStepperProps } from './types';
3
+ export declare const ProgressStepper: React.ForwardRefExoticComponent<ProgressStepperProps & React.RefAttributes<HTMLUListElement>>;
@@ -0,0 +1,42 @@
1
+ 'use client';
2
+ import { createElement as _createElement } from "react";
3
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { forwardRef, useMemo } from 'react';
5
+ import { StepItem } from './StepItem';
6
+ export const ProgressStepper = forwardRef(({ steps, size = 'medium', orientation = 'horizontal', isPacked = false, indicatorType = 'dot', activeColor = '#8B5CF6', inactiveColor = '#E5E7EB', className, style, ...rest }, ref) => {
7
+ // Generate accessible aria label based on current step
8
+ const ariaLabel = useMemo(() => {
9
+ const currentStepIndex = steps
10
+ .map((step) => step.state !== 'incomplete')
11
+ .lastIndexOf(true);
12
+ const currentStep = steps[currentStepIndex];
13
+ const label = `step ${currentStepIndex + 1} out of ${steps.length}`;
14
+ if (!currentStep?.subSteps?.length) {
15
+ return label;
16
+ }
17
+ if (currentStep.state === 'inprogress') {
18
+ return `${label} part 1`;
19
+ }
20
+ const subStepIndex = currentStep.subSteps?.findIndex((subStep) => subStep.state === 'inprogress');
21
+ if (subStepIndex !== undefined && subStepIndex >= 0) {
22
+ return `${label} part ${subStepIndex + 2}`;
23
+ }
24
+ return label;
25
+ }, [steps]);
26
+ const hiddenAriaStyle = {
27
+ height: 0,
28
+ opacity: 0,
29
+ position: 'absolute',
30
+ overflow: 'hidden',
31
+ };
32
+ const listContainerStyle = {
33
+ display: 'flex',
34
+ flexDirection: orientation === 'horizontal' ? 'row' : 'column',
35
+ alignItems: 'flex-start',
36
+ listStyleType: 'none',
37
+ padding: 0,
38
+ margin: 0,
39
+ };
40
+ return (_jsxs(_Fragment, { children: [_jsx("div", { style: hiddenAriaStyle, "aria-live": "polite", role: "status", children: ariaLabel }), _jsx("ul", { "data-aui": "progress-stepper", ref: ref, "aria-hidden": true, "data-testid": "progress-stepper", style: { ...listContainerStyle, ...style }, className: className, ...rest, children: steps.map((step, index) => (_createElement(StepItem, { ...step, key: step.id || index, index: index, stepsAmount: steps.length, size: size, orientation: orientation, isPacked: isPacked, indicatorType: indicatorType, activeColor: activeColor, inactiveColor: inactiveColor }))) })] }));
41
+ });
42
+ ProgressStepper.displayName = 'ProgressStepper';
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { ProgressStepperLineItem } from './types';
3
+ export declare const StepItem: React.FC<ProgressStepperLineItem>;
@@ -0,0 +1,349 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useMemo, useEffect } from 'react';
4
+ // Inject keyframes animation styles
5
+ const injectAnimationStyles = () => {
6
+ const styleId = 'progress-stepper-animations';
7
+ if (typeof document !== 'undefined' && !document.getElementById(styleId)) {
8
+ const styleSheet = document.createElement('style');
9
+ styleSheet.id = styleId;
10
+ styleSheet.textContent = `
11
+ @keyframes progressShimmer {
12
+ 0% {
13
+ background-position: -200% 0;
14
+ }
15
+ 100% {
16
+ background-position: 200% 0;
17
+ }
18
+ }
19
+ @keyframes progressPulse {
20
+ 0%, 100% {
21
+ opacity: 1;
22
+ }
23
+ 50% {
24
+ opacity: 0.6;
25
+ }
26
+ }
27
+ @keyframes progressGlow {
28
+ 0%, 100% {
29
+ box-shadow: 0 0 4px currentColor;
30
+ }
31
+ 50% {
32
+ box-shadow: 0 0 12px currentColor;
33
+ }
34
+ }
35
+ @keyframes progressFlow {
36
+ 0% {
37
+ transform: translateX(-100%);
38
+ }
39
+ 100% {
40
+ transform: translateX(100%);
41
+ }
42
+ }
43
+ @keyframes progressFlowVertical {
44
+ 0% {
45
+ transform: translateY(-100%);
46
+ }
47
+ 100% {
48
+ transform: translateY(100%);
49
+ }
50
+ }
51
+ `;
52
+ document.head.appendChild(styleSheet);
53
+ }
54
+ };
55
+ // Default colors
56
+ const defaultColors = {
57
+ active: '#8B5CF6',
58
+ inactive: '#E5E7EB',
59
+ complete: '#8B5CF6',
60
+ inprogress: '#8B5CF6',
61
+ warning: '#F59E0B',
62
+ error: '#EF4444',
63
+ white: '#ffffff',
64
+ text: '#374151',
65
+ supportText: '#6B7280',
66
+ };
67
+ // Size configurations
68
+ const sizeConfig = {
69
+ small: {
70
+ diameter: '1.25rem',
71
+ innerDiameter: '0.5rem',
72
+ fontSize: '0.625rem',
73
+ iconSize: '0.625rem',
74
+ connectorWidth: '2px',
75
+ marginLeft: '0.5rem',
76
+ },
77
+ medium: {
78
+ diameter: '1.75rem',
79
+ innerDiameter: '0.75rem',
80
+ fontSize: '0.75rem',
81
+ iconSize: '0.875rem',
82
+ connectorWidth: '2px',
83
+ marginLeft: '0.75rem',
84
+ },
85
+ large: {
86
+ diameter: '2.25rem',
87
+ innerDiameter: '1rem',
88
+ fontSize: '0.875rem',
89
+ iconSize: '1rem',
90
+ connectorWidth: '3px',
91
+ marginLeft: '1rem',
92
+ },
93
+ };
94
+ // Get state color
95
+ const getStateColor = (state, activeColor, inactiveColor) => {
96
+ const stateColors = {
97
+ complete: activeColor,
98
+ inprogress: activeColor,
99
+ incomplete: inactiveColor,
100
+ warning: defaultColors.warning,
101
+ error: defaultColors.error,
102
+ };
103
+ return stateColors[state];
104
+ };
105
+ // Utility functions
106
+ const calcPercentage = (part, total) => total > 0 ? (100 * part) / total : 0;
107
+ // Icon components
108
+ const CheckIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }));
109
+ const WarningIcon = () => (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", children: _jsx("path", { d: "M12 9v4m0 4h.01M12 2L2 20h20L12 2z" }) }));
110
+ const ErrorIcon = () => (_jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), _jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })] }));
111
+ const getStepItemStyle = (state, size, indicatorType, activeColor, inactiveColor) => {
112
+ const config = sizeConfig[size];
113
+ const stateColor = getStateColor(state, activeColor, inactiveColor);
114
+ const isActive = state !== 'incomplete';
115
+ const baseStyle = {
116
+ position: 'relative',
117
+ borderRadius: '50%',
118
+ display: 'inline-flex',
119
+ alignItems: 'center',
120
+ justifyContent: 'center',
121
+ flexShrink: 0,
122
+ fontWeight: 600,
123
+ transition: 'all 0.3s ease',
124
+ height: config.diameter,
125
+ width: config.diameter,
126
+ minWidth: config.diameter,
127
+ fontSize: config.fontSize,
128
+ };
129
+ if (indicatorType === 'dot' || indicatorType === 'number' || indicatorType === 'iconCircle') {
130
+ return {
131
+ ...baseStyle,
132
+ border: `2px solid ${stateColor}`,
133
+ backgroundColor: isActive ? stateColor : 'transparent',
134
+ color: isActive ? '#fff' : stateColor,
135
+ };
136
+ }
137
+ if (indicatorType === 'icon') {
138
+ return {
139
+ ...baseStyle,
140
+ border: 'none',
141
+ backgroundColor: 'transparent',
142
+ color: stateColor,
143
+ };
144
+ }
145
+ if (indicatorType === 'check') {
146
+ return {
147
+ ...baseStyle,
148
+ border: `2px solid ${stateColor}`,
149
+ backgroundColor: state === 'complete' ? stateColor : 'transparent',
150
+ color: state === 'complete' ? '#fff' : stateColor,
151
+ };
152
+ }
153
+ return baseStyle;
154
+ };
155
+ export const StepItem = ({ state = 'incomplete', subSteps, isPacked, stepTitle, stepSubTitle, stepLinkHref, stepLinkText, tagText, tagVariant = 'neutral', icon, iconSrc, stepNumber, index, stepsAmount, orientation, size, indicatorType, activeColor = defaultColors.active, inactiveColor = defaultColors.inactive, }) => {
156
+ // Inject animation styles on mount
157
+ useEffect(() => {
158
+ injectAnimationStyles();
159
+ }, []);
160
+ const steps = subSteps ?? [];
161
+ const config = sizeConfig[size];
162
+ const connectorFillPercentage = useMemo(() => {
163
+ if (steps.length === 0) {
164
+ return state === 'complete' ? 100 : 0;
165
+ }
166
+ if (steps[steps.length - 1]?.state === 'complete') {
167
+ return 100;
168
+ }
169
+ const activeSubSteps = steps.filter((subStep) => subStep.state !== 'incomplete').length;
170
+ return calcPercentage(activeSubSteps, steps.length + 1);
171
+ }, [state, steps]);
172
+ const isLast = useMemo(() => index === stepsAmount - 1, [index, stepsAmount]);
173
+ const showConnectorDot = useMemo(() => connectorFillPercentage > 0 && connectorFillPercentage < 100, [connectorFillPercentage]);
174
+ const stateWithSubSteps = useMemo(() => state === 'complete' && connectorFillPercentage < 100
175
+ ? 'inprogress'
176
+ : state, [connectorFillPercentage, state]);
177
+ const displayNumber = stepNumber ?? index + 1;
178
+ const innerDotStyle = {
179
+ position: 'absolute',
180
+ borderRadius: '50%',
181
+ backgroundColor: defaultColors.white,
182
+ opacity: state === 'inprogress' && indicatorType === 'dot' ? 1 : 0,
183
+ transition: 'opacity 0.3s ease',
184
+ height: config.innerDiameter,
185
+ width: config.innerDiameter,
186
+ };
187
+ const iconWrapperStyle = {
188
+ display: 'flex',
189
+ alignItems: 'center',
190
+ justifyContent: 'center',
191
+ width: config.iconSize,
192
+ height: config.iconSize,
193
+ };
194
+ const connectorTextGroupStyle = {
195
+ display: 'flex',
196
+ flexDirection: orientation === 'vertical' ? 'row' : 'column',
197
+ ...(orientation === 'horizontal' && !isLast ? { width: '100%' } : {}),
198
+ ...(orientation === 'horizontal' ? { marginTop: 'auto', marginBottom: 'auto' } : {}),
199
+ };
200
+ const connectorStyle = {
201
+ backgroundColor: inactiveColor,
202
+ ...(orientation === 'vertical'
203
+ ? {
204
+ height: isPacked ? '1.5rem' : '3rem',
205
+ width: config.connectorWidth,
206
+ marginLeft: config.marginLeft,
207
+ }
208
+ : {
209
+ height: config.connectorWidth,
210
+ width: '100%',
211
+ }),
212
+ };
213
+ // Check if this connector should be animated (when step is inprogress or has partial substeps)
214
+ const isAnimated = state === 'inprogress' || (connectorFillPercentage > 0 && connectorFillPercentage < 100);
215
+ const connectorFillStyle = {
216
+ position: 'relative',
217
+ backgroundColor: activeColor,
218
+ transition: orientation === 'vertical' ? 'height 0.5s ease-out' : 'width 0.5s ease-out',
219
+ overflow: 'hidden',
220
+ ...(orientation === 'vertical'
221
+ ? { height: `${connectorFillPercentage}%`, width: '100%' }
222
+ : { width: `${connectorFillPercentage}%`, height: '100%' }),
223
+ };
224
+ // Animated shimmer overlay style
225
+ const shimmerOverlayStyle = isAnimated ? {
226
+ position: 'absolute',
227
+ top: 0,
228
+ left: 0,
229
+ right: 0,
230
+ bottom: 0,
231
+ background: `linear-gradient(
232
+ ${orientation === 'vertical' ? '180deg' : '90deg'},
233
+ transparent 0%,
234
+ rgba(255, 255, 255, 0.4) 50%,
235
+ transparent 100%
236
+ )`,
237
+ backgroundSize: orientation === 'vertical' ? '100% 200%' : '200% 100%',
238
+ animation: `progressShimmer 1.5s ease-in-out infinite`,
239
+ } : {};
240
+ // Pulse effect on the fill when in progress
241
+ const pulseStyle = state === 'inprogress' ? {
242
+ animation: 'progressPulse 2s ease-in-out infinite',
243
+ } : {};
244
+ const connectorDotStyle = {
245
+ content: '""',
246
+ width: '6px',
247
+ height: '6px',
248
+ position: 'absolute',
249
+ top: 0,
250
+ bottom: 0,
251
+ right: orientation === 'vertical' ? '-2px' : '-3px',
252
+ borderRadius: '50%',
253
+ margin: 'auto 0',
254
+ backgroundColor: activeColor,
255
+ opacity: showConnectorDot ? 1 : 0,
256
+ transition: 'opacity 0.3s ease',
257
+ };
258
+ const stepTextGroupStyle = {
259
+ marginLeft: config.marginLeft,
260
+ marginBottom: '1rem',
261
+ marginTop: '-0.25rem',
262
+ };
263
+ const stepTitleStyle = {
264
+ fontSize: size === 'small' ? '0.875rem' : size === 'medium' ? '1rem' : '1.125rem',
265
+ fontWeight: 500,
266
+ color: defaultColors.text,
267
+ margin: '0 0 0.125rem 0',
268
+ maxWidth: '12rem',
269
+ overflow: 'hidden',
270
+ textOverflow: 'ellipsis',
271
+ display: '-webkit-box',
272
+ WebkitLineClamp: 3,
273
+ WebkitBoxOrient: 'vertical',
274
+ };
275
+ const stepSubTitleStyle = {
276
+ fontSize: '0.75rem',
277
+ fontWeight: 400,
278
+ color: defaultColors.supportText,
279
+ margin: '0.125rem 0',
280
+ maxWidth: '12rem',
281
+ overflow: 'hidden',
282
+ textOverflow: 'ellipsis',
283
+ display: '-webkit-box',
284
+ WebkitLineClamp: 2,
285
+ WebkitBoxOrient: 'vertical',
286
+ };
287
+ const getTagStyle = (variant) => {
288
+ const variants = {
289
+ success: { backgroundColor: '#DCFCE7', color: '#166534' },
290
+ error: { backgroundColor: '#FEE2E2', color: '#991B1B' },
291
+ warning: { backgroundColor: '#FEF3C7', color: '#92400E' },
292
+ info: { backgroundColor: '#DBEAFE', color: '#1E40AF' },
293
+ neutral: { backgroundColor: '#F3F4F6', color: '#374151' },
294
+ };
295
+ return {
296
+ display: 'inline-block',
297
+ fontSize: '0.625rem',
298
+ fontWeight: 600,
299
+ padding: '0.125rem 0.5rem',
300
+ borderRadius: '0.25rem',
301
+ marginTop: '0.25rem',
302
+ ...(variants[variant] || variants.neutral),
303
+ };
304
+ };
305
+ const stepLinkStyle = {
306
+ display: 'block',
307
+ fontSize: '0.75rem',
308
+ color: '#3b82f6',
309
+ textDecoration: 'none',
310
+ marginTop: '0.25rem',
311
+ };
312
+ const renderIndicatorContent = () => {
313
+ if (state === 'complete' && indicatorType === 'check') {
314
+ return _jsx("span", { style: iconWrapperStyle, children: _jsx(CheckIcon, {}) });
315
+ }
316
+ if (state === 'warning') {
317
+ return _jsx("span", { style: iconWrapperStyle, children: _jsx(WarningIcon, {}) });
318
+ }
319
+ if (state === 'error') {
320
+ return _jsx("span", { style: iconWrapperStyle, children: _jsx(ErrorIcon, {}) });
321
+ }
322
+ if (icon) {
323
+ return _jsx("span", { style: iconWrapperStyle, children: icon });
324
+ }
325
+ if (iconSrc) {
326
+ return (_jsx("span", { style: iconWrapperStyle, children: _jsx("img", { src: iconSrc, alt: `Step ${displayNumber}`, style: { width: '100%', height: '100%', objectFit: 'contain' } }) }));
327
+ }
328
+ if (indicatorType === 'number') {
329
+ return _jsx("span", { children: displayNumber });
330
+ }
331
+ if (indicatorType === 'dot' && state === 'incomplete') {
332
+ return null;
333
+ }
334
+ if (state === 'complete') {
335
+ return _jsx("span", { style: iconWrapperStyle, children: _jsx(CheckIcon, {}) });
336
+ }
337
+ return null;
338
+ };
339
+ // Glow animation for in-progress step indicator
340
+ const stepIndicatorGlowStyle = state === 'inprogress' ? {
341
+ boxShadow: `0 0 8px ${activeColor}`,
342
+ animation: 'progressGlow 2s ease-in-out infinite',
343
+ } : {};
344
+ return (_jsxs(_Fragment, { children: [_jsxs("li", { style: {
345
+ ...getStepItemStyle(stateWithSubSteps, size, indicatorType, activeColor, inactiveColor),
346
+ ...stepIndicatorGlowStyle,
347
+ }, "data-testid": `progress-stepper-step-${index}`, children: [indicatorType === 'dot' && state === 'inprogress' && (_jsx("div", { style: innerDotStyle })), renderIndicatorContent()] }), _jsxs("div", { style: connectorTextGroupStyle, children: [!isLast && (_jsx("div", { className: "step-connector", style: connectorStyle, "data-testid": `progress-stepper-step-${index}-connector`, children: _jsxs("div", { style: { ...connectorFillStyle, ...pulseStyle }, "data-testid": `progress-stepper-step-${index}-connector-fill`, children: [isAnimated && connectorFillPercentage > 0 && (_jsx("div", { style: shimmerOverlayStyle, "aria-hidden": "true" })), _jsx("span", { style: connectorDotStyle })] }) })), orientation === 'vertical' && (stepTitle || stepSubTitle) && (_jsxs("div", { style: stepTextGroupStyle, children: [stepTitle && (_jsx("h2", { style: stepTitleStyle, "data-testid": `step-title-${index}`, children: stepTitle })), stepSubTitle && (_jsx("h3", { style: stepSubTitleStyle, "data-testid": `step-subtitle-${index}`, children: stepSubTitle })), tagText && (_jsx("span", { style: getTagStyle(tagVariant), "data-testid": `step-tag-${index}`, children: tagText })), stepLinkText && stepLinkHref && (_jsx("a", { href: stepLinkHref, style: stepLinkStyle, "data-testid": `step-link-${index}`, children: stepLinkText }))] }))] })] }));
348
+ };
349
+ StepItem.displayName = 'StepItem';