@portosaur/theme 0.1.0

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 (76) hide show
  1. package/README.md +13 -0
  2. package/assets/img/icon-old.png +0 -0
  3. package/assets/img/icon.png +0 -0
  4. package/assets/img/project-blank.png +0 -0
  5. package/assets/img/social-card.jpeg +0 -0
  6. package/assets/img/svg/icon-blog.svg +2 -0
  7. package/assets/img/svg/icon-close.svg +3 -0
  8. package/assets/img/svg/icon-dock.svg +4 -0
  9. package/assets/img/svg/icon-link.svg +5 -0
  10. package/assets/img/svg/icon-note.svg +2 -0
  11. package/assets/img/svg/icon-popup.svg +1 -0
  12. package/assets/img/svg/icon-save.svg +5 -0
  13. package/assets/img/svg/icon.svg +240 -0
  14. package/assets/img/svg/project-blank.svg +140 -0
  15. package/assets/sample-resume.pdf +0 -0
  16. package/package.json +41 -0
  17. package/plugins/README.md +8 -0
  18. package/src/index.d.ts +11 -0
  19. package/src/index.mjs +14 -0
  20. package/src/plugins/theme.mjs +13 -0
  21. package/theme/DocCategoryGeneratedIndexPage/index.jsx +15 -0
  22. package/theme/MDXComponents.jsx +19 -0
  23. package/theme/README.md +9 -0
  24. package/theme/Root.jsx +11 -0
  25. package/theme/components/AboutSection/index.jsx +264 -0
  26. package/theme/components/AboutSection/styles.module.css +309 -0
  27. package/theme/components/ContactSection/index.jsx +188 -0
  28. package/theme/components/ContactSection/styles.module.css +343 -0
  29. package/theme/components/ExperienceSection/index.jsx +119 -0
  30. package/theme/components/ExperienceSection/styles.module.css +183 -0
  31. package/theme/components/HeroSection/index.jsx +198 -0
  32. package/theme/components/HeroSection/styles.module.css +484 -0
  33. package/theme/components/NavArrow/index.jsx +124 -0
  34. package/theme/components/NavArrow/styles.module.css +107 -0
  35. package/theme/components/NoteIndex/index.jsx +182 -0
  36. package/theme/components/NoteIndex/styles.module.css +167 -0
  37. package/theme/components/Preview/components/FeedbackStates.jsx +200 -0
  38. package/theme/components/Preview/components/FileTabs.jsx +41 -0
  39. package/theme/components/Preview/components/PreviewContent.jsx +104 -0
  40. package/theme/components/Preview/components/PreviewHeader.jsx +411 -0
  41. package/theme/components/Preview/components/Triggers/Pv.jsx +253 -0
  42. package/theme/components/Preview/components/Triggers/SrcPv.jsx +55 -0
  43. package/theme/components/Preview/components/Triggers/index.jsx +2 -0
  44. package/theme/components/Preview/components/ViewerWindow.jsx +489 -0
  45. package/theme/components/Preview/hooks/useAdaptiveSizing.jsx +90 -0
  46. package/theme/components/Preview/hooks/useDeepLinkHash.jsx +24 -0
  47. package/theme/components/Preview/hooks/useDockLayout.jsx +86 -0
  48. package/theme/components/Preview/hooks/useFileFetch.jsx +38 -0
  49. package/theme/components/Preview/hooks/useTouchZoom.jsx +98 -0
  50. package/theme/components/Preview/index.jsx +3 -0
  51. package/theme/components/Preview/renderers/CodeRenderer.jsx +124 -0
  52. package/theme/components/Preview/renderers/ImageRenderer.jsx +74 -0
  53. package/theme/components/Preview/renderers/PdfRenderer.jsx +93 -0
  54. package/theme/components/Preview/renderers/WebRenderer.jsx +59 -0
  55. package/theme/components/Preview/state/index.jsx +177 -0
  56. package/theme/components/Preview/styles.module.css +776 -0
  57. package/theme/components/Preview/utils/index.jsx +62 -0
  58. package/theme/components/ProjectsSection/index.jsx +790 -0
  59. package/theme/components/ProjectsSection/styles.module.css +900 -0
  60. package/theme/components/SocialLinks/index.jsx +115 -0
  61. package/theme/components/SocialLinks/styles.module.css +57 -0
  62. package/theme/components/Tooltip/index.jsx +104 -0
  63. package/theme/components/Tooltip/styles.module.css +168 -0
  64. package/theme/config/iconMappings.jsx +427 -0
  65. package/theme/config/prism.jsx +72 -0
  66. package/theme/config/sidebar.jsx +11 -0
  67. package/theme/css/bootstrap.css +5 -0
  68. package/theme/css/catppuccin.css +618 -0
  69. package/theme/css/custom.css +253 -0
  70. package/theme/css/tasks.css +874 -0
  71. package/theme/hooks/useScrollReveal.jsx +20 -0
  72. package/theme/pages/index.jsx +104 -0
  73. package/theme/pages/notes.jsx +131 -0
  74. package/theme/pages/tasks.jsx +989 -0
  75. package/theme/utils/HashNavigation.jsx +185 -0
  76. package/theme/utils/updateTitle.jsx +65 -0
@@ -0,0 +1,19 @@
1
+ import MDXComponents from "@docusaurus/theme-classic/lib/theme/MDXComponents";
2
+ import Details from "@theme/Details";
3
+ import Tabs from "@theme/Tabs";
4
+ import TabItem from "@theme/TabItem";
5
+ import { Pv, SrcPv } from "./components/Preview/index.js";
6
+ import Tooltip from "./components/Tooltip/index.js";
7
+ import NoteCards, { TopicList } from "./components/NoteIndex/index.js";
8
+ const components = {
9
+ ...MDXComponents,
10
+ Pv,
11
+ SrcPv,
12
+ TopicList,
13
+ NoteCards,
14
+ Details,
15
+ Tabs,
16
+ TabItem,
17
+ Tooltip,
18
+ };
19
+ export default components;
@@ -0,0 +1,9 @@
1
+ # Portosaur Theme Source
2
+
3
+ This is the heart of the Portosaur visual experience. It contains the React components, styles, and MDX configurations that define the look and feel of the site.
4
+
5
+ - **`Root.js`**: The top-level wrapper providing global state (Preview Context).
6
+ - **`MDXComponents.js`**: Maps custom components (`<Pv>`, `<SrcPv>`) so they are available in markdown files without explicit imports.
7
+ - **`components/`**: Modular React components (Navbar, Footer, Previewer, etc.).
8
+ - **`css/`**: Global styles and theme tokens.
9
+ - **`pages/`**: Template pages (Notes index, Tasks index).
package/theme/Root.jsx ADDED
@@ -0,0 +1,11 @@
1
+ import BrowserOnly from "@docusaurus/BrowserOnly";
2
+ import { PreviewProvider, ViewerWindow } from "./components/Preview/index.js";
3
+
4
+ export default function Root({ children }) {
5
+ return (
6
+ <PreviewProvider>
7
+ {children}
8
+ <BrowserOnly>{() => <ViewerWindow />}</BrowserOnly>
9
+ </PreviewProvider>
10
+ );
11
+ }
@@ -0,0 +1,264 @@
1
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
2
+ import useScrollReveal from "../../hooks/useScrollReveal";
3
+ import { FaDownload } from "react-icons/fa";
4
+ import { Pv } from "../Preview/index.js";
5
+ import useBrokenLinks from "@docusaurus/useBrokenLinks";
6
+ import styles from "./styles.module.css";
7
+ export default function AboutSection({ id, className }) {
8
+ const { siteConfig } = useDocusaurusContext();
9
+ const brokenLinks = useBrokenLinks();
10
+ if (id) {
11
+ brokenLinks.collectAnchor(id);
12
+ }
13
+ const { customFields } = siteConfig;
14
+ const aboutMe = customFields.aboutMe || {};
15
+ if (aboutMe.enable === false) return null;
16
+ const [sectionRef, isVisible] = useScrollReveal();
17
+ return jsxDEV_7x81h0kn(
18
+ "div",
19
+ {
20
+ id,
21
+ ref: sectionRef,
22
+ className: `${styles.aboutSection} ${isVisible ? "is-visible" : ""} ${className || ""}`,
23
+ role: "region",
24
+ "aria-label": "About me section",
25
+ children: jsxDEV_7x81h0kn(
26
+ "div",
27
+ {
28
+ className: styles.aboutContainer,
29
+ children: [
30
+ jsxDEV_7x81h0kn(
31
+ "div",
32
+ {
33
+ className: styles.aboutHeader,
34
+ children: jsxDEV_7x81h0kn(
35
+ "h2",
36
+ {
37
+ className: styles.aboutHeading,
38
+ children: aboutMe.heading || "About Me",
39
+ },
40
+ undefined,
41
+ false,
42
+ undefined,
43
+ this,
44
+ ),
45
+ },
46
+ undefined,
47
+ false,
48
+ undefined,
49
+ this,
50
+ ),
51
+ jsxDEV_7x81h0kn(
52
+ "div",
53
+ {
54
+ className: styles.aboutContent,
55
+ children: jsxDEV_7x81h0kn(
56
+ "div",
57
+ {
58
+ className: styles.aboutCard,
59
+ children: [
60
+ jsxDEV_7x81h0kn(
61
+ "div",
62
+ {
63
+ className: styles.bioImageContainer,
64
+ children: [
65
+ aboutMe.image &&
66
+ jsxDEV_7x81h0kn(
67
+ "div",
68
+ {
69
+ className: styles.imageWrapper,
70
+ children: jsxDEV_7x81h0kn(
71
+ "img",
72
+ {
73
+ src: aboutMe.image,
74
+ alt: aboutMe.name || "About Me",
75
+ className: styles.aboutImage,
76
+ },
77
+ undefined,
78
+ false,
79
+ undefined,
80
+ this,
81
+ ),
82
+ },
83
+ undefined,
84
+ false,
85
+ undefined,
86
+ this,
87
+ ),
88
+ aboutMe.resume &&
89
+ jsxDEV_7x81h0kn(
90
+ "div",
91
+ {
92
+ className: styles.resumeContainer,
93
+ children: jsxDEV_7x81h0kn(
94
+ Pv,
95
+ {
96
+ href: aboutMe.resume,
97
+ title: "My Resume",
98
+ children: jsxDEV_7x81h0kn(
99
+ "span",
100
+ {
101
+ className: styles.resumeButton,
102
+ children: [
103
+ jsxDEV_7x81h0kn(
104
+ FaDownload,
105
+ {},
106
+ undefined,
107
+ false,
108
+ undefined,
109
+ this,
110
+ ),
111
+ " View Resume",
112
+ ],
113
+ },
114
+ undefined,
115
+ true,
116
+ undefined,
117
+ this,
118
+ ),
119
+ },
120
+ undefined,
121
+ false,
122
+ undefined,
123
+ this,
124
+ ),
125
+ },
126
+ undefined,
127
+ false,
128
+ undefined,
129
+ this,
130
+ ),
131
+ ],
132
+ },
133
+ undefined,
134
+ true,
135
+ undefined,
136
+ this,
137
+ ),
138
+ jsxDEV_7x81h0kn(
139
+ "div",
140
+ {
141
+ className: styles.bioTextContainer,
142
+ children: [
143
+ jsxDEV_7x81h0kn(
144
+ "div",
145
+ {
146
+ className: styles.bioText,
147
+ children: Array.isArray(aboutMe.bio)
148
+ ? aboutMe.bio.map((paragraph, index) =>
149
+ jsxDEV_7x81h0kn(
150
+ "p",
151
+ {
152
+ className: styles.aboutParagraph,
153
+ children: paragraph,
154
+ },
155
+ index,
156
+ false,
157
+ undefined,
158
+ this,
159
+ ),
160
+ )
161
+ : jsxDEV_7x81h0kn(
162
+ "p",
163
+ {
164
+ className: styles.aboutParagraph,
165
+ children: aboutMe.bio,
166
+ },
167
+ undefined,
168
+ false,
169
+ undefined,
170
+ this,
171
+ ),
172
+ },
173
+ undefined,
174
+ false,
175
+ undefined,
176
+ this,
177
+ ),
178
+ aboutMe.skills &&
179
+ aboutMe.skills.length > 0 &&
180
+ jsxDEV_7x81h0kn(
181
+ "div",
182
+ {
183
+ className: styles.skillsContainer,
184
+ children: [
185
+ jsxDEV_7x81h0kn(
186
+ "h3",
187
+ {
188
+ className: styles.skillsTitle,
189
+ children:
190
+ aboutMe.skillsHeading || "My Skills",
191
+ },
192
+ undefined,
193
+ false,
194
+ undefined,
195
+ this,
196
+ ),
197
+ jsxDEV_7x81h0kn(
198
+ "div",
199
+ {
200
+ className: styles.skillsGrid,
201
+ children: aboutMe.skills.map(
202
+ (skill, index) =>
203
+ jsxDEV_7x81h0kn(
204
+ "span",
205
+ {
206
+ className: styles.skillTag,
207
+ style: {
208
+ animationDelay: `${index * 0.05}s`,
209
+ },
210
+ children: skill,
211
+ },
212
+ index,
213
+ false,
214
+ undefined,
215
+ this,
216
+ ),
217
+ ),
218
+ },
219
+ undefined,
220
+ false,
221
+ undefined,
222
+ this,
223
+ ),
224
+ ],
225
+ },
226
+ undefined,
227
+ true,
228
+ undefined,
229
+ this,
230
+ ),
231
+ ],
232
+ },
233
+ undefined,
234
+ true,
235
+ undefined,
236
+ this,
237
+ ),
238
+ ],
239
+ },
240
+ undefined,
241
+ true,
242
+ undefined,
243
+ this,
244
+ ),
245
+ },
246
+ undefined,
247
+ false,
248
+ undefined,
249
+ this,
250
+ ),
251
+ ],
252
+ },
253
+ undefined,
254
+ true,
255
+ undefined,
256
+ this,
257
+ ),
258
+ },
259
+ undefined,
260
+ false,
261
+ undefined,
262
+ this,
263
+ );
264
+ }
@@ -0,0 +1,309 @@
1
+ /* Animations */
2
+
3
+ @keyframes slideUp {
4
+ from {
5
+ opacity: 0;
6
+ transform: translateY(30px);
7
+ }
8
+ to {
9
+ opacity: 1;
10
+ transform: translateY(0);
11
+ }
12
+ }
13
+
14
+ @keyframes fadeIn {
15
+ from {
16
+ opacity: 0;
17
+ }
18
+ to {
19
+ opacity: 1;
20
+ }
21
+ }
22
+
23
+ @keyframes scaleIn {
24
+ from {
25
+ opacity: 0;
26
+ transform: scale(0.9);
27
+ }
28
+ to {
29
+ opacity: 1;
30
+ transform: scale(1);
31
+ }
32
+ }
33
+
34
+ /* Base Section */
35
+ .aboutSection {
36
+ scroll-margin-top: var(--ifm-scroll-margin-top);
37
+ padding: 2rem 0 4rem;
38
+ background-color: var(--ifm-background-color);
39
+ width: 100%;
40
+ min-height: 100vh;
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ justify-content: flex-start;
45
+ }
46
+
47
+ .aboutContainer {
48
+ max-width: 1100px;
49
+ margin: 0 auto;
50
+ padding: 3rem 2rem 0;
51
+ }
52
+
53
+ .aboutHeader {
54
+ text-align: center;
55
+ margin-bottom: 2.5rem;
56
+ }
57
+
58
+ .aboutHeading {
59
+ font-size: 2.5rem;
60
+ font-weight: 600;
61
+ color: var(--ifm-color-primary);
62
+ margin-bottom: 0.6rem;
63
+ opacity: 0;
64
+ position: relative;
65
+ display: inline-block;
66
+ }
67
+
68
+ :global(.is-visible) .aboutHeading {
69
+ animation: slideUp 0.6s ease-out forwards;
70
+ }
71
+
72
+ .aboutHeading::after {
73
+ content: "";
74
+ position: absolute;
75
+ width: 40px;
76
+ height: 3px;
77
+ bottom: -0.5rem;
78
+ left: 50%;
79
+ transform: translateX(-50%);
80
+ background-color: var(--ifm-color-primary);
81
+ border-radius: 2px;
82
+ }
83
+
84
+ /* The Main Card */
85
+ .aboutCard {
86
+ display: flex;
87
+ background-color: var(--ifm-card-background-color);
88
+ border: 1px solid var(--ifm-color-emphasis-200);
89
+ border-radius: 24px;
90
+ overflow: hidden;
91
+ box-shadow: var(--ifm-global-shadow-md);
92
+ opacity: 0;
93
+ transform: translateY(20px);
94
+ transition: all 0.5s cubic-bezier(0.4, 0, 0.2, 1);
95
+ }
96
+
97
+ :global(.is-visible) .aboutCard {
98
+ animation: slideUp 0.8s ease-out forwards;
99
+ }
100
+
101
+ /* Left Column: Image & Resume */
102
+ .bioImageContainer {
103
+ flex: 0.8;
104
+ background-color: rgba(var(--ifm-color-primary-rgb), 0.03);
105
+ padding: 3rem 2rem;
106
+ display: flex;
107
+ flex-direction: column;
108
+ align-items: center;
109
+ justify-content: center;
110
+ gap: 3.5rem;
111
+ border-right: 1px solid var(--ifm-color-emphasis-200);
112
+ }
113
+
114
+ .imageWrapper {
115
+ width: 200px;
116
+ height: 200px;
117
+ border-radius: 50%;
118
+ padding: 6px;
119
+ background: linear-gradient(
120
+ 135deg,
121
+ var(--ifm-color-primary),
122
+ var(--ifm-color-primary-light)
123
+ );
124
+ box-shadow: 0 10px 30px rgba(var(--ifm-color-primary-rgb), 0.2);
125
+ transition: transform 0.3s ease;
126
+ }
127
+
128
+ .imageWrapper:hover {
129
+ transform: scale(1.05);
130
+ }
131
+
132
+ .aboutImage {
133
+ width: 100%;
134
+ height: 100%;
135
+ object-fit: cover;
136
+ border-radius: 50%;
137
+ border: 4px solid var(--ifm-card-background-color);
138
+ }
139
+
140
+ .resumeContainer {
141
+ width: 100%;
142
+ display: flex;
143
+ justify-content: center;
144
+ }
145
+
146
+ .resumeButton {
147
+ display: inline-flex;
148
+ align-items: center;
149
+ gap: 0.6rem;
150
+ padding: 0.7rem 1.4rem;
151
+ background-color: var(--ifm-color-primary);
152
+ color: var(--ifm-background-color);
153
+ border: 1px solid var(--ifm-color-primary);
154
+ border-radius: 12px;
155
+ font-size: 0.9rem;
156
+ font-weight: 600;
157
+ text-decoration: none !important;
158
+ transition: all 0.2s ease;
159
+ }
160
+
161
+ .resumeButton:hover {
162
+ background-color: var(--ifm-background-surface-color);
163
+ color: var(--ifm-color-primary);
164
+ transform: translateY(-2px);
165
+ box-shadow: 0 5px 15px rgba(var(--ifm-color-primary-rgb), 0.2);
166
+ }
167
+
168
+ /* Right Column: Bio & Skills */
169
+ .bioTextContainer {
170
+ flex: 1.2;
171
+ padding: 3rem;
172
+ display: flex;
173
+ flex-direction: column;
174
+ gap: 0.4rem;
175
+ }
176
+
177
+ .bioText {
178
+ display: flex;
179
+ flex-direction: column;
180
+ gap: 0.8rem;
181
+ max-height: 320px;
182
+ overflow-y: auto;
183
+ padding-right: 1rem;
184
+ }
185
+
186
+ /* Custom Scrollbar for Bio */
187
+ .bioText::-webkit-scrollbar {
188
+ width: 5px;
189
+ }
190
+
191
+ .bioText::-webkit-scrollbar-track {
192
+ background: rgba(var(--ifm-color-primary-rgb), 0.05);
193
+ border-radius: 10px;
194
+ }
195
+
196
+ .bioText::-webkit-scrollbar-thumb {
197
+ background: rgba(var(--ifm-color-primary-rgb), 0.2);
198
+ border-radius: 10px;
199
+ }
200
+
201
+ .bioText::-webkit-scrollbar-thumb:hover {
202
+ background: var(--ifm-color-primary);
203
+ }
204
+
205
+ .aboutParagraph {
206
+ font-size: 1.1rem;
207
+ line-height: 1.4;
208
+ color: var(--ifm-font-color-base);
209
+ margin: 0;
210
+ }
211
+
212
+ /* Skills Grid */
213
+ .skillsContainer {
214
+ margin-top: 1.7rem;
215
+ }
216
+
217
+ .skillsTitle {
218
+ font-size: 1.4rem;
219
+ color: var(--ifm-color-primary);
220
+ margin-bottom: 1.4rem;
221
+ font-weight: 600;
222
+ position: relative;
223
+ display: inline-block;
224
+ }
225
+
226
+ .skillsTitle::after {
227
+ content: "";
228
+ position: absolute;
229
+ width: 30px;
230
+ height: 2px;
231
+ bottom: -0.4rem;
232
+ left: 0;
233
+ background-color: var(--ifm-color-primary);
234
+ border-radius: 1px;
235
+ opacity: 0.6;
236
+ }
237
+
238
+ .skillsGrid {
239
+ display: flex;
240
+ flex-wrap: wrap;
241
+ gap: 0.6rem;
242
+ }
243
+
244
+ .skillTag {
245
+ background-color: var(--ifm-background-surface-color);
246
+ color: var(--ifm-font-color-tertiary);
247
+ padding: 0.4rem 0.8rem;
248
+ border-radius: 8px;
249
+ font-size: 0.8rem;
250
+ font-weight: 600;
251
+ border: 1px solid var(--ifm-color-emphasis-200);
252
+ transition: all 0.2s ease;
253
+ cursor: default;
254
+ }
255
+
256
+ .skillTag:hover {
257
+ border-color: var(--ifm-color-primary);
258
+ color: var(--ifm-color-primary);
259
+ transform: translateY(-2px);
260
+ background-color: rgba(var(--ifm-color-primary-rgb), 0.05);
261
+ }
262
+
263
+ /* Responsive */
264
+ @media (max-width: 992px) {
265
+ .aboutCard {
266
+ flex-direction: column;
267
+ }
268
+
269
+ .bioImageContainer {
270
+ border-right: none;
271
+ border-bottom: 1px solid var(--ifm-color-emphasis-200);
272
+ padding: 2.5rem;
273
+ }
274
+
275
+ .bioTextContainer {
276
+ padding: 2rem;
277
+ }
278
+ }
279
+
280
+ @media (max-width: 768px) {
281
+ .aboutSection {
282
+ padding: 4rem 0;
283
+ }
284
+
285
+ .aboutHeading {
286
+ font-size: 2rem;
287
+ }
288
+
289
+ .imageWrapper {
290
+ width: 160px;
291
+ height: 160px;
292
+ }
293
+
294
+ .aboutParagraph {
295
+ font-size: 1rem;
296
+ }
297
+ }
298
+
299
+ @media (prefers-reduced-motion: reduce) {
300
+ .aboutCard,
301
+ .imageWrapper,
302
+ .resumeButton,
303
+ .skillTag {
304
+ animation: none !important;
305
+ transition: none !important;
306
+ opacity: 1 !important;
307
+ transform: none !important;
308
+ }
309
+ }