@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,115 @@
1
+ import { useState, useEffect, useMemo, useCallback } from "react";
2
+ import styles from "./styles.module.css";
3
+ import { FaQuestionCircle } from "react-icons/fa";
4
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
5
+ import useIsBrowser from "@docusaurus/useIsBrowser";
6
+ import Tooltip from "../Tooltip";
7
+ import { iconMap } from "../../config/iconMappings";
8
+ const DEFAULT_ICON = FaQuestionCircle;
9
+ const DEFAULT_COLOR = "var(--ifm-color-primary)";
10
+ export default function SocialIcons({ showAll = false, links = null }) {
11
+ const { siteConfig } = useDocusaurusContext();
12
+ const { customFields } = siteConfig;
13
+ const isBrowser = useIsBrowser();
14
+ const [animationDelays, setAnimationDelays] = useState({});
15
+ const allSocialLinks = customFields.socialLinks.links || [];
16
+ const socialLinks = useMemo(() => {
17
+ if (links) return links;
18
+ return showAll ? allSocialLinks : allSocialLinks.filter((link) => link.pin);
19
+ }, [allSocialLinks, showAll, links]);
20
+ const calculateDelays = useCallback(() => {
21
+ if (!isBrowser) return {};
22
+ const isTablet = window.innerWidth <= 768;
23
+ const isMobile = window.innerWidth <= 480;
24
+ const delays = {};
25
+ const baseDelay = isMobile ? 0.7 : isTablet ? 0.9 : 1.3;
26
+ const incrementDelay = 0.1;
27
+ socialLinks.forEach((_, index) => {
28
+ delays[index] = `${baseDelay + index * incrementDelay}s`;
29
+ });
30
+ return delays;
31
+ }, [isBrowser, socialLinks]);
32
+ useEffect(() => {
33
+ if (!isBrowser) return;
34
+ setAnimationDelays(calculateDelays());
35
+ const handleResize = () => {
36
+ setAnimationDelays(calculateDelays());
37
+ };
38
+ window.addEventListener("resize", handleResize);
39
+ return () => window.removeEventListener("resize", handleResize);
40
+ }, [isBrowser, calculateDelays]);
41
+ const getIconDetails = (iconName) => {
42
+ if (!iconName) {
43
+ return { icon: DEFAULT_ICON, color: DEFAULT_COLOR };
44
+ }
45
+ const formattedIconName = iconName.toLowerCase();
46
+ const iconDetails = iconMap[formattedIconName];
47
+ if (!iconDetails) {
48
+ return { icon: DEFAULT_ICON, color: DEFAULT_COLOR };
49
+ }
50
+ return {
51
+ icon: iconDetails.icon,
52
+ color: iconDetails.color || DEFAULT_COLOR,
53
+ };
54
+ };
55
+ if (socialLinks.length === 0) {
56
+ return null;
57
+ }
58
+ return jsxDEV_7x81h0kn(
59
+ "div",
60
+ {
61
+ className: styles.socialIcons,
62
+ children: socialLinks.map((social, index) => {
63
+ const { icon: IconComponent, color: iconColor } = getIconDetails(
64
+ social.icon || social.name,
65
+ );
66
+ const href = social.url || "#";
67
+ const displayColor = social.color || iconColor;
68
+ return jsxDEV_7x81h0kn(
69
+ Tooltip,
70
+ {
71
+ msg: social.desc || social.name || social.icon || "Link",
72
+ position: "top",
73
+ bg: displayColor,
74
+ underline: false,
75
+ gap: 17,
76
+ children: jsxDEV_7x81h0kn(
77
+ "a",
78
+ {
79
+ href,
80
+ target: "_blank",
81
+ rel: "noopener noreferrer",
82
+ className: styles.socialLink,
83
+ style: {
84
+ "--hover-color": displayColor,
85
+ animationDelay: animationDelays[index] || "0s",
86
+ },
87
+ "aria-label": social.name || social.icon || "social link",
88
+ children: jsxDEV_7x81h0kn(
89
+ IconComponent,
90
+ { size: 24 },
91
+ undefined,
92
+ false,
93
+ undefined,
94
+ this,
95
+ ),
96
+ },
97
+ undefined,
98
+ false,
99
+ undefined,
100
+ this,
101
+ ),
102
+ },
103
+ index,
104
+ false,
105
+ undefined,
106
+ this,
107
+ );
108
+ }),
109
+ },
110
+ undefined,
111
+ false,
112
+ undefined,
113
+ this,
114
+ );
115
+ }
@@ -0,0 +1,57 @@
1
+ /* Animation */
2
+ @keyframes fadeIn {
3
+ from {
4
+ opacity: 0;
5
+ }
6
+ to {
7
+ opacity: 1;
8
+ }
9
+ }
10
+
11
+ .socialIcons {
12
+ display: flex;
13
+ align-items: center;
14
+ gap: 18px;
15
+ height: 38px;
16
+ }
17
+
18
+ .socialLink {
19
+ display: flex;
20
+ align-items: center;
21
+ justify-content: center;
22
+ color: var(--ifm-color-primary);
23
+ transition:
24
+ color 0.3s,
25
+ transform 0.2s;
26
+ position: relative;
27
+ animation: fadeIn 0.3s ease-out forwards;
28
+ opacity: 0;
29
+ }
30
+
31
+ .socialLink:hover {
32
+ opacity: 0.9;
33
+ transform: translateY(-4px) scale(1.15);
34
+ text-decoration: none;
35
+ color: var(--hover-color, var(--ifm-color-primary-dark));
36
+ }
37
+
38
+ /* Responsive */
39
+ @media (max-width: 768px) {
40
+ .socialIcons {
41
+ justify-content: center;
42
+ width: 100%;
43
+ }
44
+
45
+ .socialLink {
46
+ margin: 0 9px;
47
+ }
48
+ }
49
+
50
+ /* Accessibility */
51
+ @media (prefers-reduced-motion: reduce) {
52
+ .socialLink {
53
+ animation: none !important;
54
+ opacity: 1;
55
+ transition: none;
56
+ }
57
+ }
@@ -0,0 +1,104 @@
1
+ import React, { useState, useRef, useCallback } from "react";
2
+ import { createPortal } from "react-dom";
3
+ import styles from "./styles.module.css";
4
+ export default function Tooltip({
5
+ children,
6
+ msg,
7
+ position = "top",
8
+ color,
9
+ bg,
10
+ underline = true,
11
+ gap = 5,
12
+ shadow,
13
+ className = "",
14
+ }) {
15
+ if (!msg) {
16
+ throw new Error(
17
+ "Tooltip: 'msg' prop is required to display tooltip content.",
18
+ );
19
+ }
20
+ const [isVisible, setIsVisible] = useState(false);
21
+ const [coords, setCoords] = useState({ top: 0, left: 0 });
22
+ const containerRef = useRef(null);
23
+ const tooltipStyle = {
24
+ ...(bg && { "--tooltip-color": bg }),
25
+ ...(color && { "--tooltip-text-color": color }),
26
+ ...(!color &&
27
+ bg && { "--tooltip-text-color": "var(--ifm-font-color-base-inverse)" }),
28
+ ...(shadow && { "--tooltip-shadow": shadow }),
29
+ };
30
+ const show = useCallback(() => {
31
+ if (!containerRef.current || !containerRef.current.children[0]) return;
32
+ const rect = containerRef.current.children[0].getBoundingClientRect();
33
+ const tooltipGap = gap;
34
+ let top, left;
35
+ switch (position) {
36
+ case "bottom":
37
+ top = rect.bottom + tooltipGap;
38
+ left = rect.left + rect.width / 2;
39
+ break;
40
+ case "left":
41
+ top = rect.top + rect.height / 2;
42
+ left = rect.left - tooltipGap;
43
+ break;
44
+ case "right":
45
+ top = rect.top + rect.height / 2;
46
+ left = rect.right + tooltipGap;
47
+ break;
48
+ case "top":
49
+ default:
50
+ top = rect.top - tooltipGap;
51
+ left = rect.left + rect.width / 2;
52
+ break;
53
+ }
54
+ setCoords({ top, left });
55
+ setIsVisible(true);
56
+ }, [position, gap]);
57
+ const hide = useCallback(() => setIsVisible(false), []);
58
+ const tooltip =
59
+ isVisible && typeof document !== "undefined"
60
+ ? createPortal(
61
+ jsxDEV_7x81h0kn(
62
+ "span",
63
+ {
64
+ className: `${styles.tooltip} ${styles[position]}`,
65
+ style: { ...tooltipStyle, top: coords.top, left: coords.left },
66
+ role: "tooltip",
67
+ children: [
68
+ msg,
69
+ jsxDEV_7x81h0kn(
70
+ "span",
71
+ { className: styles.arrow },
72
+ undefined,
73
+ false,
74
+ undefined,
75
+ this,
76
+ ),
77
+ ],
78
+ },
79
+ undefined,
80
+ true,
81
+ undefined,
82
+ this,
83
+ ),
84
+ document.body,
85
+ )
86
+ : null;
87
+ return jsxDEV_7x81h0kn(
88
+ "div",
89
+ {
90
+ ref: containerRef,
91
+ className: `${styles.tooltipContainer} ${underline ? styles.hasUnderline : ""} ${className}`,
92
+ onMouseEnter: show,
93
+ onMouseLeave: hide,
94
+ onFocus: show,
95
+ onBlur: hide,
96
+ style: { display: "contents" },
97
+ children: [children, tooltip],
98
+ },
99
+ undefined,
100
+ true,
101
+ undefined,
102
+ this,
103
+ );
104
+ }
@@ -0,0 +1,168 @@
1
+ .tooltipContainer {
2
+ position: relative;
3
+ display: inline-flex;
4
+ vertical-align: baseline;
5
+ cursor: pointer;
6
+ transition: opacity 0.2s ease;
7
+ }
8
+
9
+ .hasUnderline {
10
+ cursor: help;
11
+ text-decoration: none;
12
+ background-image: radial-gradient(
13
+ circle,
14
+ color-mix(in srgb, var(--ifm-color-primary), transparent 40%) 1px,
15
+ transparent 1.2px
16
+ );
17
+ background-position: bottom;
18
+ background-size: 6px 2.5px;
19
+ background-repeat: space no-repeat;
20
+ padding-bottom: 1px;
21
+ transition: background-image 0.2s ease;
22
+ }
23
+
24
+ .hasUnderline:hover {
25
+ background-image: radial-gradient(
26
+ circle,
27
+ color-mix(in srgb, var(--ifm-color-primary-darker), transparent 10%) 1.2px,
28
+ transparent 1.5px
29
+ );
30
+ }
31
+
32
+ .tooltip {
33
+ position: fixed;
34
+ background-color: var(--tooltip-color, var(--ifm-background-surface-color));
35
+ color: var(--tooltip-text-color, var(--ifm-font-color-base));
36
+ padding: 8px 12px;
37
+ border-radius: var(--ifm-global-radius);
38
+ font-size: 0.85rem;
39
+ font-weight: 450;
40
+ text-align: center;
41
+ line-height: 1.4;
42
+ white-space: normal;
43
+ word-break: break-word;
44
+ overflow-wrap: anywhere;
45
+ max-width: min(240px, 90vw);
46
+ width: max-content;
47
+ z-index: 9999;
48
+ opacity: 0;
49
+ filter: var(
50
+ --tooltip-shadow,
51
+ drop-shadow(0 8px 24px rgba(var(--ifm-color-emphasis-900-rgb), 0.3))
52
+ );
53
+ border: 1px solid var(--ifm-color-emphasis-300);
54
+ pointer-events: none;
55
+ }
56
+
57
+ .top {
58
+ transform: translateX(-50%) translateY(-100%);
59
+ animation: popUp 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
60
+ }
61
+
62
+ .bottom {
63
+ transform: translateX(-50%);
64
+ animation: popDown 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
65
+ }
66
+
67
+ .left {
68
+ transform: translateX(-100%) translateY(-50%);
69
+ animation: popLeft 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
70
+ }
71
+
72
+ .right {
73
+ transform: translateY(-50%);
74
+ animation: popRight 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
75
+ }
76
+
77
+ .arrow {
78
+ position: absolute;
79
+ width: 10px;
80
+ height: 10px;
81
+ background-color: inherit;
82
+ }
83
+
84
+ .top .arrow {
85
+ top: 100%;
86
+ left: 50%;
87
+ transform: translateX(-50%) rotate(45deg);
88
+ margin-top: -5.5px;
89
+ border-right: 1px solid var(--ifm-color-emphasis-300);
90
+ border-bottom: 1px solid var(--ifm-color-emphasis-300);
91
+ }
92
+
93
+ .bottom .arrow {
94
+ bottom: 100%;
95
+ left: 50%;
96
+ transform: translateX(-50%) rotate(45deg);
97
+ margin-bottom: -5.5px;
98
+ border-left: 1px solid var(--ifm-color-emphasis-300);
99
+ border-top: 1px solid var(--ifm-color-emphasis-300);
100
+ }
101
+
102
+ .left .arrow {
103
+ right: -5.5px;
104
+ top: 50%;
105
+ transform: translateY(-50%) rotate(45deg);
106
+ border-right: 1px solid var(--ifm-color-emphasis-300);
107
+ border-top: 1px solid var(--ifm-color-emphasis-300);
108
+ }
109
+
110
+ .right .arrow {
111
+ left: -5.5px;
112
+ top: 50%;
113
+ transform: translateY(-50%) rotate(45deg);
114
+ border-left: 1px solid var(--ifm-color-emphasis-300);
115
+ border-bottom: 1px solid var(--ifm-color-emphasis-300);
116
+ }
117
+
118
+ @keyframes popUp {
119
+ from {
120
+ opacity: 0;
121
+ transform: translateX(-50%) translateY(-95%) scale(0.9);
122
+ }
123
+ to {
124
+ opacity: 1;
125
+ transform: translateX(-50%) translateY(-100%) scale(1);
126
+ }
127
+ }
128
+
129
+ @keyframes popDown {
130
+ from {
131
+ opacity: 0;
132
+ transform: translateX(-50%) translateY(-5%) scale(0.9);
133
+ }
134
+ to {
135
+ opacity: 1;
136
+ transform: translateX(-50%) translateY(0) scale(1);
137
+ }
138
+ }
139
+
140
+ @keyframes popLeft {
141
+ from {
142
+ opacity: 0;
143
+ transform: translateX(-95%) translateY(-50%) scale(0.9);
144
+ }
145
+ to {
146
+ opacity: 1;
147
+ transform: translateX(-100%) translateY(-50%) scale(1);
148
+ }
149
+ }
150
+
151
+ @keyframes popRight {
152
+ from {
153
+ opacity: 0;
154
+ transform: translateX(5%) translateY(-50%) scale(0.9);
155
+ }
156
+ to {
157
+ opacity: 1;
158
+ transform: translateX(0) translateY(-50%) scale(1);
159
+ }
160
+ }
161
+
162
+ /* Accessibility */
163
+ @media (prefers-reduced-motion: reduce) {
164
+ .tooltip {
165
+ animation: none !important;
166
+ opacity: 1;
167
+ }
168
+ }