@tantainnovative/ndpr-toolkit 1.0.1 → 1.0.3

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 (212) hide show
  1. package/.claude/settings.local.json +20 -0
  2. package/.eslintrc.json +10 -0
  3. package/.github/workflows/ci.yml +36 -0
  4. package/.github/workflows/nextjs.yml +104 -0
  5. package/.husky/commit-msg +4 -0
  6. package/.husky/pre-commit +4 -0
  7. package/.lintstagedrc.js +4 -0
  8. package/.nvmrc +1 -0
  9. package/.versionrc +17 -0
  10. package/CHANGELOG.md +16 -0
  11. package/CLAUDE.md +90 -0
  12. package/CNAME +1 -0
  13. package/CONTRIBUTING.md +87 -0
  14. package/README.md +84 -431
  15. package/RELEASE-NOTES-v1.0.0.md +140 -0
  16. package/RELEASE-NOTES-v1.0.1.md +69 -0
  17. package/SECURITY.md +21 -0
  18. package/commitlint.config.js +36 -0
  19. package/components.json +21 -0
  20. package/eslint.config.mjs +16 -0
  21. package/jest.config.js +31 -0
  22. package/jest.setup.js +15 -0
  23. package/next.config.js +15 -0
  24. package/next.config.ts +62 -0
  25. package/package.json +70 -52
  26. package/packages/ndpr-toolkit/README.md +467 -0
  27. package/packages/ndpr-toolkit/jest.config.js +23 -0
  28. package/packages/ndpr-toolkit/package-lock.json +8197 -0
  29. package/packages/ndpr-toolkit/package.json +71 -0
  30. package/packages/ndpr-toolkit/rollup.config.js +34 -0
  31. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentBanner.test.tsx +119 -0
  32. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentManager.test.tsx +122 -0
  33. package/packages/ndpr-toolkit/src/__tests__/components/consent/ConsentStorage.test.tsx +270 -0
  34. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRDashboard.test.tsx +199 -0
  35. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRRequestForm.test.tsx +224 -0
  36. package/packages/ndpr-toolkit/src/__tests__/components/dsr/DSRTracker.test.tsx +104 -0
  37. package/packages/ndpr-toolkit/src/__tests__/hooks/useConsent.test.tsx +161 -0
  38. package/packages/ndpr-toolkit/src/__tests__/hooks/useDSR.test.tsx +330 -0
  39. package/packages/ndpr-toolkit/src/__tests__/utils/breach.test.ts +149 -0
  40. package/packages/ndpr-toolkit/src/__tests__/utils/consent.test.ts +88 -0
  41. package/packages/ndpr-toolkit/src/__tests__/utils/dpia.test.ts +160 -0
  42. package/packages/ndpr-toolkit/src/__tests__/utils/dsr.test.ts +110 -0
  43. package/packages/ndpr-toolkit/src/__tests__/utils/privacy.test.ts +97 -0
  44. package/packages/ndpr-toolkit/src/components/breach/BreachNotificationManager.tsx +701 -0
  45. package/packages/ndpr-toolkit/src/components/breach/BreachReportForm.tsx +631 -0
  46. package/packages/ndpr-toolkit/src/components/breach/BreachRiskAssessment.tsx +569 -0
  47. package/packages/ndpr-toolkit/src/components/breach/RegulatoryReportGenerator.tsx +496 -0
  48. package/packages/ndpr-toolkit/src/components/consent/ConsentBanner.tsx +270 -0
  49. package/packages/ndpr-toolkit/src/components/consent/ConsentManager.tsx +217 -0
  50. package/packages/ndpr-toolkit/src/components/consent/ConsentStorage.tsx +206 -0
  51. package/packages/ndpr-toolkit/src/components/dpia/DPIAQuestionnaire.tsx +342 -0
  52. package/packages/ndpr-toolkit/src/components/dpia/DPIAReport.tsx +373 -0
  53. package/packages/ndpr-toolkit/src/components/dpia/StepIndicator.tsx +174 -0
  54. package/packages/ndpr-toolkit/src/components/dsr/DSRDashboard.tsx +717 -0
  55. package/packages/ndpr-toolkit/src/components/dsr/DSRRequestForm.tsx +476 -0
  56. package/packages/ndpr-toolkit/src/components/dsr/DSRTracker.tsx +620 -0
  57. package/packages/ndpr-toolkit/src/components/policy/PolicyExporter.tsx +541 -0
  58. package/packages/ndpr-toolkit/src/components/policy/PolicyGenerator.tsx +454 -0
  59. package/packages/ndpr-toolkit/src/components/policy/PolicyPreview.tsx +333 -0
  60. package/packages/ndpr-toolkit/src/hooks/useBreach.ts +409 -0
  61. package/packages/ndpr-toolkit/src/hooks/useConsent.ts +263 -0
  62. package/packages/ndpr-toolkit/src/hooks/useDPIA.ts +457 -0
  63. package/packages/ndpr-toolkit/src/hooks/useDSR.ts +236 -0
  64. package/packages/ndpr-toolkit/src/hooks/usePrivacyPolicy.ts +428 -0
  65. package/{dist/index.d.ts → packages/ndpr-toolkit/src/index.ts} +14 -1
  66. package/packages/ndpr-toolkit/src/setupTests.ts +5 -0
  67. package/packages/ndpr-toolkit/src/types/breach.ts +283 -0
  68. package/packages/ndpr-toolkit/src/types/consent.ts +111 -0
  69. package/packages/ndpr-toolkit/src/types/dpia.ts +236 -0
  70. package/packages/ndpr-toolkit/src/types/dsr.ts +192 -0
  71. package/packages/ndpr-toolkit/src/types/index.ts +42 -0
  72. package/packages/ndpr-toolkit/src/types/privacy.ts +246 -0
  73. package/packages/ndpr-toolkit/src/utils/breach.ts +122 -0
  74. package/packages/ndpr-toolkit/src/utils/consent.ts +51 -0
  75. package/packages/ndpr-toolkit/src/utils/dpia.ts +104 -0
  76. package/packages/ndpr-toolkit/src/utils/dsr.ts +77 -0
  77. package/packages/ndpr-toolkit/src/utils/privacy.ts +100 -0
  78. package/packages/ndpr-toolkit/tsconfig.json +23 -0
  79. package/postcss.config.mjs +5 -0
  80. package/public/NDPR TOOLKIT.svg +1 -0
  81. package/public/favicon/android-chrome-192x192.png +0 -0
  82. package/public/favicon/android-chrome-512x512.png +0 -0
  83. package/public/favicon/apple-touch-icon.png +0 -0
  84. package/public/favicon/favicon-16x16.png +0 -0
  85. package/public/favicon/favicon-32x32.png +0 -0
  86. package/public/favicon/site.webmanifest +1 -0
  87. package/public/file.svg +1 -0
  88. package/public/globe.svg +1 -0
  89. package/public/ndpr-toolkit-logo.svg +108 -0
  90. package/public/next.svg +1 -0
  91. package/public/vercel.svg +1 -0
  92. package/public/window.svg +1 -0
  93. package/src/__tests__/example.test.ts +13 -0
  94. package/src/__tests__/requestService.test.ts +57 -0
  95. package/src/app/accessibility.css +70 -0
  96. package/src/app/docs/components/DocLayout.tsx +267 -0
  97. package/src/app/docs/components/breach-notification/page.tsx +797 -0
  98. package/src/app/docs/components/consent-management/page.tsx +576 -0
  99. package/src/app/docs/components/data-subject-rights/page.tsx +511 -0
  100. package/src/app/docs/components/dpia-questionnaire/layout.tsx +15 -0
  101. package/src/app/docs/components/dpia-questionnaire/metadata.ts +31 -0
  102. package/src/app/docs/components/dpia-questionnaire/page.tsx +666 -0
  103. package/src/app/docs/components/hooks/page.tsx +305 -0
  104. package/src/app/docs/components/page.tsx +84 -0
  105. package/src/app/docs/components/privacy-policy-generator/page.tsx +634 -0
  106. package/src/app/docs/guides/breach-notification-process/components/BestPractices.tsx +123 -0
  107. package/src/app/docs/guides/breach-notification-process/components/ImplementationSteps.tsx +328 -0
  108. package/src/app/docs/guides/breach-notification-process/components/Introduction.tsx +28 -0
  109. package/src/app/docs/guides/breach-notification-process/components/NotificationTimeline.tsx +91 -0
  110. package/src/app/docs/guides/breach-notification-process/components/Resources.tsx +118 -0
  111. package/src/app/docs/guides/breach-notification-process/page.tsx +39 -0
  112. package/src/app/docs/guides/conducting-dpia/page.tsx +593 -0
  113. package/src/app/docs/guides/data-subject-requests/page.tsx +666 -0
  114. package/src/app/docs/guides/managing-consent/page.tsx +738 -0
  115. package/src/app/docs/guides/ndpr-compliance-checklist/components/ComplianceChecklist.tsx +296 -0
  116. package/src/app/docs/guides/ndpr-compliance-checklist/components/ImplementationTools.tsx +145 -0
  117. package/src/app/docs/guides/ndpr-compliance-checklist/components/Introduction.tsx +33 -0
  118. package/src/app/docs/guides/ndpr-compliance-checklist/components/KeyRequirements.tsx +99 -0
  119. package/src/app/docs/guides/ndpr-compliance-checklist/components/Resources.tsx +159 -0
  120. package/src/app/docs/guides/ndpr-compliance-checklist/page.tsx +38 -0
  121. package/src/app/docs/guides/page.tsx +67 -0
  122. package/src/app/docs/layout.tsx +15 -0
  123. package/src/app/docs/metadata.ts +31 -0
  124. package/src/app/docs/page.tsx +572 -0
  125. package/src/app/favicon.ico +0 -0
  126. package/src/app/globals.css +123 -0
  127. package/src/app/layout.tsx +37 -0
  128. package/src/app/ndpr-demos/breach/page.tsx +354 -0
  129. package/src/app/ndpr-demos/consent/page.tsx +366 -0
  130. package/src/app/ndpr-demos/dpia/page.tsx +495 -0
  131. package/src/app/ndpr-demos/dsr/page.tsx +280 -0
  132. package/src/app/ndpr-demos/page.tsx +73 -0
  133. package/src/app/ndpr-demos/policy/page.tsx +771 -0
  134. package/src/app/page.tsx +452 -0
  135. package/src/components/ErrorBoundary.tsx +90 -0
  136. package/src/components/breach-notification/BreachNotificationForm.tsx +479 -0
  137. package/src/components/consent/ConsentBanner.tsx +159 -0
  138. package/src/components/data-subject-rights/DataSubjectRequestForm.tsx +419 -0
  139. package/src/components/docs/DocLayout.tsx +289 -0
  140. package/src/components/docs/index.ts +2 -0
  141. package/src/components/dpia/DPIAQuestionnaire.tsx +483 -0
  142. package/src/components/privacy-policy/PolicyGenerator.tsx +1062 -0
  143. package/src/components/privacy-policy/data.ts +98 -0
  144. package/src/components/privacy-policy/shared/CheckboxField.tsx +38 -0
  145. package/src/components/privacy-policy/shared/CheckboxGroup.tsx +85 -0
  146. package/src/components/privacy-policy/shared/FormField.tsx +79 -0
  147. package/src/components/privacy-policy/shared/StepIndicator.tsx +86 -0
  148. package/src/components/privacy-policy/steps/CustomSectionsStep.tsx +335 -0
  149. package/src/components/privacy-policy/steps/DataCollectionStep.tsx +231 -0
  150. package/src/components/privacy-policy/steps/DataSharingStep.tsx +418 -0
  151. package/src/components/privacy-policy/steps/OrganizationInfoStep.tsx +202 -0
  152. package/src/components/privacy-policy/steps/PolicyPreviewStep.tsx +172 -0
  153. package/src/components/ui/Badge.tsx +46 -0
  154. package/src/components/ui/Button.tsx +59 -0
  155. package/src/components/ui/Card.tsx +92 -0
  156. package/src/components/ui/Checkbox.tsx +57 -0
  157. package/src/components/ui/FormField.tsx +50 -0
  158. package/src/components/ui/Input.tsx +38 -0
  159. package/src/components/ui/Loading.tsx +201 -0
  160. package/src/components/ui/Select.tsx +42 -0
  161. package/src/components/ui/TextArea.tsx +38 -0
  162. package/src/components/ui/label.tsx +24 -0
  163. package/src/components/ui/switch.tsx +31 -0
  164. package/src/components/ui/tabs.tsx +66 -0
  165. package/src/hooks/useConsent.ts +64 -0
  166. package/src/hooks/useLoadingState.ts +85 -0
  167. package/src/lib/consentService.ts +137 -0
  168. package/src/lib/dpiaQuestions.ts +148 -0
  169. package/src/lib/requestService.ts +75 -0
  170. package/src/lib/sanitize.ts +108 -0
  171. package/src/lib/storage.ts +222 -0
  172. package/src/lib/utils.ts +6 -0
  173. package/src/types/html-to-docx.d.ts +30 -0
  174. package/src/types/index.ts +72 -0
  175. package/tailwind.config.ts +65 -0
  176. package/tsconfig.json +41 -0
  177. package/dist/components/breach/BreachNotificationManager.d.ts +0 -62
  178. package/dist/components/breach/BreachReportForm.d.ts +0 -66
  179. package/dist/components/breach/BreachRiskAssessment.d.ts +0 -50
  180. package/dist/components/breach/RegulatoryReportGenerator.d.ts +0 -94
  181. package/dist/components/consent/ConsentBanner.d.ts +0 -79
  182. package/dist/components/consent/ConsentManager.d.ts +0 -73
  183. package/dist/components/consent/ConsentStorage.d.ts +0 -41
  184. package/dist/components/dpia/DPIAQuestionnaire.d.ts +0 -70
  185. package/dist/components/dpia/DPIAReport.d.ts +0 -40
  186. package/dist/components/dpia/StepIndicator.d.ts +0 -64
  187. package/dist/components/dsr/DSRDashboard.d.ts +0 -58
  188. package/dist/components/dsr/DSRRequestForm.d.ts +0 -74
  189. package/dist/components/dsr/DSRTracker.d.ts +0 -56
  190. package/dist/components/policy/PolicyExporter.d.ts +0 -65
  191. package/dist/components/policy/PolicyGenerator.d.ts +0 -54
  192. package/dist/components/policy/PolicyPreview.d.ts +0 -71
  193. package/dist/hooks/useBreach.d.ts +0 -97
  194. package/dist/hooks/useConsent.d.ts +0 -63
  195. package/dist/hooks/useDPIA.d.ts +0 -92
  196. package/dist/hooks/useDSR.d.ts +0 -72
  197. package/dist/hooks/usePrivacyPolicy.d.ts +0 -87
  198. package/dist/index.esm.js +0 -2
  199. package/dist/index.esm.js.map +0 -1
  200. package/dist/index.js +0 -2
  201. package/dist/index.js.map +0 -1
  202. package/dist/setupTests.d.ts +0 -2
  203. package/dist/types/breach.d.ts +0 -239
  204. package/dist/types/consent.d.ts +0 -95
  205. package/dist/types/dpia.d.ts +0 -196
  206. package/dist/types/dsr.d.ts +0 -162
  207. package/dist/types/privacy.d.ts +0 -204
  208. package/dist/utils/breach.d.ts +0 -14
  209. package/dist/utils/consent.d.ts +0 -10
  210. package/dist/utils/dpia.d.ts +0 -12
  211. package/dist/utils/dsr.d.ts +0 -11
  212. package/dist/utils/privacy.d.ts +0 -12
@@ -0,0 +1,289 @@
1
+ 'use client';
2
+
3
+ import React, { useState } from 'react';
4
+ import Link from 'next/link';
5
+ import { usePathname } from 'next/navigation';
6
+ import { Button } from '@/components/ui/Button';
7
+
8
+ type NavItem = {
9
+ title: string;
10
+ href: string;
11
+ icon?: React.ReactNode;
12
+ children?: NavItem[];
13
+ };
14
+
15
+ type DocLayoutProps = {
16
+ children: React.ReactNode;
17
+ title: string;
18
+ description?: string;
19
+ };
20
+
21
+ const navigation: NavItem[] = [
22
+ {
23
+ title: 'Getting Started',
24
+ href: '/docs',
25
+ icon: (
26
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
27
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 10V3L4 14h7v7l9-11h-7z" />
28
+ </svg>
29
+ ),
30
+ },
31
+ {
32
+ title: 'Components',
33
+ href: '/docs/components',
34
+ icon: (
35
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
36
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2V6zM14 6a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2V6zM4 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2H6a2 2 0 01-2-2v-2zM14 16a2 2 0 012-2h2a2 2 0 012 2v2a2 2 0 01-2 2h-2a2 2 0 01-2-2v-2z" />
37
+ </svg>
38
+ ),
39
+ children: [
40
+ { title: 'DPIA Questionnaire', href: '/docs/components/dpia-questionnaire' },
41
+ { title: 'Consent Management', href: '/docs/components/consent-management' },
42
+ { title: 'Data Subject Rights', href: '/docs/components/data-subject-rights' },
43
+ { title: 'Breach Notification', href: '/docs/components/breach-notification' },
44
+ { title: 'Privacy Policy Generator', href: '/docs/components/privacy-policy-generator' },
45
+ ],
46
+ },
47
+ {
48
+ title: 'Implementation Guides',
49
+ href: '/docs/guides',
50
+ icon: (
51
+ <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
52
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253" />
53
+ </svg>
54
+ ),
55
+ children: [
56
+ { title: 'NDPR Compliance Checklist', href: '/docs/guides/ndpr-compliance-checklist' },
57
+ { title: 'Conducting a DPIA', href: '/docs/guides/conducting-dpia' },
58
+ { title: 'Managing Consent', href: '/docs/guides/managing-consent' },
59
+ { title: 'Handling Data Subject Requests', href: '/docs/guides/data-subject-requests' },
60
+ { title: 'Breach Notification Process', href: '/docs/guides/breach-notification-process' },
61
+ ],
62
+ },
63
+ // {
64
+ // title: 'API Reference',
65
+ // href: '#',
66
+ // icon: (
67
+ // <svg className="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
68
+ // <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 20l4-16m4 4l4 4-4 4M6 16l-4-4 4-4" />
69
+ // </svg>
70
+ // ),
71
+ // },
72
+ ];
73
+
74
+ export function DocLayout({ children, title, description }: DocLayoutProps) {
75
+ const pathname = usePathname();
76
+ const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
77
+
78
+ // Function to check if a nav item is active
79
+ const isActive = (href: string) => {
80
+ if (href === '/docs' && pathname === '/docs') {
81
+ return true;
82
+ }
83
+ return pathname !== '/docs' && pathname.startsWith(href);
84
+ };
85
+
86
+ // Function to check if a nav item should be expanded
87
+ const shouldExpand = (item: NavItem) => {
88
+ if (!item.children) return false;
89
+ return item.children.some(child => pathname === child.href || pathname.startsWith(child.href));
90
+ };
91
+
92
+ return (
93
+ <div className="min-h-screen bg-gray-50 dark:bg-gray-900">
94
+ {/* Mobile menu button */}
95
+ <div className="lg:hidden fixed top-4 left-4 z-50">
96
+ <button
97
+ type="button"
98
+ className="p-2 rounded-md text-gray-500 hover:text-gray-600 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-300 dark:hover:bg-gray-800"
99
+ onClick={() => setMobileMenuOpen(!mobileMenuOpen)}
100
+ >
101
+ <span className="sr-only">Open sidebar</span>
102
+ {mobileMenuOpen ? (
103
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
104
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
105
+ </svg>
106
+ ) : (
107
+ <svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
108
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16M4 18h16" />
109
+ </svg>
110
+ )}
111
+ </button>
112
+ </div>
113
+
114
+ {/* Sidebar for desktop */}
115
+ <div className="hidden lg:flex lg:w-64 lg:flex-col lg:fixed lg:inset-y-0">
116
+ <div className="flex flex-col flex-grow bg-white dark:bg-gray-800 shadow-lg overflow-y-auto">
117
+ <div className="flex items-center flex-shrink-0 px-4 py-5 border-b border-gray-200 dark:border-gray-700">
118
+ <Link href="/" className="flex items-center">
119
+ <span className="text-xl font-semibold text-gray-900 dark:text-white">NDPR Toolkit</span>
120
+ </Link>
121
+ </div>
122
+ <div className="mt-5 flex-1 flex flex-col">
123
+ <nav className="flex-1 px-4 space-y-1">
124
+ {navigation.map((item) => (
125
+ <div key={item.title} className="py-1">
126
+ <Link
127
+ href={item.href}
128
+ className={`group flex items-center px-3 py-2 text-sm font-medium rounded-md ${
129
+ isActive(item.href)
130
+ ? 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-200'
131
+ : 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'
132
+ }`}
133
+ >
134
+ {item.icon && (
135
+ <span className={`mr-3 ${isActive(item.href) ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 dark:text-gray-400'}`}>
136
+ {item.icon}
137
+ </span>
138
+ )}
139
+ {item.title}
140
+ </Link>
141
+ {item.children && shouldExpand(item) && (
142
+ <div className="mt-1 ml-8 space-y-1">
143
+ {item.children.map((child) => (
144
+ <Link
145
+ key={child.title}
146
+ href={child.href}
147
+ className={`group flex items-center px-3 py-2 text-sm font-medium rounded-md ${
148
+ pathname === child.href
149
+ ? 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-200'
150
+ : 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'
151
+ }`}
152
+ >
153
+ {child.title}
154
+ {pathname === child.href && (
155
+ <span className="ml-auto">
156
+ <svg className="h-4 w-4 text-blue-500 dark:text-blue-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
157
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
158
+ </svg>
159
+ </span>
160
+ )}
161
+ </Link>
162
+ ))}
163
+ </div>
164
+ )}
165
+ </div>
166
+ ))}
167
+ </nav>
168
+ </div>
169
+ <div className="p-4 border-t border-gray-200 dark:border-gray-700">
170
+ <Button asChild variant="outline" size="sm" className="w-full">
171
+ <a href="https://github.com/tantainnovative/ndpr-toolkit" target="_blank" rel="noopener noreferrer" className="flex items-center">
172
+ <svg className="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 24 24">
173
+ <path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
174
+ </svg>
175
+ GitHub
176
+ </a>
177
+ </Button>
178
+ </div>
179
+ </div>
180
+ </div>
181
+
182
+ {/* Mobile menu, show/hide based on menu state */}
183
+ <div
184
+ className={`lg:hidden fixed inset-0 z-40 ${mobileMenuOpen ? 'block' : 'hidden'}`}
185
+ aria-hidden="true"
186
+ >
187
+ <div className="fixed inset-0 bg-gray-600 bg-opacity-75" onClick={() => setMobileMenuOpen(false)}></div>
188
+ <div className="fixed inset-y-0 left-0 max-w-xs w-full bg-white dark:bg-gray-800 shadow-lg overflow-y-auto">
189
+ <div className="flex items-center justify-between px-4 py-5 border-b border-gray-200 dark:border-gray-700">
190
+ <Link href="/" className="flex items-center" onClick={() => setMobileMenuOpen(false)}>
191
+ <span className="text-xl font-semibold text-gray-900 dark:text-white">NDPR Toolkit</span>
192
+ </Link>
193
+ <button
194
+ type="button"
195
+ className="ml-1 flex items-center justify-center h-10 w-10 rounded-full focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white"
196
+ onClick={() => setMobileMenuOpen(false)}
197
+ >
198
+ <span className="sr-only">Close sidebar</span>
199
+ <svg className="h-6 w-6 text-gray-500 dark:text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
200
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
201
+ </svg>
202
+ </button>
203
+ </div>
204
+ <div className="mt-5 flex-1 flex flex-col">
205
+ <nav className="flex-1 px-4 space-y-1">
206
+ {navigation.map((item) => (
207
+ <div key={item.title} className="py-1">
208
+ <Link
209
+ href={item.href}
210
+ className={`group flex items-center px-3 py-2 text-sm font-medium rounded-md ${
211
+ isActive(item.href)
212
+ ? 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-200'
213
+ : 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'
214
+ }`}
215
+ onClick={() => setMobileMenuOpen(false)}
216
+ >
217
+ {item.icon && (
218
+ <span className={`mr-3 ${isActive(item.href) ? 'text-blue-500 dark:text-blue-400' : 'text-gray-500 dark:text-gray-400'}`}>
219
+ {item.icon}
220
+ </span>
221
+ )}
222
+ {item.title}
223
+ </Link>
224
+ {item.children && shouldExpand(item) && (
225
+ <div className="mt-1 ml-8 space-y-1">
226
+ {item.children.map((child) => (
227
+ <Link
228
+ key={child.title}
229
+ href={child.href}
230
+ className={`group flex items-center px-3 py-2 text-sm font-medium rounded-md ${
231
+ pathname === child.href
232
+ ? 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-200'
233
+ : 'text-gray-700 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700'
234
+ }`}
235
+ onClick={() => setMobileMenuOpen(false)}
236
+ >
237
+ {child.title}
238
+ </Link>
239
+ ))}
240
+ </div>
241
+ )}
242
+ </div>
243
+ ))}
244
+ </nav>
245
+ </div>
246
+ <div className="p-4 border-t border-gray-200 dark:border-gray-700">
247
+ <Button asChild variant="outline" size="sm" className="w-full">
248
+ <a href="https://github.com/tantainnovative/ndpr-toolkit" target="_blank" rel="noopener noreferrer" className="flex items-center">
249
+ <svg className="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 24 24">
250
+ <path fillRule="evenodd" d="M12 2C6.477 2 2 6.484 2 12.017c0 4.425 2.865 8.18 6.839 9.504.5.092.682-.217.682-.483 0-.237-.008-.868-.013-1.703-2.782.605-3.369-1.343-3.369-1.343-.454-1.158-1.11-1.466-1.11-1.466-.908-.62.069-.608.069-.608 1.003.07 1.531 1.032 1.531 1.032.892 1.53 2.341 1.088 2.91.832.092-.647.35-1.088.636-1.338-2.22-.253-4.555-1.113-4.555-4.951 0-1.093.39-1.988 1.029-2.688-.103-.253-.446-1.272.098-2.65 0 0 .84-.27 2.75 1.026A9.564 9.564 0 0112 6.844c.85.004 1.705.115 2.504.337 1.909-1.296 2.747-1.027 2.747-1.027.546 1.379.202 2.398.1 2.651.64.7 1.028 1.595 1.028 2.688 0 3.848-2.339 4.695-4.566 4.943.359.309.678.92.678 1.855 0 1.338-.012 2.419-.012 2.747 0 .268.18.58.688.482A10.019 10.019 0 0022 12.017C22 6.484 17.522 2 12 2z" clipRule="evenodd" />
251
+ </svg>
252
+ GitHub
253
+ </a>
254
+ </Button>
255
+ </div>
256
+ </div>
257
+ </div>
258
+
259
+ {/* Main content */}
260
+ <div className="lg:pl-64">
261
+ <main className="py-10">
262
+ <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
263
+ <div className="pb-5 border-b border-gray-200 dark:border-gray-700 mb-6">
264
+ <div className="flex flex-col md:flex-row md:items-center md:justify-between">
265
+ <div>
266
+ <h1 className="text-3xl font-bold text-gray-900 dark:text-white">{title}</h1>
267
+ {description && <p className="mt-2 text-lg text-gray-500 dark:text-gray-400">{description}</p>}
268
+ </div>
269
+ <div className="mt-4 md:mt-0 flex space-x-3">
270
+ <Button asChild variant="outline" size="sm">
271
+ <Link href="/ndpr-demos">View Demos</Link>
272
+ </Button>
273
+ <Button asChild variant="default" size="sm">
274
+ <Link href="/">Back to Home</Link>
275
+ </Button>
276
+ </div>
277
+ </div>
278
+ </div>
279
+
280
+ {/* Page content */}
281
+ <div className="prose prose-blue max-w-none dark:prose-invert">
282
+ {children}
283
+ </div>
284
+ </div>
285
+ </main>
286
+ </div>
287
+ </div>
288
+ );
289
+ }
@@ -0,0 +1,2 @@
1
+ // Re-export DocLayout for easier imports
2
+ export * from './DocLayout';