Skip to content

Commit be204bb

Browse files
committed
Add frontend view to show frameworks
1 parent e0a0993 commit be204bb

File tree

16 files changed

+335
-25
lines changed

16 files changed

+335
-25
lines changed

public/consolidated/_index.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,12 @@
3737
{
3838
"name": "JAVASCRIPT",
3939
"icon": "/icons/javascript.svg",
40-
"subLanguages": []
40+
"subLanguages": [
41+
{
42+
"name": "REACT",
43+
"icon": "/icons/javascript--react.svg"
44+
}
45+
]
4146
},
4247
{
4348
"name": "PYTHON",

public/consolidated/cpp.json

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
]
3434
},
3535
{
36-
"categoryName": "Debuging",
3736
"name": "Debugging",
3837
"snippets": [
3938
{
@@ -50,6 +49,23 @@
5049
}
5150
]
5251
},
52+
{
53+
"name": "Debuging",
54+
"snippets": [
55+
{
56+
"title": "Vector Print",
57+
"description": "Overloads the << operator to print the contents of a vector just like in python.",
58+
"author": "Mohamed-faaris",
59+
"tags": [
60+
"printing",
61+
"debuging",
62+
"vector"
63+
],
64+
"contributors": [],
65+
"code": "#include <iostream> \n#include <vector> \n\ntemplate <typename T>\nstd::ostream& operator<<(std::ostream& os, const std::vector<T>& vec) {\n os << \"[\"; \n for (size_t i = 0; i < vec.size(); ++i) {\n os << vec[i]; // Print each vector element\n if (i != vec.size() - 1) {\n os << \", \"; // Add separator\n }\n }\n os << \"]\"; \n return os; // Return the stream\n}\n\n// Usage:\nstd::vector<int> numbers = {1, 2, 3, 4, 5};\nstd::cout << numbers << std::endl; // Outputs: [1, 2, 3, 4, 5]\n\n"
66+
}
67+
]
68+
},
5369
{
5470
"name": "Math And Numbers",
5571
"snippets": [

public/consolidated/css.json

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,67 @@
11
[
2+
{
3+
"name": "Animations",
4+
"snippets": [
5+
{
6+
"title": "Blink Animation",
7+
"description": "Adds an infinite blinking animation to an element",
8+
"author": "AlsoKnownAs-Ax",
9+
"tags": [
10+
"animation",
11+
"blink",
12+
"infinite"
13+
],
14+
"contributors": [],
15+
"code": ".blink {\n animation: blink 1s linear infinite;\n}\n\n@keyframes blink{\n 0%{\n opacity: 0;\n }\n 50%{\n opacity: 1;\n }\n 100%{\n opacity: 0;\n }\n}\n"
16+
},
17+
{
18+
"title": "Pulse Animation",
19+
"description": "Adds a smooth pulsing animation with opacity and scale effects",
20+
"author": "AlsoKnownAs-Ax",
21+
"tags": [
22+
"animation",
23+
"pulse",
24+
"pulse-scale"
25+
],
26+
"contributors": [],
27+
"code": ".pulse {\n animation: pulse 2s ease-in-out infinite;\n}\n\n@keyframes pulse {\n 0% {\n opacity: 0.5;\n transform: scale(1);\n }\n 50% {\n opacity: 1;\n transform: scale(1.05);\n }\n 100% {\n opacity: 0.5;\n transform: scale(1);\n }\n}\n"
28+
},
29+
{
30+
"title": "Shake Animation",
31+
"description": "Adds a shake animation ( commonly used to mark invalid fields )",
32+
"author": "AlsoKnownAs-Ax",
33+
"tags": [
34+
"shake",
35+
"shake-horizontal"
36+
],
37+
"contributors": [],
38+
"code": ".shake {\n animation: shake .5s ease-in-out;\n}\n\n@keyframes shake {\n 0%, 100% {\n transform: translateX(0);\n }\n 25% {\n transform: translateX(-10px);\n }\n 50% {\n transform: translateX(10px);\n }\n 75% {\n transform: translateX(-10px);\n }\n}\n"
39+
},
40+
{
41+
"title": "Slide-in Animation",
42+
"description": "Adds a slide-in from the right side of the screen",
43+
"author": "AlsoKnownAs-Ax",
44+
"tags": [
45+
"animation",
46+
"slide-in",
47+
"slide-right"
48+
],
49+
"contributors": [],
50+
"code": ".slide-in {\n animation: slide-in 1s ease-in-out;\n}\n\n@keyframes slide-in {\n from {\n scale: 300% 1;\n translate: 150vw 0;\n }\n\n to {\n scale: 100% 1;\n translate: 0 0;\n }\n}\n"
51+
},
52+
{
53+
"title": "Typewriter Animation",
54+
"description": "Adds a typewriter animation + blinking cursor",
55+
"author": "AlsoKnownAs-Ax",
56+
"tags": [
57+
"blinking",
58+
"typewriter"
59+
],
60+
"contributors": [],
61+
"code": " <div class=\"typewriter\">\n <div>\n <p>Typerwriter Animation</p>\n </div>\n </div>\n```\n\n```css\n .typewriter{\n display: flex;\n justify-content: center;\n }\n\n .typewriter p {\n overflow: hidden;\n font-size: 1.5rem;\n font-family: monospace;\n border-right: 1px solid;\n margin-inline: auto;\n white-space: nowrap;\n /* The cursor will inherit the text's color by default */\n /* border-color: red */ \n /* Steps: number of chars (better to set directly in js)*/\n animation: typing 3s steps(21) forwards,\n blink 1s step-end infinite;\n }\n\n @keyframes typing{\n from{\n width: 0%\n }\n to{\n width: 100%\n }\n }\n\n @keyframes blink{\n 50%{\n border-color: transparent;\n }\n }\n"
62+
}
63+
]
64+
},
265
{
366
"name": "Buttons",
467
"snippets": [

public/consolidated/java.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,22 @@
11
[
2+
{
3+
"name": "Array Manipulation",
4+
"snippets": [
5+
{
6+
"title": "Zip Two Lists",
7+
"description": "Zips two lists into a list of paired elements, combining corresponding elements from both lists.",
8+
"author": "davidanukam",
9+
"tags": [
10+
"lists",
11+
"zip",
12+
"stream-api",
13+
"collections"
14+
],
15+
"contributors": [],
16+
"code": "import java.util.*; // Importing utility classes for List and Arrays\nimport java.util.stream.IntStream; // Importing IntStream for range and mapping\nimport java.util.stream.Collectors; // Importing Collectors for collecting stream results\n\npublic <A, B> List<List<Object>> zip(List<A> list1, List<B> list2) {\n // Create pairs by iterating through the indices of both lists\n return IntStream.range(0, Math.min(list1.size(), list2.size())) // Limit the range to the smaller list\n .mapToObj(i -> Arrays.asList(list1.get(i), list2.get(i))) // Pair elements from both lists at index i\n .collect(Collectors.toList()); // Collect the pairs into a List\n}\n\n// Usage:\nList<String> arr1 = Arrays.asList(\"a\", \"b\", \"c\");\nList<Integer> arr2 = Arrays.asList(1, 2, 3);\nList<List<Object>> zipped = zip(arr1, arr2);\n\nSystem.out.println(zipped); // Output: [[a, 1], [b, 2], [c, 3]]\n"
17+
}
18+
]
19+
},
220
{
321
"name": "Basics",
422
"snippets": [
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[
2+
{
3+
"name": "Basics",
4+
"snippets": [
5+
{
6+
"title": "Hello, World!",
7+
"description": "Show Hello World on the page.",
8+
"author": "ACR1209",
9+
"tags": [
10+
"printing",
11+
"hello-world"
12+
],
13+
"contributors": [],
14+
"code": "import React from 'react';\nimport ReactDOM from 'react-dom';\n\nconst App = () => {\n return (\n <div>\n <h1>Hello, World!</h1>\n </div>\n );\n};\n\nReactDOM.render(<App />, document.getElementById('root'));\n"
15+
}
16+
]
17+
}
18+
]

public/icons/javascript--react.svg

Lines changed: 9 additions & 0 deletions
Loading
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
title: Hello, World!
3+
description: Show Hello World on the page.
4+
author: ACR1209
5+
tags: printing,hello-world
6+
---
7+
8+
```tsx
9+
import React from 'react';
10+
import ReactDOM from 'react-dom';
11+
12+
const App = () => {
13+
return (
14+
<div>
15+
<h1>Hello, World!</h1>
16+
</div>
17+
);
18+
};
19+
20+
ReactDOM.render(<App />, document.getElementById('root'));
21+
```

snippets/javascript/[react]/icon.svg

Lines changed: 9 additions & 0 deletions
Loading

src/components/LanguageSelector.tsx

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
1-
import { useRef, useEffect, useState } from "react";
1+
import { useRef, useEffect, useState, useMemo } from "react";
22

33
import { useAppContext } from "@contexts/AppContext";
44
import { useKeyboardNavigation } from "@hooks/useKeyboardNavigation";
55
import { useLanguages } from "@hooks/useLanguages";
66
import { LanguageType } from "@types";
7+
import SubLanguageSelector from "./SublanguageSelector";
78

89
// Inspired by https://blog.logrocket.com/creating-custom-select-dropdown-css/
910

1011
const LanguageSelector = () => {
1112
const { language, setLanguage } = useAppContext();
1213
const { fetchedLanguages, loading, error } = useLanguages();
14+
const allLanguages = useMemo(() =>
15+
fetchedLanguages.flatMap((lang) =>
16+
lang.subLanguages.length > 0
17+
? [lang, ...lang.subLanguages.map((subLang) => ({ ...subLang, mainLanguage: lang, subLanguages: [] }))]
18+
: [lang]
19+
),
20+
[fetchedLanguages]
21+
);
1322

1423
const dropdownRef = useRef<HTMLDivElement>(null);
1524
const [isOpen, setIsOpen] = useState(false);
25+
const [openedLanguages, setOpenedLanguages] = useState<LanguageType[]>([]);
1626

1727
const handleSelect = (selected: LanguageType) => {
1828
setLanguage(selected);
@@ -21,8 +31,9 @@ const LanguageSelector = () => {
2131

2232
const { focusedIndex, handleKeyDown, resetFocus, focusFirst } =
2333
useKeyboardNavigation({
24-
items: fetchedLanguages,
25-
isOpen,
34+
items: allLanguages,
35+
isOpen,
36+
openedLanguages,
2637
onSelect: handleSelect,
2738
onClose: () => setIsOpen(false),
2839
});
@@ -38,6 +49,14 @@ const LanguageSelector = () => {
3849
}, 0);
3950
};
4051

52+
const handleOpenedSublanguage = (open: boolean, openedLang: LanguageType) => {
53+
if (open) {
54+
setOpenedLanguages((prev) => [...prev, openedLang]);
55+
} else {
56+
setOpenedLanguages((prev) => prev.filter((lang) => lang.name !== openedLang.name));
57+
}
58+
};
59+
4160
const toggleDropdown = () => {
4261
setIsOpen((prev) => {
4362
if (!prev) setTimeout(focusFirst, 0);
@@ -91,21 +110,25 @@ const LanguageSelector = () => {
91110
tabIndex={-1}
92111
>
93112
{fetchedLanguages.map((lang, index) => (
94-
<li
95-
key={lang.name}
96-
role="option"
97-
tabIndex={-1}
98-
onClick={() => handleSelect(lang)}
99-
className={`selector__item ${
100-
language.name === lang.name ? "selected" : ""
101-
} ${focusedIndex === index ? "focused" : ""}`}
102-
aria-selected={language.name === lang.name}
103-
>
104-
<label>
105-
<img src={lang.icon} alt="" />
106-
<span>{lang.name}</span>
107-
</label>
108-
</li>
113+
lang.subLanguages.length > 0 ? (
114+
<SubLanguageSelector key={index} mainLanguage={lang} afterSelect={()=>{ setIsOpen(false)}} onDropdownChange={handleOpenedSublanguage}/>
115+
) : (
116+
<li
117+
key={lang.name}
118+
role="option"
119+
tabIndex={-1}
120+
onClick={() => handleSelect(lang)}
121+
className={`selector__item ${
122+
language.name === lang.name ? "selected" : ""
123+
} ${focusedIndex === index ? "focused" : ""}`}
124+
aria-selected={language.name === lang.name}
125+
>
126+
<label>
127+
<img src={lang.icon} alt="" />
128+
<span>{lang.name}</span>
129+
</label>
130+
</li>
131+
)
109132
))}
110133
</ul>
111134
)}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import { useAppContext } from "@contexts/AppContext";
2+
import { LanguageType } from "@types";
3+
import { useEffect, useState } from "react";
4+
5+
type SubLanguageSelectorProps = {
6+
mainLanguage: LanguageType;
7+
afterSelect: () => void;
8+
onDropdownChange: (open: boolean, openedLang: LanguageType) => void;
9+
};
10+
11+
const SubLanguageSelector = ({
12+
mainLanguage,
13+
afterSelect,
14+
onDropdownChange
15+
}: SubLanguageSelectorProps) => {
16+
const { language, setLanguage } = useAppContext();
17+
const [isOpen, setIsOpen] = useState(
18+
mainLanguage.subLanguages.some(
19+
(subLanguage) => language.name === subLanguage.name
20+
)
21+
);
22+
23+
const handleSelect = (selected: LanguageType) => {
24+
setLanguage(selected);
25+
setIsOpen(false);
26+
afterSelect();
27+
};
28+
29+
useEffect(() => {
30+
onDropdownChange(isOpen, mainLanguage);
31+
}, [isOpen]);
32+
33+
return (
34+
<>
35+
<li
36+
key={mainLanguage.name}
37+
role="option"
38+
tabIndex={-1}
39+
className={`selector__item ${
40+
language.name === mainLanguage.name ? "selected" : ""
41+
}`}
42+
aria-selected={language.name === mainLanguage.name}
43+
onClick={() => setLanguage(mainLanguage)}
44+
>
45+
<label>
46+
<img src={mainLanguage.icon} alt={mainLanguage.name} />
47+
<span>{mainLanguage.name}</span>
48+
<button
49+
className="sublanguage__button"
50+
tabIndex={-1}
51+
aria-expanded={isOpen}
52+
aria-haspopup="listbox"
53+
onClick={(e) => {
54+
e.stopPropagation();
55+
setIsOpen(!isOpen);
56+
}}
57+
>
58+
<span className="sublanguage__arrow" />
59+
</button>
60+
</label>
61+
</li>
62+
63+
{isOpen && (
64+
<>
65+
{mainLanguage.subLanguages.map((subLanguage) => (
66+
<li
67+
key={subLanguage.name}
68+
role="option"
69+
tabIndex={-1}
70+
className={`selector__item sublanguage__item ${
71+
language.name === subLanguage.name ? "selected" : ""
72+
}`}
73+
aria-selected={language.name === subLanguage.name}
74+
onClick={() => {
75+
handleSelect({
76+
...subLanguage,
77+
mainLanguage: mainLanguage,
78+
subLanguages: [],
79+
});
80+
setIsOpen(false);
81+
}}
82+
>
83+
<label>
84+
<img src={subLanguage.icon} alt={subLanguage.name} />
85+
<span>{subLanguage.name}</span>
86+
</label>
87+
</li>
88+
))}
89+
</>
90+
)}
91+
</>
92+
);
93+
};
94+
95+
export default SubLanguageSelector;

0 commit comments

Comments
 (0)