@diwauhris/ui 1.1.0 → 1.1.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.
- package/lib/index1773.cjs +75 -55
- package/lib/index1773.cjs.map +1 -1
- package/lib/index1773.mjs +75 -55
- package/lib/index1773.mjs.map +1 -1
- package/package.json +4 -3
package/lib/index1773.cjs
CHANGED
|
@@ -23,72 +23,92 @@ function StepCircle({ state, number, icon }) {
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
function Stepper({ steps, currentStep, completedSteps = [], disabledSteps = [], orientation = "horizontal", className = "" }) {
|
|
26
|
-
|
|
27
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
26
|
+
if (!(orientation === "horizontal")) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
28
27
|
"aria-label": "Progress",
|
|
29
|
-
"aria-orientation":
|
|
30
|
-
className: [
|
|
28
|
+
"aria-orientation": "vertical",
|
|
29
|
+
className: ["flex flex-col", className].filter(Boolean).join(" "),
|
|
31
30
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
|
|
32
|
-
className:
|
|
31
|
+
className: "flex flex-col",
|
|
33
32
|
children: steps.map((step, idx) => {
|
|
34
33
|
const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);
|
|
35
34
|
const isCurrent = state === "current";
|
|
36
35
|
const isLast = idx === steps.length - 1;
|
|
37
|
-
const labelColor = {
|
|
38
|
-
completed: "text-brand-blue",
|
|
39
|
-
current: "text-brand-navy font-bold",
|
|
40
|
-
upcoming: "text-slate-500",
|
|
41
|
-
disabled: "text-slate-300"
|
|
42
|
-
};
|
|
43
36
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
44
37
|
"aria-current": isCurrent ? "step" : void 0,
|
|
45
|
-
className:
|
|
46
|
-
children: [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
className: "flex items-start gap-4 pb-8 last:pb-0",
|
|
39
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
40
|
+
className: "relative flex flex-col items-center",
|
|
41
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepCircle, {
|
|
42
|
+
state,
|
|
43
|
+
number: idx + 1,
|
|
44
|
+
icon: step.icon
|
|
45
|
+
}), !isLast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
46
|
+
className: `mt-1 w-0.5 flex-1 min-h-[32px] ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
47
|
+
"aria-hidden": "true"
|
|
48
|
+
})]
|
|
49
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
50
|
+
className: "min-w-0 flex-1 pt-1",
|
|
51
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
52
|
+
className: `text-sm leading-tight ${{
|
|
53
|
+
completed: "text-brand-blue",
|
|
54
|
+
current: "text-brand-navy font-bold",
|
|
55
|
+
upcoming: "text-slate-500",
|
|
56
|
+
disabled: "text-slate-300"
|
|
57
|
+
}[state]}`,
|
|
58
|
+
children: step.label
|
|
59
|
+
}), step.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
60
|
+
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
61
|
+
children: step.description
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
}, step.id);
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
const resolvedStates = steps.map((step) => resolveState(step.id, currentStep, completedSteps, disabledSteps));
|
|
69
|
+
const labelColor = {
|
|
70
|
+
completed: "text-brand-blue",
|
|
71
|
+
current: "text-brand-navy font-bold",
|
|
72
|
+
upcoming: "text-slate-500",
|
|
73
|
+
disabled: "text-slate-300"
|
|
74
|
+
};
|
|
75
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
76
|
+
"aria-label": "Progress",
|
|
77
|
+
"aria-orientation": "horizontal",
|
|
78
|
+
className: ["w-full", className].filter(Boolean).join(" "),
|
|
79
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("ol", {
|
|
80
|
+
className: "flex items-start w-full",
|
|
81
|
+
children: steps.map((step, idx) => {
|
|
82
|
+
const state = resolvedStates[idx];
|
|
83
|
+
const isCurrent = state === "current";
|
|
84
|
+
const isLast = idx === steps.length - 1;
|
|
85
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
|
|
86
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
87
|
+
className: ["flex flex-col items-center relative", isLast ? "" : "flex-1"].filter(Boolean).join(" "),
|
|
88
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
89
|
+
className: "flex items-center w-full",
|
|
90
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
91
|
+
className: "shrink-0 z-10",
|
|
92
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepCircle, {
|
|
50
93
|
state,
|
|
51
94
|
number: idx + 1,
|
|
52
95
|
icon: step.icon
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})]
|
|
70
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
71
|
-
className: "mt-2 text-center px-1",
|
|
72
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
73
|
-
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
74
|
-
children: step.label
|
|
75
|
-
}), step.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
76
|
-
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
77
|
-
children: step.description
|
|
78
|
-
})]
|
|
79
|
-
})]
|
|
80
|
-
}),
|
|
81
|
-
!isHorizontal && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
82
|
-
className: "min-w-0 flex-1 pt-1",
|
|
83
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
84
|
-
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
85
|
-
children: step.label
|
|
86
|
-
}), step.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
87
|
-
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
88
|
-
children: step.description
|
|
89
|
-
})]
|
|
90
|
-
})
|
|
91
|
-
]
|
|
96
|
+
})
|
|
97
|
+
}), !isLast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
98
|
+
className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
99
|
+
"aria-hidden": "true"
|
|
100
|
+
})]
|
|
101
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
102
|
+
className: "mt-2 flex flex-col items-center text-center w-max max-w-[120px]",
|
|
103
|
+
style: { transform: isLast ? "translateX(calc(50% - 1.125rem))" : idx === 0 ? "translateX(calc(-50% + 1.125rem))" : void 0 },
|
|
104
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
105
|
+
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
106
|
+
children: step.label
|
|
107
|
+
}), step.description && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
108
|
+
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
109
|
+
children: step.description
|
|
110
|
+
})]
|
|
111
|
+
})]
|
|
92
112
|
}, step.id);
|
|
93
113
|
})
|
|
94
114
|
})
|
package/lib/index1773.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index1773.cjs","names":[],"sources":["../src/ui-library/gallery/stepper/Stepper.tsx"],"sourcesContent":["/**\n * Stepper — Design System Component\n *\n * A step progress indicator for multi-step workflows.\n *\n * Step states: completed | current | upcoming | disabled\n *\n * Accessibility:\n * - The current step receives aria-current=\"step\".\n * - Completed steps have aria-label with a \"Completed\" suffix when no icon.\n * - The step list is an ordered list (<ol>) — each step is an <li>.\n * - Orientation is exposed via aria-orientation on the container.\n *\n * API:\n * <Stepper\n * steps={[\n * { id: '1', label: 'Personal Details', description: 'Name and contact' },\n * { id: '2', label: 'Employment', description: 'IDs and dates' },\n * ]}\n * currentStep=\"2\"\n * completedSteps={['1']}\n * />\n */\n\nimport type { ReactNode } from 'react';\nimport { Check } from 'lucide-react';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type StepState = 'completed' | 'current' | 'upcoming' | 'disabled';\n\nexport interface StepDef {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepDef[];\n /** The id of the currently active step */\n currentStep: string;\n /** IDs of steps that are completed */\n completedSteps?: string[];\n /** IDs of steps that are disabled */\n disabledSteps?: string[];\n orientation?: 'horizontal' | 'vertical';\n className?: string;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveState(\n id: string,\n currentStep: string,\n completedSteps: string[],\n disabledSteps: string[],\n): StepState {\n if (disabledSteps.includes(id)) return 'disabled';\n if (completedSteps.includes(id)) return 'completed';\n if (id === currentStep) return 'current';\n return 'upcoming';\n}\n\n// ── Step indicator circle ─────────────────────────────────────────────────────\n\nfunction StepCircle({ state, number, icon }: { state: StepState; number: number; icon?: ReactNode }) {\n const base = 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full border-2 text-sm font-bold transition-all';\n\n const styles: Record<StepState, string> = {\n completed: 'border-brand-blue bg-brand-blue text-white',\n current: 'border-brand-blue bg-white text-brand-blue shadow-md shadow-brand-blue/15',\n upcoming: 'border-slate-300 bg-white text-slate-400',\n disabled: 'border-slate-200 bg-slate-50 text-slate-300',\n };\n\n return (\n <div className={`${base} ${styles[state]}`} aria-hidden=\"true\">\n {state === 'completed' ? (\n icon ?? <Check size={16} strokeWidth={3} />\n ) : (\n icon ?? <span>{number}</span>\n )}\n </div>\n );\n}\n\n// ── Stepper ───────────────────────────────────────────────────────────────────\n\nexport function Stepper({\n steps,\n currentStep,\n completedSteps = [],\n disabledSteps = [],\n orientation = 'horizontal',\n className = '',\n}: StepperProps) {\n const isHorizontal = orientation === 'horizontal';\n\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation={orientation}\n className={[\n isHorizontal\n ? 'flex items-start'\n : 'flex flex-col',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <ol\n className={[\n isHorizontal ? 'flex w-full items-start' : 'flex flex-col',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {steps.map((step, idx) => {\n const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className={isHorizontal ? 'flex flex-1 items-start' : 'flex items-start gap-4 pb-8 last:pb-0'}\n >\n {/* Vertical connector + circle column */}\n {!isHorizontal && (\n <div className=\"relative flex flex-col items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`mt-1 w-0.5 flex-1 min-h-[32px] ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n )}\n\n {/* Horizontal: circle + connector */}\n {isHorizontal && (\n <div className=\"flex flex-1 flex-col items-center\">\n <div className=\"flex w-full items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`h-0.5 flex-1 ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n {/* Label below circle */}\n <div className=\"mt-2 text-center px-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Vertical: label to the right */}\n {!isHorizontal && (\n <div className=\"min-w-0 flex-1 pt-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n )}\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index1773.cjs","names":[],"sources":["../src/ui-library/gallery/stepper/Stepper.tsx"],"sourcesContent":["/**\n * Stepper — Design System Component\n *\n * A step progress indicator for multi-step workflows.\n *\n * Step states: completed | current | upcoming | disabled\n *\n * Accessibility:\n * - The current step receives aria-current=\"step\".\n * - Completed steps have aria-label with a \"Completed\" suffix when no icon.\n * - The step list is an ordered list (<ol>) — each step is an <li>.\n * - Orientation is exposed via aria-orientation on the container.\n *\n * API:\n * <Stepper\n * steps={[\n * { id: '1', label: 'Personal Details', description: 'Name and contact' },\n * { id: '2', label: 'Employment', description: 'IDs and dates' },\n * ]}\n * currentStep=\"2\"\n * completedSteps={['1']}\n * />\n */\n\nimport type { ReactNode } from 'react';\nimport { Check } from 'lucide-react';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type StepState = 'completed' | 'current' | 'upcoming' | 'disabled';\n\nexport interface StepDef {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepDef[];\n /** The id of the currently active step */\n currentStep: string;\n /** IDs of steps that are completed */\n completedSteps?: string[];\n /** IDs of steps that are disabled */\n disabledSteps?: string[];\n orientation?: 'horizontal' | 'vertical';\n className?: string;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveState(\n id: string,\n currentStep: string,\n completedSteps: string[],\n disabledSteps: string[],\n): StepState {\n if (disabledSteps.includes(id)) return 'disabled';\n if (completedSteps.includes(id)) return 'completed';\n if (id === currentStep) return 'current';\n return 'upcoming';\n}\n\n// ── Step indicator circle ─────────────────────────────────────────────────────\n\nfunction StepCircle({ state, number, icon }: { state: StepState; number: number; icon?: ReactNode }) {\n const base = 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full border-2 text-sm font-bold transition-all';\n\n const styles: Record<StepState, string> = {\n completed: 'border-brand-blue bg-brand-blue text-white',\n current: 'border-brand-blue bg-white text-brand-blue shadow-md shadow-brand-blue/15',\n upcoming: 'border-slate-300 bg-white text-slate-400',\n disabled: 'border-slate-200 bg-slate-50 text-slate-300',\n };\n\n return (\n <div className={`${base} ${styles[state]}`} aria-hidden=\"true\">\n {state === 'completed' ? (\n icon ?? <Check size={16} strokeWidth={3} />\n ) : (\n icon ?? <span>{number}</span>\n )}\n </div>\n );\n}\n\n// ── Stepper ───────────────────────────────────────────────────────────────────\n\nexport function Stepper({\n steps,\n currentStep,\n completedSteps = [],\n disabledSteps = [],\n orientation = 'horizontal',\n className = '',\n}: StepperProps) {\n const isHorizontal = orientation === 'horizontal';\n\n if (!isHorizontal) {\n // ── Vertical layout ───────────────────────────────────────────────────────\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation=\"vertical\"\n className={['flex flex-col', className].filter(Boolean).join(' ')}\n >\n <ol className=\"flex flex-col\">\n {steps.map((step, idx) => {\n const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className=\"flex items-start gap-4 pb-8 last:pb-0\"\n >\n <div className=\"relative flex flex-col items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`mt-1 w-0.5 flex-1 min-h-[32px] ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n <div className=\"min-w-0 flex-1 pt-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n );\n }\n\n // ── Horizontal layout ─────────────────────────────────────────────────────\n // Render as two rows:\n // Row 1 — circles + connectors, all on one baseline\n // Row 2 — labels, each centred under its circle\n const resolvedStates = steps.map((step) =>\n resolveState(step.id, currentStep, completedSteps, disabledSteps)\n );\n\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation=\"horizontal\"\n className={['w-full', className].filter(Boolean).join(' ')}\n >\n {/* Single row — circles, connectors, and labels all positioned relative to circles */}\n <ol className=\"flex items-start w-full\">\n {steps.map((step, idx) => {\n const state = resolvedStates[idx];\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className={['flex flex-col items-center relative', isLast ? '' : 'flex-1'].filter(Boolean).join(' ')}\n >\n {/* Circle + connector row */}\n <div className=\"flex items-center w-full\">\n {/* Circle — always centred in its slot */}\n <div className=\"shrink-0 z-10\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n </div>\n {/* Connector stretches to next circle */}\n {!isLast && (\n <div\n className={`h-0.5 flex-1 ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n\n {/* Label — centred under the circle via translate */}\n <div className=\"mt-2 flex flex-col items-center text-center w-max max-w-[120px]\"\n style={{ transform: isLast ? 'translateX(calc(50% - 1.125rem))' : idx === 0 ? 'translateX(calc(-50% + 1.125rem))' : undefined }}>\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n"],"mappings":";;;AAoDA,SAAS,aACP,IACA,aACA,gBACA,eACW;CACX,IAAI,cAAc,SAAS,EAAE,GAAG,OAAO;CACvC,IAAI,eAAe,SAAS,EAAE,GAAG,OAAO;CACxC,IAAI,OAAO,aAAa,OAAO;CAC/B,OAAO;AACT;AAIA,SAAS,WAAW,EAAE,OAAO,QAAQ,QAAgE;CAUnG,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EAAK,WAAW,4GAAW;GAP3B,WAAW;GACX,SAAW;GACX,UAAW;GACX,UAAW;EAIgB,EAAO;EAAU,eAAY;EACrD,UAAA,UAAU,cACT,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,cAAA,SAAD;GAAO,MAAM;GAAI,aAAa;EAAI,CAAA,IAE1C,QAAQ,iBAAA,GAAA,kBAAA,IAAA,CAAC,QAAD,EAAA,UAAO,OAAa,CAAA;CAE3B,CAAA;AAET;AAIA,SAAgB,QAAQ,EACtB,OACA,aACA,iBAAiB,CAAC,GAClB,gBAAiB,CAAC,GAClB,cAAc,cACd,YAAY,MACG;CAGf,IAAI,EAFiB,gBAAgB,eAInC,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,cAAW;EACX,oBAAiB;EACjB,WAAW,CAAC,iBAAiB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAEhE,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;GAAI,WAAU;GACX,UAAA,MAAM,KAAK,MAAM,QAAQ;IACxB,MAAM,QAAQ,aAAa,KAAK,IAAI,aAAa,gBAAgB,aAAa;IAC9E,MAAM,YAAY,UAAU;IAC5B,MAAM,SAAS,QAAQ,MAAM,SAAS;IAOtC,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;KAEE,gBAAc,YAAY,SAAS,KAAA;KACnC,WAAU;KAHZ,UAAA,CAKE,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;OAAmB;OAAO,QAAQ,MAAM;OAAG,MAAM,KAAK;MAAO,CAAA,GAC5D,CAAC,UACA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OACE,WAAW,kCACT,UAAU,cAAc,qBAAqB;OAE/C,eAAY;MACb,CAAA,CAEA;KACL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAW,yBAAyB;QAvB3C,WAAW;QACX,SAAW;QACX,UAAW;QACX,UAAW;OAoBgC,EAAW;OAAW,UAAA,KAAK;MAAS,CAAA,GAC1E,KAAK,eACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAA+C,UAAA,KAAK;MAAe,CAAA,CAE/E;KACH,CAAA,CAAA;IArBG,GAAA,KAAK,EAqBR;GAER,CAAC;EACC,CAAA;CACD,CAAA;CAQT,MAAM,iBAAiB,MAAM,KAAK,SAChC,aAAa,KAAK,IAAI,aAAa,gBAAgB,aAAa,CAClE;CAEA,MAAM,aAAwC;EAC5C,WAAW;EACX,SAAW;EACX,UAAW;EACX,UAAW;CACb;CAEA,OACE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;EACE,cAAW;EACX,oBAAiB;EACjB,WAAW,CAAC,UAAU,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;EAGzD,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,MAAD;GAAI,WAAU;GACX,UAAA,MAAM,KAAK,MAAM,QAAQ;IACxB,MAAM,QAAQ,eAAe;IAC7B,MAAM,YAAY,UAAU;IAC5B,MAAM,SAAS,QAAQ,MAAM,SAAS;IAEtC,OACE,iBAAA,GAAA,kBAAA,KAAA,CAAC,MAAD;KAEE,gBAAc,YAAY,SAAS,KAAA;KACnC,WAAW,CAAC,uCAAuC,SAAS,KAAK,QAAQ,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;KAHrG,UAAA,CAME,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OAAK,WAAU;OACb,UAAA,iBAAA,GAAA,kBAAA,IAAA,CAAC,YAAD;QAAmB;QAAO,QAAQ,MAAM;QAAG,MAAM,KAAK;OAAO,CAAA;MAC1D,CAAA,GAEJ,CAAC,UACA,iBAAA,GAAA,kBAAA,IAAA,CAAC,OAAD;OACE,WAAW,gBACT,UAAU,cAAc,qBAAqB;OAE/C,eAAY;MACb,CAAA,CAEA;KAGL,CAAA,GAAA,iBAAA,GAAA,kBAAA,KAAA,CAAC,OAAD;MAAK,WAAU;MACV,OAAO,EAAE,WAAW,SAAS,qCAAqC,QAAQ,IAAI,sCAAsC,KAAA,EAAU;MADnI,UAAA,CAEE,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAW,yBAAyB,WAAW;OAAW,UAAA,KAAK;MAAS,CAAA,GAC1E,KAAK,eACJ,iBAAA,GAAA,kBAAA,IAAA,CAAC,KAAD;OAAG,WAAU;OAA+C,UAAA,KAAK;MAAe,CAAA,CAE/E;KACH,CAAA,CAAA;IA7BG,GAAA,KAAK,EA6BR;GAER,CAAC;EACC,CAAA;CACD,CAAA;AAET"}
|
package/lib/index1773.mjs
CHANGED
|
@@ -23,72 +23,92 @@ function StepCircle({ state, number, icon }) {
|
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
25
|
function Stepper({ steps, currentStep, completedSteps = [], disabledSteps = [], orientation = "horizontal", className = "" }) {
|
|
26
|
-
|
|
27
|
-
return /* @__PURE__ */ jsx("div", {
|
|
26
|
+
if (!(orientation === "horizontal")) return /* @__PURE__ */ jsx("div", {
|
|
28
27
|
"aria-label": "Progress",
|
|
29
|
-
"aria-orientation":
|
|
30
|
-
className: [
|
|
28
|
+
"aria-orientation": "vertical",
|
|
29
|
+
className: ["flex flex-col", className].filter(Boolean).join(" "),
|
|
31
30
|
children: /* @__PURE__ */ jsx("ol", {
|
|
32
|
-
className:
|
|
31
|
+
className: "flex flex-col",
|
|
33
32
|
children: steps.map((step, idx) => {
|
|
34
33
|
const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);
|
|
35
34
|
const isCurrent = state === "current";
|
|
36
35
|
const isLast = idx === steps.length - 1;
|
|
37
|
-
const labelColor = {
|
|
38
|
-
completed: "text-brand-blue",
|
|
39
|
-
current: "text-brand-navy font-bold",
|
|
40
|
-
upcoming: "text-slate-500",
|
|
41
|
-
disabled: "text-slate-300"
|
|
42
|
-
};
|
|
43
36
|
return /* @__PURE__ */ jsxs("li", {
|
|
44
37
|
"aria-current": isCurrent ? "step" : void 0,
|
|
45
|
-
className:
|
|
46
|
-
children: [
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
className: "flex items-start gap-4 pb-8 last:pb-0",
|
|
39
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
40
|
+
className: "relative flex flex-col items-center",
|
|
41
|
+
children: [/* @__PURE__ */ jsx(StepCircle, {
|
|
42
|
+
state,
|
|
43
|
+
number: idx + 1,
|
|
44
|
+
icon: step.icon
|
|
45
|
+
}), !isLast && /* @__PURE__ */ jsx("div", {
|
|
46
|
+
className: `mt-1 w-0.5 flex-1 min-h-[32px] ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
47
|
+
"aria-hidden": "true"
|
|
48
|
+
})]
|
|
49
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
50
|
+
className: "min-w-0 flex-1 pt-1",
|
|
51
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
52
|
+
className: `text-sm leading-tight ${{
|
|
53
|
+
completed: "text-brand-blue",
|
|
54
|
+
current: "text-brand-navy font-bold",
|
|
55
|
+
upcoming: "text-slate-500",
|
|
56
|
+
disabled: "text-slate-300"
|
|
57
|
+
}[state]}`,
|
|
58
|
+
children: step.label
|
|
59
|
+
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
60
|
+
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
61
|
+
children: step.description
|
|
62
|
+
})]
|
|
63
|
+
})]
|
|
64
|
+
}, step.id);
|
|
65
|
+
})
|
|
66
|
+
})
|
|
67
|
+
});
|
|
68
|
+
const resolvedStates = steps.map((step) => resolveState(step.id, currentStep, completedSteps, disabledSteps));
|
|
69
|
+
const labelColor = {
|
|
70
|
+
completed: "text-brand-blue",
|
|
71
|
+
current: "text-brand-navy font-bold",
|
|
72
|
+
upcoming: "text-slate-500",
|
|
73
|
+
disabled: "text-slate-300"
|
|
74
|
+
};
|
|
75
|
+
return /* @__PURE__ */ jsx("div", {
|
|
76
|
+
"aria-label": "Progress",
|
|
77
|
+
"aria-orientation": "horizontal",
|
|
78
|
+
className: ["w-full", className].filter(Boolean).join(" "),
|
|
79
|
+
children: /* @__PURE__ */ jsx("ol", {
|
|
80
|
+
className: "flex items-start w-full",
|
|
81
|
+
children: steps.map((step, idx) => {
|
|
82
|
+
const state = resolvedStates[idx];
|
|
83
|
+
const isCurrent = state === "current";
|
|
84
|
+
const isLast = idx === steps.length - 1;
|
|
85
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
86
|
+
"aria-current": isCurrent ? "step" : void 0,
|
|
87
|
+
className: ["flex flex-col items-center relative", isLast ? "" : "flex-1"].filter(Boolean).join(" "),
|
|
88
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
89
|
+
className: "flex items-center w-full",
|
|
90
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
91
|
+
className: "shrink-0 z-10",
|
|
92
|
+
children: /* @__PURE__ */ jsx(StepCircle, {
|
|
50
93
|
state,
|
|
51
94
|
number: idx + 1,
|
|
52
95
|
icon: step.icon
|
|
53
|
-
})
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
})]
|
|
70
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
71
|
-
className: "mt-2 text-center px-1",
|
|
72
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
73
|
-
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
74
|
-
children: step.label
|
|
75
|
-
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
76
|
-
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
77
|
-
children: step.description
|
|
78
|
-
})]
|
|
79
|
-
})]
|
|
80
|
-
}),
|
|
81
|
-
!isHorizontal && /* @__PURE__ */ jsxs("div", {
|
|
82
|
-
className: "min-w-0 flex-1 pt-1",
|
|
83
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
84
|
-
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
85
|
-
children: step.label
|
|
86
|
-
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
87
|
-
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
88
|
-
children: step.description
|
|
89
|
-
})]
|
|
90
|
-
})
|
|
91
|
-
]
|
|
96
|
+
})
|
|
97
|
+
}), !isLast && /* @__PURE__ */ jsx("div", {
|
|
98
|
+
className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
|
|
99
|
+
"aria-hidden": "true"
|
|
100
|
+
})]
|
|
101
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
102
|
+
className: "mt-2 flex flex-col items-center text-center w-max max-w-[120px]",
|
|
103
|
+
style: { transform: isLast ? "translateX(calc(50% - 1.125rem))" : idx === 0 ? "translateX(calc(-50% + 1.125rem))" : void 0 },
|
|
104
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
105
|
+
className: `text-sm leading-tight ${labelColor[state]}`,
|
|
106
|
+
children: step.label
|
|
107
|
+
}), step.description && /* @__PURE__ */ jsx("p", {
|
|
108
|
+
className: "mt-0.5 text-xs text-slate-400 leading-tight",
|
|
109
|
+
children: step.description
|
|
110
|
+
})]
|
|
111
|
+
})]
|
|
92
112
|
}, step.id);
|
|
93
113
|
})
|
|
94
114
|
})
|
package/lib/index1773.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index1773.mjs","names":[],"sources":["../src/ui-library/gallery/stepper/Stepper.tsx"],"sourcesContent":["/**\n * Stepper — Design System Component\n *\n * A step progress indicator for multi-step workflows.\n *\n * Step states: completed | current | upcoming | disabled\n *\n * Accessibility:\n * - The current step receives aria-current=\"step\".\n * - Completed steps have aria-label with a \"Completed\" suffix when no icon.\n * - The step list is an ordered list (<ol>) — each step is an <li>.\n * - Orientation is exposed via aria-orientation on the container.\n *\n * API:\n * <Stepper\n * steps={[\n * { id: '1', label: 'Personal Details', description: 'Name and contact' },\n * { id: '2', label: 'Employment', description: 'IDs and dates' },\n * ]}\n * currentStep=\"2\"\n * completedSteps={['1']}\n * />\n */\n\nimport type { ReactNode } from 'react';\nimport { Check } from 'lucide-react';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type StepState = 'completed' | 'current' | 'upcoming' | 'disabled';\n\nexport interface StepDef {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepDef[];\n /** The id of the currently active step */\n currentStep: string;\n /** IDs of steps that are completed */\n completedSteps?: string[];\n /** IDs of steps that are disabled */\n disabledSteps?: string[];\n orientation?: 'horizontal' | 'vertical';\n className?: string;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveState(\n id: string,\n currentStep: string,\n completedSteps: string[],\n disabledSteps: string[],\n): StepState {\n if (disabledSteps.includes(id)) return 'disabled';\n if (completedSteps.includes(id)) return 'completed';\n if (id === currentStep) return 'current';\n return 'upcoming';\n}\n\n// ── Step indicator circle ─────────────────────────────────────────────────────\n\nfunction StepCircle({ state, number, icon }: { state: StepState; number: number; icon?: ReactNode }) {\n const base = 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full border-2 text-sm font-bold transition-all';\n\n const styles: Record<StepState, string> = {\n completed: 'border-brand-blue bg-brand-blue text-white',\n current: 'border-brand-blue bg-white text-brand-blue shadow-md shadow-brand-blue/15',\n upcoming: 'border-slate-300 bg-white text-slate-400',\n disabled: 'border-slate-200 bg-slate-50 text-slate-300',\n };\n\n return (\n <div className={`${base} ${styles[state]}`} aria-hidden=\"true\">\n {state === 'completed' ? (\n icon ?? <Check size={16} strokeWidth={3} />\n ) : (\n icon ?? <span>{number}</span>\n )}\n </div>\n );\n}\n\n// ── Stepper ───────────────────────────────────────────────────────────────────\n\nexport function Stepper({\n steps,\n currentStep,\n completedSteps = [],\n disabledSteps = [],\n orientation = 'horizontal',\n className = '',\n}: StepperProps) {\n const isHorizontal = orientation === 'horizontal';\n\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation={orientation}\n className={[\n isHorizontal\n ? 'flex items-start'\n : 'flex flex-col',\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <ol\n className={[\n isHorizontal ? 'flex w-full items-start' : 'flex flex-col',\n ]\n .filter(Boolean)\n .join(' ')}\n >\n {steps.map((step, idx) => {\n const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className={isHorizontal ? 'flex flex-1 items-start' : 'flex items-start gap-4 pb-8 last:pb-0'}\n >\n {/* Vertical connector + circle column */}\n {!isHorizontal && (\n <div className=\"relative flex flex-col items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`mt-1 w-0.5 flex-1 min-h-[32px] ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n )}\n\n {/* Horizontal: circle + connector */}\n {isHorizontal && (\n <div className=\"flex flex-1 flex-col items-center\">\n <div className=\"flex w-full items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`h-0.5 flex-1 ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n {/* Label below circle */}\n <div className=\"mt-2 text-center px-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </div>\n )}\n\n {/* Vertical: label to the right */}\n {!isHorizontal && (\n <div className=\"min-w-0 flex-1 pt-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n )}\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n"],"mappings":";;;AAoDA,SAAS,aACP,IACA,aACA,gBACA,eACW;CACX,IAAI,cAAc,SAAS,EAAE,GAAG,OAAO;CACvC,IAAI,eAAe,SAAS,EAAE,GAAG,OAAO;CACxC,IAAI,OAAO,aAAa,OAAO;CAC/B,OAAO;AACT;AAIA,SAAS,WAAW,EAAE,OAAO,QAAQ,QAAgE;CAUnG,OACE,oBAAC,OAAD;EAAK,WAAW,4GAAW;GAP3B,WAAW;GACX,SAAW;GACX,UAAW;GACX,UAAW;EAIgB,EAAO;EAAU,eAAY;EACrD,UAAA,UAAU,cACT,QAAQ,oBAAC,OAAD;GAAO,MAAM;GAAI,aAAa;EAAI,CAAA,IAE1C,QAAQ,oBAAC,QAAD,EAAA,UAAO,OAAa,CAAA;CAE3B,CAAA;AAET;AAIA,SAAgB,QAAQ,EACtB,OACA,aACA,iBAAiB,CAAC,GAClB,gBAAiB,CAAC,GAClB,cAAc,cACd,YAAY,MACG;CACf,MAAM,eAAe,gBAAgB;CAErC,OACE,oBAAC,OAAD;EACE,cAAW;EACX,oBAAkB;EAClB,WAAW,CACT,eACI,qBACA,iBACJ,SACF,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;EAEX,UAAA,oBAAC,MAAD;GACE,WAAW,CACT,eAAe,4BAA4B,eAC7C,CAAC,CACE,OAAO,OAAO,CAAC,CACf,KAAK,GAAG;GAEV,UAAA,MAAM,KAAK,MAAM,QAAQ;IACxB,MAAM,QAAQ,aAAa,KAAK,IAAI,aAAa,gBAAgB,aAAa;IAC9E,MAAM,YAAY,UAAU;IAC5B,MAAM,SAAS,QAAQ,MAAM,SAAS;IAEtC,MAAM,aAAwC;KAC5C,WAAW;KACX,SAAW;KACX,UAAW;KACX,UAAW;IACb;IAEA,OACE,qBAAC,MAAD;KAEE,gBAAc,YAAY,SAAS,KAAA;KACnC,WAAW,eAAe,4BAA4B;KAHxD,UAAA;MAMG,CAAC,gBACA,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,YAAD;QAAmB;QAAO,QAAQ,MAAM;QAAG,MAAM,KAAK;OAAO,CAAA,GAC5D,CAAC,UACA,oBAAC,OAAD;QACE,WAAW,kCACT,UAAU,cAAc,qBAAqB;QAE/C,eAAY;OACb,CAAA,CAEA;;MAIN,gBACC,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,qBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,oBAAC,YAAD;SAAmB;SAAO,QAAQ,MAAM;SAAG,MAAM,KAAK;QAAO,CAAA,GAC5D,CAAC,UACA,oBAAC,OAAD;SACE,WAAW,gBACT,UAAU,cAAc,qBAAqB;SAE/C,eAAY;QACb,CAAA,CAEA;OAEL,CAAA,GAAA,qBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,oBAAC,KAAD;SAAG,WAAW,yBAAyB,WAAW;SAAW,UAAA,KAAK;QAAS,CAAA,GAC1E,KAAK,eACJ,oBAAC,KAAD;SAAG,WAAU;SAA+C,UAAA,KAAK;QAAe,CAAA,CAE/E;OACF,CAAA,CAAA;;MAIN,CAAC,gBACA,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,KAAD;QAAG,WAAW,yBAAyB,WAAW;QAAW,UAAA,KAAK;OAAS,CAAA,GAC1E,KAAK,eACJ,oBAAC,KAAD;QAAG,WAAU;QAA+C,UAAA,KAAK;OAAe,CAAA,CAE/E;;KAEL;IApDG,GAAA,KAAK,EAoDR;GAER,CAAC;EACC,CAAA;CACD,CAAA;AAET"}
|
|
1
|
+
{"version":3,"file":"index1773.mjs","names":[],"sources":["../src/ui-library/gallery/stepper/Stepper.tsx"],"sourcesContent":["/**\n * Stepper — Design System Component\n *\n * A step progress indicator for multi-step workflows.\n *\n * Step states: completed | current | upcoming | disabled\n *\n * Accessibility:\n * - The current step receives aria-current=\"step\".\n * - Completed steps have aria-label with a \"Completed\" suffix when no icon.\n * - The step list is an ordered list (<ol>) — each step is an <li>.\n * - Orientation is exposed via aria-orientation on the container.\n *\n * API:\n * <Stepper\n * steps={[\n * { id: '1', label: 'Personal Details', description: 'Name and contact' },\n * { id: '2', label: 'Employment', description: 'IDs and dates' },\n * ]}\n * currentStep=\"2\"\n * completedSteps={['1']}\n * />\n */\n\nimport type { ReactNode } from 'react';\nimport { Check } from 'lucide-react';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\nexport type StepState = 'completed' | 'current' | 'upcoming' | 'disabled';\n\nexport interface StepDef {\n id: string;\n label: string;\n description?: string;\n icon?: ReactNode;\n}\n\nexport interface StepperProps {\n steps: StepDef[];\n /** The id of the currently active step */\n currentStep: string;\n /** IDs of steps that are completed */\n completedSteps?: string[];\n /** IDs of steps that are disabled */\n disabledSteps?: string[];\n orientation?: 'horizontal' | 'vertical';\n className?: string;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction resolveState(\n id: string,\n currentStep: string,\n completedSteps: string[],\n disabledSteps: string[],\n): StepState {\n if (disabledSteps.includes(id)) return 'disabled';\n if (completedSteps.includes(id)) return 'completed';\n if (id === currentStep) return 'current';\n return 'upcoming';\n}\n\n// ── Step indicator circle ─────────────────────────────────────────────────────\n\nfunction StepCircle({ state, number, icon }: { state: StepState; number: number; icon?: ReactNode }) {\n const base = 'flex h-9 w-9 shrink-0 items-center justify-center rounded-full border-2 text-sm font-bold transition-all';\n\n const styles: Record<StepState, string> = {\n completed: 'border-brand-blue bg-brand-blue text-white',\n current: 'border-brand-blue bg-white text-brand-blue shadow-md shadow-brand-blue/15',\n upcoming: 'border-slate-300 bg-white text-slate-400',\n disabled: 'border-slate-200 bg-slate-50 text-slate-300',\n };\n\n return (\n <div className={`${base} ${styles[state]}`} aria-hidden=\"true\">\n {state === 'completed' ? (\n icon ?? <Check size={16} strokeWidth={3} />\n ) : (\n icon ?? <span>{number}</span>\n )}\n </div>\n );\n}\n\n// ── Stepper ───────────────────────────────────────────────────────────────────\n\nexport function Stepper({\n steps,\n currentStep,\n completedSteps = [],\n disabledSteps = [],\n orientation = 'horizontal',\n className = '',\n}: StepperProps) {\n const isHorizontal = orientation === 'horizontal';\n\n if (!isHorizontal) {\n // ── Vertical layout ───────────────────────────────────────────────────────\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation=\"vertical\"\n className={['flex flex-col', className].filter(Boolean).join(' ')}\n >\n <ol className=\"flex flex-col\">\n {steps.map((step, idx) => {\n const state = resolveState(step.id, currentStep, completedSteps, disabledSteps);\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className=\"flex items-start gap-4 pb-8 last:pb-0\"\n >\n <div className=\"relative flex flex-col items-center\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n {!isLast && (\n <div\n className={`mt-1 w-0.5 flex-1 min-h-[32px] ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n <div className=\"min-w-0 flex-1 pt-1\">\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n );\n }\n\n // ── Horizontal layout ─────────────────────────────────────────────────────\n // Render as two rows:\n // Row 1 — circles + connectors, all on one baseline\n // Row 2 — labels, each centred under its circle\n const resolvedStates = steps.map((step) =>\n resolveState(step.id, currentStep, completedSteps, disabledSteps)\n );\n\n const labelColor: Record<StepState, string> = {\n completed: 'text-brand-blue',\n current: 'text-brand-navy font-bold',\n upcoming: 'text-slate-500',\n disabled: 'text-slate-300',\n };\n\n return (\n <div\n aria-label=\"Progress\"\n aria-orientation=\"horizontal\"\n className={['w-full', className].filter(Boolean).join(' ')}\n >\n {/* Single row — circles, connectors, and labels all positioned relative to circles */}\n <ol className=\"flex items-start w-full\">\n {steps.map((step, idx) => {\n const state = resolvedStates[idx];\n const isCurrent = state === 'current';\n const isLast = idx === steps.length - 1;\n\n return (\n <li\n key={step.id}\n aria-current={isCurrent ? 'step' : undefined}\n className={['flex flex-col items-center relative', isLast ? '' : 'flex-1'].filter(Boolean).join(' ')}\n >\n {/* Circle + connector row */}\n <div className=\"flex items-center w-full\">\n {/* Circle — always centred in its slot */}\n <div className=\"shrink-0 z-10\">\n <StepCircle state={state} number={idx + 1} icon={step.icon} />\n </div>\n {/* Connector stretches to next circle */}\n {!isLast && (\n <div\n className={`h-0.5 flex-1 ${\n state === 'completed' ? 'bg-brand-blue/50' : 'bg-slate-200'\n }`}\n aria-hidden=\"true\"\n />\n )}\n </div>\n\n {/* Label — centred under the circle via translate */}\n <div className=\"mt-2 flex flex-col items-center text-center w-max max-w-[120px]\"\n style={{ transform: isLast ? 'translateX(calc(50% - 1.125rem))' : idx === 0 ? 'translateX(calc(-50% + 1.125rem))' : undefined }}>\n <p className={`text-sm leading-tight ${labelColor[state]}`}>{step.label}</p>\n {step.description && (\n <p className=\"mt-0.5 text-xs text-slate-400 leading-tight\">{step.description}</p>\n )}\n </div>\n </li>\n );\n })}\n </ol>\n </div>\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diwauhris/ui",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "1.1.
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "DIWA UHRIS UI component library — React + Tailwind CSS",
|
|
7
7
|
"keywords": [
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"react-dom": ">=18"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
+
"@diwauhris/ui": "^1.1.0",
|
|
41
42
|
"@fontsource-variable/libre-franklin": "^5.3.0",
|
|
42
43
|
"@fontsource/barlow": "^5.3.0",
|
|
43
44
|
"@radix-ui/react-dialog": "^1.1.23",
|
|
@@ -49,9 +50,9 @@
|
|
|
49
50
|
"date-fns": "^4.4.0",
|
|
50
51
|
"lucide-react": "^1.17.0",
|
|
51
52
|
"postcss": "^8.5.15",
|
|
52
|
-
"react": "
|
|
53
|
+
"react": ">=18",
|
|
53
54
|
"react-calendar": "^6.0.1",
|
|
54
|
-
"react-dom": "
|
|
55
|
+
"react-dom": ">=18",
|
|
55
56
|
"react-router-dom": "^7.17.0",
|
|
56
57
|
"sonner": "^2.0.7",
|
|
57
58
|
"tailwind-merge": "^3.6.0",
|