afront 1.0.19 → 1.0.20
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/build-prod/index.html +1 -1
- package/build-prod/offline.html +1024 -0
- package/build-prod/service-worker.js +1 -0
- package/build-prod/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
- package/build-prod/static/js/3-b7f6c4256e55d2c173ac.js +1 -0
- package/build-prod/static/js/41-d729186c867a4a7f5f49.js +1 -0
- package/build-prod/static/js/525-506bbc7da1b98d130181.js +1 -0
- package/build-prod/static/js/573-8fcda455788ea4aa45cd.js +1 -0
- package/build-prod/static/js/99-ccf46a26c15904ecb674.js +1 -0
- package/build-prod/static/js/main-34c866ebbc6fbc291b85.js +1 -0
- package/build-prod-ssr/3.ssr.prod.js +1 -1
- package/build-prod-ssr/41.ssr.prod.js +1 -1
- package/build-prod-ssr/525.ssr.prod.js +1 -0
- package/build-prod-ssr/573.ssr.prod.js +1 -1
- package/build-prod-ssr/ssr.prod.js +1 -1
- package/build-prod-ssr/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
- package/build-prod-static/index.html +1 -1
- package/build-prod-static/offline.html +1024 -0
- package/build-prod-static/service-worker.js +1 -0
- package/build-prod-static/static/css/main-b7c0f6b3ea505263e9a2.css +1 -0
- package/build-prod-static/static/js/23-c9124d3cac34021e3406.js +1 -0
- package/build-prod-static/static/js/303-0d29064b1a912a7441ef.js +1 -0
- package/build-prod-static/static/js/636-adf7ca5d4e262a755df3.js +1 -0
- package/build-prod-static/static/js/863-2c35feb0663baeecb6f8.js +1 -0
- package/build-prod-static/static/js/main-02c8c189d5bec6c0a7f1.js +1 -0
- package/install.js +2 -2
- package/package.json +5 -4
- package/server.js +2 -0
- package/src/ARoutes/AFRoutes.js +22 -5
- package/src/Api/api.config.js +266 -0
- package/src/Api/login.service.js +44 -0
- package/src/App.js +10 -9
- package/src/Components/Loading/LoadingIndicator.js +12 -0
- package/src/Components/Loading/LoadingIndicator.module.css +34 -0
- package/src/Components/Loading/LoadingSpinner.js +27 -0
- package/src/Components/Loading/LoadingSpinner.module.css +100 -0
- package/src/Components/RequireAuth.js +30 -0
- package/src/PageNotFound.js +1 -1
- package/src/Pages/Signup.js +230 -0
- package/src/Routes/ARoutes.js +47 -6
- package/src/Routes/ARoutesStatic.js +83 -0
- package/src/Static/appStatic.js +10 -20
- package/src/Static/indexStatic.js +3 -0
- package/src/Utils/LoadingContext.js +5 -0
- package/src/index.js +0 -4
- package/webpack.build-prod.js +13 -0
- package/webpack.dev.js +18 -0
- package/webpack.prod.js +11 -2
- package/webpack.ssr.prod.js +4 -0
- package/build-prod/static/css/main-7f7c4e72ce002df48179.css +0 -1
- package/build-prod/static/js/3-985f8801e97b3b2025e2.js +0 -1
- package/build-prod/static/js/41-a66fae84fd39cfb1e349.js +0 -1
- package/build-prod/static/js/573-f7791eb491c75b0ccfb7.js +0 -1
- package/build-prod/static/js/main-1cbe42ef1eb3d942625c.js +0 -1
- package/build-prod-ssr/static/css/main-7f7c4e72ce002df48179.css +0 -1
- package/build-prod-static/static/css/main-7f7c4e72ce002df48179.css +0 -1
- package/build-prod-static/static/js/23-9e69ffb20f982ca1ba75.js +0 -1
- package/build-prod-static/static/js/303-1b6136e5efb4925c5f98.js +0 -1
- package/build-prod-static/static/js/636-7f7bf68f9765bc200b86.js +0 -1
- package/build-prod-static/static/js/main-6c6f40c44813930620ed.js +0 -1
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { useNavigate } from "react-router";
|
|
3
|
+
import auth from "../Api/login.service";
|
|
4
|
+
|
|
5
|
+
function Signup() {
|
|
6
|
+
const navigate = useNavigate();
|
|
7
|
+
const [step, setStep] = useState(1);
|
|
8
|
+
const [email, setEmail] = useState("");
|
|
9
|
+
const [password, setPassword] = useState("");
|
|
10
|
+
const [name, setName] = useState("");
|
|
11
|
+
const [accountType, setAccountType] = useState("personal"); // personal/creator or business
|
|
12
|
+
const [companyName, setCompanyName] = useState("");
|
|
13
|
+
const [loading, setLoading] = useState(false);
|
|
14
|
+
const [error, setError] = useState(null);
|
|
15
|
+
|
|
16
|
+
const validateStep = () => {
|
|
17
|
+
setError(null);
|
|
18
|
+
if (step === 1) {
|
|
19
|
+
if (!email) return "Email is required";
|
|
20
|
+
// basic email regex
|
|
21
|
+
const emailRegex = /^[^@\s]+@[^@\s]+\.[^@\s]+$/;
|
|
22
|
+
if (!emailRegex.test(email)) return "Enter a valid email address";
|
|
23
|
+
if (!password) return "Password is required";
|
|
24
|
+
if (password.length < 8) return "Password must be at least 8 characters";
|
|
25
|
+
}
|
|
26
|
+
if (step === 2) {
|
|
27
|
+
if (!name || name.trim().length === 0) return "Full name is required";
|
|
28
|
+
}
|
|
29
|
+
if (step === 3) {
|
|
30
|
+
if (!accountType) return "Select account type";
|
|
31
|
+
if (
|
|
32
|
+
accountType === "business" &&
|
|
33
|
+
(!companyName || companyName.trim().length === 0)
|
|
34
|
+
)
|
|
35
|
+
return "Brand / Company Name is required for business accounts";
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleNext = (e) => {
|
|
41
|
+
(async () => {
|
|
42
|
+
if (e) e.preventDefault();
|
|
43
|
+
const err = validateStep();
|
|
44
|
+
if (err) return setError(err);
|
|
45
|
+
setError(null);
|
|
46
|
+
// On step 1, call backend to check email (exists/disposable)
|
|
47
|
+
if (step === 1) {
|
|
48
|
+
try {
|
|
49
|
+
const res = await auth.checkSignup({ email });
|
|
50
|
+
if (!res || !res.ok) {
|
|
51
|
+
setError(
|
|
52
|
+
(res && res.data && (res.data.error || res.data.message)) ||
|
|
53
|
+
"Check failed"
|
|
54
|
+
);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (res.data.disposable) {
|
|
58
|
+
setError("Disposable email addresses are not allowed");
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (res.data.exists) {
|
|
62
|
+
setError("An account already exists with this email");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
} catch (err) {
|
|
66
|
+
setError("Email check failed");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
setStep((s) => Math.min(3, s + 1));
|
|
71
|
+
})();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const handleBack = (e) => {
|
|
75
|
+
if (e) e.preventDefault();
|
|
76
|
+
setError(null);
|
|
77
|
+
setStep((s) => Math.max(1, s - 1));
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const handleSubmit = async (e) => {
|
|
81
|
+
if (e) e.preventDefault();
|
|
82
|
+
const err = validateStep();
|
|
83
|
+
if (err) return setError(err);
|
|
84
|
+
setLoading(true);
|
|
85
|
+
setError(null);
|
|
86
|
+
try {
|
|
87
|
+
const payload = {
|
|
88
|
+
email,
|
|
89
|
+
password,
|
|
90
|
+
name,
|
|
91
|
+
accountType,
|
|
92
|
+
companyName: accountType === "business" ? companyName : undefined,
|
|
93
|
+
};
|
|
94
|
+
const res = await auth.signup(payload);
|
|
95
|
+
if (!res || !res.ok) {
|
|
96
|
+
setError(
|
|
97
|
+
(res && res.data && (res.data.error || res.data.message)) ||
|
|
98
|
+
"Registration failed"
|
|
99
|
+
);
|
|
100
|
+
setLoading(false);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
localStorage.setItem("auth-event", String(Date.now()));
|
|
106
|
+
} catch (e) {}
|
|
107
|
+
window.dispatchEvent(new Event("auth-changed"));
|
|
108
|
+
navigate("/");
|
|
109
|
+
} catch (err) {
|
|
110
|
+
setError("Registration failed");
|
|
111
|
+
} finally {
|
|
112
|
+
setLoading(false);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<div className="page auth-page signup-page">
|
|
118
|
+
<h2>Sign up</h2>
|
|
119
|
+
{error && <div className="auth-error">{error}</div>}
|
|
120
|
+
<form
|
|
121
|
+
className="auth-form"
|
|
122
|
+
onSubmit={step === 3 ? handleSubmit : handleNext}>
|
|
123
|
+
{step === 1 && (
|
|
124
|
+
<>
|
|
125
|
+
<label>
|
|
126
|
+
Email Address (required)
|
|
127
|
+
<input
|
|
128
|
+
type="email"
|
|
129
|
+
value={email}
|
|
130
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
131
|
+
disabled={loading}
|
|
132
|
+
/>
|
|
133
|
+
</label>
|
|
134
|
+
{/* Work/personal choice removed — backend tracks only personal emails */}
|
|
135
|
+
<label>
|
|
136
|
+
Password (required, min 8 characters)
|
|
137
|
+
<input
|
|
138
|
+
type="password"
|
|
139
|
+
value={password}
|
|
140
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
141
|
+
disabled={loading}
|
|
142
|
+
/>
|
|
143
|
+
</label>
|
|
144
|
+
<div className="form-actions">
|
|
145
|
+
<button type="button" onClick={handleNext} disabled={loading}>
|
|
146
|
+
Next
|
|
147
|
+
</button>
|
|
148
|
+
</div>
|
|
149
|
+
</>
|
|
150
|
+
)}
|
|
151
|
+
|
|
152
|
+
{step === 2 && (
|
|
153
|
+
<>
|
|
154
|
+
<label>
|
|
155
|
+
Full Name (required)
|
|
156
|
+
<input
|
|
157
|
+
value={name}
|
|
158
|
+
onChange={(e) => setName(e.target.value)}
|
|
159
|
+
disabled={loading}
|
|
160
|
+
/>
|
|
161
|
+
</label>
|
|
162
|
+
<div className="form-actions">
|
|
163
|
+
<button type="button" onClick={handleBack} disabled={loading}>
|
|
164
|
+
Back
|
|
165
|
+
</button>
|
|
166
|
+
<button type="button" onClick={handleNext} disabled={loading}>
|
|
167
|
+
Next
|
|
168
|
+
</button>
|
|
169
|
+
</div>
|
|
170
|
+
</>
|
|
171
|
+
)}
|
|
172
|
+
|
|
173
|
+
{step === 3 && (
|
|
174
|
+
<>
|
|
175
|
+
<label>
|
|
176
|
+
Account Type (required)
|
|
177
|
+
<div>
|
|
178
|
+
<label>
|
|
179
|
+
<input
|
|
180
|
+
type="radio"
|
|
181
|
+
name="accountType"
|
|
182
|
+
value="personal"
|
|
183
|
+
checked={accountType === "personal"}
|
|
184
|
+
onChange={() => setAccountType("personal")}
|
|
185
|
+
disabled={loading}
|
|
186
|
+
/>
|
|
187
|
+
Personal / Creator
|
|
188
|
+
</label>
|
|
189
|
+
<label>
|
|
190
|
+
<input
|
|
191
|
+
type="radio"
|
|
192
|
+
name="accountType"
|
|
193
|
+
value="business"
|
|
194
|
+
checked={accountType === "business"}
|
|
195
|
+
onChange={() => setAccountType("business")}
|
|
196
|
+
disabled={loading}
|
|
197
|
+
/>
|
|
198
|
+
Business / Brand / Company
|
|
199
|
+
</label>
|
|
200
|
+
</div>
|
|
201
|
+
</label>
|
|
202
|
+
{accountType === "business" && (
|
|
203
|
+
<label>
|
|
204
|
+
Brand / Company Name (required for business)
|
|
205
|
+
<input
|
|
206
|
+
value={companyName}
|
|
207
|
+
onChange={(e) => setCompanyName(e.target.value)}
|
|
208
|
+
disabled={loading}
|
|
209
|
+
/>
|
|
210
|
+
</label>
|
|
211
|
+
)}
|
|
212
|
+
|
|
213
|
+
{error && <div className="auth-error">{error}</div>}
|
|
214
|
+
|
|
215
|
+
<div className="form-actions">
|
|
216
|
+
<button type="button" onClick={handleBack} disabled={loading}>
|
|
217
|
+
Back
|
|
218
|
+
</button>
|
|
219
|
+
<button type="submit" disabled={loading}>
|
|
220
|
+
{loading ? "Signing up..." : "Sign up"}
|
|
221
|
+
</button>
|
|
222
|
+
</div>
|
|
223
|
+
</>
|
|
224
|
+
)}
|
|
225
|
+
</form>
|
|
226
|
+
</div>
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export default Signup;
|
package/src/Routes/ARoutes.js
CHANGED
|
@@ -1,24 +1,65 @@
|
|
|
1
|
-
import React, { Suspense } from "react";
|
|
1
|
+
import React, { Suspense, useContext } from "react";
|
|
2
2
|
import { Route, Routes } from "react-router";
|
|
3
3
|
import routes from "../ARoutes/AFRoutes.js";
|
|
4
|
-
import
|
|
4
|
+
import RequireAuth from "../Components/RequireAuth.js";
|
|
5
|
+
import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
|
|
6
|
+
import Header from "../Components/Header/Header.js";
|
|
7
|
+
import Footer from "../Components/Footer/Footer.js";
|
|
8
|
+
import LoadingContext from "../Utils/LoadingContext.js";
|
|
5
9
|
|
|
6
10
|
|
|
11
|
+
const Layout = ({ children }) => (
|
|
12
|
+
<>
|
|
13
|
+
<Header />
|
|
14
|
+
{children}
|
|
15
|
+
<Footer />
|
|
16
|
+
</>
|
|
17
|
+
);
|
|
18
|
+
|
|
7
19
|
const ARoutes = ({ context }) => {
|
|
20
|
+
const { setLoading } = useContext(LoadingContext);
|
|
8
21
|
return (
|
|
9
|
-
<Suspense fallback={<LoadingFallback />}>
|
|
10
22
|
<Routes>
|
|
11
23
|
{/* Pages Routes */}
|
|
12
|
-
{routes.map(({ path, element: Element }, index) => (
|
|
24
|
+
{routes.map(({ path, element: Element, withHeaderFooter, protected: isProtected }, index) => (
|
|
13
25
|
<Route
|
|
14
26
|
key={index}
|
|
15
27
|
path={path}
|
|
16
|
-
element={
|
|
28
|
+
element={
|
|
29
|
+
withHeaderFooter ? (
|
|
30
|
+
<Layout>
|
|
31
|
+
<Suspense
|
|
32
|
+
fallback={<LoadingIndicator />}
|
|
33
|
+
onPromiseStart={() => setLoading(true)}
|
|
34
|
+
onPromiseEnd={() => setLoading(false)}>
|
|
35
|
+
{isProtected ? (
|
|
36
|
+
<RequireAuth>
|
|
37
|
+
<Element context={context} />
|
|
38
|
+
</RequireAuth>
|
|
39
|
+
) : (
|
|
40
|
+
<Element context={context} />
|
|
41
|
+
)}
|
|
42
|
+
</Suspense>
|
|
43
|
+
</Layout>
|
|
44
|
+
) : (
|
|
45
|
+
<Suspense
|
|
46
|
+
fallback={<LoadingIndicator />}
|
|
47
|
+
onPromiseStart={() => setLoading(true)}
|
|
48
|
+
onPromiseEnd={() => setLoading(false)}>
|
|
49
|
+
{isProtected ? (
|
|
50
|
+
<RequireAuth>
|
|
51
|
+
<Element context={context} />
|
|
52
|
+
</RequireAuth>
|
|
53
|
+
) : (
|
|
54
|
+
<Element context={context} />
|
|
55
|
+
)}
|
|
56
|
+
</Suspense>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
17
59
|
/>
|
|
18
60
|
))}
|
|
19
61
|
{/* Pages Routes */}
|
|
20
62
|
</Routes>
|
|
21
|
-
</Suspense>
|
|
22
63
|
);
|
|
23
64
|
};
|
|
24
65
|
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* File Name: ARoutesStatic.js
|
|
3
|
+
*
|
|
4
|
+
* Description: This file handles the logic for Handling Header and Footer to be visible or not for the every specific page for single page application (Static Page).
|
|
5
|
+
*
|
|
6
|
+
*
|
|
7
|
+
* Author: Mark Sea.
|
|
8
|
+
*
|
|
9
|
+
* Created: 14/Dec/2024
|
|
10
|
+
*
|
|
11
|
+
* Dependencies: {react-router}
|
|
12
|
+
*
|
|
13
|
+
* Assumptions: This file is used in appStatic.js
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import React, { Suspense, useContext } from "react";
|
|
17
|
+
import { Route, Routes } from "react-router";
|
|
18
|
+
import routes from "../ARoutes/AFRoutes.js";
|
|
19
|
+
import RequireAuth from "../Components/RequireAuth.js";
|
|
20
|
+
import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
|
|
21
|
+
import Header from "../Components/Header/Header.js";
|
|
22
|
+
import Footer from "../Components/Footer/Footer.js";
|
|
23
|
+
import LoadingContext from "../Utils/LoadingContext.js";
|
|
24
|
+
|
|
25
|
+
const Layout = ({ children }) => (
|
|
26
|
+
<>
|
|
27
|
+
<Header />
|
|
28
|
+
{children}
|
|
29
|
+
<Footer />
|
|
30
|
+
</>
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const ARoutesStatic = ({ context }) => {
|
|
34
|
+
const { setLoading } = useContext(LoadingContext);
|
|
35
|
+
return (
|
|
36
|
+
<Routes>
|
|
37
|
+
{routes.map(
|
|
38
|
+
(
|
|
39
|
+
{ path, element: Element, withHeaderFooter, protected: isProtected },
|
|
40
|
+
index
|
|
41
|
+
) => (
|
|
42
|
+
<Route
|
|
43
|
+
key={index}
|
|
44
|
+
path={path}
|
|
45
|
+
element={
|
|
46
|
+
withHeaderFooter ? (
|
|
47
|
+
<Layout>
|
|
48
|
+
<Suspense
|
|
49
|
+
fallback={<LoadingIndicator />}
|
|
50
|
+
onPromiseStart={() => setLoading(true)}
|
|
51
|
+
onPromiseEnd={() => setLoading(false)}>
|
|
52
|
+
{isProtected ? (
|
|
53
|
+
<RequireAuth>
|
|
54
|
+
<Element context={context} />
|
|
55
|
+
</RequireAuth>
|
|
56
|
+
) : (
|
|
57
|
+
<Element context={context} />
|
|
58
|
+
)}
|
|
59
|
+
</Suspense>
|
|
60
|
+
</Layout>
|
|
61
|
+
) : (
|
|
62
|
+
<Suspense
|
|
63
|
+
fallback={<LoadingIndicator />}
|
|
64
|
+
onPromiseStart={() => setLoading(true)}
|
|
65
|
+
onPromiseEnd={() => setLoading(false)}>
|
|
66
|
+
{isProtected ? (
|
|
67
|
+
<RequireAuth>
|
|
68
|
+
<Element context={context} />
|
|
69
|
+
</RequireAuth>
|
|
70
|
+
) : (
|
|
71
|
+
<Element context={context} />
|
|
72
|
+
)}
|
|
73
|
+
</Suspense>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
/>
|
|
77
|
+
)
|
|
78
|
+
)}
|
|
79
|
+
</Routes>
|
|
80
|
+
);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export default ARoutesStatic;
|
package/src/Static/appStatic.js
CHANGED
|
@@ -1,26 +1,16 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import ARoutesStatic from "../Routes/ARoutesStatic.js";
|
|
3
|
+
import LoadingContext from "../Utils/LoadingContext.js";
|
|
4
|
+
import LoadingIndicator from "../Components/Loading/LoadingIndicator.js";
|
|
5
5
|
|
|
6
|
-
import Header from "../Components/Header/Header.js";
|
|
7
|
-
import Footer from "../Components/Footer/Footer.js";
|
|
8
6
|
|
|
9
|
-
function appStatic() {
|
|
7
|
+
function appStatic({ context }) {
|
|
8
|
+
const [loading, setLoading] = useState(false);
|
|
10
9
|
return (
|
|
11
|
-
<
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{/* Pages Routes */}
|
|
16
|
-
{routes.map(({ path, element: Element }, index) => (
|
|
17
|
-
<Route key={index} path={path} element={<Element />} />
|
|
18
|
-
))}
|
|
19
|
-
{/* Pages Routes */}
|
|
20
|
-
</Routes>
|
|
21
|
-
<Footer />
|
|
22
|
-
</Suspense>
|
|
23
|
-
</Router>
|
|
10
|
+
<LoadingContext.Provider value={{ loading, setLoading }}>
|
|
11
|
+
{loading && <LoadingIndicator />}
|
|
12
|
+
<ARoutesStatic context={context} />
|
|
13
|
+
</LoadingContext.Provider>
|
|
24
14
|
);
|
|
25
15
|
}
|
|
26
16
|
export default appStatic;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import ReactDOM from "react-dom/client";
|
|
3
|
+
import { BrowserRouter } from "react-router";
|
|
3
4
|
import App from "./appStatic";
|
|
4
5
|
|
|
5
6
|
const asggen = ReactDOM.createRoot(document.getElementById("asggen"));
|
|
6
7
|
asggen.render(
|
|
7
8
|
<React.StrictMode>
|
|
9
|
+
<BrowserRouter>
|
|
8
10
|
<App />
|
|
11
|
+
</BrowserRouter>
|
|
9
12
|
</React.StrictMode>
|
|
10
13
|
);
|
package/src/index.js
CHANGED
|
@@ -12,18 +12,14 @@ if (process.env.NODE_ENV === "production") {
|
|
|
12
12
|
// Use `hydrateRoot` for production
|
|
13
13
|
hydrateRoot(
|
|
14
14
|
container,
|
|
15
|
-
<React.StrictMode>
|
|
16
15
|
<BrowserRouter>
|
|
17
16
|
<App />
|
|
18
17
|
</BrowserRouter>
|
|
19
|
-
</React.StrictMode>
|
|
20
18
|
);
|
|
21
19
|
} else {
|
|
22
20
|
root.render(
|
|
23
|
-
<React.StrictMode>
|
|
24
21
|
<BrowserRouter>
|
|
25
22
|
<App />
|
|
26
23
|
</BrowserRouter>
|
|
27
|
-
</React.StrictMode>
|
|
28
24
|
);
|
|
29
25
|
}
|
package/webpack.build-prod.js
CHANGED
|
@@ -13,6 +13,7 @@ module.exports = {
|
|
|
13
13
|
output: {
|
|
14
14
|
filename: "static/js/[name]-[contenthash].js",
|
|
15
15
|
path: path.resolve(__dirname, "build-prod-static"),
|
|
16
|
+
publicPath: "/",
|
|
16
17
|
clean: true,
|
|
17
18
|
},
|
|
18
19
|
module: {
|
|
@@ -39,6 +40,7 @@ module.exports = {
|
|
|
39
40
|
modules: {
|
|
40
41
|
localIdentName: "asggen-[hash:base64:7]",
|
|
41
42
|
},
|
|
43
|
+
sourceMap: true,
|
|
42
44
|
},
|
|
43
45
|
},
|
|
44
46
|
],
|
|
@@ -70,6 +72,9 @@ module.exports = {
|
|
|
70
72
|
minimizer: [
|
|
71
73
|
new TerserWebpackPlugin({
|
|
72
74
|
terserOptions: {
|
|
75
|
+
compress: {
|
|
76
|
+
drop_console: false,
|
|
77
|
+
},
|
|
73
78
|
format: {
|
|
74
79
|
comments: false, // Remove all comments
|
|
75
80
|
},
|
|
@@ -85,6 +90,12 @@ module.exports = {
|
|
|
85
90
|
template: "./dev/index.html",
|
|
86
91
|
buildTag: `prod-[contenthash]`,
|
|
87
92
|
hash: true,
|
|
93
|
+
minify: {
|
|
94
|
+
removeComments: true,
|
|
95
|
+
collapseWhitespace: true,
|
|
96
|
+
minifyCSS: true,
|
|
97
|
+
minifyJS: true,
|
|
98
|
+
},
|
|
88
99
|
templateParameters: (compilation, options) => {
|
|
89
100
|
const hash = crypto.createHash("sha1");
|
|
90
101
|
hash.update(compilation.hash);
|
|
@@ -110,6 +121,8 @@ module.exports = {
|
|
|
110
121
|
{ from: "dev/manifest.json", to: "manifest.json" }, // Copy manifest
|
|
111
122
|
{ from: "dev/style.css", to: "style.css" },
|
|
112
123
|
{ from: "dev/robots.txt", to: "robots.txt" },
|
|
124
|
+
{ from: "dev/service-worker.js", to: "service-worker.js" },
|
|
125
|
+
{ from: "dev/offline.html", to: "offline.html" },
|
|
113
126
|
],
|
|
114
127
|
}),
|
|
115
128
|
],
|
package/webpack.dev.js
CHANGED
|
@@ -3,10 +3,12 @@ const path = require("path");
|
|
|
3
3
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
4
4
|
const TerserWebpackPlugin = require("terser-webpack-plugin");
|
|
5
5
|
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
|
|
6
|
+
const crypto = require("crypto");
|
|
6
7
|
|
|
7
8
|
module.exports = {
|
|
8
9
|
mode: "development",
|
|
9
10
|
entry: "./src/index.js",
|
|
11
|
+
devtool: "cheap-module-source-map",
|
|
10
12
|
devServer: {
|
|
11
13
|
static: {
|
|
12
14
|
directory: path.join(__dirname, "dev"),
|
|
@@ -18,6 +20,7 @@ module.exports = {
|
|
|
18
20
|
output: {
|
|
19
21
|
filename: "[name].bundle.js",
|
|
20
22
|
path: `${__dirname}/dev`,
|
|
23
|
+
publicPath: "/",
|
|
21
24
|
clean: true,
|
|
22
25
|
},
|
|
23
26
|
module: {
|
|
@@ -89,6 +92,21 @@ module.exports = {
|
|
|
89
92
|
new htmlWebpackPlugin({
|
|
90
93
|
title: "AFront",
|
|
91
94
|
template: `${__dirname}/dev/index.html`,
|
|
95
|
+
filename: "index.html",
|
|
96
|
+
hash: true, // This will add the hash in the injected scripts
|
|
97
|
+
templateParameters: (compilation) => {
|
|
98
|
+
const hash = crypto.createHash("sha1");
|
|
99
|
+
hash.update(compilation.hash);
|
|
100
|
+
const sha1Hash = hash.digest("hex");
|
|
101
|
+
return {
|
|
102
|
+
htmlWebpackPlugin: {
|
|
103
|
+
options: {
|
|
104
|
+
title: "AFront",
|
|
105
|
+
buildTag: `dev-${sha1Hash}`, // Set the build tag with the hash for dev
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
},
|
|
92
110
|
}),
|
|
93
111
|
],
|
|
94
112
|
};
|
package/webpack.prod.js
CHANGED
|
@@ -12,6 +12,7 @@ module.exports = {
|
|
|
12
12
|
output: {
|
|
13
13
|
filename: "static/js/[name]-[contenthash].js",
|
|
14
14
|
path: path.resolve(__dirname, "build-prod"),
|
|
15
|
+
publicPath: "/",
|
|
15
16
|
clean: true,
|
|
16
17
|
},
|
|
17
18
|
module: {
|
|
@@ -72,6 +73,9 @@ module.exports = {
|
|
|
72
73
|
minimizer: [
|
|
73
74
|
new TerserWebpackPlugin({
|
|
74
75
|
terserOptions: {
|
|
76
|
+
compress: {
|
|
77
|
+
drop_console: false,
|
|
78
|
+
},
|
|
75
79
|
format: {
|
|
76
80
|
comments: false,
|
|
77
81
|
},
|
|
@@ -80,6 +84,9 @@ module.exports = {
|
|
|
80
84
|
}),
|
|
81
85
|
new CssMinimizerPlugin(),
|
|
82
86
|
],
|
|
87
|
+
splitChunks: {
|
|
88
|
+
chunks: "all", // Automatically split vendor and app code
|
|
89
|
+
},
|
|
83
90
|
},
|
|
84
91
|
plugins: [
|
|
85
92
|
new HtmlWebpackPlugin({
|
|
@@ -90,6 +97,8 @@ module.exports = {
|
|
|
90
97
|
minify: {
|
|
91
98
|
removeComments: true,
|
|
92
99
|
collapseWhitespace: true,
|
|
100
|
+
minifyCSS: true,
|
|
101
|
+
minifyJS: true,
|
|
93
102
|
},
|
|
94
103
|
templateParameters: (compilation) => {
|
|
95
104
|
const hash = crypto.createHash("sha1");
|
|
@@ -116,12 +125,12 @@ module.exports = {
|
|
|
116
125
|
{ from: "dev/manifest.json", to: "manifest.json" },
|
|
117
126
|
{ from: "dev/style.css", to: "style.css" },
|
|
118
127
|
{ from: "dev/robots.txt", to: "robots.txt" },
|
|
128
|
+
{ from: "dev/service-worker.js", to: "service-worker.js" },
|
|
129
|
+
{ from: "dev/offline.html", to: "offline.html" },
|
|
119
130
|
],
|
|
120
131
|
}),
|
|
121
132
|
],
|
|
122
133
|
performance: {
|
|
123
134
|
hints: "warning",
|
|
124
|
-
maxEntrypointSize: 400000,
|
|
125
|
-
maxAssetSize: 400000,
|
|
126
135
|
},
|
|
127
136
|
};
|
package/webpack.ssr.prod.js
CHANGED
|
@@ -10,6 +10,7 @@ module.exports = {
|
|
|
10
10
|
output: {
|
|
11
11
|
path: path.resolve(__dirname, "build-prod-ssr"),
|
|
12
12
|
filename: "ssr.prod.js",
|
|
13
|
+
publicPath: "/",
|
|
13
14
|
clean: true,
|
|
14
15
|
libraryTarget: "commonjs2",
|
|
15
16
|
},
|
|
@@ -72,6 +73,9 @@ module.exports = {
|
|
|
72
73
|
minimizer: [
|
|
73
74
|
new TerserWebpackPlugin({
|
|
74
75
|
terserOptions: {
|
|
76
|
+
compress: {
|
|
77
|
+
drop_console: false,
|
|
78
|
+
},
|
|
75
79
|
format: {
|
|
76
80
|
comments: false,
|
|
77
81
|
},
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@import url(https://fonts.googleapis.com/css2?family=Rubik:wght@400;500;600;700&display=swap);.asggen-khZCOtF{align-items:center;display:flex;height:100vh;justify-content:center}.asggen-DnF_4DH{height:auto;width:150px}:root{--light:#fff;--dark:#000;--color-white-100:#fff;--color-white-200:#e4e6e7;--color-white-300:#c9cccf;--color-white-400:#a1a6aa;--color-white-500:#798086;--color-black-100:#14191f;--color-black-200:#101419;--color-black-300:#0c0f13;--color-black-400:#0c0f13;--color-black-500:#080a0c;--color-black-600:#060709;--color-black-700:#040506;--color-black-800:#020303;--color-blue-100:#dcebfe;--color-blue-200:#bedbfe;--color-blue-300:#91c3fd;--color-blue-400:#61a6fa;--color-blue-500:#3c83f6;--color-blue-600:#2463eb;--color-blue-700:#1d4fd7;--color-blue-800:#1e3fae;--color-blue-900:#1e3b8a;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 16px 32px -16px rgba(0,0,0,.1),0 0 0 1px rgba(0,0,0,.1);--base__color-2__rgb:32,32,32;--shadow-small:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06);--shadow-medium:0 4px 6px -1px rgba(0,0,0,.1),0 2px 4px -1px rgba(0,0,0,.06);--shadow-large:0 10px 15px -3px rgba(0,0,0,.1),0 4px 6px -2px rgba(0,0,0,.05)}*,:after,:before{box-sizing:border-box;list-style:none;list-style-type:none;margin:0;padding:0;text-decoration:none;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-rendering:optimizeLegibility}html{box-sizing:inherit;font-size:100%;scroll-behavior:smooth}body,html{height:-webkit-fill-available}body{font-family:Rubik,sans-serif;font-size:clamp(1rem,2vw,1.125rem);font-weight:400;line-height:1.5;min-width:320px}main{overflow:hidden}a,button{background:none;border:none;box-shadow:none;cursor:pointer;outline:none;text-decoration:none;user-select:none}a{color:var(--color-black-400)}img,video{display:block;height:auto;max-width:100%;object-fit:cover}.asggen-vCnhqcW{margin:0 auto;padding:6rem 0 8rem}.asggen-yYmSvug{height:auto;margin:0 auto;max-width:75rem}.asggen-k7ux6uU{margin-bottom:1rem;text-align:center;vertical-align:middle}.asggen-GSXjAs2{font-size:clamp(2.648rem,6vw,4.241rem)}.asggen-GSXjAs2,.asggen-I9IojjR{font-family:inherit;font-weight:700;letter-spacing:-1px;line-height:1.15}.asggen-I9IojjR{font-size:clamp(2.179rem,5vw,3.176rem)}.asggen-FDKWcrI{font-family:inherit;font-size:clamp(1.794rem,4vw,2.379rem);font-weight:700;letter-spacing:-1px;line-height:1.25}.asggen-SbGaSDq{font-size:clamp(1.476rem,3vw,1.782rem);font-weight:600}.asggen-SbGaSDq,.asggen-kc5w7ZM{font-family:inherit;line-height:1.5}.asggen-kc5w7ZM{font-size:clamp(1.215rem,2vw,1.335rem);font-weight:500}.asggen-ypntYRK{font-family:inherit;font-size:clamp(1rem,2vw,1.125rem);text-wrap:balance}.asggen-XT_r9I4{border:none;border-radius:.75rem;display:inline-block;font-family:inherit;font-size:1rem;font-weight:500;line-height:1.5;outline:none;text-align:center;text-transform:unset;user-select:none;vertical-align:middle;white-space:nowrap}.asggen-ik053am{align-items:center;column-gap:.5rem;display:inline-flex;justify-content:center}.asggen-e3fixws.asggen-YFITMpr{align-items:center;background-color:var(--color-black-200);border-bottom:none;display:flex;height:2.7rem;justify-content:center;line-height:0;margin-left:0;padding:.75rem 2rem}.asggen-bremE3g{fill:#fff;height:1rem;margin-left:1rem}.asggen-e3fixws.asggen-YFITMpr:hover{border-bottom:2px solid var(--color-blue-600)}.asggen-iNmPF4j{background-color:var(--color-white-100);box-shadow:var(--shadow-medium);color:var(--color-black-500);padding:.75rem 2rem}.asggen-FaJ4Ou8{height:auto;left:0;margin:0 auto;position:fixed;top:0;transition:all .3s ease;width:100%;z-index:100}.asggen-FaJ4Ou8.asggen-zfxwI26{background:var(--light);background-color:rgba(var(--light),.2);box-shadow:var(--shadow-medium)}.asggen-FaJ4Ou8.asggen-zfxwI26,.asggen-QfNYU76{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-bottom:1px solid var(--color-blue-800)}.asggen-QfNYU76{background-color:rgba(#ffffff,.2);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.asggen-b2RQ1kV{align-items:center;column-gap:1.25rem;display:flex;flex-direction:row;height:4.25rem;justify-content:flex-start;margin:0 auto;width:100%}.asggen-EVWqcuk{font-family:inherit;font-size:1.6rem;font-weight:600;letter-spacing:-1px;line-height:1.5;margin-bottom:0}.asggen-b2RQ1kV.asggen-yYmSvug{margin-bottom:0;padding:0 1.25rem}.asggen-b2RQ1kV.asggen-yYmSvug a:hover{border-bottom:2px solid var(--color-black-800)}.asggen-DIqmOCa.asggen-uIPgGK7{padding:.5rem 1.5rem}.asggen-DIqmOCa.asggen-uIPgGK7:hover{background-color:rgba(35,39,47,.05);border-bottom:none!important;border-radius:3rem}.asggen-F6t44Vy{background-color:var(--light);box-shadow:var(--shadow-medium);height:auto;left:0;position:fixed;top:-100%;width:100%}.asggen-F6t44Vy.asggen-E8o0IXn{border-top:1px solid var(--color-blue-800);height:100vh;top:68px;width:100%}.asggen-F6t44Vy.asggen-E8o0IXn .asggen-yMiHRly{border-bottom:.75px solid #000;gap:.2rem;padding:1rem}.asggen-F6t44Vy.asggen-hcpN3fG{opacity:0;transition:opacity .4s ease-in-out;visibility:hidden}.asggen-yMiHRly{display:flex;justify-content:space-around;overflow-x:auto;row-gap:1.25rem;-ms-overflow-style:none;scrollbar-width:none}.asggen-yMiHRly::-webkit-scrollbar{display:none}.asggen-DIqmOCa{font-size:1rem;line-height:1.5;text-transform:uppercase}.asggen-DIqmOCa,.asggen-YFITMpr{font-family:inherit;font-weight:500;margin-bottom:0}.asggen-YFITMpr{background-color:var(--color-blue-600);border-radius:.75rem;box-shadow:var(--shadow-medium);color:var(--light);display:inline-block;font-size:.875rem;line-height:1.25;margin-left:auto;padding:.65rem 1.5rem;text-align:center;text-transform:capitalize;user-select:none;white-space:nowrap}@media only screen and (min-width:48rem){.asggen-F6t44Vy{background:none;box-shadow:none;height:auto;margin-left:auto;padding:0;position:relative;top:0;transition:none;width:auto}.asggen-F6t44Vy.asggen-hcpN3fG{opacity:1;transition:opacity .4s ease-in-out;visibility:visible}.asggen-yMiHRly{column-gap:2rem;display:flex;flex-direction:row;margin:0 auto}.asggen-DIqmOCa{text-transform:capitalize}.asggen-YFITMpr{margin-left:2rem}}.asggen-LsM7ZjZ{background:none;border:none;cursor:pointer;display:block;height:1.15rem;order:-1;outline:none;position:relative;transform:rotate(0deg);transition:.35s ease;user-select:none;visibility:visible;width:1.6rem;z-index:10}@media only screen and (min-width:48rem){.asggen-LsM7ZjZ{display:none;visibility:hidden}}.asggen-_Tz4jNZ{background-color:var(--color-black-800);border:none;border-radius:1rem;display:block;height:2px;left:0;opacity:1;outline:none;position:absolute;transform:rotate(0deg);transition:.25s ease-in-out;width:100%}.asggen-_Tz4jNZ:first-child{top:0}.asggen-_Tz4jNZ:nth-child(2){top:.5rem;width:70%}.asggen-_Tz4jNZ:nth-child(3){top:1rem}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:first-child{top:.5rem;transform:rotate(135deg)}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:nth-child(2){opacity:0;visibility:hidden}.asggen-LsM7ZjZ.asggen-E8o0IXn .asggen-_Tz4jNZ:nth-child(3){top:.5rem;transform:rotate(-135deg)}.asggen-Y2cbpWB{align-items:center;display:grid;padding:0 1rem;position:relative;row-gap:3rem}@media only screen and (min-width:48rem){.asggen-Y2cbpWB{grid-template-columns:repeat(2,minmax(0,1fr));justify-content:center}}@media only screen and (min-width:64rem){.asggen-Y2cbpWB{column-gap:4rem;grid-template-columns:1fr max-content;margin-top:3rem}}@keyframes asggen-tnBiLe1{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}.asggen-lxgipYD{display:block;height:18rem;justify-self:center;margin-top:2rem;max-width:18rem;object-fit:cover}@media only screen and (min-width:48rem){.asggen-lxgipYD{height:20rem;max-width:20rem;order:1}}@media only screen and (min-width:64rem){.asggen-lxgipYD{height:25rem;margin-right:1rem;max-width:25rem}}.asggen-Dz7DCBs{align-items:flex-start;display:flex;flex-direction:column;row-gap:1.75rem}.asggen-vOcQaWi{background-color:#fff;color:#333;overflow:hidden;padding:2.5rem 0;position:relative}.asggen-vOcQaWi:before{color:rgba(0,0,0,.05);content:"AFront";font-size:20rem;left:50%;pointer-events:none;position:absolute;top:70%;transform:translate(-50%,-50%);white-space:nowrap;z-index:0}.asggen-Kou5AQf{align-items:flex-start;display:flex;flex-wrap:wrap;justify-content:space-between;margin:0 auto;max-width:75rem;padding:0 1.25rem;position:relative;z-index:1}.asggen-qKHdMcH{flex:1;margin-bottom:2rem}.asggen-slMjjDc{color:var(--color-black-400);font-size:1.5rem;font-weight:700;text-decoration:none}.asggen-cazhRP1{color:#8b8b8b;font-size:.875rem;margin-top:.625rem}.asggen-a78uDCQ{display:flex;flex:2;flex-wrap:wrap;justify-content:space-between}.asggen-_UtUx79{flex:1;margin-bottom:2rem;min-width:12rem}.asggen-N07cS94{color:#777;font-size:1rem;margin-bottom:.625rem}.asggen-vfO0fUG{list-style:none;padding:0}.asggen-iRs41ng{color:#909090;display:block;font-size:.875rem;margin-bottom:.5rem;text-decoration:none;transition:color .3s ease}.asggen-iRs41ng:hover{color:#3a3a3a}.asggen-w3fUm2Q{color:#777;font-size:.875rem;margin-top:2.5rem;text-align:center}.asggen-FTFjC4T{margin-bottom:.625rem}.asggen-HczpTuP{display:flex;flex-wrap:wrap;justify-content:center}.asggen-rUwKNuA{color:#909090;font-size:1.125rem;margin:0 .625rem;text-decoration:none;transition:color .3s ease}.asggen-rUwKNuA:hover{color:#3a3a3a}@media (max-width:768px){.asggen-Kou5AQf,.asggen-a78uDCQ{align-items:center;flex-direction:column}.asggen-a78uDCQ{text-align:center}.asggen-_UtUx79{margin-bottom:1.5rem}.asggen-FTFjC4T{font-size:.75rem}.asggen-HczpTuP{margin-top:1rem}.asggen-rUwKNuA{font-size:1rem;margin:0 .5rem}.asggen-vOcQaWi:before{content:"AFront";font-size:5rem;top:82%}}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunkafront=self.webpackChunkafront||[]).push([[3],{572:(e,t,a)=>{const{useEffect:n}=a(540);function s(e,t){if(t){let a=document.querySelector(`meta[name="${e}"]`);a?a.setAttribute("content",t):(a=document.createElement("meta"),a.setAttribute("name",e),a.setAttribute("content",t),document.head.appendChild(a))}}e.exports=function({title:e,description:t,keywords:a,context:r}){n((()=>{"undefined"!=typeof document&&(document.title=e,s("title",e),s("description",t),s("keywords",a))}),[e,t,a]),r&&(r.title=e,r.description=t,r.keywords=a)}},210:(e,t,a)=>{"use strict";a.d(t,{A:()=>r});var n=a(540),s="asggen-UsaK2zv";const r=function(e){var t=e.children;return n.createElement("div",{className:"asggen-y0_CWMe"},n.createElement("div",{className:"asggen-wv3xAF6"},n.createElement("div",{className:"".concat(s," ").concat("asggen-F7uI_Qg")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-HPCM5Cq")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-oGWLGVI")}),n.createElement("div",{className:"".concat(s," ").concat("asggen-hpj3_CH")})),t)}},3:(e,t,a)=>{"use strict";a.r(t),a.d(t,{default:()=>m});var n=a(540),s=a(572),r=a.n(s),c="asggen-fs7zTHj",o="asggen-kTCHPjF",l="asggen-ZHWXW17",i=a(210);const m=function(e){var t=e.context;return r()({title:"Support - AFront",description:"Get support for AFront, a front-end JavaScript library for seamless server-side rendering.",keywords:"support, AFront, server-side rendering, JavaScript",context:t}),n.createElement(i.A,null,n.createElement("div",{className:"asggen-kJBmVCe"},n.createElement("h1",{className:"asggen-xhjDCMD"},"Need Assistance?"),n.createElement("p",{className:"asggen-RwTbVGb"},"AFront is a cutting-edge front-end JavaScript library designed for seamless server-side rendering (SSR). We're committed to providing you with top-notch support to ensure your experience is smooth and productive."),n.createElement("div",{className:"asggen-_9xGCTU"},n.createElement("div",{className:c},n.createElement("h2",{className:l},"Technical Assistance"),n.createElement("p",{className:o},"Our dedicated technical support team is available around the clock to resolve any issues you may face with AFront. Connect with us through email or our support portal for prompt assistance.")),n.createElement("div",{className:c},n.createElement("h2",{className:l},"Product Information"),n.createElement("p",{className:o},"Curious about AFront’s capabilities? Reach out to our sales team for detailed insights on features, benefits, and how our library can enhance your web development projects.")),n.createElement("div",{className:c},n.createElement("h2",{className:l},"Community and Forums"),n.createElement("p",{className:o},"Join our vibrant community forums to discuss AFront with fellow developers, exchange tips, and troubleshoot common issues collaboratively."))),n.createElement("div",{className:"asggen-pmghQyO"},n.createElement("h2",{className:l},"Frequently Asked Questions"),n.createElement("ul",{className:"asggen-F8poZey"},n.createElement("li",null,"What is AFront and how does it work?"),n.createElement("li",null,"How do I get started with AFront?"),n.createElement("li",null,"Where can I find documentation and tutorials?"),n.createElement("li",null,"How can I report a bug or request a feature?"))),n.createElement("a",{href:"/",className:"asggen-cwDmzqU"},"Back to Homepage")))}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunkafront=self.webpackChunkafront||[]).push([[41],{572:(e,t,n)=>{const{useEffect:a}=n(540);function c(e,t){if(t){let n=document.querySelector(`meta[name="${e}"]`);n?n.setAttribute("content",t):(n=document.createElement("meta"),n.setAttribute("name",e),n.setAttribute("content",t),document.head.appendChild(n))}}e.exports=function({title:e,description:t,keywords:n,context:s}){a((()=>{"undefined"!=typeof document&&(document.title=e,c("title",e),c("description",t),c("keywords",n))}),[e,t,n]),s&&(s.title=e,s.description=t,s.keywords=n)}},210:(e,t,n)=>{"use strict";n.d(t,{A:()=>s});var a=n(540),c="asggen-UsaK2zv";const s=function(e){var t=e.children;return a.createElement("div",{className:"asggen-y0_CWMe"},a.createElement("div",{className:"asggen-wv3xAF6"},a.createElement("div",{className:"".concat(c," ").concat("asggen-F7uI_Qg")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-HPCM5Cq")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-oGWLGVI")}),a.createElement("div",{className:"".concat(c," ").concat("asggen-hpj3_CH")})),t)}},488:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>i});var a=n(540),c=n(210);const s=n.p+"static/media/52f06bb716d4ecad087a.png",r=n.p+"static/media/adeaead125c45715106d.svg";var l=n(572),o=n.n(l),m=n(833);const i=function(e){var t=e.context;return o()({title:"AFront by Asggen Inc.",description:"Home for all AFront products and services.",keywords:"Home, Afront, help",context:t}),a.createElement(c.A,null,a.createElement("main",null,a.createElement("section",{className:m.uW},a.createElement("div",{className:"".concat(m.kL," ").concat(m.vd)},a.createElement("img",{className:m._e,src:s,alt:"banner"}),a.createElement("div",{className:m.B4},a.createElement("h1",{className:m.nX},"Empower Your Front-End with AFront"),a.createElement("p",{className:m.FY},"AFront streamlines front-end development with robust tools and",a.createElement("b",null," seamless server-side rendering (SSSR)"),". Build dynamic, high-performance web experiences effortlessly."),a.createElement("div",null,a.createElement("a",{href:"/",className:"".concat(m.OK," ").concat(m.DG)},"Get Started"," ",a.createElement("img",{className:m.h_,src:r}))))))))}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunkafront=self.webpackChunkafront||[]).push([[573],{573:(e,a,s)=>{s.r(a),s.d(a,{default:()=>n});var t=s(540);const n=function(){return t.createElement("div",{className:"asggen-CTEvvlo"},t.createElement("h2",{className:"asggen-FVOWslk"},"Oops! The page you're looking for doesn't exist."),t.createElement("p",{className:"asggen-Bk8OzYB"},"It seems you’ve taken a wrong turn. Let’s get you back on track!"),t.createElement("a",{href:"/",className:"asggen-wbWn6vo"},"Go to Homepage"))}}}]);
|