slicejs-web-framework 2.4.4 → 2.4.5
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/Slice/Slice.js
CHANGED
|
@@ -254,30 +254,20 @@ async function init() {
|
|
|
254
254
|
return;
|
|
255
255
|
}
|
|
256
256
|
|
|
257
|
-
// 1.
|
|
258
|
-
// In production
|
|
259
|
-
|
|
260
|
-
try {
|
|
261
|
-
const envRes = await fetch('/slice-env.json', { cache: 'no-store' });
|
|
262
|
-
if (envRes.ok) {
|
|
263
|
-
const env = await envRes.json();
|
|
264
|
-
envMode = env.mode; // 'development' | 'production'
|
|
265
|
-
}
|
|
266
|
-
} catch (error) {
|
|
267
|
-
// Endpoint not available — normal in production
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
// 2. Fetch bundle config (existing logic, unchanged)
|
|
257
|
+
// 1+2. Fetch mode endpoint and bundle config in parallel — both are independent.
|
|
258
|
+
// In production, /slice-env.json returns 404 (catch is expected and normal).
|
|
259
|
+
// bundleConfigJson.production serves as a mode fallback when env endpoint is absent.
|
|
271
260
|
let frameworkClasses = null;
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
261
|
+
const [envResult, configResult] = await Promise.all([
|
|
262
|
+
fetch('/slice-env.json', { cache: 'no-store' })
|
|
263
|
+
.then(r => r.ok ? r.json() : null)
|
|
264
|
+
.catch(() => null),
|
|
265
|
+
fetch('/bundles/bundle.config.json', { cache: 'no-store' })
|
|
266
|
+
.then(r => r.ok ? r.json() : null)
|
|
267
|
+
.catch(() => null)
|
|
268
|
+
]);
|
|
269
|
+
const envMode = envResult?.mode ?? null;
|
|
270
|
+
const bundleConfigJson = configResult;
|
|
281
271
|
|
|
282
272
|
// 3. Determine canonical mode: env endpoint takes precedence, then bundle config
|
|
283
273
|
let resolvedMode;
|
|
@@ -289,6 +279,17 @@ async function init() {
|
|
|
289
279
|
resolvedMode = 'development';
|
|
290
280
|
}
|
|
291
281
|
|
|
282
|
+
// Pre-fetch critical bundle to warm the browser HTTP cache while the framework
|
|
283
|
+
// bundle is downloading and executing. fetch() downloads bytes without evaluating
|
|
284
|
+
// the module, so the auto-registration block runs safely later when window.slice
|
|
285
|
+
// already exists. Errors are silently ignored — import() will retry if needed.
|
|
286
|
+
const criticalBundleUrl = (resolvedMode === 'production' && bundleConfigJson?.bundles?.critical?.file)
|
|
287
|
+
? `/bundles/${bundleConfigJson.bundles.critical.file}`
|
|
288
|
+
: null;
|
|
289
|
+
if (criticalBundleUrl) {
|
|
290
|
+
fetch(criticalBundleUrl).catch(() => {});
|
|
291
|
+
}
|
|
292
|
+
|
|
292
293
|
// 4. Load framework classes.
|
|
293
294
|
// In production the bundler generates slice-bundle.framework.js which
|
|
294
295
|
// sets window.SLICE_FRAMEWORK_CLASSES. In dev mode always use individual
|
|
@@ -336,12 +337,18 @@ async function init() {
|
|
|
336
337
|
if (window.slice.controller.bundleConfig) {
|
|
337
338
|
const config = window.slice.controller.bundleConfig;
|
|
338
339
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
340
|
+
const criticalFile = config?.bundles?.critical?.file;
|
|
341
|
+
if (criticalFile) {
|
|
342
|
+
// Bundle auto-registers itself on import via its own registration block.
|
|
343
|
+
// The block pushes its registerBundle() Promise to window.__slicePendingRegistrations
|
|
344
|
+
// so we can await full chunk processing before continuing to build('Loading').
|
|
345
|
+
// criticalBundleUrl was pre-fetched above — import() reuses the cached bytes.
|
|
346
|
+
await import(criticalBundleUrl);
|
|
347
|
+
if (window.__slicePendingRegistrations?.length) {
|
|
348
|
+
await Promise.all(window.__slicePendingRegistrations);
|
|
349
|
+
window.__slicePendingRegistrations = [];
|
|
350
|
+
}
|
|
351
|
+
}
|
|
345
352
|
|
|
346
353
|
const routeBundles = config?.routeBundles || {};
|
|
347
354
|
const initialPath = window.location.pathname || '/';
|
package/package.json
CHANGED
|
@@ -6,200 +6,196 @@ slice-home-page {
|
|
|
6
6
|
color: var(--font-primary-color);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
|
-
/*
|
|
9
|
+
/* ── HERO ── */
|
|
10
10
|
.hero-section {
|
|
11
|
-
position: relative;
|
|
12
11
|
min-height: 80vh;
|
|
13
12
|
display: flex;
|
|
14
13
|
align-items: center;
|
|
15
14
|
justify-content: center;
|
|
16
15
|
text-align: center;
|
|
17
|
-
padding: 2rem;
|
|
16
|
+
padding: 7rem 2rem 5rem;
|
|
18
17
|
background-color: var(--primary-background-color);
|
|
18
|
+
position: relative;
|
|
19
19
|
overflow: hidden;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.hero-section::before {
|
|
23
|
+
content: '';
|
|
24
|
+
position: absolute;
|
|
25
|
+
top: -150px;
|
|
26
|
+
left: 50%;
|
|
27
|
+
transform: translateX(-50%);
|
|
28
|
+
width: 700px;
|
|
29
|
+
height: 700px;
|
|
30
|
+
background: radial-gradient(
|
|
31
|
+
circle,
|
|
32
|
+
rgba(var(--primary-color-rgb), 0.07) 0%,
|
|
33
|
+
transparent 70%
|
|
34
|
+
);
|
|
35
|
+
pointer-events: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
22
38
|
.hero-content {
|
|
23
|
-
max-width:
|
|
39
|
+
max-width: 640px;
|
|
40
|
+
position: relative;
|
|
24
41
|
z-index: 1;
|
|
25
42
|
}
|
|
26
43
|
|
|
27
|
-
.hero-
|
|
44
|
+
.hero-badge {
|
|
45
|
+
display: inline-block;
|
|
46
|
+
background: rgba(var(--primary-color-rgb), 0.1);
|
|
47
|
+
color: var(--primary-color);
|
|
48
|
+
font-size: 0.75rem;
|
|
49
|
+
font-weight: 700;
|
|
50
|
+
letter-spacing: 0.08em;
|
|
51
|
+
text-transform: uppercase;
|
|
52
|
+
padding: 0.3rem 0.85rem;
|
|
53
|
+
border-radius: 20px;
|
|
28
54
|
margin-bottom: 1.5rem;
|
|
29
55
|
}
|
|
30
56
|
|
|
31
|
-
.hero-logo {
|
|
32
|
-
max-width: 150px;
|
|
33
|
-
height: auto;
|
|
34
|
-
/* Convertir el logo a una silueta */
|
|
35
|
-
filter: brightness(0) drop-shadow(0 0 8px var(--primary-color));
|
|
36
|
-
}
|
|
37
|
-
|
|
38
57
|
.hero-title {
|
|
39
58
|
font-size: 3rem;
|
|
40
|
-
|
|
59
|
+
font-weight: 800;
|
|
41
60
|
color: var(--font-primary-color);
|
|
61
|
+
line-height: 1.1;
|
|
62
|
+
margin-bottom: 1rem;
|
|
63
|
+
letter-spacing: -0.03em;
|
|
42
64
|
}
|
|
43
65
|
|
|
44
66
|
.hero-title .highlight {
|
|
45
67
|
color: var(--primary-color);
|
|
46
68
|
}
|
|
47
69
|
|
|
48
|
-
.hero-
|
|
49
|
-
font-size: 1.
|
|
50
|
-
margin-bottom: 1.5rem;
|
|
70
|
+
.hero-sub {
|
|
71
|
+
font-size: 1.05rem;
|
|
51
72
|
color: var(--font-secondary-color);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
.hero-description {
|
|
55
|
-
font-size: 1.1rem;
|
|
56
73
|
margin-bottom: 2rem;
|
|
57
74
|
line-height: 1.6;
|
|
58
75
|
}
|
|
59
76
|
|
|
60
|
-
.cta
|
|
77
|
+
.hero-cta {
|
|
61
78
|
display: flex;
|
|
62
|
-
gap:
|
|
79
|
+
gap: 0.75rem;
|
|
63
80
|
justify-content: center;
|
|
64
|
-
margin-
|
|
81
|
+
margin-bottom: 2.5rem;
|
|
65
82
|
}
|
|
66
83
|
|
|
67
|
-
|
|
84
|
+
.hero-chips {
|
|
85
|
+
display: flex;
|
|
86
|
+
gap: 0.5rem;
|
|
87
|
+
justify-content: center;
|
|
88
|
+
flex-wrap: wrap;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.hero-chip {
|
|
92
|
+
background: white;
|
|
93
|
+
border: 1px solid var(--disabled-color);
|
|
94
|
+
color: var(--primary-color);
|
|
95
|
+
font-size: 0.75rem;
|
|
96
|
+
font-weight: 600;
|
|
97
|
+
padding: 0.3rem 0.75rem;
|
|
98
|
+
border-radius: 20px;
|
|
99
|
+
box-shadow: var(--box-shadow-primary);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* ── FEATURES ── */
|
|
68
103
|
.features-section {
|
|
69
104
|
padding: 5rem 2rem;
|
|
70
|
-
background
|
|
105
|
+
background: white;
|
|
106
|
+
border-top: 1px solid var(--disabled-color);
|
|
71
107
|
}
|
|
72
108
|
|
|
73
|
-
.section-
|
|
109
|
+
.section-header {
|
|
74
110
|
text-align: center;
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
111
|
+
margin-bottom: 2.5rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.section-label {
|
|
115
|
+
font-size: 0.72rem;
|
|
116
|
+
font-weight: 700;
|
|
117
|
+
color: var(--accent-color);
|
|
118
|
+
text-transform: uppercase;
|
|
119
|
+
letter-spacing: 0.1em;
|
|
120
|
+
margin-bottom: 0.4rem;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.section-title {
|
|
124
|
+
font-size: 1.9rem;
|
|
125
|
+
font-weight: 800;
|
|
126
|
+
color: var(--font-primary-color);
|
|
127
|
+
letter-spacing: -0.02em;
|
|
78
128
|
}
|
|
79
129
|
|
|
80
130
|
.feature-grid {
|
|
81
131
|
display: grid;
|
|
82
132
|
grid-template-columns: repeat(3, 1fr);
|
|
83
|
-
gap: 2rem;
|
|
84
|
-
max-width:
|
|
133
|
+
gap: 1.2rem;
|
|
134
|
+
max-width: 820px;
|
|
85
135
|
margin: 0 auto;
|
|
86
136
|
}
|
|
87
137
|
|
|
88
138
|
.feature-item {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
transition:
|
|
139
|
+
background: var(--primary-background-color);
|
|
140
|
+
border-radius: 10px;
|
|
141
|
+
padding: 1.4rem 1.2rem;
|
|
142
|
+
border: 1px solid var(--disabled-color);
|
|
143
|
+
transition: box-shadow 0.2s, transform 0.15s;
|
|
94
144
|
}
|
|
95
145
|
|
|
96
146
|
.feature-item:hover {
|
|
97
|
-
|
|
98
|
-
|
|
147
|
+
box-shadow: var(--box-shadow-primary);
|
|
148
|
+
transform: translateY(-2px);
|
|
99
149
|
}
|
|
100
150
|
|
|
101
151
|
.feature-title {
|
|
102
|
-
font-size:
|
|
103
|
-
|
|
104
|
-
color: var(--primary-color);
|
|
152
|
+
font-size: 0.9rem;
|
|
153
|
+
font-weight: 700;
|
|
154
|
+
color: var(--font-primary-color);
|
|
155
|
+
margin-bottom: 0.35rem;
|
|
105
156
|
}
|
|
106
157
|
|
|
107
158
|
.feature-description {
|
|
108
|
-
|
|
109
|
-
|
|
159
|
+
font-size: 0.78rem;
|
|
160
|
+
color: var(--medium-color);
|
|
161
|
+
line-height: 1.5;
|
|
110
162
|
}
|
|
111
163
|
|
|
112
|
-
/*
|
|
113
|
-
.
|
|
164
|
+
/* ── SHOWCASE ── */
|
|
165
|
+
.showcase-section {
|
|
114
166
|
padding: 5rem 2rem;
|
|
115
|
-
background
|
|
167
|
+
background: var(--primary-background-color);
|
|
168
|
+
border-top: 1px solid var(--disabled-color);
|
|
116
169
|
}
|
|
117
170
|
|
|
118
|
-
.
|
|
119
|
-
text-align: center;
|
|
120
|
-
max-width: 800px;
|
|
121
|
-
margin: 0 auto 3rem auto;
|
|
122
|
-
color: var(--font-secondary-color);
|
|
123
|
-
font-size: 1.2rem;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
.examples-container {
|
|
171
|
+
.showcase-grid {
|
|
127
172
|
display: grid;
|
|
128
|
-
grid-template-columns: repeat(
|
|
129
|
-
gap: 3rem;
|
|
130
|
-
max-width: 1000px;
|
|
131
|
-
margin: 0 auto;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
.example-item {
|
|
135
|
-
display: flex;
|
|
136
|
-
flex-direction: column;
|
|
173
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
137
174
|
gap: 1rem;
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
border-radius: var(--border-radius-slice);
|
|
141
|
-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
.example-item h3 {
|
|
145
|
-
margin: 0;
|
|
146
|
-
font-size: 1.3rem;
|
|
147
|
-
color: var(--primary-color);
|
|
175
|
+
max-width: 860px;
|
|
176
|
+
margin: 0 auto;
|
|
148
177
|
}
|
|
149
178
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
179
|
+
.comp-card {
|
|
180
|
+
background: white;
|
|
181
|
+
border-radius: 10px;
|
|
182
|
+
padding: 1.3rem 1.2rem;
|
|
183
|
+
border: 1px solid var(--disabled-color);
|
|
184
|
+
box-shadow: 0 2px 8px rgba(var(--primary-color-rgb), 0.06);
|
|
155
185
|
}
|
|
156
186
|
|
|
157
|
-
.
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
187
|
+
.comp-label {
|
|
188
|
+
font-size: 0.65rem;
|
|
189
|
+
font-weight: 700;
|
|
190
|
+
color: var(--medium-color);
|
|
191
|
+
text-transform: uppercase;
|
|
192
|
+
letter-spacing: 0.1em;
|
|
193
|
+
margin-bottom: 0.75rem;
|
|
161
194
|
}
|
|
162
195
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
color: var(--primary-color-contrast);
|
|
196
|
+
.comp-demo {
|
|
197
|
+
display: flex;
|
|
198
|
+
align-items: center;
|
|
199
|
+
gap: 0.6rem;
|
|
200
|
+
flex-wrap: wrap;
|
|
169
201
|
}
|
|
170
|
-
|
|
171
|
-
.copyright {
|
|
172
|
-
margin-top: 1rem;
|
|
173
|
-
font-size: 0.9rem;
|
|
174
|
-
opacity: 0.8;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/* Responsive styles */
|
|
178
|
-
@media (max-width: 992px) {
|
|
179
|
-
.feature-grid {
|
|
180
|
-
grid-template-columns: repeat(2, 1fr);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
.examples-container {
|
|
184
|
-
grid-template-columns: 1fr;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
@media (max-width: 768px) {
|
|
189
|
-
.hero-title {
|
|
190
|
-
font-size: 2.5rem;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
.hero-subtitle {
|
|
194
|
-
font-size: 1.3rem;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
.feature-grid {
|
|
198
|
-
grid-template-columns: 1fr;
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
.cta-buttons {
|
|
202
|
-
flex-direction: column;
|
|
203
|
-
align-items: center;
|
|
204
|
-
}
|
|
205
|
-
}
|
|
@@ -1,49 +1,37 @@
|
|
|
1
1
|
<div class="home-page-container">
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
<section class="hero-section">
|
|
3
4
|
<div class="hero-content">
|
|
4
|
-
<div class="hero-
|
|
5
|
-
|
|
5
|
+
<div class="hero-badge">v2.4 · Vanilla JS Framework</div>
|
|
6
|
+
<h1 class="hero-title">Build your web app<br>one <span class="highlight">Slice</span> at a time</h1>
|
|
7
|
+
<p class="hero-sub">A lightweight, component-based framework for building web applications with vanilla JavaScript and web standards.</p>
|
|
8
|
+
<div class="hero-cta"></div>
|
|
9
|
+
<div class="hero-chips">
|
|
10
|
+
<span class="hero-chip">Button</span>
|
|
11
|
+
<span class="hero-chip">Input</span>
|
|
12
|
+
<span class="hero-chip">Switch</span>
|
|
13
|
+
<span class="hero-chip">Navbar</span>
|
|
14
|
+
<span class="hero-chip">Grid</span>
|
|
15
|
+
<span class="hero-chip">Card</span>
|
|
16
|
+
<span class="hero-chip">+ more</span>
|
|
6
17
|
</div>
|
|
7
|
-
<h1 class="hero-title">Welcome to <span class="highlight">Slice.js</span></h1>
|
|
8
|
-
<p class="hero-subtitle">Build Your Web App One Slice at a Time</p>
|
|
9
|
-
<p class="hero-description">
|
|
10
|
-
A modern, lightweight component-based framework for building web applications using vanilla JavaScript and web standards.
|
|
11
|
-
</p>
|
|
12
|
-
<div class="cta-buttons"></div>
|
|
13
18
|
</div>
|
|
14
|
-
</
|
|
19
|
+
</section>
|
|
15
20
|
|
|
16
21
|
<section class="features-section">
|
|
17
|
-
<
|
|
22
|
+
<div class="section-header">
|
|
23
|
+
<p class="section-label">Why Slice.js</p>
|
|
24
|
+
<h2 class="section-title">Everything you need, nothing you don't</h2>
|
|
25
|
+
</div>
|
|
18
26
|
<div class="feature-grid"></div>
|
|
19
27
|
</section>
|
|
20
28
|
|
|
21
|
-
<section class="
|
|
22
|
-
<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
</p>
|
|
26
|
-
<div class="examples-container"></div>
|
|
27
|
-
</section>
|
|
28
|
-
|
|
29
|
-
<section class="getting-started-section">
|
|
30
|
-
<h2 class="section-title">Get Started Now</h2>
|
|
31
|
-
<div class="code-sample">
|
|
32
|
-
<pre><code>
|
|
33
|
-
// Initialize a new Slice.js project
|
|
34
|
-
npm run slice:init
|
|
35
|
-
|
|
36
|
-
// Create a new component
|
|
37
|
-
npm run slice:create
|
|
38
|
-
|
|
39
|
-
// Start your application
|
|
40
|
-
npm run slice:start
|
|
41
|
-
</code></pre>
|
|
29
|
+
<section class="showcase-section">
|
|
30
|
+
<div class="section-header">
|
|
31
|
+
<p class="section-label">Component Showcase</p>
|
|
32
|
+
<h2 class="section-title">Ready-to-use components</h2>
|
|
42
33
|
</div>
|
|
34
|
+
<div class="showcase-grid"></div>
|
|
43
35
|
</section>
|
|
44
36
|
|
|
45
|
-
|
|
46
|
-
<p>Made with ❤️ using Slice.js</p>
|
|
47
|
-
<p class="copyright">© 2025 Slice.js Framework</p>
|
|
48
|
-
</footer>
|
|
49
|
-
</div>
|
|
37
|
+
</div>
|
|
@@ -2,15 +2,20 @@ export default class HomePage extends HTMLElement {
|
|
|
2
2
|
constructor(props) {
|
|
3
3
|
super();
|
|
4
4
|
slice.attachTemplate(this);
|
|
5
|
-
|
|
6
|
-
this.$examplesContainer = this.querySelector('.examples-container');
|
|
7
|
-
|
|
8
5
|
slice.controller.setComponentProps(this, props);
|
|
9
6
|
this.debuggerProps = [];
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
async init() {
|
|
13
|
-
|
|
10
|
+
await Promise.all([
|
|
11
|
+
this._buildNavbar(),
|
|
12
|
+
this._buildHeroCta(),
|
|
13
|
+
this._buildFeatures(),
|
|
14
|
+
this._buildShowcase(),
|
|
15
|
+
]);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
async _buildNavbar() {
|
|
14
19
|
const navbar = await slice.build('Navbar', {
|
|
15
20
|
position: 'fixed',
|
|
16
21
|
logo: {
|
|
@@ -20,177 +25,186 @@ export default class HomePage extends HTMLElement {
|
|
|
20
25
|
items: [
|
|
21
26
|
{ text: 'Home', path: '/' },
|
|
22
27
|
{ text: 'Playground', path: '/Playground' },
|
|
23
|
-
|
|
24
28
|
],
|
|
25
29
|
buttons: [
|
|
26
30
|
{
|
|
27
31
|
value: 'Change Theme',
|
|
28
32
|
onClickCallback: async () => {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
} else {
|
|
35
|
-
await slice.setTheme('Slice');
|
|
36
|
-
}
|
|
33
|
+
const current = slice.stylesManager.themeManager.currentTheme;
|
|
34
|
+
const next = current === 'Slice' ? 'Light'
|
|
35
|
+
: current === 'Light' ? 'Dark'
|
|
36
|
+
: 'Slice';
|
|
37
|
+
await slice.setTheme(next);
|
|
37
38
|
},
|
|
38
39
|
},
|
|
39
40
|
],
|
|
40
41
|
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
this.insertBefore(navbar, this.firstChild);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async _buildHeroCta() {
|
|
46
|
+
const docsBtn = await slice.build('Button', {
|
|
44
47
|
value: 'Documentation',
|
|
45
|
-
onClickCallback: () =>
|
|
46
|
-
|
|
48
|
+
onClickCallback: () =>
|
|
49
|
+
window.open('https://slice-js-docs.vercel.app/Documentation', '_blank'),
|
|
47
50
|
customColor: {
|
|
48
51
|
button: 'var(--primary-color)',
|
|
49
|
-
label: 'var(--primary-color-contrast)'
|
|
50
|
-
}
|
|
52
|
+
label: 'var(--primary-color-contrast)',
|
|
53
|
+
},
|
|
51
54
|
});
|
|
52
|
-
|
|
53
|
-
const
|
|
55
|
+
|
|
56
|
+
const componentsBtn = await slice.build('Button', {
|
|
54
57
|
value: 'Components Library',
|
|
55
|
-
onClickCallback: () =>
|
|
58
|
+
onClickCallback: () =>
|
|
59
|
+
window.open('https://slice-js-docs.vercel.app/Documentation/Visual', '_blank'),
|
|
56
60
|
customColor: {
|
|
57
|
-
button: 'var(--secondary-color)',
|
|
58
|
-
label: 'var(--
|
|
59
|
-
}
|
|
61
|
+
button: 'var(--secondary-background-color)',
|
|
62
|
+
label: 'var(--primary-color)',
|
|
63
|
+
},
|
|
60
64
|
});
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
// Crear features section con un enfoque diferente (sin usar Cards)
|
|
67
|
-
await this.createFeatures();
|
|
68
|
-
|
|
69
|
-
// Crear ejemplos de componentes
|
|
70
|
-
await this.createComponentExamples();
|
|
71
|
-
|
|
72
|
-
// Configurar la sección de código de inicio
|
|
73
|
-
await this.setupGettingStartedSection();
|
|
74
|
-
|
|
75
|
-
// Añadir la barra de navegación al inicio del componente
|
|
76
|
-
this.insertBefore(navbar, this.firstChild);
|
|
65
|
+
|
|
66
|
+
const cta = this.querySelector('.hero-cta');
|
|
67
|
+
cta.appendChild(docsBtn);
|
|
68
|
+
cta.appendChild(componentsBtn);
|
|
77
69
|
}
|
|
78
|
-
|
|
79
|
-
async
|
|
80
|
-
// Definir características
|
|
70
|
+
|
|
71
|
+
async _buildFeatures() {
|
|
81
72
|
const features = [
|
|
82
73
|
{
|
|
83
74
|
title: 'Component-Based',
|
|
84
|
-
description: 'Build your app using modular, reusable components following web standards.'
|
|
75
|
+
description: 'Build your app using modular, reusable components following web standards.',
|
|
85
76
|
},
|
|
86
77
|
{
|
|
87
|
-
title: '
|
|
88
|
-
description: '
|
|
78
|
+
title: 'Themeable',
|
|
79
|
+
description: 'Swap themes at runtime. Ships with Slice, Light, Dark and more.',
|
|
89
80
|
},
|
|
90
81
|
{
|
|
91
|
-
title: '
|
|
92
|
-
description: '
|
|
82
|
+
title: 'Lightweight',
|
|
83
|
+
description: 'No heavy runtime. Just vanilla JavaScript and web standards.',
|
|
93
84
|
},
|
|
94
85
|
{
|
|
95
|
-
title: '
|
|
96
|
-
description: '
|
|
86
|
+
title: 'Built-in Router',
|
|
87
|
+
description: 'Client-side routing with MultiRoute — no extra libraries needed.',
|
|
97
88
|
},
|
|
98
89
|
{
|
|
99
|
-
title: '
|
|
100
|
-
description: '
|
|
90
|
+
title: 'CLI Tools',
|
|
91
|
+
description: 'Scaffold projects, create components and build bundles from the command line.',
|
|
101
92
|
},
|
|
102
93
|
{
|
|
103
|
-
title: '
|
|
104
|
-
description: '
|
|
105
|
-
}
|
|
94
|
+
title: 'Services',
|
|
95
|
+
description: 'Built-in FetchManager, LocalStorage and IndexedDB integrations.',
|
|
96
|
+
},
|
|
106
97
|
];
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
featureElement.appendChild(featureDescription);
|
|
125
|
-
|
|
126
|
-
featureGrid.appendChild(featureElement);
|
|
98
|
+
|
|
99
|
+
const grid = this.querySelector('.feature-grid');
|
|
100
|
+
for (const { title, description } of features) {
|
|
101
|
+
const item = document.createElement('div');
|
|
102
|
+
item.classList.add('feature-item');
|
|
103
|
+
|
|
104
|
+
const h3 = document.createElement('h3');
|
|
105
|
+
h3.classList.add('feature-title');
|
|
106
|
+
h3.textContent = title;
|
|
107
|
+
|
|
108
|
+
const p = document.createElement('p');
|
|
109
|
+
p.classList.add('feature-description');
|
|
110
|
+
p.textContent = description;
|
|
111
|
+
|
|
112
|
+
item.appendChild(h3);
|
|
113
|
+
item.appendChild(p);
|
|
114
|
+
grid.appendChild(item);
|
|
127
115
|
}
|
|
128
116
|
}
|
|
129
|
-
|
|
130
|
-
async
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
|
|
118
|
+
async _buildShowcase() {
|
|
119
|
+
const grid = this.querySelector('.showcase-grid');
|
|
120
|
+
|
|
121
|
+
// Helper: wrap built components in a labeled card and append to grid
|
|
122
|
+
const addCard = (label, ...components) => {
|
|
123
|
+
const card = document.createElement('div');
|
|
124
|
+
card.classList.add('comp-card');
|
|
125
|
+
|
|
126
|
+
const labelEl = document.createElement('p');
|
|
127
|
+
labelEl.classList.add('comp-label');
|
|
128
|
+
labelEl.textContent = label;
|
|
129
|
+
|
|
130
|
+
const demo = document.createElement('div');
|
|
131
|
+
demo.classList.add('comp-demo');
|
|
132
|
+
components.forEach(c => demo.appendChild(c));
|
|
133
|
+
|
|
134
|
+
card.appendChild(labelEl);
|
|
135
|
+
card.appendChild(demo);
|
|
136
|
+
grid.appendChild(card);
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
// Button — primary + secondary variants
|
|
140
|
+
const [btnPrimary, btnSecondary] = await Promise.all([
|
|
141
|
+
slice.build('Button', {
|
|
142
|
+
value: 'Primary',
|
|
143
|
+
onClickCallback: () => {},
|
|
144
|
+
customColor: {
|
|
145
|
+
button: 'var(--primary-color)',
|
|
146
|
+
label: 'var(--primary-color-contrast)',
|
|
147
|
+
},
|
|
148
|
+
}),
|
|
149
|
+
slice.build('Button', {
|
|
150
|
+
value: 'Secondary',
|
|
151
|
+
onClickCallback: () => {},
|
|
152
|
+
customColor: {
|
|
153
|
+
button: 'var(--secondary-background-color)',
|
|
154
|
+
label: 'var(--primary-color)',
|
|
155
|
+
},
|
|
156
|
+
}),
|
|
157
|
+
]);
|
|
158
|
+
addCard('Button', btnPrimary, btnSecondary);
|
|
159
|
+
|
|
160
|
+
// Input
|
|
161
|
+
const input = await slice.build('Input', {
|
|
162
|
+
placeholder: 'Type something...',
|
|
163
|
+
type: 'text',
|
|
135
164
|
});
|
|
136
|
-
|
|
137
|
-
|
|
165
|
+
addCard('Input', input);
|
|
166
|
+
|
|
167
|
+
// Switch
|
|
168
|
+
const sw = await slice.build('Switch', {
|
|
138
169
|
label: 'Toggle me',
|
|
139
|
-
checked: true
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
const checkboxExample = await slice.build('Checkbox', {
|
|
143
|
-
label: 'Check me',
|
|
144
|
-
labelPlacement: 'right'
|
|
170
|
+
checked: true,
|
|
145
171
|
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
{ title: 'Input Component', component: inputExample },
|
|
155
|
-
{ title: 'Switch Component', component: switchExample },
|
|
156
|
-
{ title: 'Checkbox Component', component: checkboxExample },
|
|
157
|
-
{ title: 'Details Component', component: detailsExample }
|
|
172
|
+
addCard('Switch', sw);
|
|
173
|
+
|
|
174
|
+
// Select — theme chooser
|
|
175
|
+
const themeOptions = [
|
|
176
|
+
{ name: 'Slice Theme' },
|
|
177
|
+
{ name: 'Light Theme' },
|
|
178
|
+
{ name: 'Dark Theme' },
|
|
179
|
+
{ name: 'Purple Theme' },
|
|
158
180
|
];
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
npm run slice:create
|
|
184
|
-
|
|
185
|
-
// Start your application
|
|
186
|
-
npm run slice:start`,
|
|
187
|
-
language: 'bash'
|
|
181
|
+
const select = await slice.build('Select', {
|
|
182
|
+
label: 'Pick a theme',
|
|
183
|
+
options: themeOptions,
|
|
184
|
+
visibleProp: 'name',
|
|
185
|
+
onOptionSelect: async (option) => {
|
|
186
|
+
if (!option) return;
|
|
187
|
+
const themeName = option.name.replace(' Theme', '');
|
|
188
|
+
await slice.setTheme(themeName);
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
addCard('Select', select);
|
|
192
|
+
|
|
193
|
+
// Loading — triggered by a demo button (Loading appends to document.body)
|
|
194
|
+
const loading = await slice.build('Loading', {});
|
|
195
|
+
const demoBtn = await slice.build('Button', {
|
|
196
|
+
value: 'Demo Loading',
|
|
197
|
+
onClickCallback: () => {
|
|
198
|
+
loading.start();
|
|
199
|
+
setTimeout(() => loading.stop(), 1500);
|
|
200
|
+
},
|
|
201
|
+
customColor: {
|
|
202
|
+
button: 'var(--primary-color)',
|
|
203
|
+
label: 'var(--primary-color-contrast)',
|
|
204
|
+
},
|
|
188
205
|
});
|
|
189
|
-
|
|
190
|
-
const codeSample = this.querySelector('.code-sample');
|
|
191
|
-
codeSample.innerHTML = ''; // Clear the static code sample
|
|
192
|
-
codeSample.appendChild(codeVisualizer);
|
|
206
|
+
addCard('Loading', demoBtn);
|
|
193
207
|
}
|
|
194
208
|
}
|
|
195
209
|
|
|
196
|
-
customElements.define('slice-home-page', HomePage);
|
|
210
|
+
customElements.define('slice-home-page', HomePage);
|