create-aziz-app 1.0.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.
- package/.vscode/settings.json +2 -0
- package/app.html +110 -0
- package/app.js +88 -0
- package/components/Counter.jsx +18 -0
- package/components/Footer.jsx +9 -0
- package/components/Header.jsx +10 -0
- package/package.json +18 -0
package/app.html
ADDED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>My Vanilla JS App</title>
|
|
7
|
+
|
|
8
|
+
<!-- Babel compiles our JSX in the browser -->
|
|
9
|
+
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
10
|
+
|
|
11
|
+
<style>
|
|
12
|
+
* {
|
|
13
|
+
margin: 0;
|
|
14
|
+
padding: 0;
|
|
15
|
+
box-sizing: border-box;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
body {
|
|
19
|
+
font-family: Arial, sans-serif;
|
|
20
|
+
background-color: #f0f0f0;
|
|
21
|
+
display: flex;
|
|
22
|
+
flex-direction: column;
|
|
23
|
+
align-items: center;
|
|
24
|
+
min-height: 100vh;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.header {
|
|
28
|
+
width: 100%;
|
|
29
|
+
background-color: #282c34;
|
|
30
|
+
color: white;
|
|
31
|
+
padding: 20px;
|
|
32
|
+
text-align: center;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.main {
|
|
36
|
+
margin-top: 60px;
|
|
37
|
+
text-align: center;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.counter-box {
|
|
41
|
+
background-color: white;
|
|
42
|
+
padding: 40px 60px;
|
|
43
|
+
border-radius: 12px;
|
|
44
|
+
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.counter-box h2 {
|
|
48
|
+
margin-bottom: 20px;
|
|
49
|
+
color: #333;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.count-display {
|
|
53
|
+
font-size: 64px;
|
|
54
|
+
font-weight: bold;
|
|
55
|
+
color: #282c34;
|
|
56
|
+
margin: 20px 0;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.btn {
|
|
60
|
+
padding: 12px 28px;
|
|
61
|
+
margin: 0 8px;
|
|
62
|
+
font-size: 24px;
|
|
63
|
+
border: none;
|
|
64
|
+
border-radius: 8px;
|
|
65
|
+
cursor: pointer;
|
|
66
|
+
transition: background-color 0.2s;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.btn-plus { background-color: #61dafb; color: #282c34; }
|
|
70
|
+
.btn-minus { background-color: #ff6b6b; color: white; }
|
|
71
|
+
|
|
72
|
+
.btn-reset {
|
|
73
|
+
background-color: #ccc;
|
|
74
|
+
color: #333;
|
|
75
|
+
font-size: 16px;
|
|
76
|
+
padding: 12px 24px;
|
|
77
|
+
margin-top: 20px;
|
|
78
|
+
display: block;
|
|
79
|
+
width: 100%;
|
|
80
|
+
border-radius: 8px;
|
|
81
|
+
border: none;
|
|
82
|
+
cursor: pointer;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.btn:hover { opacity: 0.85; }
|
|
86
|
+
|
|
87
|
+
.footer {
|
|
88
|
+
margin-top: auto;
|
|
89
|
+
padding: 20px;
|
|
90
|
+
color: #888;
|
|
91
|
+
font-size: 14px;
|
|
92
|
+
}
|
|
93
|
+
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body>
|
|
96
|
+
|
|
97
|
+
<div id="root">
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<!-- Load components first (Babel compiles each one) -->
|
|
101
|
+
|
|
102
|
+
<script type="text/babel" src="components/Header.jsx"></script>
|
|
103
|
+
<script type="text/babel" src="components/Counter.jsx"></script>
|
|
104
|
+
<script type="text/babel" src="components/Footer.jsx"></script>
|
|
105
|
+
|
|
106
|
+
<!-- Then load the main app -->
|
|
107
|
+
<script type="text/babel" src="app.js"></script>
|
|
108
|
+
|
|
109
|
+
</body>
|
|
110
|
+
</html>
|
package/app.js
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/** @jsx h */
|
|
2
|
+
|
|
3
|
+
// ==============================
|
|
4
|
+
// h() — our own createElement
|
|
5
|
+
// Babel compiles JSX like <div class="x"> into h("div", { class: "x" }, ...children)
|
|
6
|
+
// This function turns that into a real DOM element
|
|
7
|
+
// ==============================
|
|
8
|
+
function h(tag, props, ...children) {
|
|
9
|
+
// If tag is a function (a component like Header), call it
|
|
10
|
+
if (typeof tag === "function") {
|
|
11
|
+
return tag(props, ...children);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Create the real DOM element
|
|
15
|
+
const el = document.createElement(tag);
|
|
16
|
+
|
|
17
|
+
// Apply props (class, onClick, etc.)
|
|
18
|
+
if (props) {
|
|
19
|
+
for (let key in props) {
|
|
20
|
+
if (key.startsWith("on")) {
|
|
21
|
+
// onClick -> click event
|
|
22
|
+
const eventName = key.slice(2).toLowerCase();
|
|
23
|
+
el.addEventListener(eventName, props[key]);
|
|
24
|
+
} else if (key === "className") {
|
|
25
|
+
el.className = props[key];
|
|
26
|
+
} else {
|
|
27
|
+
el.setAttribute(key, props[key]);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Append children (text or elements)
|
|
33
|
+
for (let child of children) {
|
|
34
|
+
if (child === null || child === undefined) continue;
|
|
35
|
+
if (typeof child === "string" || typeof child === "number") {
|
|
36
|
+
el.appendChild(document.createTextNode(child));
|
|
37
|
+
} else {
|
|
38
|
+
el.appendChild(child);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return el;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
// ==============================
|
|
47
|
+
// STATE
|
|
48
|
+
// ==============================
|
|
49
|
+
let state = {
|
|
50
|
+
count: 0
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
// ==============================
|
|
55
|
+
// RENDER
|
|
56
|
+
// ==============================
|
|
57
|
+
function render() {
|
|
58
|
+
const root = document.getElementById("root");
|
|
59
|
+
root.innerHTML = "";
|
|
60
|
+
root.appendChild(Header());
|
|
61
|
+
root.appendChild(Counter());
|
|
62
|
+
root.appendChild(Footer());
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
// ==============================
|
|
67
|
+
// STATE UPDATER FUNCTIONS
|
|
68
|
+
// ==============================
|
|
69
|
+
function increment() {
|
|
70
|
+
state.count = state.count + 1;
|
|
71
|
+
render();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function decrement() {
|
|
75
|
+
state.count = state.count - 1;
|
|
76
|
+
render();
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function reset() {
|
|
80
|
+
state.count = 0;
|
|
81
|
+
render();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
// ==============================
|
|
86
|
+
// FIRST RENDER
|
|
87
|
+
// ==============================
|
|
88
|
+
render();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** @jsx h */
|
|
2
|
+
|
|
3
|
+
function Counter() {
|
|
4
|
+
return (
|
|
5
|
+
<div class="main">
|
|
6
|
+
<div class="counter-box">
|
|
7
|
+
<h2>Counter App</h2>
|
|
8
|
+
|
|
9
|
+
<div class="count-display">{state.count}</div>
|
|
10
|
+
|
|
11
|
+
<button class="btn btn-minus" onClick={() => decrement()}>−</button>
|
|
12
|
+
<button class="btn btn-plus" onClick={() => increment()}>+</button>
|
|
13
|
+
|
|
14
|
+
<button class="btn-reset" onClick={() => reset()}>Reset</button>
|
|
15
|
+
</div>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-aziz-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "so close to react ~~ just joking",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"js",
|
|
7
|
+
"hrml",
|
|
8
|
+
"css",
|
|
9
|
+
"reactlike"
|
|
10
|
+
],
|
|
11
|
+
"license": "Aziz",
|
|
12
|
+
"author": "Syed Muhammad Aziz Ahmed",
|
|
13
|
+
"type": "commonjs",
|
|
14
|
+
"main": "app.js",
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
|
+
}
|
|
18
|
+
}
|