@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,188 @@
1
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
2
+ import { iconMap } from "../../config/iconMappings";
3
+ import { FaQuestionCircle } from "react-icons/fa";
4
+ import useScrollReveal from "../../hooks/useScrollReveal";
5
+ import useBrokenLinks from "@docusaurus/useBrokenLinks";
6
+ import styles from "./styles.module.css";
7
+ const sortEmail = (links) => {
8
+ return [...links].sort((a, b) => {
9
+ const isEmailA =
10
+ a.url?.startsWith("mailto:") ||
11
+ a.icon?.toLowerCase().includes("email") ||
12
+ a.name?.toLowerCase().includes("email");
13
+ const isEmailB =
14
+ b.url?.startsWith("mailto:") ||
15
+ b.icon?.toLowerCase().includes("email") ||
16
+ b.name?.toLowerCase().includes("email");
17
+ if (isEmailA && !isEmailB) return -1;
18
+ if (!isEmailA && isEmailB) return 1;
19
+ return 0;
20
+ });
21
+ };
22
+ export default function ContactSection({ id, className }) {
23
+ const { siteConfig } = useDocusaurusContext();
24
+ const brokenLinks = useBrokenLinks();
25
+ if (id) {
26
+ brokenLinks.collectAnchor(id);
27
+ }
28
+ const { customFields } = siteConfig;
29
+ const socialLinksConfig = customFields.socialLinks || {};
30
+ if (socialLinksConfig.enable === false) return null;
31
+ let socialLinks = socialLinksConfig.links || [];
32
+ const displayHeading = socialLinksConfig.heading;
33
+ const displaySubheading = socialLinksConfig.subheading;
34
+ const [sectionRef, isVisible] = useScrollReveal();
35
+ socialLinks = sortEmail(socialLinks);
36
+ return jsxDEV_7x81h0kn(
37
+ "div",
38
+ {
39
+ id,
40
+ ref: sectionRef,
41
+ className: `${styles.contactSection} ${isVisible ? "is-visible" : ""} ${className || ""}`,
42
+ role: "region",
43
+ "aria-label": "Contact section",
44
+ children: jsxDEV_7x81h0kn(
45
+ "div",
46
+ {
47
+ className: styles.contactContainer,
48
+ children: [
49
+ jsxDEV_7x81h0kn(
50
+ "div",
51
+ {
52
+ className: styles.contactHeader,
53
+ children: [
54
+ jsxDEV_7x81h0kn(
55
+ "h2",
56
+ {
57
+ className: styles.contactTitle,
58
+ children: displayHeading,
59
+ },
60
+ undefined,
61
+ false,
62
+ undefined,
63
+ this,
64
+ ),
65
+ jsxDEV_7x81h0kn(
66
+ "p",
67
+ {
68
+ className: styles.contactSubtitle,
69
+ children: displaySubheading,
70
+ },
71
+ undefined,
72
+ false,
73
+ undefined,
74
+ this,
75
+ ),
76
+ ],
77
+ },
78
+ undefined,
79
+ true,
80
+ undefined,
81
+ this,
82
+ ),
83
+ jsxDEV_7x81h0kn(
84
+ "div",
85
+ {
86
+ className: styles.gridWrapper,
87
+ children: jsxDEV_7x81h0kn(
88
+ "div",
89
+ {
90
+ className: styles.socialGrid,
91
+ role: "list",
92
+ "aria-label": "Social media and contact links",
93
+ children: socialLinks.map((social, index) => {
94
+ const iconKey = (
95
+ social.icon ||
96
+ social.name ||
97
+ ""
98
+ ).toLowerCase();
99
+ const iconData = iconMap[iconKey] || {};
100
+ const name = social.name;
101
+ const Icon = iconData.icon || FaQuestionCircle;
102
+ const iconColor =
103
+ iconData.color || "var(--ifm-color-primary)";
104
+ const desc = social.desc || `Connect with me on ${name}`;
105
+ const url = social.url;
106
+ return jsxDEV_7x81h0kn(
107
+ "a",
108
+ {
109
+ href: url,
110
+ target: "_blank",
111
+ rel: "noopener noreferrer",
112
+ className: styles.socialCard,
113
+ style: {
114
+ "--card-index": index,
115
+ "--icon-hover-color": iconColor,
116
+ },
117
+ "aria-label": `Connect with me on ${name}: ${desc}`,
118
+ role: "listitem",
119
+ children: [
120
+ Icon &&
121
+ jsxDEV_7x81h0kn(
122
+ "div",
123
+ {
124
+ className: styles.socialIcon,
125
+ children: jsxDEV_7x81h0kn(
126
+ Icon,
127
+ { "aria-hidden": "true" },
128
+ undefined,
129
+ false,
130
+ undefined,
131
+ this,
132
+ ),
133
+ },
134
+ undefined,
135
+ false,
136
+ undefined,
137
+ this,
138
+ ),
139
+ jsxDEV_7x81h0kn(
140
+ "h3",
141
+ { className: styles.socialTitle, children: name },
142
+ undefined,
143
+ false,
144
+ undefined,
145
+ this,
146
+ ),
147
+ jsxDEV_7x81h0kn(
148
+ "p",
149
+ { className: styles.socialDesc, children: desc },
150
+ undefined,
151
+ false,
152
+ undefined,
153
+ this,
154
+ ),
155
+ ],
156
+ },
157
+ name,
158
+ true,
159
+ undefined,
160
+ this,
161
+ );
162
+ }),
163
+ },
164
+ undefined,
165
+ false,
166
+ undefined,
167
+ this,
168
+ ),
169
+ },
170
+ undefined,
171
+ false,
172
+ undefined,
173
+ this,
174
+ ),
175
+ ],
176
+ },
177
+ undefined,
178
+ true,
179
+ undefined,
180
+ this,
181
+ ),
182
+ },
183
+ undefined,
184
+ false,
185
+ undefined,
186
+ this,
187
+ );
188
+ }
@@ -0,0 +1,343 @@
1
+ /* Animations */
2
+ @keyframes fadeIn {
3
+ from {
4
+ opacity: 0;
5
+ transform: translateY(30px);
6
+ }
7
+ to {
8
+ opacity: 1;
9
+ transform: translateY(0);
10
+ }
11
+ }
12
+
13
+ @keyframes slideUp {
14
+ from {
15
+ opacity: 0;
16
+ transform: translateY(30px);
17
+ }
18
+ to {
19
+ opacity: 1;
20
+ transform: translateY(0);
21
+ }
22
+ }
23
+
24
+ /* Contact Section styles */
25
+ .contactSection {
26
+ scroll-margin-top: var(--ifm-scroll-margin-top);
27
+ scroll-margin-top: 90px;
28
+ min-height: calc(100vh - 60px);
29
+ margin-bottom: 0;
30
+ width: 100%;
31
+ padding: 0rem 0 5rem;
32
+ background-color: var(--ifm-background-color);
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ }
37
+
38
+ .contactContainer {
39
+ max-width: 1300px;
40
+ margin: 0 auto;
41
+ padding: 0;
42
+ width: 100%;
43
+ position: relative;
44
+ z-index: 1;
45
+ }
46
+
47
+ .contactHeader {
48
+ text-align: center;
49
+ margin-bottom: 1.5rem;
50
+ margin-top: 0rem;
51
+ }
52
+
53
+ .contactTitle {
54
+ font-size: 2.5rem;
55
+ font-weight: 600;
56
+ color: var(--ifm-color-primary);
57
+ margin-bottom: 0.6rem;
58
+ opacity: 0;
59
+ position: relative;
60
+ display: inline-block;
61
+ }
62
+
63
+ :global(.is-visible) .contactTitle {
64
+ animation: slideUp 0.4s ease-out forwards;
65
+ }
66
+
67
+ .contactSubtitle {
68
+ font-size: 0.95rem;
69
+ color: var(--ifm-font-color-tertiary);
70
+ max-width: 600px;
71
+ margin: 0.05rem auto 0;
72
+ opacity: 0;
73
+ }
74
+
75
+ :global(.is-visible) .contactSubtitle {
76
+ animation: slideUp 0.4s ease-out 0.1s forwards;
77
+ }
78
+
79
+ /* SocialCard */
80
+ .gridWrapper {
81
+ display: flex;
82
+ justify-content: center;
83
+ width: 100%;
84
+ margin-top: 1.2rem;
85
+ }
86
+
87
+ .socialGrid {
88
+ display: flex;
89
+ flex-wrap: wrap;
90
+ gap: 1.2rem;
91
+ justify-content: center;
92
+ margin: 0 auto;
93
+ margin-top: 0.9rem;
94
+ max-width: 1300px;
95
+ width: 100%;
96
+ padding: 0 0.5rem;
97
+ }
98
+
99
+ .socialCard {
100
+ width: 150px;
101
+ min-height: 160px;
102
+ border-radius: var(--ifm-card-border-radius);
103
+ padding: 1.3rem 1.2rem;
104
+ background-color: var(--ifm-card-background-color);
105
+ opacity: 0;
106
+ transition:
107
+ transform 0.3s ease,
108
+ box-shadow 0.3s ease,
109
+ background-color 0.3s ease;
110
+ box-shadow: var(--ifm-global-shadow-lw);
111
+ text-decoration: none;
112
+ display: flex;
113
+ flex-direction: column;
114
+ align-items: center;
115
+ justify-content: flex-start;
116
+ cursor: pointer;
117
+ position: relative;
118
+ --icon-hover-color: var(--ifm-color-primary);
119
+ text-align: center;
120
+ overflow: hidden;
121
+ }
122
+
123
+ :global(.is-visible) .socialCard {
124
+ animation: fadeIn 0.8s ease-out forwards;
125
+ animation-delay: calc(0.3s + (var(--card-index, 0) * 0.1s));
126
+ }
127
+
128
+ .socialCard:hover {
129
+ transform: translateY(-5px);
130
+ box-shadow: var(--ifm-global-shadow-md);
131
+ background-color: var(--ifm-shadow-color);
132
+ text-decoration: none;
133
+ }
134
+
135
+ .socialCard::after {
136
+ content: "";
137
+ position: absolute;
138
+ bottom: 0;
139
+ left: 0;
140
+ width: 0;
141
+ height: 2px;
142
+ background-color: var(--ifm-color-primary);
143
+ transition: width 0.3s ease;
144
+ }
145
+
146
+ .socialCard:hover::after {
147
+ width: 100%;
148
+ }
149
+
150
+ .socialIcon {
151
+ font-size: 3.5rem;
152
+ margin-bottom: 0.3rem;
153
+ color: var(--ifm-color-primary);
154
+ transition:
155
+ color 0.3s ease,
156
+ transform 0.3s ease;
157
+ }
158
+
159
+ .socialCard:hover .socialIcon {
160
+ transform: scale(1.1);
161
+ color: var(--icon-hover-color);
162
+ }
163
+
164
+ .socialTitle {
165
+ font-size: 1.6rem;
166
+ font-weight: 700;
167
+ margin-bottom: 0.5rem;
168
+ color: var(--ifm-color-primary);
169
+ letter-spacing: 0.5px;
170
+ position: relative;
171
+ display: inline-block;
172
+ padding-bottom: 3px;
173
+ }
174
+
175
+ .socialTitle::after {
176
+ content: "";
177
+ position: absolute;
178
+ bottom: 0;
179
+ left: 50%;
180
+ transform: translateX(-50%);
181
+ width: 70px;
182
+ height: 1px;
183
+ background-color: var(--ifm-color-gray-400);
184
+ opacity: 0.15;
185
+ }
186
+
187
+ .socialDesc {
188
+ color: var(--ifm-font-color-tertiary);
189
+ font-size: 0.9rem;
190
+ margin-top: 0.3rem;
191
+ margin-bottom: 0;
192
+ opacity: 0.8;
193
+ text-align: center;
194
+ width: 100%;
195
+ }
196
+
197
+ .socialTitle:hover,
198
+ .socialDesc:hover {
199
+ text-decoration: none;
200
+ }
201
+
202
+ /* Responsive styles */
203
+ @media (max-width: 1200px) {
204
+ .socialCard {
205
+ width: 140px;
206
+ }
207
+
208
+ .socialGrid {
209
+ gap: 1.1rem;
210
+ }
211
+ }
212
+
213
+ @media (max-width: 1024px) {
214
+ .socialCard {
215
+ width: 150px;
216
+ }
217
+
218
+ .socialGrid {
219
+ gap: 1rem;
220
+ max-width: 100%;
221
+ }
222
+ }
223
+
224
+ @media (max-width: 768px) {
225
+ .contactSection {
226
+ scroll-margin-top: 70px;
227
+ padding: 0.5rem 0 4rem;
228
+ }
229
+
230
+ .contactContainer {
231
+ padding: 0;
232
+ }
233
+
234
+ .contactHeader {
235
+ margin-bottom: 1.2rem;
236
+ margin-top: 0rem;
237
+ }
238
+
239
+ .contactTitle {
240
+ font-size: 2.2rem;
241
+ }
242
+
243
+ .contactSubtitle {
244
+ font-size: 0.9rem;
245
+ }
246
+
247
+ .socialCard {
248
+ width: 150px;
249
+ min-height: 150px;
250
+ padding: 1.2rem 1.2rem;
251
+ }
252
+
253
+ .socialIcon {
254
+ font-size: 3rem;
255
+ margin-bottom: 0.25rem;
256
+ }
257
+
258
+ .socialTitle {
259
+ font-size: 1.5rem;
260
+ }
261
+
262
+ .socialGrid {
263
+ padding: 0 1rem;
264
+ }
265
+
266
+ .gridWrapper {
267
+ margin-top: 1rem;
268
+ }
269
+ }
270
+
271
+ @media (max-width: 480px) {
272
+ .contactSection {
273
+ scroll-margin-top: var(--ifm-scroll-margin-top-mobile);
274
+ padding: 0rem 0 3rem;
275
+ }
276
+
277
+ .contactContainer {
278
+ padding: 0;
279
+ }
280
+
281
+ .contactHeader {
282
+ margin-bottom: 1rem;
283
+ margin-top: 0rem;
284
+ }
285
+
286
+ .contactTitle {
287
+ font-size: 1.9rem;
288
+ }
289
+
290
+ .contactSubtitle {
291
+ font-size: 0.9rem;
292
+ max-width: 90%;
293
+ }
294
+
295
+ .socialGrid {
296
+ gap: 1rem;
297
+ padding: 0 0.5rem;
298
+ }
299
+
300
+ .socialCard {
301
+ width: 60px;
302
+ height: 60px;
303
+ min-height: unset;
304
+ padding: 0;
305
+ border-radius: var(--ifm-card-border-radius);
306
+ justify-content: center;
307
+ align-items: center;
308
+ }
309
+
310
+ .socialIcon {
311
+ font-size: 2.5rem;
312
+ margin: 3px 0 0;
313
+ position: relative;
314
+ top: 1.5px;
315
+ }
316
+
317
+ .socialTitle,
318
+ .socialDesc,
319
+ .socialCard::after {
320
+ display: none;
321
+ }
322
+
323
+ .socialCard:hover {
324
+ transform: translateY(-3px) scale(1.05);
325
+ }
326
+
327
+ .gridWrapper {
328
+ margin-top: 0.8rem;
329
+ }
330
+ }
331
+
332
+ @media (prefers-reduced-motion: reduce) {
333
+ .contactTitle,
334
+ .contactSubtitle,
335
+ .socialCard {
336
+ animation: none !important;
337
+ transition: none !important;
338
+ }
339
+
340
+ .socialCard {
341
+ opacity: 1;
342
+ }
343
+ }
@@ -0,0 +1,119 @@
1
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
2
+ import useBrokenLinks from "@docusaurus/useBrokenLinks";
3
+ import styles from "./styles.module.css";
4
+ export default function ExperienceSection({ id, className }) {
5
+ const { siteConfig } = useDocusaurusContext();
6
+ const brokenLinks = useBrokenLinks();
7
+ if (id) {
8
+ brokenLinks.collectAnchor(id);
9
+ }
10
+ const experience = siteConfig.customFields?.experience || {};
11
+ if (experience.enable === false) return null;
12
+ const displayHeading = experience.heading;
13
+ const displaySubheading = experience.subheading;
14
+ return jsxDEV_7x81h0kn(
15
+ "div",
16
+ {
17
+ id,
18
+ className: `${styles.experienceSection} ${className || ""}`,
19
+ role: "region",
20
+ "aria-label": "Experience section",
21
+ children: jsxDEV_7x81h0kn(
22
+ "div",
23
+ {
24
+ className: styles.experienceContainer,
25
+ children: [
26
+ jsxDEV_7x81h0kn(
27
+ "div",
28
+ {
29
+ className: styles.experienceHeader,
30
+ children: [
31
+ jsxDEV_7x81h0kn(
32
+ "h2",
33
+ {
34
+ className: styles.experienceTitle,
35
+ children: displayHeading,
36
+ },
37
+ undefined,
38
+ false,
39
+ undefined,
40
+ this,
41
+ ),
42
+ jsxDEV_7x81h0kn(
43
+ "p",
44
+ {
45
+ className: styles.experienceSubtitle,
46
+ children: displaySubheading,
47
+ },
48
+ undefined,
49
+ false,
50
+ undefined,
51
+ this,
52
+ ),
53
+ ],
54
+ },
55
+ undefined,
56
+ true,
57
+ undefined,
58
+ this,
59
+ ),
60
+ jsxDEV_7x81h0kn(
61
+ "div",
62
+ {
63
+ className: styles.noticeWrapper,
64
+ children: jsxDEV_7x81h0kn(
65
+ "div",
66
+ {
67
+ className: styles.noticeBox,
68
+ role: "status",
69
+ "aria-live": "polite",
70
+ children: [
71
+ jsxDEV_7x81h0kn(
72
+ "p",
73
+ {
74
+ className: styles.noticeText,
75
+ children: "Coming Soon!",
76
+ },
77
+ undefined,
78
+ false,
79
+ undefined,
80
+ this,
81
+ ),
82
+ jsxDEV_7x81h0kn(
83
+ "p",
84
+ {
85
+ className: styles.noticeDesc,
86
+ children: "This section is under construction.",
87
+ },
88
+ undefined,
89
+ false,
90
+ undefined,
91
+ this,
92
+ ),
93
+ ],
94
+ },
95
+ undefined,
96
+ true,
97
+ undefined,
98
+ this,
99
+ ),
100
+ },
101
+ undefined,
102
+ false,
103
+ undefined,
104
+ this,
105
+ ),
106
+ ],
107
+ },
108
+ undefined,
109
+ true,
110
+ undefined,
111
+ this,
112
+ ),
113
+ },
114
+ undefined,
115
+ false,
116
+ undefined,
117
+ this,
118
+ );
119
+ }