tkeron 4.0.0-beta.9 → 4.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/{readme.md → README.md} +36 -4
- package/bun.lock +23 -21
- package/changelog.md +274 -8
- package/docs/best-practices.md +127 -101
- package/docs/cli-reference.md +58 -38
- package/docs/components-html.md +30 -24
- package/docs/components-typescript.md +110 -79
- package/docs/getting-started.md +24 -18
- package/docs/mcp-server.md +19 -36
- package/docs/overview.md +16 -10
- package/docs/pre-rendering.md +163 -157
- package/docs/testing.md +331 -0
- package/examples/basic_build/src/index.ts +5 -5
- package/examples/with_assets/src/index.ts +5 -5
- package/examples/with_com_html_priority/src/admin/admin-panel.com.html +1 -1
- package/examples/with_com_html_priority/src/admin/dashboard.html +16 -16
- package/examples/with_com_html_priority/src/admin/nested-stat.com.html +1 -1
- package/examples/with_com_html_priority/src/admin/site-header.com.html +1 -1
- package/examples/with_com_html_priority/src/blog/comment-item.com.html +1 -1
- package/examples/with_com_html_priority/src/blog/comment-section.com.html +1 -1
- package/examples/with_com_html_priority/src/blog/post.html +22 -19
- package/examples/with_com_html_priority/src/index.html +15 -15
- package/examples/with_com_html_priority/src/info-box.com.html +1 -1
- package/examples/with_com_html_priority/src/site-header.com.html +1 -1
- package/examples/with_com_mixed_priority/src/dashboard/main.html +17 -17
- package/examples/with_com_mixed_priority/src/dashboard/stats-widget.com.ts +1 -1
- package/examples/with_com_mixed_priority/src/footer-info.com.html +3 -1
- package/examples/with_com_mixed_priority/src/index.html +16 -16
- package/examples/with_com_mixed_priority/src/page-header.com.html +8 -1
- package/examples/with_com_mixed_priority/src/settings/config.html +16 -16
- package/examples/with_com_mixed_priority/src/settings/priority-test.com.html +3 -1
- package/examples/with_com_mixed_priority/src/users/profiles/activity-feed.com.ts +7 -3
- package/examples/with_com_mixed_priority/src/users/profiles/page-header.com.html +8 -1
- package/examples/with_com_mixed_priority/src/users/profiles/profile-actions.com.html +45 -4
- package/examples/with_com_mixed_priority/src/users/profiles/user-profile.com.ts +1 -1
- package/examples/with_com_mixed_priority/src/users/profiles/view.html +17 -17
- package/examples/with_com_ts/src/index.html +15 -11
- package/examples/with_com_ts_priority/src/analytics/chart-widget.com.ts +7 -5
- package/examples/with_com_ts_priority/src/analytics/report.html +16 -16
- package/examples/with_com_ts_priority/src/analytics/user-stats.com.ts +1 -1
- package/examples/with_com_ts_priority/src/data-table.com.ts +7 -4
- package/examples/with_com_ts_priority/src/index.html +15 -15
- package/examples/with_com_ts_priority/src/sales/regional/data-table.com.ts +8 -5
- package/examples/with_com_ts_priority/src/sales/regional/overview.html +16 -16
- package/examples/with_com_ts_priority/src/sales/regional/sales-summary.com.ts +7 -4
- package/examples/with_com_ts_priority/src/user-stats.com.ts +1 -1
- package/examples/with_component_iteration/src/card-list.com.ts +40 -12
- package/examples/with_component_iteration/src/engagement-meter.com.ts +11 -6
- package/examples/with_component_iteration/src/index.html +108 -51
- package/examples/with_component_iteration/src/index.ts +1 -1
- package/examples/with_component_iteration/src/note-box.com.html +12 -2
- package/examples/with_component_iteration/src/status-badge.com.ts +14 -7
- package/examples/with_component_iteration/src/user-card.com.ts +10 -9
- package/examples/with_pre/src/contact.pre.ts +3 -3
- package/examples/with_pre/src/index.ts +5 -5
- package/examples/with_pre/src/section/index.pre.ts +2 -4
- package/index.ts +31 -40
- package/mcp-server.ts +168 -445
- package/package.json +19 -8
- package/src/banner.ts +5 -4
- package/src/build.ts +29 -29
- package/src/buildDir.ts +36 -18
- package/src/buildEntrypoints.ts +17 -6
- package/src/buildWrapper.ts +21 -0
- package/src/cleanupOrphanedTempDirs.ts +31 -0
- package/src/createTestLogger.ts +24 -0
- package/src/develop.ts +47 -46
- package/src/getBuildResult.ts +146 -0
- package/src/index.ts +7 -0
- package/src/init.ts +39 -42
- package/src/initWrapper.ts +39 -26
- package/src/logger.ts +4 -11
- package/src/loggerObj.ts +13 -0
- package/src/processCom.ts +136 -108
- package/src/processComTs.ts +173 -151
- package/src/processPre.ts +24 -27
- package/src/promptUser.ts +15 -0
- package/src/setupSigintHandler.ts +6 -0
- package/src/silentLogger.ts +8 -0
- package/tests/test-helpers.ts +30 -0
- package/funciones.md +0 -63
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
<div
|
|
1
|
+
<div
|
|
2
|
+
style="background: #e74c3c; color: white; padding: 1rem; border-radius: 8px"
|
|
3
|
+
>
|
|
2
4
|
<h3>This is the HTML component</h3>
|
|
3
5
|
<p>If you see this, the .com.ts version was NOT used</p>
|
|
4
6
|
</div>
|
|
@@ -2,10 +2,12 @@ const activities = [
|
|
|
2
2
|
{ action: "Updated profile", time: "2 hours ago", icon: "✏️" },
|
|
3
3
|
{ action: "Posted a comment", time: "5 hours ago", icon: "💬" },
|
|
4
4
|
{ action: "Uploaded a file", time: "1 day ago", icon: "📁" },
|
|
5
|
-
{ action: "Joined the platform", time: "2 weeks ago", icon: "🎉" }
|
|
5
|
+
{ action: "Joined the platform", time: "2 weeks ago", icon: "🎉" },
|
|
6
6
|
];
|
|
7
7
|
|
|
8
|
-
const items = activities
|
|
8
|
+
const items = activities
|
|
9
|
+
.map(
|
|
10
|
+
(act) => `
|
|
9
11
|
<div style="padding: 1rem; border-bottom: 1px solid #ecf0f1; display: flex; align-items: center; gap: 1rem;">
|
|
10
12
|
<div style="font-size: 1.5rem;">${act.icon}</div>
|
|
11
13
|
<div style="flex: 1;">
|
|
@@ -13,7 +15,9 @@ const items = activities.map(act => `
|
|
|
13
15
|
<div style="font-size: 0.875rem; color: #666;">${act.time}</div>
|
|
14
16
|
</div>
|
|
15
17
|
</div>
|
|
16
|
-
|
|
18
|
+
`,
|
|
19
|
+
)
|
|
20
|
+
.join("");
|
|
17
21
|
|
|
18
22
|
com.innerHTML = `
|
|
19
23
|
<div style="border: 2px solid #9b59b6; padding: 1rem; margin: 1rem 0; border-radius: 8px;">
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
<header
|
|
1
|
+
<header
|
|
2
|
+
style="
|
|
3
|
+
background: linear-gradient(90deg, #11998e 0%, #38ef7d 100%);
|
|
4
|
+
color: white;
|
|
5
|
+
padding: 2rem;
|
|
6
|
+
text-align: center;
|
|
7
|
+
"
|
|
8
|
+
>
|
|
2
9
|
<h2>👤 Profile Header (Deep Local HTML Override)</h2>
|
|
3
10
|
<p>This HTML component is from users/profiles/ directory</p>
|
|
4
11
|
</header>
|
|
@@ -1,5 +1,46 @@
|
|
|
1
|
-
<div
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
<div
|
|
2
|
+
style="
|
|
3
|
+
display: flex;
|
|
4
|
+
gap: 0.5rem;
|
|
5
|
+
margin-top: 1rem;
|
|
6
|
+
padding-top: 1rem;
|
|
7
|
+
border-top: 1px solid #ddd;
|
|
8
|
+
"
|
|
9
|
+
>
|
|
10
|
+
<button
|
|
11
|
+
style="
|
|
12
|
+
padding: 0.5rem 1rem;
|
|
13
|
+
background: #11998e;
|
|
14
|
+
color: white;
|
|
15
|
+
border: none;
|
|
16
|
+
border-radius: 4px;
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
"
|
|
19
|
+
>
|
|
20
|
+
Edit Profile
|
|
21
|
+
</button>
|
|
22
|
+
<button
|
|
23
|
+
style="
|
|
24
|
+
padding: 0.5rem 1rem;
|
|
25
|
+
background: #3498db;
|
|
26
|
+
color: white;
|
|
27
|
+
border: none;
|
|
28
|
+
border-radius: 4px;
|
|
29
|
+
cursor: pointer;
|
|
30
|
+
"
|
|
31
|
+
>
|
|
32
|
+
View Activity
|
|
33
|
+
</button>
|
|
34
|
+
<button
|
|
35
|
+
style="
|
|
36
|
+
padding: 0.5rem 1rem;
|
|
37
|
+
background: #95a5a6;
|
|
38
|
+
color: white;
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: 4px;
|
|
41
|
+
cursor: pointer;
|
|
42
|
+
"
|
|
43
|
+
>
|
|
44
|
+
Settings
|
|
45
|
+
</button>
|
|
5
46
|
</div>
|
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
</body>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Profile - Nested Priority</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>User Profile</h1>
|
|
10
|
+
|
|
11
|
+
<section>
|
|
12
|
+
<h2>Deep Nesting with Both Component Types</h2>
|
|
13
|
+
<page-header></page-header>
|
|
14
|
+
<user-profile></user-profile>
|
|
15
|
+
<activity-feed></activity-feed>
|
|
16
|
+
<footer-info></footer-info>
|
|
17
|
+
</section>
|
|
18
|
+
</body>
|
|
19
19
|
</html>
|
|
@@ -1,18 +1,22 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8"
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>TypeScript Components Example</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
9
|
<h1>TypeScript Components Demo</h1>
|
|
10
|
-
|
|
11
|
-
<user-card
|
|
10
|
+
|
|
11
|
+
<user-card
|
|
12
|
+
data-name="Alice"
|
|
13
|
+
data-role="Developer"
|
|
14
|
+
data-age="28"
|
|
15
|
+
></user-card>
|
|
12
16
|
<user-card data-name="Bob" data-role="Designer" data-age="32"></user-card>
|
|
13
|
-
|
|
17
|
+
|
|
14
18
|
<dynamic-list></dynamic-list>
|
|
15
|
-
|
|
19
|
+
|
|
16
20
|
<greeting-message data-name="World"></greeting-message>
|
|
17
|
-
</body>
|
|
21
|
+
</body>
|
|
18
22
|
</html>
|
|
@@ -5,12 +5,13 @@ const dataPoints = [
|
|
|
5
5
|
{ label: "Tue", value: 200 },
|
|
6
6
|
{ label: "Wed", value: 150 },
|
|
7
7
|
{ label: "Thu", value: 300 },
|
|
8
|
-
{ label: "Fri", value: 250 }
|
|
8
|
+
{ label: "Fri", value: 250 },
|
|
9
9
|
];
|
|
10
10
|
|
|
11
|
-
const bars = dataPoints
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const bars = dataPoints
|
|
12
|
+
.map((point) => {
|
|
13
|
+
const height = (point.value / 300) * 100;
|
|
14
|
+
return `
|
|
14
15
|
<div style="display: flex; flex-direction: column; align-items: center;">
|
|
15
16
|
<div style="height: 150px; display: flex; align-items: flex-end;">
|
|
16
17
|
<div style="width: 40px; height: ${height}%; background: #667eea;"></div>
|
|
@@ -19,7 +20,8 @@ const bars = dataPoints.map(point => {
|
|
|
19
20
|
<div style="font-size: 0.75rem; color: #666;">${point.value}</div>
|
|
20
21
|
</div>
|
|
21
22
|
`;
|
|
22
|
-
})
|
|
23
|
+
})
|
|
24
|
+
.join("");
|
|
23
25
|
|
|
24
26
|
com.innerHTML = `
|
|
25
27
|
<div style="border: 3px solid #667eea; padding: 1rem; margin: 1rem 0; border-radius: 8px;">
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
</body>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Analytics Dashboard</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Analytics Dashboard</h1>
|
|
10
|
+
|
|
11
|
+
<section>
|
|
12
|
+
<h2>Local Components Override Root</h2>
|
|
13
|
+
<user-stats></user-stats>
|
|
14
|
+
<data-table></data-table>
|
|
15
|
+
<chart-widget type="bar"></chart-widget>
|
|
16
|
+
</section>
|
|
17
|
+
</body>
|
|
18
18
|
</html>
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
const data = [
|
|
2
2
|
{ id: 1, name: "Item A", value: 100 },
|
|
3
3
|
{ id: 2, name: "Item B", value: 200 },
|
|
4
|
-
{ id: 3, name: "Item C", value: 300 }
|
|
4
|
+
{ id: 3, name: "Item C", value: 300 },
|
|
5
5
|
];
|
|
6
6
|
|
|
7
|
-
const rows = data
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const rows = data
|
|
8
|
+
.map(
|
|
9
|
+
(item) =>
|
|
10
|
+
`<tr><td>${item.id}</td><td>${item.name}</td><td>${item.value}</td></tr>`,
|
|
11
|
+
)
|
|
12
|
+
.join("");
|
|
10
13
|
|
|
11
14
|
com.innerHTML = `
|
|
12
15
|
<div style="border: 2px solid #3498db; padding: 1rem; margin: 1rem 0;">
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
</body>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Component Priority - TypeScript Components</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>TypeScript Component Priority Demo</h1>
|
|
10
|
+
|
|
11
|
+
<section>
|
|
12
|
+
<h2>Root Level Components</h2>
|
|
13
|
+
<user-stats></user-stats>
|
|
14
|
+
<data-table></data-table>
|
|
15
|
+
</section>
|
|
16
|
+
</body>
|
|
17
17
|
</html>
|
|
@@ -2,16 +2,19 @@ const regionalData = [
|
|
|
2
2
|
{ region: "North", sales: 45000, orders: 123 },
|
|
3
3
|
{ region: "South", sales: 38000, orders: 98 },
|
|
4
4
|
{ region: "East", sales: 52000, orders: 145 },
|
|
5
|
-
{ region: "West", sales: 41000, orders: 110 }
|
|
5
|
+
{ region: "West", sales: 41000, orders: 110 },
|
|
6
6
|
];
|
|
7
7
|
|
|
8
|
-
const rows = regionalData
|
|
9
|
-
|
|
8
|
+
const rows = regionalData
|
|
9
|
+
.map(
|
|
10
|
+
(item) =>
|
|
11
|
+
`<tr style="border-bottom: 1px solid #ecf0f1;">
|
|
10
12
|
<td style="padding: 0.75rem;">${item.region}</td>
|
|
11
13
|
<td style="padding: 0.75rem;">$${item.sales.toLocaleString()}</td>
|
|
12
14
|
<td style="padding: 0.75rem;">${item.orders}</td>
|
|
13
|
-
</tr
|
|
14
|
-
)
|
|
15
|
+
</tr>`,
|
|
16
|
+
)
|
|
17
|
+
.join("");
|
|
15
18
|
|
|
16
19
|
com.innerHTML = `
|
|
17
20
|
<div style="border: 3px solid #e74c3c; padding: 1rem; margin: 1rem 0; border-radius: 8px;">
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
<!
|
|
1
|
+
<!doctype html>
|
|
2
2
|
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
</body>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>Sales Overview</title>
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>Sales Overview</h1>
|
|
10
|
+
|
|
11
|
+
<section>
|
|
12
|
+
<h2>Multi-level Nesting</h2>
|
|
13
|
+
<user-stats></user-stats>
|
|
14
|
+
<data-table></data-table>
|
|
15
|
+
<sales-summary></sales-summary>
|
|
16
|
+
</section>
|
|
17
|
+
</body>
|
|
18
18
|
</html>
|
|
@@ -2,14 +2,17 @@ const regions = ["North", "South", "East", "West"];
|
|
|
2
2
|
const totalSales = 176000;
|
|
3
3
|
const avgPerRegion = totalSales / regions.length;
|
|
4
4
|
|
|
5
|
-
const regionCards = regions
|
|
6
|
-
|
|
5
|
+
const regionCards = regions
|
|
6
|
+
.map(
|
|
7
|
+
(region) =>
|
|
8
|
+
`<div style="background: #f8f9fa; padding: 0.75rem; border-radius: 4px; text-align: center;">
|
|
7
9
|
<strong>${region}</strong>
|
|
8
10
|
<div style="font-size: 0.875rem; color: #666; margin-top: 0.25rem;">
|
|
9
11
|
~$${avgPerRegion.toLocaleString()}
|
|
10
12
|
</div>
|
|
11
|
-
</div
|
|
12
|
-
)
|
|
13
|
+
</div>`,
|
|
14
|
+
)
|
|
15
|
+
.join("");
|
|
13
16
|
|
|
14
17
|
com.innerHTML = `
|
|
15
18
|
<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 1.5rem; border-radius: 12px; margin: 1rem 0;">
|
|
@@ -1,34 +1,62 @@
|
|
|
1
1
|
// ITERATION 1: This .com.ts fetches/processes data and generates dynamic content
|
|
2
2
|
// It simulates fetching user data and calculates statistics
|
|
3
3
|
|
|
4
|
-
const count = parseInt(com.getAttribute(
|
|
4
|
+
const count = parseInt(com.getAttribute("count") || "5");
|
|
5
5
|
|
|
6
6
|
// Simulating data processing - real TS logic here
|
|
7
7
|
const users = [
|
|
8
|
-
{
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
{
|
|
9
|
+
name: "Alice Johnson",
|
|
10
|
+
role: "admin",
|
|
11
|
+
loginCount: 342,
|
|
12
|
+
lastLogin: Date.now() - 30 * 60 * 1000,
|
|
13
|
+
}, // 30min ago - online
|
|
14
|
+
{
|
|
15
|
+
name: "Bob Smith",
|
|
16
|
+
role: "user",
|
|
17
|
+
loginCount: 128,
|
|
18
|
+
lastLogin: Date.now() - 5 * 60 * 60 * 1000,
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: "Carol White",
|
|
22
|
+
role: "moderator",
|
|
23
|
+
loginCount: 256,
|
|
24
|
+
lastLogin: Date.now() - 1 * 60 * 60 * 1000,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: "David Brown",
|
|
28
|
+
role: "user",
|
|
29
|
+
loginCount: 89,
|
|
30
|
+
lastLogin: Date.now() - 24 * 60 * 60 * 1000,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "Eve Davis",
|
|
34
|
+
role: "admin",
|
|
35
|
+
loginCount: 512,
|
|
36
|
+
lastLogin: Date.now() - 30 * 60 * 1000,
|
|
37
|
+
},
|
|
13
38
|
];
|
|
14
39
|
|
|
15
40
|
// TypeScript processing: calculate engagement score
|
|
16
|
-
const processedUsers = users.slice(0, count).map(user => {
|
|
41
|
+
const processedUsers = users.slice(0, count).map((user) => {
|
|
17
42
|
const hoursAgo = Math.floor((Date.now() - user.lastLogin) / (1000 * 60 * 60));
|
|
18
|
-
const engagementScore = Math.min(
|
|
19
|
-
|
|
43
|
+
const engagementScore = Math.min(
|
|
44
|
+
100,
|
|
45
|
+
Math.floor(user.loginCount / 10 + (24 - Math.min(hoursAgo, 24)) * 2),
|
|
46
|
+
);
|
|
47
|
+
|
|
20
48
|
return {
|
|
21
49
|
...user,
|
|
22
50
|
hoursAgo,
|
|
23
51
|
engagementScore,
|
|
24
|
-
status: hoursAgo < 1 ?
|
|
52
|
+
status: hoursAgo < 1 ? "online" : hoursAgo < 24 ? "recent" : "away",
|
|
25
53
|
};
|
|
26
54
|
});
|
|
27
55
|
|
|
28
56
|
// Generate <user-card> components with computed data
|
|
29
57
|
let html = '<div style="display: grid; gap: 1rem;">';
|
|
30
58
|
|
|
31
|
-
processedUsers.forEach(user => {
|
|
59
|
+
processedUsers.forEach((user) => {
|
|
32
60
|
// Each user-card will be processed by user-card.com.html (static template)
|
|
33
61
|
html += `<user-card
|
|
34
62
|
name="${user.name}"
|
|
@@ -39,6 +67,6 @@ processedUsers.forEach(user => {
|
|
|
39
67
|
</user-card>`;
|
|
40
68
|
});
|
|
41
69
|
|
|
42
|
-
html +=
|
|
70
|
+
html += "</div>";
|
|
43
71
|
|
|
44
72
|
com.innerHTML = html;
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
// ITERATION 3: This .com.ts processes <engagement-meter> and performs CALCULATIONS
|
|
2
2
|
// Real TypeScript processing: percentage calculations, conditional rendering
|
|
3
3
|
|
|
4
|
-
const engagement = parseInt(com.getAttribute(
|
|
4
|
+
const engagement = parseInt(com.getAttribute("engagement") || "0");
|
|
5
5
|
|
|
6
6
|
// TypeScript calculations and logic
|
|
7
7
|
const percentage = Math.min(100, Math.max(0, engagement));
|
|
8
|
-
const level = percentage >= 75 ?
|
|
8
|
+
const level = percentage >= 75 ? "high" : percentage >= 40 ? "medium" : "low";
|
|
9
9
|
|
|
10
10
|
// Conditional color based on calculated level
|
|
11
11
|
const colors = {
|
|
12
|
-
high: { bar:
|
|
13
|
-
medium: { bar:
|
|
14
|
-
low: { bar:
|
|
12
|
+
high: { bar: "#27ae60", bg: "#d5f4e6", text: "#27ae60" },
|
|
13
|
+
medium: { bar: "#f39c12", bg: "#fef5e7", text: "#f39c12" },
|
|
14
|
+
low: { bar: "#e74c3c", bg: "#fadbd8", text: "#e74c3c" },
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const color = colors[level];
|
|
18
18
|
|
|
19
19
|
// TypeScript string manipulation and template generation
|
|
20
|
-
const label =
|
|
20
|
+
const label =
|
|
21
|
+
level === "high"
|
|
22
|
+
? "🔥 Active"
|
|
23
|
+
: level === "medium"
|
|
24
|
+
? "📊 Moderate"
|
|
25
|
+
: "💤 Low";
|
|
21
26
|
|
|
22
27
|
com.innerHTML = `
|
|
23
28
|
<div style="margin: 0.5rem 0;">
|