@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 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
- const isHorizontal = orientation === "horizontal";
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": orientation,
30
- className: [isHorizontal ? "flex items-start" : "flex flex-col", className].filter(Boolean).join(" "),
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: [isHorizontal ? "flex w-full items-start" : "flex flex-col"].filter(Boolean).join(" "),
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: isHorizontal ? "flex flex-1 items-start" : "flex items-start gap-4 pb-8 last:pb-0",
46
- children: [
47
- !isHorizontal && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
48
- className: "relative flex flex-col items-center",
49
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepCircle, {
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
- }), !isLast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
54
- className: `mt-1 w-0.5 flex-1 min-h-[32px] ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
55
- "aria-hidden": "true"
56
- })]
57
- }),
58
- isHorizontal && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
59
- className: "flex flex-1 flex-col items-center",
60
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
61
- className: "flex w-full items-center",
62
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StepCircle, {
63
- state,
64
- number: idx + 1,
65
- icon: step.icon
66
- }), !isLast && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
67
- className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
68
- "aria-hidden": "true"
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
  })
@@ -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":"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"}
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
- const isHorizontal = orientation === "horizontal";
27
- return /* @__PURE__ */ jsx("div", {
26
+ if (!(orientation === "horizontal")) return /* @__PURE__ */ jsx("div", {
28
27
  "aria-label": "Progress",
29
- "aria-orientation": orientation,
30
- className: [isHorizontal ? "flex items-start" : "flex flex-col", className].filter(Boolean).join(" "),
28
+ "aria-orientation": "vertical",
29
+ className: ["flex flex-col", className].filter(Boolean).join(" "),
31
30
  children: /* @__PURE__ */ jsx("ol", {
32
- className: [isHorizontal ? "flex w-full items-start" : "flex flex-col"].filter(Boolean).join(" "),
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: isHorizontal ? "flex flex-1 items-start" : "flex items-start gap-4 pb-8 last:pb-0",
46
- children: [
47
- !isHorizontal && /* @__PURE__ */ jsxs("div", {
48
- className: "relative flex flex-col items-center",
49
- children: [/* @__PURE__ */ jsx(StepCircle, {
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
- }), !isLast && /* @__PURE__ */ jsx("div", {
54
- className: `mt-1 w-0.5 flex-1 min-h-[32px] ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
55
- "aria-hidden": "true"
56
- })]
57
- }),
58
- isHorizontal && /* @__PURE__ */ jsxs("div", {
59
- className: "flex flex-1 flex-col items-center",
60
- children: [/* @__PURE__ */ jsxs("div", {
61
- className: "flex w-full items-center",
62
- children: [/* @__PURE__ */ jsx(StepCircle, {
63
- state,
64
- number: idx + 1,
65
- icon: step.icon
66
- }), !isLast && /* @__PURE__ */ jsx("div", {
67
- className: `h-0.5 flex-1 ${state === "completed" ? "bg-brand-blue/50" : "bg-slate-200"}`,
68
- "aria-hidden": "true"
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
  })
@@ -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.0",
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": "^19.2.8",
53
+ "react": ">=18",
53
54
  "react-calendar": "^6.0.1",
54
- "react-dom": "^19.2.8",
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",