@tantainnovative/ndpr-toolkit 1.0.3 → 1.0.4

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 (156) hide show
  1. package/next-env.d.ts +5 -0
  2. package/package.json +1 -1
  3. package/.claude/settings.local.json +0 -20
  4. package/.eslintrc.json +0 -10
  5. package/.github/workflows/ci.yml +0 -36
  6. package/.github/workflows/nextjs.yml +0 -104
  7. package/.husky/commit-msg +0 -4
  8. package/.husky/pre-commit +0 -4
  9. package/.lintstagedrc.js +0 -4
  10. package/.nvmrc +0 -1
  11. package/.versionrc +0 -17
  12. package/CLAUDE.md +0 -90
  13. package/commitlint.config.js +0 -36
  14. package/eslint.config.mjs +0 -16
  15. package/jest.config.js +0 -31
  16. package/jest.setup.js +0 -15
  17. package/next.config.js +0 -15
  18. package/next.config.ts +0 -62
  19. package/packages/ndpr-toolkit/README.md +0 -467
  20. package/packages/ndpr-toolkit/jest.config.js +0 -23
  21. package/packages/ndpr-toolkit/package-lock.json +0 -8197
  22. package/packages/ndpr-toolkit/package.json +0 -71
  23. package/packages/ndpr-toolkit/rollup.config.js +0 -34
  24. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +0 -119
  25. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +0 -122
  26. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +0 -270
  27. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +0 -199
  28. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +0 -224
  29. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +0 -104
  30. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +0 -161
  31. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +0 -330
  32. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +0 -149
  33. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +0 -88
  34. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +0 -160
  35. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +0 -110
  36. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +0 -97
  37. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +0 -701
  38. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +0 -631
  39. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +0 -569
  40. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +0 -496
  41. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +0 -270
  42. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +0 -217
  43. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +0 -206
  44. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +0 -342
  45. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +0 -373
  46. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +0 -174
  47. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +0 -717
  48. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +0 -476
  49. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +0 -620
  50. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +0 -541
  51. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +0 -454
  52. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +0 -333
  53. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +0 -409
  54. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +0 -263
  55. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +0 -457
  56. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +0 -236
  57. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +0 -428
  58. package/packages/ndpr-toolkit/src/index.ts +0 -44
  59. package/packages/ndpr-toolkit/src/setupTests.ts +0 -5
  60. package/packages/ndpr-toolkit/src/types/breach.ts +0 -283
  61. package/packages/ndpr-toolkit/src/types/consent.ts +0 -111
  62. package/packages/ndpr-toolkit/src/types/dpia.ts +0 -236
  63. package/packages/ndpr-toolkit/src/types/dsr.ts +0 -192
  64. package/packages/ndpr-toolkit/src/types/index.ts +0 -42
  65. package/packages/ndpr-toolkit/src/types/privacy.ts +0 -246
  66. package/packages/ndpr-toolkit/src/utils/breach.ts +0 -122
  67. package/packages/ndpr-toolkit/src/utils/consent.ts +0 -51
  68. package/packages/ndpr-toolkit/src/utils/dpia.ts +0 -104
  69. package/packages/ndpr-toolkit/src/utils/dsr.ts +0 -77
  70. package/packages/ndpr-toolkit/src/utils/privacy.ts +0 -100
  71. package/packages/ndpr-toolkit/tsconfig.json +0 -23
  72. package/postcss.config.mjs +0 -5
  73. package/src/__tests__/example.test.ts +0 -13
  74. package/src/__tests__/requestService.test.ts +0 -57
  75. package/src/app/accessibility.css +0 -70
  76. package/src/app/docs/components/DocLayout.tsx +0 -267
  77. package/src/app/docs/components/breach-notification/page.tsx +0 -797
  78. package/src/app/docs/components/consent-management/page.tsx +0 -576
  79. package/src/app/docs/components/data-subject-rights/page.tsx +0 -511
  80. package/src/app/docs/components/dpia-questionnaire/layout.tsx +0 -15
  81. package/src/app/docs/components/dpia-questionnaire/metadata.ts +0 -31
  82. package/src/app/docs/components/dpia-questionnaire/page.tsx +0 -666
  83. package/src/app/docs/components/hooks/page.tsx +0 -305
  84. package/src/app/docs/components/page.tsx +0 -84
  85. package/src/app/docs/components/privacy-policy-generator/page.tsx +0 -634
  86. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +0 -123
  87. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +0 -328
  88. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +0 -28
  89. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +0 -91
  90. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +0 -118
  91. package/src/app/docs/guides/breach-notification-process/page.tsx +0 -39
  92. package/src/app/docs/guides/conducting-dpia/page.tsx +0 -593
  93. package/src/app/docs/guides/data-subject-requests/page.tsx +0 -666
  94. package/src/app/docs/guides/managing-consent/page.tsx +0 -738
  95. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +0 -296
  96. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +0 -145
  97. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +0 -33
  98. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +0 -99
  99. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +0 -159
  100. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +0 -38
  101. package/src/app/docs/guides/page.tsx +0 -67
  102. package/src/app/docs/layout.tsx +0 -15
  103. package/src/app/docs/metadata.ts +0 -31
  104. package/src/app/docs/page.tsx +0 -572
  105. package/src/app/favicon.ico +0 -0
  106. package/src/app/globals.css +0 -123
  107. package/src/app/layout.tsx +0 -37
  108. package/src/app/ndpr-demos/breach/page.tsx +0 -354
  109. package/src/app/ndpr-demos/consent/page.tsx +0 -366
  110. package/src/app/ndpr-demos/dpia/page.tsx +0 -495
  111. package/src/app/ndpr-demos/dsr/page.tsx +0 -280
  112. package/src/app/ndpr-demos/page.tsx +0 -73
  113. package/src/app/ndpr-demos/policy/page.tsx +0 -771
  114. package/src/app/page.tsx +0 -452
  115. package/src/components/ErrorBoundary.tsx +0 -90
  116. package/src/components/breach-notification/BreachNotificationForm.tsx +0 -479
  117. package/src/components/consent/ConsentBanner.tsx +0 -159
  118. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +0 -419
  119. package/src/components/docs/DocLayout.tsx +0 -289
  120. package/src/components/docs/index.ts +0 -2
  121. package/src/components/dpia/DPIAQuestionnaire.tsx +0 -483
  122. package/src/components/privacy-policy/PolicyGenerator.tsx +0 -1062
  123. package/src/components/privacy-policy/data.ts +0 -98
  124. package/src/components/privacy-policy/shared/CheckboxField.tsx +0 -38
  125. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +0 -85
  126. package/src/components/privacy-policy/shared/FormField.tsx +0 -79
  127. package/src/components/privacy-policy/shared/StepIndicator.tsx +0 -86
  128. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +0 -335
  129. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +0 -231
  130. package/src/components/privacy-policy/steps/DataSharingStep.tsx +0 -418
  131. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +0 -202
  132. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +0 -172
  133. package/src/components/ui/Badge.tsx +0 -46
  134. package/src/components/ui/Button.tsx +0 -59
  135. package/src/components/ui/Card.tsx +0 -92
  136. package/src/components/ui/Checkbox.tsx +0 -57
  137. package/src/components/ui/FormField.tsx +0 -50
  138. package/src/components/ui/Input.tsx +0 -38
  139. package/src/components/ui/Loading.tsx +0 -201
  140. package/src/components/ui/Select.tsx +0 -42
  141. package/src/components/ui/TextArea.tsx +0 -38
  142. package/src/components/ui/label.tsx +0 -24
  143. package/src/components/ui/switch.tsx +0 -31
  144. package/src/components/ui/tabs.tsx +0 -66
  145. package/src/hooks/useConsent.ts +0 -64
  146. package/src/hooks/useLoadingState.ts +0 -85
  147. package/src/lib/consentService.ts +0 -137
  148. package/src/lib/dpiaQuestions.ts +0 -148
  149. package/src/lib/requestService.ts +0 -75
  150. package/src/lib/sanitize.ts +0 -108
  151. package/src/lib/storage.ts +0 -222
  152. package/src/lib/utils.ts +0 -6
  153. package/src/types/html-to-docx.d.ts +0 -30
  154. package/src/types/index.ts +0 -72
  155. package/tailwind.config.ts +0 -65
  156. package/tsconfig.json +0 -41
@@ -1,98 +0,0 @@
1
- export const defaultDataPurposes = [
2
- 'Providing and maintaining our services',
3
- 'Processing transactions',
4
- 'Sending administrative information',
5
- 'Improving user experience',
6
- 'Marketing and promotional communications',
7
- 'Analytics and research',
8
- 'Legal compliance',
9
- 'Customer support',
10
- 'Personalization of content',
11
- 'Account management',
12
- ];
13
-
14
- export const defaultSecurityMeasures = [
15
- 'Encryption of sensitive data in transit and at rest',
16
- 'Multi-factor authentication for system access',
17
- 'Regular security assessments and penetration testing',
18
- 'Access controls with principle of least privilege',
19
- 'Data backup procedures with regular testing',
20
- 'Comprehensive staff training on data protection',
21
- 'Documented incident response plan with regular drills',
22
- 'Physical security measures including CCTV and access controls',
23
- 'Network security monitoring with intrusion detection',
24
- 'Vulnerability management and timely patching',
25
- 'Third-party security assessments for vendors',
26
- 'Data loss prevention (DLP) systems',
27
- 'Regular security audits and compliance checks',
28
- 'Secure development practices and code reviews',
29
- 'Privacy by design and default in all systems',
30
- 'Data minimization and pseudonymization where appropriate',
31
- 'Secure disposal of data and equipment',
32
- 'Endpoint protection and mobile device management',
33
- ];
34
-
35
- export const dataSubjectCategories = [
36
- 'Customers and clients',
37
- 'Employees and contractors',
38
- 'Job applicants',
39
- 'Suppliers and vendors',
40
- 'Website visitors and users',
41
- 'Marketing recipients',
42
- 'Business partners',
43
- 'Shareholders and investors',
44
- 'Children (under 18 years)',
45
- 'Vulnerable individuals',
46
- 'Patients (for healthcare organizations)',
47
- 'Students (for educational institutions)',
48
- 'Members (for membership organizations)',
49
- 'Beneficiaries (for charities/NGOs)',
50
- ];
51
-
52
- export const trackingTechnologies = [
53
- 'HTTP cookies',
54
- 'Web beacons and pixel tags',
55
- 'Local storage objects',
56
- 'Session replay tools',
57
- 'Device fingerprinting',
58
- 'IP address tracking',
59
- 'JavaScript trackers',
60
- 'Mobile app SDKs',
61
- 'Cross-device tracking',
62
- 'Social media widgets and buttons',
63
- 'Heatmaps and clicktracking',
64
- 'UTM parameters',
65
- 'Server logs',
66
- ];
67
-
68
- export const transferSafeguards = [
69
- 'Standard Contractual Clauses (SCCs)',
70
- 'Binding Corporate Rules (BCRs)',
71
- 'Adequacy decisions by the Nigerian Data Protection Commission',
72
- 'Data Processing Agreements with appropriate safeguards',
73
- 'Explicit consent of the data subject',
74
- 'Necessary for the performance of a contract',
75
- 'Necessary for important reasons of public interest',
76
- 'Necessary to protect vital interests',
77
- 'Transfer is from a register intended to provide information to the public',
78
- 'Compliance with NDPR Section 2.11 and 2.12 on international transfers',
79
- ];
80
-
81
- export const defaultCookieTypes = [
82
- 'Strictly necessary cookies',
83
- 'Functional cookies',
84
- 'Performance cookies',
85
- 'Targeting/advertising cookies',
86
- 'Social media cookies',
87
- ];
88
-
89
- export const commonTransferCountries = [
90
- 'United States',
91
- 'United Kingdom',
92
- 'European Union countries',
93
- 'Canada',
94
- 'Australia',
95
- 'India',
96
- 'South Africa',
97
- 'Kenya',
98
- ];
@@ -1,38 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import { Checkbox } from '@/components/ui/Checkbox';
5
- import { cn } from '@/lib/utils';
6
-
7
- interface CheckboxFieldProps {
8
- id: string;
9
- name: string;
10
- label: string;
11
- checked: boolean;
12
- onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
13
- className?: string;
14
- description?: string;
15
- }
16
-
17
- export default function CheckboxField({
18
- id,
19
- name,
20
- label,
21
- checked,
22
- onChange,
23
- className = '',
24
- description,
25
- }: CheckboxFieldProps) {
26
- return (
27
- <div className={cn('mb-4', className)}>
28
- <Checkbox
29
- id={id}
30
- name={name}
31
- label={label}
32
- checked={checked}
33
- onChange={onChange}
34
- description={description}
35
- />
36
- </div>
37
- );
38
- }
@@ -1,85 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import { cn } from '@/lib/utils';
5
-
6
- interface CheckboxGroupProps {
7
- title: string;
8
- items: string[];
9
- selectedItems: string[];
10
- onToggleItem: (item: string) => void;
11
- required?: boolean;
12
- error?: string;
13
- columns?: 1 | 2 | 3;
14
- className?: string;
15
- }
16
-
17
- export default function CheckboxGroup({
18
- title,
19
- items,
20
- selectedItems,
21
- onToggleItem,
22
- required = false,
23
- error,
24
- columns = 2,
25
- className = '',
26
- }: CheckboxGroupProps) {
27
- return (
28
- <div className={cn("relative", className)}>
29
- {title && (
30
- <label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
31
- {title} {required && <span className="text-red-500">*</span>}
32
- </label>
33
- )}
34
-
35
- {error && (
36
- <p className="mt-1 mb-2 text-sm font-medium text-red-600 dark:text-red-400">{error}</p>
37
- )}
38
-
39
- <div className={cn(
40
- "grid gap-x-4 gap-y-2 mt-1",
41
- columns === 1 ? "grid-cols-1" :
42
- columns === 2 ? "grid-cols-1 sm:grid-cols-2" :
43
- "grid-cols-1 sm:grid-cols-2 md:grid-cols-3"
44
- )}>
45
- {items.map((item) => {
46
- const isSelected = selectedItems.includes(item);
47
- const itemId = `item-${item.replace(/\s+/g, '-').toLowerCase()}`;
48
-
49
- return (
50
- <div key={itemId} className="flex items-start group">
51
- <div className="flex items-center h-5">
52
- <input
53
- id={itemId}
54
- type="checkbox"
55
- checked={isSelected}
56
- onChange={() => onToggleItem(item)}
57
- className={cn(
58
- "h-4 w-4 rounded border-2 transition-colors duration-200",
59
- "focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500",
60
- isSelected
61
- ? "bg-blue-600 border-blue-600 dark:bg-blue-500 dark:border-blue-500"
62
- : "border-gray-300 dark:border-gray-600",
63
- "hover:border-blue-500 dark:hover:border-blue-400"
64
- )}
65
- />
66
- </div>
67
- <label
68
- htmlFor={itemId}
69
- className={cn(
70
- "ml-2 text-sm leading-tight",
71
- isSelected
72
- ? "text-gray-900 dark:text-white font-medium"
73
- : "text-gray-700 dark:text-gray-300",
74
- "group-hover:text-gray-900 dark:group-hover:text-white transition-colors duration-200"
75
- )}
76
- >
77
- {item}
78
- </label>
79
- </div>
80
- );
81
- })}
82
- </div>
83
- </div>
84
- );
85
- }
@@ -1,79 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
- import { cn } from '@/lib/utils';
5
-
6
- interface FormFieldProps {
7
- id: string;
8
- label: string;
9
- required?: boolean;
10
- error?: string;
11
- children: React.ReactNode;
12
- className?: string;
13
- description?: string;
14
- }
15
-
16
- export default function FormField({
17
- id,
18
- label,
19
- required = false,
20
- error,
21
- children,
22
- className = '',
23
- description,
24
- }: FormFieldProps) {
25
- const hasError = !!error;
26
-
27
- return (
28
- <div className={cn('mb-5 space-y-2', className)}>
29
- <div className="flex items-center justify-between">
30
- <label
31
- htmlFor={id}
32
- className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-gray-700 dark:text-gray-200"
33
- >
34
- {label} {required && <span className="text-red-500 ml-1" aria-hidden="true">*</span>}
35
- {required && <span className="sr-only">(required)</span>}
36
- </label>
37
- </div>
38
-
39
- {description && (
40
- <p className="text-sm text-gray-500 dark:text-gray-400">{description}</p>
41
- )}
42
-
43
- <div className={`relative ${hasError ? 'has-error' : ''}`}>
44
- {children}
45
-
46
- {hasError && (
47
- <div className="absolute inset-y-0 right-0 pr-3 flex items-center pointer-events-none">
48
- <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-red-500" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
49
- <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z" clipRule="evenodd" />
50
- </svg>
51
- </div>
52
- )}
53
- </div>
54
-
55
- {hasError && (
56
- <p className="text-sm font-medium text-red-600 dark:text-red-400" id={`${id}-error`} role="alert">
57
- {error}
58
- </p>
59
- )}
60
-
61
- <style jsx>{`
62
- /* This ensures the error icon doesn&apos;t appear on elements that shouldn't have it */
63
- .has-error > :global(textarea),
64
- .has-error > :global(input:not([type="checkbox"]):not([type="radio"])),
65
- .has-error > :global(select) {
66
- padding-right: 2.5rem;
67
- border-color: rgb(239, 68, 68);
68
- }
69
-
70
- .has-error > :global(textarea:focus),
71
- .has-error > :global(input:focus),
72
- .has-error > :global(select:focus) {
73
- border-color: rgb(239, 68, 68);
74
- --tw-ring-color: rgba(239, 68, 68, 0.2);
75
- }
76
- `}</style>
77
- </div>
78
- );
79
- }
@@ -1,86 +0,0 @@
1
- 'use client';
2
-
3
- import React from 'react';
4
-
5
- interface StepIndicatorProps {
6
- currentStep: number;
7
- totalSteps: number;
8
- stepLabels: string[];
9
- }
10
-
11
- export default function StepIndicator({
12
- currentStep,
13
- totalSteps,
14
- stepLabels
15
- }: StepIndicatorProps) {
16
- return (
17
- <div className="mb-10" role="navigation" aria-label="Form progress">
18
- <div className="flex items-center justify-between">
19
- {Array.from({ length: totalSteps }).map((_, index) => {
20
- const stepNumber = index + 1;
21
- const isActive = stepNumber === currentStep;
22
- const isCompleted = stepNumber < currentStep;
23
- const isPending = stepNumber > currentStep;
24
-
25
- return (
26
- <div
27
- key={stepNumber}
28
- className={`flex items-center ${stepNumber < totalSteps ? 'w-full' : ''}`}
29
- >
30
- <div
31
- className={`
32
- flex items-center justify-center w-10 h-10 rounded-full text-sm font-medium
33
- transition-all duration-200 ease-in-out
34
- ${isActive ? 'bg-indigo-600 text-white ring-4 ring-indigo-100 dark:ring-indigo-900/30 scale-110' : ''}
35
- ${isCompleted ? 'bg-indigo-600 text-white' : ''}
36
- ${isPending ? 'bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-400' : ''}
37
- `}
38
- aria-current={isActive ? 'step' : undefined}
39
- aria-label={`Step ${stepNumber}: ${stepLabels[index]}`}
40
- >
41
- {isCompleted ? (
42
- <svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
43
- <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
44
- </svg>
45
- ) : (
46
- stepNumber
47
- )}
48
- </div>
49
- {stepNumber < totalSteps && (
50
- <div
51
- className={`
52
- flex-1 h-1 mx-2 rounded-full
53
- transition-all duration-200 ease-in-out
54
- ${stepNumber < currentStep ? 'bg-indigo-600' : 'bg-gray-200 dark:bg-gray-700'}
55
- `}
56
- aria-hidden="true"
57
- />
58
- )}
59
- </div>
60
- );
61
- })}
62
- </div>
63
- <div className="flex justify-between mt-3">
64
- {stepLabels.map((label, index) => {
65
- const stepNumber = index + 1;
66
- const isActive = stepNumber === currentStep;
67
- const isCompleted = stepNumber < currentStep;
68
-
69
- return (
70
- <span
71
- key={index}
72
- className={`
73
- text-sm transition-colors duration-200 ease-in-out
74
- ${isActive ? 'text-indigo-600 dark:text-indigo-400 font-medium' : ''}
75
- ${isCompleted ? 'text-gray-700 dark:text-gray-300' : ''}
76
- ${!isActive && !isCompleted ? 'text-gray-500 dark:text-gray-400' : ''}
77
- `}
78
- >
79
- {label}
80
- </span>
81
- );
82
- })}
83
- </div>
84
- </div>
85
- );
86
- }