@slexkit/mcp 0.5.0 → 0.5.2
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/dist/data/llms-full.txt +370 -60
- package/dist/data/llms.txt +3 -3
- package/dist/data/slexkit-ai-manifest.json +61 -61
- package/dist/data/standard/slex-custom-elements.catalog.json +1 -1
- package/dist/data/standard/slex-html-conformance.json +1 -1
- package/dist/data/standard/slex-html-profile.json +1 -1
- package/dist/data/standard/slex-sandbox-sdk.json +1 -1
- package/dist/data/standard/slex-standard-manifest.json +7 -7
- package/dist/data/standard/slex-static-policy.json +1 -1
- package/package.json +1 -1
package/dist/data/llms-full.txt
CHANGED
|
@@ -1175,24 +1175,69 @@ Use `dist/custom-elements.json` for exact types and full descriptions. Use attri
|
|
|
1175
1175
|
|
|
1176
1176
|
---
|
|
1177
1177
|
|
|
1178
|
-
# Artifact Shared
|
|
1178
|
+
# Artifact Shared State Lab
|
|
1179
1179
|
|
|
1180
1180
|
Source: site/content/examples/cross-doc-state-lab/en-US.md
|
|
1181
1181
|
|
|
1182
|
-
# Artifact Shared
|
|
1182
|
+
# Artifact Shared State Lab
|
|
1183
1183
|
|
|
1184
|
-
|
|
1184
|
+
Change the name, font size, or color in the control panel. The two independent panels below update through shared JSON.
|
|
1185
|
+
|
|
1186
|
+
## Control panel
|
|
1187
|
+
|
|
1188
|
+
```slex
|
|
1189
|
+
<slex-card title="Control panel">
|
|
1190
|
+
<slex-grid columns="3">
|
|
1191
|
+
<slex-input id="name" label="Display name" value="SlexKit"></slex-input>
|
|
1192
|
+
<slex-slider id="size" label="Font size" min="12" max="30" value="18" unit="px"></slex-slider>
|
|
1193
|
+
<slex-select id="color" label="Text color"><option value="blue">Blue</option><option value="green">Green</option><option value="orange">Orange</option></slex-select>
|
|
1194
|
+
</slex-grid>
|
|
1195
|
+
</slex-card>
|
|
1196
|
+
<script type="module">
|
|
1197
|
+
const get = id => slex.root.querySelector(`#${id}`);
|
|
1198
|
+
const controls = ["name", "size", "color"].map(get);
|
|
1199
|
+
const publish = () => slex.shared.set("profile", { name: get("name").value, size: Number(get("size").value), color: get("color").value });
|
|
1200
|
+
controls.forEach(control => control.addEventListener("input", publish));
|
|
1201
|
+
publish();
|
|
1202
|
+
slex.onDispose(() => controls.forEach(control => control.removeEventListener("input", publish)));
|
|
1203
|
+
</script>
|
|
1204
|
+
```
|
|
1205
|
+
|
|
1206
|
+
## Live preview
|
|
1207
|
+
|
|
1208
|
+
This panel subscribes to the shared value.
|
|
1185
1209
|
|
|
1186
1210
|
```slex
|
|
1187
|
-
<slex-card title="
|
|
1211
|
+
<slex-card title="Live preview"><slex-text id="message"></slex-text></slex-card>
|
|
1188
1212
|
<script type="module">
|
|
1189
|
-
const
|
|
1190
|
-
const
|
|
1191
|
-
|
|
1213
|
+
const message = slex.root.querySelector("#message");
|
|
1214
|
+
const stop = slex.shared.subscribe("profile", profile => {
|
|
1215
|
+
if (!profile) return;
|
|
1216
|
+
message.text = String(profile.name);
|
|
1217
|
+
message.size = Number(profile.size);
|
|
1218
|
+
message.color = ({ blue: "#2563eb", green: "#15803d", orange: "#c2410c" })[profile.color] || "#2563eb";
|
|
1219
|
+
});
|
|
1220
|
+
slex.onDispose(stop);
|
|
1192
1221
|
</script>
|
|
1193
1222
|
```
|
|
1194
1223
|
|
|
1195
|
-
|
|
1224
|
+
## Observer panel
|
|
1225
|
+
|
|
1226
|
+
A second independent fence subscribes to the same JSON.
|
|
1227
|
+
|
|
1228
|
+
```slex
|
|
1229
|
+
<slex-card title="Observer panel"><slex-grid columns="2"><slex-stat id="nameValue" label="Current name"></slex-stat><slex-stat id="sizeValue" label="Font size" unit="px"></slex-stat></slex-grid></slex-card>
|
|
1230
|
+
<script type="module">
|
|
1231
|
+
const stop = slex.shared.subscribe("profile", profile => {
|
|
1232
|
+
if (!profile) return;
|
|
1233
|
+
slex.root.querySelector("#nameValue").value = String(profile.name);
|
|
1234
|
+
slex.root.querySelector("#sizeValue").value = Number(profile.size);
|
|
1235
|
+
});
|
|
1236
|
+
slex.onDispose(stop);
|
|
1237
|
+
</script>
|
|
1238
|
+
```
|
|
1239
|
+
|
|
1240
|
+
The fences share JSON only, not DOM nodes or JavaScript globals. Subscriptions and listeners are cleaned up on disposal.
|
|
1196
1241
|
|
|
1197
1242
|
---
|
|
1198
1243
|
|
|
@@ -1232,18 +1277,25 @@ Source: site/content/examples/baud-rate-calculator/en-US.md
|
|
|
1232
1277
|
|
|
1233
1278
|
# Baud Rate Error Calculator
|
|
1234
1279
|
|
|
1235
|
-
Enter a peripheral clock and divider
|
|
1280
|
+
Enter a peripheral clock, target baud rate, and integer divider. The module calculates the actual baud rate and error using 16× oversampling.
|
|
1236
1281
|
|
|
1237
1282
|
```slex
|
|
1238
|
-
<slex-card title="Baud Rate Error Calculator"><slex-grid columns="
|
|
1283
|
+
<slex-card title="Baud Rate Error Calculator"><slex-grid columns="3"><slex-input id="clock" type="number" label="Peripheral clock" unit="MHz" value="48" min="0"></slex-input><slex-input id="divider" type="number" label="Divider" value="26" min="1" step="1"></slex-input><slex-input id="target" type="number" label="Target baud" value="115200" min="1"></slex-input></slex-grid><slex-stat id="result" label="Actual baud / error"></slex-stat></slex-card>
|
|
1239
1284
|
<script type="module">
|
|
1240
|
-
const
|
|
1241
|
-
const
|
|
1242
|
-
|
|
1285
|
+
const fields = ["clock", "divider", "target"].map(id => slex.root.querySelector(`#${id}`));
|
|
1286
|
+
const result = slex.root.querySelector("#result");
|
|
1287
|
+
const update = () => {
|
|
1288
|
+
const [clock, divider, target] = fields.map(field => Number(field.value));
|
|
1289
|
+
if (!(clock > 0 && target > 0 && Number.isInteger(divider) && divider > 0)) { result.value = "Enter valid parameters"; return; }
|
|
1290
|
+
const baud = clock * 1e6 / (16 * divider);
|
|
1291
|
+
result.value = `${baud.toFixed(0)} / ${((baud / target - 1) * 100).toFixed(2)}%`;
|
|
1292
|
+
};
|
|
1293
|
+
fields.forEach(field => field.addEventListener("input", update)); update();
|
|
1294
|
+
slex.onDispose(() => fields.forEach(field => field.removeEventListener("input", update)));
|
|
1243
1295
|
</script>
|
|
1244
1296
|
```
|
|
1245
1297
|
|
|
1246
|
-
Input values are read from live control properties, and the calculated baud
|
|
1298
|
+
Input values are read from live control properties, and the calculated baud rate and error appear in one stat.
|
|
1247
1299
|
|
|
1248
1300
|
---
|
|
1249
1301
|
|
|
@@ -1253,13 +1305,40 @@ Source: site/content/examples/tabs-and-branching/en-US.md
|
|
|
1253
1305
|
|
|
1254
1306
|
# Branching: Mode Selector
|
|
1255
1307
|
|
|
1256
|
-
|
|
1308
|
+
Choose a length, weight, or temperature conversion. The input and result update with the selected mode.
|
|
1257
1309
|
|
|
1258
1310
|
```slex
|
|
1259
|
-
<
|
|
1311
|
+
<slex-card title="Unit conversion">
|
|
1312
|
+
<slex-select id="mode" label="Conversion mode"><option value="length">Centimeters → meters</option><option value="weight">Kilograms → pounds</option><option value="temperature">Celsius → Fahrenheit</option></slex-select>
|
|
1313
|
+
<slex-input id="amount" type="number" label="Value (cm)" value="100"></slex-input>
|
|
1314
|
+
<slex-stat id="result" label="Result"></slex-stat>
|
|
1315
|
+
<slex-text id="description"></slex-text>
|
|
1316
|
+
</slex-card>
|
|
1317
|
+
<script type="module">
|
|
1318
|
+
const mode = slex.root.querySelector("#mode");
|
|
1319
|
+
const amount = slex.root.querySelector("#amount");
|
|
1320
|
+
const result = slex.root.querySelector("#result");
|
|
1321
|
+
const description = slex.root.querySelector("#description");
|
|
1322
|
+
const modes = {
|
|
1323
|
+
length: { label: "Value (cm)", description: "Divide centimeters by 100 to obtain meters.", convert: n => `${(n / 100).toFixed(2)} m` },
|
|
1324
|
+
weight: { label: "Value (kg)", description: "Multiply kilograms by 2.20462 to obtain pounds.", convert: n => `${(n * 2.20462).toFixed(2)} lb` },
|
|
1325
|
+
temperature: { label: "Value (°C)", description: "Multiply Celsius by 9/5, then add 32.", convert: n => `${(n * 9 / 5 + 32).toFixed(1)} °F` },
|
|
1326
|
+
};
|
|
1327
|
+
const update = () => {
|
|
1328
|
+
const selected = modes[mode.value] || modes.length;
|
|
1329
|
+
const number = amount.value === "" ? NaN : Number(amount.value);
|
|
1330
|
+
amount.label = selected.label;
|
|
1331
|
+
description.text = selected.description;
|
|
1332
|
+
result.value = Number.isFinite(number) ? selected.convert(number) : "Enter a number";
|
|
1333
|
+
};
|
|
1334
|
+
mode.addEventListener("change", update);
|
|
1335
|
+
amount.addEventListener("input", update);
|
|
1336
|
+
update();
|
|
1337
|
+
slex.onDispose(() => { mode.removeEventListener("change", update); amount.removeEventListener("input", update); });
|
|
1338
|
+
</script>
|
|
1260
1339
|
```
|
|
1261
1340
|
|
|
1262
|
-
|
|
1341
|
+
Native events drive the mode and input value; listeners are removed when the document is disposed.
|
|
1263
1342
|
|
|
1264
1343
|
---
|
|
1265
1344
|
|
|
@@ -1269,18 +1348,37 @@ Source: site/content/examples/roi-estimator/en-US.md
|
|
|
1269
1348
|
|
|
1270
1349
|
# Build vs Buy Decision
|
|
1271
1350
|
|
|
1272
|
-
Compare
|
|
1351
|
+
Compare feature fit, cost, delivery time, and vendor risk. The scores are illustrative.
|
|
1273
1352
|
|
|
1274
1353
|
```slex
|
|
1275
|
-
<slex-card title="Build vs Buy Decision"
|
|
1354
|
+
<slex-card title="Build vs Buy Decision">
|
|
1355
|
+
<slex-select id="scope" label="Function role"><option value="core">Core business</option><option value="non-core">Supporting function</option></slex-select>
|
|
1356
|
+
<slex-grid columns="2">
|
|
1357
|
+
<slex-card title="Build"><slex-slider id="buildFit" label="Feature fit" min="0" max="100" step="5" value="60"></slex-slider><slex-slider id="buildCost" label="Cost score (lower is better)" min="0" max="100" step="5" value="80"></slex-slider><slex-slider id="buildTime" label="Time to launch (months)" min="1" max="12" value="6"></slex-slider></slex-card>
|
|
1358
|
+
<slex-card title="Buy"><slex-slider id="buyFit" label="Feature fit" min="0" max="100" step="5" value="85"></slex-slider><slex-slider id="buyCost" label="Cost score (lower is better)" min="0" max="100" step="5" value="40"></slex-slider><slex-slider id="buyTime" label="Time to launch (months)" min="1" max="12" value="1"></slex-slider><slex-slider id="buyLock" label="Vendor lock-in risk" min="0" max="100" step="5" value="30"></slex-slider></slex-card>
|
|
1359
|
+
</slex-grid>
|
|
1360
|
+
<slex-grid columns="2"><slex-stat id="buildScore" label="Build score"></slex-stat><slex-stat id="buyScore" label="Buy score"></slex-stat></slex-grid>
|
|
1361
|
+
<slex-text id="advice" label="Decision notes"></slex-text>
|
|
1362
|
+
</slex-card>
|
|
1276
1363
|
<script type="module">
|
|
1277
|
-
const
|
|
1278
|
-
const
|
|
1279
|
-
|
|
1364
|
+
const get = id => slex.root.querySelector(`#${id}`);
|
|
1365
|
+
const ids = ["scope", "buildFit", "buildCost", "buildTime", "buyFit", "buyCost", "buyTime", "buyLock"];
|
|
1366
|
+
const copy = {"close": "The scores are close; investigate both options further.", "buildWins": "Build scores higher", "buyWins": "Buy scores higher", "coreNote": "For core capabilities, also consider long-term control.", "noncoreNote": "For supporting capabilities, also consider maintenance cost."};
|
|
1367
|
+
const update = () => {
|
|
1368
|
+
const value = id => Number(get(id).value);
|
|
1369
|
+
const timeScore = id => Math.max(0, 100 - value(id) * 10);
|
|
1370
|
+
const build = (value("buildFit") + 100 - value("buildCost") + timeScore("buildTime")) / 3;
|
|
1371
|
+
const buy = (value("buyFit") + 100 - value("buyCost") + timeScore("buyTime") - value("buyLock") * 0.5) / 3;
|
|
1372
|
+
get("buildScore").value = build.toFixed(1); get("buyScore").value = buy.toFixed(1);
|
|
1373
|
+
const verdict = Math.abs(build - buy) < 10 ? copy.close : build > buy ? copy.buildWins : copy.buyWins;
|
|
1374
|
+
get("advice").text = `${verdict} ${get("scope").value === "core" ? copy.coreNote : copy.noncoreNote}`;
|
|
1375
|
+
};
|
|
1376
|
+
ids.forEach(id => get(id).addEventListener("input", update)); update();
|
|
1377
|
+
slex.onDispose(() => ids.forEach(id => get(id).removeEventListener("input", update)));
|
|
1280
1378
|
</script>
|
|
1281
1379
|
```
|
|
1282
1380
|
|
|
1283
|
-
|
|
1381
|
+
These adjustable example scores do not replace a real budget, procurement, or risk assessment.
|
|
1284
1382
|
|
|
1285
1383
|
---
|
|
1286
1384
|
|
|
@@ -1370,10 +1468,51 @@ Source: site/content/examples/project-dashboard/en-US.md
|
|
|
1370
1468
|
The dashboard composes cards, grids, controls, and stats while one JavaScript update function coordinates the displayed project metrics.
|
|
1371
1469
|
|
|
1372
1470
|
```slex
|
|
1373
|
-
<slex-
|
|
1471
|
+
<slex-section title="Sprint dashboard" subtitle="Adjust the inputs to explore progress, quality, and team load.">
|
|
1472
|
+
<slex-grid columns="3">
|
|
1473
|
+
<slex-card title="Sprint progress">
|
|
1474
|
+
<slex-slider id="progress" label="Completion" value="72" min="0" max="100" unit="%"></slex-slider>
|
|
1475
|
+
<slex-progress id="progressBar" label="Completion"></slex-progress>
|
|
1476
|
+
<slex-select id="scope" label="Scope status"><option value="on-track">On track</option><option value="at-risk">At risk</option><option value="off-track">Off track</option></slex-select>
|
|
1477
|
+
<slex-badge id="scopeBadge"></slex-badge>
|
|
1478
|
+
</slex-card>
|
|
1479
|
+
<slex-card title="Quality">
|
|
1480
|
+
<slex-input id="bugs" type="number" min="0" label="Total defects" value="12"></slex-input>
|
|
1481
|
+
<slex-input id="resolved" type="number" min="0" label="Resolved" value="9"></slex-input>
|
|
1482
|
+
<slex-stat id="remaining" label="Remaining defects"></slex-stat>
|
|
1483
|
+
<slex-progress id="fixRate" label="Resolution rate"></slex-progress>
|
|
1484
|
+
</slex-card>
|
|
1485
|
+
<slex-card title="Team health">
|
|
1486
|
+
<slex-input id="workload" type="number" min="0" label="Workload" value="8"></slex-input>
|
|
1487
|
+
<slex-input id="team" type="number" min="1" label="Team members" value="6"></slex-input>
|
|
1488
|
+
<slex-stat id="load" label="Load index" unit="%"></slex-stat>
|
|
1489
|
+
<slex-text id="note"></slex-text>
|
|
1490
|
+
</slex-card>
|
|
1491
|
+
</slex-grid>
|
|
1492
|
+
<slex-card title="Task details"><slex-table id="tasks"></slex-table></slex-card>
|
|
1493
|
+
</slex-section>
|
|
1374
1494
|
<script type="module">
|
|
1375
|
-
const
|
|
1376
|
-
|
|
1495
|
+
const get = id => slex.root.querySelector(`#${id}`);
|
|
1496
|
+
const controls = ["progress", "scope", "bugs", "resolved", "workload", "team"].map(get);
|
|
1497
|
+
const statuses = { "on-track": ["On track", "success"], "at-risk": ["At risk", "warning"], "off-track": ["Off track", "destructive"] };
|
|
1498
|
+
const update = () => {
|
|
1499
|
+
const bugs = Math.max(0, Number(get("bugs").value) || 0);
|
|
1500
|
+
const resolved = Math.min(bugs, Math.max(0, Number(get("resolved").value) || 0));
|
|
1501
|
+
const team = Math.max(1, Number(get("team").value) || 1);
|
|
1502
|
+
const load = Math.min(100, Math.max(0, Number(get("workload").value) || 0) / team * 20);
|
|
1503
|
+
const [label, tone] = statuses[get("scope").value] || statuses["on-track"];
|
|
1504
|
+
get("progressBar").value = Number(get("progress").value);
|
|
1505
|
+
get("scopeBadge").label = label; get("scopeBadge").tone = tone;
|
|
1506
|
+
get("remaining").value = bugs - resolved;
|
|
1507
|
+
get("fixRate").value = bugs ? resolved / bugs * 100 : 0;
|
|
1508
|
+
get("load").value = load.toFixed(1);
|
|
1509
|
+
get("note").text = load > 80 ? "Team load is high; consider redistributing work." : "Team load is within the healthy range.";
|
|
1510
|
+
};
|
|
1511
|
+
get("tasks").columns = ["Task", "Owner", "Status"];
|
|
1512
|
+
get("tasks").rows = [["API refactor", "Alex", "Done"], ["UI components", "Lee", "In progress"], ["Integration tests", "Sam", "Review"]];
|
|
1513
|
+
controls.forEach(control => control.addEventListener("input", update));
|
|
1514
|
+
update();
|
|
1515
|
+
slex.onDispose(() => controls.forEach(control => control.removeEventListener("input", update)));
|
|
1377
1516
|
</script>
|
|
1378
1517
|
```
|
|
1379
1518
|
|
|
@@ -1390,12 +1529,126 @@ Source: site/content/examples/rc-low-pass-filter/en-US.md
|
|
|
1390
1529
|
The cutoff calculation is ordinary JavaScript: \(f_c = 1 / (2\pi RC)\). Values are read from live custom-element properties.
|
|
1391
1530
|
|
|
1392
1531
|
```slex
|
|
1393
|
-
<
|
|
1532
|
+
<div class="rc-filter-demo">
|
|
1533
|
+
<div id="inputs" class="rc-filter-grid">
|
|
1534
|
+
<div class="rc-filter-field">
|
|
1535
|
+
<slex-input id="r" label="Resistance R" type="engineering" value="10kΩ" placeholder="10kΩ"></slex-input>
|
|
1536
|
+
<slex-slider id="rControl" label="R" value="10000" min="1000" max="100000" step="1000" unit="Ω"></slex-slider>
|
|
1537
|
+
</div>
|
|
1538
|
+
<div class="rc-filter-field">
|
|
1539
|
+
<slex-input id="c" label="Capacitance C" type="engineering" value="100nF" placeholder="100nF"></slex-input>
|
|
1540
|
+
<slex-slider id="cControl" label="C" value="100" min="10" max="1000" step="10" unit="nF"></slex-slider>
|
|
1541
|
+
</div>
|
|
1542
|
+
<div class="rc-filter-field">
|
|
1543
|
+
<slex-input id="f" label="Input frequency f" type="engineering" value="1kHz" placeholder="1kHz"></slex-input>
|
|
1544
|
+
<slex-slider id="fControl" label="f" value="1000" min="0" max="5000" step="10" unit="Hz"></slex-slider>
|
|
1545
|
+
</div>
|
|
1546
|
+
<div class="rc-filter-field">
|
|
1547
|
+
<slex-input id="vin" label="Input amplitude Vin" type="engineering" value="1V" placeholder="1V"></slex-input>
|
|
1548
|
+
<slex-slider id="vinControl" label="Vin" value="1" min="0" max="5" step="0.1" unit="V"></slex-slider>
|
|
1549
|
+
</div>
|
|
1550
|
+
</div>
|
|
1551
|
+
|
|
1552
|
+
<p id="inputHint" class="rc-filter-muted">Try 4.7kΩ, 220nF, 10kHz, and 500mV. value keeps the source text; number drives the calculation.</p>
|
|
1553
|
+
|
|
1554
|
+
<div id="outputs" class="rc-filter-grid">
|
|
1555
|
+
<slex-stat id="tau" label="Time constant" unit="ms" animate-initial></slex-stat>
|
|
1556
|
+
<slex-stat id="cutoff" label="Cutoff frequency" unit="Hz" animate-initial></slex-stat>
|
|
1557
|
+
<slex-stat id="gain" label="Magnitude gain" animate-initial></slex-stat>
|
|
1558
|
+
<slex-stat id="output" label="Output amplitude" unit="V" animate-initial></slex-stat>
|
|
1559
|
+
</div>
|
|
1560
|
+
|
|
1561
|
+
<div id="formula" class="rc-filter-formula"></div>
|
|
1562
|
+
<div class="rc-filter-actions">
|
|
1563
|
+
<p id="status" class="rc-filter-muted"></p>
|
|
1564
|
+
<slex-button id="reset" label="Reset" variant="secondary"></slex-button>
|
|
1565
|
+
</div>
|
|
1566
|
+
</div>
|
|
1567
|
+
|
|
1568
|
+
<style>
|
|
1569
|
+
.rc-filter-demo { display: grid; gap: 1rem; min-width: 0; }
|
|
1570
|
+
.rc-filter-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; min-width: 0; }
|
|
1571
|
+
@media (min-width: 600px) { .rc-filter-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
|
|
1572
|
+
.rc-filter-field { display: grid; align-content: start; gap: 1rem; min-width: 0; }
|
|
1573
|
+
.rc-filter-formula { border: 1px solid var(--border); border-radius: var(--radius); background: var(--muted); padding: .625rem .75rem; font-family: var(--font-mono, monospace); font-weight: 600; line-height: 1.7; }
|
|
1574
|
+
.rc-filter-muted { margin: 0; color: var(--muted-foreground); font-size: .875rem; line-height: 1.625; }
|
|
1575
|
+
.rc-filter-actions { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: 1rem; }
|
|
1576
|
+
#status { flex: 1 1 24rem; min-width: 0; }
|
|
1577
|
+
@media (max-width: 599px) {
|
|
1578
|
+
.rc-filter-actions { flex-direction: column; align-items: stretch; }
|
|
1579
|
+
#status { flex: 0 1 auto; }
|
|
1580
|
+
#reset { width: 100%; }
|
|
1581
|
+
}
|
|
1582
|
+
</style>
|
|
1583
|
+
|
|
1394
1584
|
<script type="module">
|
|
1395
|
-
const
|
|
1396
|
-
const
|
|
1397
|
-
|
|
1398
|
-
|
|
1585
|
+
const byId = (id) => slex.root.querySelector(`#${id}`);
|
|
1586
|
+
const inputs = {
|
|
1587
|
+
r: byId("r"),
|
|
1588
|
+
c: byId("c"),
|
|
1589
|
+
f: byId("f"),
|
|
1590
|
+
vin: byId("vin"),
|
|
1591
|
+
};
|
|
1592
|
+
const sliders = {
|
|
1593
|
+
r: byId("rControl"),
|
|
1594
|
+
c: byId("cControl"),
|
|
1595
|
+
f: byId("fControl"),
|
|
1596
|
+
vin: byId("vinControl"),
|
|
1597
|
+
};
|
|
1598
|
+
const defaults = { r: "10kΩ", c: "100nF", f: "1kHz", vin: "1V" };
|
|
1599
|
+
const units = { r: "Ω", c: "nF", f: "Hz", vin: "V" };
|
|
1600
|
+
const sliderScale = { r: 1, c: 1e9, f: 1, vin: 1 };
|
|
1601
|
+
const format = (value, digits) => Number.isFinite(value) ? value.toFixed(digits) : "Invalid";
|
|
1602
|
+
|
|
1603
|
+
const update = (origin) => {
|
|
1604
|
+
const r = inputs.r.valueAsNumber;
|
|
1605
|
+
const c = inputs.c.valueAsNumber;
|
|
1606
|
+
const f = inputs.f.valueAsNumber;
|
|
1607
|
+
const vin = inputs.vin.valueAsNumber;
|
|
1608
|
+
const valid = [r, c, f, vin].every(Number.isFinite) && r > 0 && c > 0 && f >= 0 && vin >= 0;
|
|
1609
|
+
const tau = valid ? r * c : NaN;
|
|
1610
|
+
const cutoff = valid && tau > 0 ? 1 / (2 * Math.PI * tau) : NaN;
|
|
1611
|
+
const gain = valid && cutoff > 0 ? 1 / Math.sqrt(1 + (f / cutoff) ** 2) : NaN;
|
|
1612
|
+
const gainDb = Number.isFinite(gain) && gain > 0 ? 20 * Math.log10(gain) : NaN;
|
|
1613
|
+
const output = Number.isFinite(gain) ? vin * gain : NaN;
|
|
1614
|
+
|
|
1615
|
+
if (origin !== "slider") {
|
|
1616
|
+
for (const key of Object.keys(sliders)) {
|
|
1617
|
+
const number = inputs[key].valueAsNumber;
|
|
1618
|
+
if (Number.isFinite(number)) sliders[key].value = String(number * sliderScale[key]);
|
|
1619
|
+
}
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
byId("tau").value = format(tau * 1000, 3);
|
|
1623
|
+
byId("cutoff").value = format(cutoff, 2);
|
|
1624
|
+
byId("gain").value = format(gain, 3);
|
|
1625
|
+
byId("output").value = format(output, 3);
|
|
1626
|
+
byId("formula").textContent = `|H(f)| = ${format(gain, 3)}, Gain = ${format(gainDb, 2)} dB`;
|
|
1627
|
+
byId("status").textContent = valid
|
|
1628
|
+
? "Low frequencies pass through; higher frequencies are attenuated by the first-order RC network."
|
|
1629
|
+
: "Check the engineering input format. R and C must be greater than 0; frequency and input amplitude cannot be negative.";
|
|
1630
|
+
};
|
|
1631
|
+
|
|
1632
|
+
const onInput = () => update("input");
|
|
1633
|
+
const sliderHandlers = Object.fromEntries(Object.keys(sliders).map((key) => [key, () => {
|
|
1634
|
+
inputs[key].value = `${sliders[key].value}${units[key]}`;
|
|
1635
|
+
update("slider");
|
|
1636
|
+
}]));
|
|
1637
|
+
const reset = () => {
|
|
1638
|
+
for (const [key, value] of Object.entries(defaults)) inputs[key].value = value;
|
|
1639
|
+
update("input");
|
|
1640
|
+
};
|
|
1641
|
+
|
|
1642
|
+
Object.values(inputs).forEach((control) => control.addEventListener("input", onInput));
|
|
1643
|
+
for (const [key, control] of Object.entries(sliders)) control.addEventListener("input", sliderHandlers[key]);
|
|
1644
|
+
byId("reset").addEventListener("click", reset);
|
|
1645
|
+
update("input");
|
|
1646
|
+
|
|
1647
|
+
slex.onDispose(() => {
|
|
1648
|
+
Object.values(inputs).forEach((control) => control.removeEventListener("input", onInput));
|
|
1649
|
+
for (const [key, control] of Object.entries(sliders)) control.removeEventListener("input", sliderHandlers[key]);
|
|
1650
|
+
byId("reset").removeEventListener("click", reset);
|
|
1651
|
+
});
|
|
1399
1652
|
</script>
|
|
1400
1653
|
```
|
|
1401
1654
|
|
|
@@ -1412,31 +1665,27 @@ Source: site/content/examples/search-filter-table/en-US.md
|
|
|
1412
1665
|
The search input filters an in-memory array and assigns the matching rows to the table's live `.rows` property.
|
|
1413
1666
|
|
|
1414
1667
|
```slex
|
|
1415
|
-
<slex-card title="Search and Filter Table"><slex-input id="query" label="Filter"></slex-input><slex-table id="results"></slex-table></slex-card>
|
|
1668
|
+
<slex-card title="Search and Filter Table"><slex-input id="query" label="Filter"></slex-input><slex-table id="results"></slex-table><div id="details"></div></slex-card>
|
|
1416
1669
|
<script type="module">
|
|
1417
1670
|
const rows = [{ name: "Ada", role: "Engineer" }, { name: "Lin", role: "Designer" }]; const query = slex.root.querySelector("#query"); const table = slex.root.querySelector("#results");
|
|
1418
|
-
|
|
1671
|
+
const details = slex.root.querySelector("#details");
|
|
1672
|
+
table.columns = [{ key: "name", label: "Name" }, { key: "role", label: "Role" }];
|
|
1673
|
+
const update = () => {
|
|
1674
|
+
const needle = query.value.toLowerCase();
|
|
1675
|
+
const matches = rows.filter((row) => Object.values(row).some((value) => value.toLowerCase().includes(needle)));
|
|
1676
|
+
table.rows = matches;
|
|
1677
|
+
details.replaceChildren(...matches.map((row) => {
|
|
1678
|
+
const item = document.createElement("slex-collapsible");
|
|
1679
|
+
item.setAttribute("trigger", `${row.name} — details`);
|
|
1680
|
+
item.setAttribute("content", `Role: ${row.role}`);
|
|
1681
|
+
return item;
|
|
1682
|
+
}));
|
|
1683
|
+
};
|
|
1419
1684
|
query.addEventListener("input", update); update(); slex.onDispose(() => query.removeEventListener("input", update));
|
|
1420
1685
|
</script>
|
|
1421
1686
|
```
|
|
1422
1687
|
|
|
1423
|
-
Table data is assigned as arrays through properties rather than encoded into HTML attributes
|
|
1424
|
-
|
|
1425
|
-
---
|
|
1426
|
-
|
|
1427
|
-
# Semantic Details Layout
|
|
1428
|
-
|
|
1429
|
-
Source: site/content/examples/tech-selection-evaluator/en-US.md
|
|
1430
|
-
|
|
1431
|
-
# Semantic Details Layout
|
|
1432
|
-
|
|
1433
|
-
This fragment uses semantic native `<section>` and `<details>` elements for a compound disclosure layout that needs no custom component or script.
|
|
1434
|
-
|
|
1435
|
-
```slex
|
|
1436
|
-
<section><h2>Semantic Details Layout</h2><details open><summary>First section</summary><p>Unsupported compound widgets use semantic native HTML.</p></details><details><summary>Second section</summary><p>Native disclosure behavior needs no custom script.</p></details></section>
|
|
1437
|
-
```
|
|
1438
|
-
|
|
1439
|
-
Native disclosure behavior remains inside this fence's isolated document and requires no hidden JavaScript state.
|
|
1688
|
+
Table data is assigned as arrays through properties rather than encoded into HTML attributes. Expand a matching row's details below the table; text is not parsed as HTML.
|
|
1440
1689
|
|
|
1441
1690
|
---
|
|
1442
1691
|
|
|
@@ -1449,7 +1698,7 @@ Source: site/content/examples/salary-calculator/en-US.md
|
|
|
1449
1698
|
Adjust the contribution rate to estimate the employee deduction and remaining pay.
|
|
1450
1699
|
|
|
1451
1700
|
```slex
|
|
1452
|
-
<slex-card title="Social Insurance Calculator"><slex-grid columns="2"><slex-input id="salary" type="number" label="Monthly salary" value="18000"></slex-input><slex-slider id="rate" label="Employee contribution" unit="%" min="0" max="30" value="10.5"></slex-slider></slex-grid><slex-grid columns="2"><slex-stat id="deduction" label="Deduction"></slex-stat><slex-stat id="remaining" label="Remaining before tax"></slex-stat></slex-grid></slex-card>
|
|
1701
|
+
<slex-card title="Social Insurance Calculator"><slex-grid columns="2"><slex-input id="salary" type="number" label="Monthly salary" value="18000"></slex-input><slex-slider id="rate" label="Employee contribution" unit="%" min="0" max="30" step="0.1" value="10.5"></slex-slider></slex-grid><slex-grid columns="2"><slex-stat id="deduction" label="Deduction"></slex-stat><slex-stat id="remaining" label="Remaining before tax"></slex-stat></slex-grid></slex-card>
|
|
1453
1702
|
<script type="module">
|
|
1454
1703
|
const salary = slex.root.querySelector("#salary"); const rate = slex.root.querySelector("#rate"); const deduction = slex.root.querySelector("#deduction"); const remaining = slex.root.querySelector("#remaining");
|
|
1455
1704
|
const update = () => { const amount = Number(salary.value) * Number(rate.value) / 100; deduction.value = amount.toFixed(2); remaining.value = (Number(salary.value) - amount).toFixed(2); };
|
|
@@ -1512,6 +1761,48 @@ Source: `examples/streamdown`.
|
|
|
1512
1761
|
|
|
1513
1762
|
---
|
|
1514
1763
|
|
|
1764
|
+
# Technology Selection Evaluator
|
|
1765
|
+
|
|
1766
|
+
Source: site/content/examples/tech-selection-evaluator/en-US.md
|
|
1767
|
+
|
|
1768
|
+
# Technology Selection Evaluator
|
|
1769
|
+
|
|
1770
|
+
Choose a set of example scores, then adjust each dimension for your team. The weighted result is an illustration, not an objective ranking of frameworks.
|
|
1771
|
+
|
|
1772
|
+
```slex
|
|
1773
|
+
<slex-card title="Technology selection">
|
|
1774
|
+
<slex-select id="technology" label="Technology"><option value="react">React</option><option value="vue">Vue</option><option value="svelte">Svelte</option><option value="angular">Angular</option></slex-select>
|
|
1775
|
+
<slex-grid columns="2">
|
|
1776
|
+
<slex-slider id="performance" label="Performance (30%)" value="85" min="0" max="100" step="5"></slex-slider>
|
|
1777
|
+
<slex-slider id="ecosystem" label="Ecosystem (25%)" value="95" min="0" max="100" step="5"></slex-slider>
|
|
1778
|
+
<slex-slider id="learning" label="Learning (20%)" value="70" min="0" max="100" step="5"></slex-slider>
|
|
1779
|
+
<slex-slider id="maintenance" label="Maintenance (25%)" value="80" min="0" max="100" step="5"></slex-slider>
|
|
1780
|
+
</slex-grid>
|
|
1781
|
+
<slex-stat id="score" label="Weighted score" unit="points"></slex-stat>
|
|
1782
|
+
<slex-text id="recommendation"></slex-text>
|
|
1783
|
+
</slex-card>
|
|
1784
|
+
<script type="module">
|
|
1785
|
+
const get = id => slex.root.querySelector(`#${id}`);
|
|
1786
|
+
const ids = ["performance", "ecosystem", "learning", "maintenance"];
|
|
1787
|
+
const presets = { react: [85, 95, 70, 80], vue: [80, 85, 85, 85], svelte: [95, 70, 90, 90], angular: [80, 80, 60, 75] };
|
|
1788
|
+
const update = () => {
|
|
1789
|
+
const values = ids.map(id => Number(get(id).value));
|
|
1790
|
+
const score = values[0] * 0.3 + values[1] * 0.25 + values[2] * 0.2 + values[3] * 0.25;
|
|
1791
|
+
get("score").value = score.toFixed(1);
|
|
1792
|
+
get("recommendation").text = score >= 85 ? "Example result: strongly recommended" : score >= 75 ? "Example result: recommended" : score >= 60 ? "Example result: worth considering" : "Example result: proceed with caution";
|
|
1793
|
+
};
|
|
1794
|
+
const choose = () => { (presets[get("technology").value] || presets.react).forEach((value, i) => { get(ids[i]).value = value; }); update(); };
|
|
1795
|
+
get("technology").addEventListener("change", choose);
|
|
1796
|
+
ids.forEach(id => get(id).addEventListener("input", update));
|
|
1797
|
+
update();
|
|
1798
|
+
slex.onDispose(() => { get("technology").removeEventListener("change", choose); ids.forEach(id => get(id).removeEventListener("input", update)); });
|
|
1799
|
+
</script>
|
|
1800
|
+
```
|
|
1801
|
+
|
|
1802
|
+
The weights are 30%, 25%, 20%, and 25%. The local sample scores can be adjusted to match your own decision criteria.
|
|
1803
|
+
|
|
1804
|
+
---
|
|
1805
|
+
|
|
1515
1806
|
# Tiptap Editor Integration
|
|
1516
1807
|
|
|
1517
1808
|
Source: site/content/examples/tiptap-host/en-US.md
|
|
@@ -1550,11 +1841,16 @@ Source: site/content/examples/form-wizard-steps/en-US.md
|
|
|
1550
1841
|
|
|
1551
1842
|
ToolHost renders trusted host-side form UI and resolves an explicit submitted or ignored structured result; it is separate from display-only `slex` execution.
|
|
1552
1843
|
|
|
1553
|
-
```
|
|
1554
|
-
|
|
1844
|
+
```js
|
|
1845
|
+
const handle = renderToolCall({
|
|
1846
|
+
id: "project-form",
|
|
1847
|
+
name: "fill-form",
|
|
1848
|
+
arguments: { fields: [{ name: "name", label: "Project name", type: "text", required: true }] },
|
|
1849
|
+
}, container);
|
|
1850
|
+
const result = await handle.promise;
|
|
1555
1851
|
```
|
|
1556
1852
|
|
|
1557
|
-
|
|
1853
|
+
The form below is rendered by ToolHost in the host. Submit or ignore it to see the returned structured result.
|
|
1558
1854
|
|
|
1559
1855
|
---
|
|
1560
1856
|
|
|
@@ -1567,17 +1863,18 @@ Source: site/content/examples/toolhost-demo/en-US.md
|
|
|
1567
1863
|
ToolHost is a host-side tool-call renderer, not an authoring element inside a `slex` payload. The host selects a registered template from a trusted `function_call` name and passes only the call arguments to that template.
|
|
1568
1864
|
|
|
1569
1865
|
```js
|
|
1570
|
-
const
|
|
1866
|
+
const handle = renderToolCall({
|
|
1571
1867
|
name: "fill-form",
|
|
1572
|
-
|
|
1868
|
+
id: item.call_id,
|
|
1573
1869
|
arguments: JSON.parse(item.arguments),
|
|
1574
|
-
});
|
|
1870
|
+
}, container);
|
|
1871
|
+
const output = await handle.promise;
|
|
1575
1872
|
responsesInput.push({ type: "function_call_output", call_id: item.call_id, output: JSON.stringify(output) });
|
|
1576
1873
|
```
|
|
1577
1874
|
|
|
1578
1875
|
## Tool-call boundary
|
|
1579
1876
|
|
|
1580
|
-
When an agent emits a `function_call`, the browser host can render it as an inline ToolHost card.
|
|
1877
|
+
When an agent emits a `function_call`, the browser host can render it as an inline ToolHost card. The returned handle's promise resolves after submit or ignore, then the host writes a `function_call_output` using the original call ID. This workflow does not execute a deployment or other domain action by itself.
|
|
1581
1878
|
|
|
1582
1879
|
---
|
|
1583
1880
|
|
|
@@ -1593,13 +1890,13 @@ The module script implements \(V_{out} = V_{in} R_2 / (R_1 + R_2)\) with native
|
|
|
1593
1890
|
<slex-card title="Voltage Divider Calculator"><slex-grid columns="3"><slex-input id="vin" type="number" label="Input voltage" value="12"></slex-input><slex-input id="r1" type="number" label="R1" unit="kΩ" value="10"></slex-input><slex-input id="r2" type="number" label="R2" unit="kΩ" value="20"></slex-input></slex-grid><slex-stat id="vout" label="Output voltage" unit="V"></slex-stat></slex-card>
|
|
1594
1891
|
<script type="module">
|
|
1595
1892
|
const fields = ["vin", "r1", "r2"].map(id => slex.root.querySelector(`#${id}`)); const vout = slex.root.querySelector("#vout");
|
|
1596
|
-
const update = () => { const [vin, r1, r2] = fields.map(field => Number(field.value)); vout.value = (vin * r2 / (r1 + r2)).toFixed(2); };
|
|
1893
|
+
const update = () => { const [vin, r1, r2] = fields.map(field => Number(field.value)); vout.value = fields.some(field => field.value === "") || !Number.isFinite(vin) || r1 < 0 || r2 < 0 || r1 + r2 <= 0 ? "—" : (vin * r2 / (r1 + r2)).toFixed(2); };
|
|
1597
1894
|
fields.forEach(field => field.addEventListener("input", update)); update();
|
|
1598
1895
|
slex.onDispose(() => fields.forEach(field => field.removeEventListener("input", update)));
|
|
1599
1896
|
</script>
|
|
1600
1897
|
```
|
|
1601
1898
|
|
|
1602
|
-
The three
|
|
1899
|
+
The three numeric inputs drive one calculation function, which updates the output voltage. Invalid resistor values display a dash.
|
|
1603
1900
|
|
|
1604
1901
|
---
|
|
1605
1902
|
|
|
@@ -1882,6 +2179,19 @@ Source: site/content/releases/changelog/en-US.md
|
|
|
1882
2179
|
|
|
1883
2180
|
All notable changes to SlexKit.
|
|
1884
2181
|
|
|
2182
|
+
## v0.5.2 - Runtime rendering fixes
|
|
2183
|
+
|
|
2184
|
+
### Fixed
|
|
2185
|
+
- Preserve explicit text, label, and content attributes when custom elements have no light DOM children.
|
|
2186
|
+
- Keep the sandbox's CSP hash in sync with the trusted component layout styles so isolated components render correctly without relaxing the policy.
|
|
2187
|
+
- Restore interactive website examples and build adapter demos from pinned local dependencies.
|
|
2188
|
+
- Keep grids and their cards aligned in embedded previews, preload sandbox styles, and reduce the documentation site's initial asset size.
|
|
2189
|
+
|
|
2190
|
+
## @slexkit/assistant-ui v0.5.1
|
|
2191
|
+
|
|
2192
|
+
### Fixed
|
|
2193
|
+
- Constrain `@assistant-ui/react-streamdown` to versions compatible with `@assistant-ui/react` 0.14 so a fresh npm install resolves its peer dependencies.
|
|
2194
|
+
|
|
1885
2195
|
## v0.5.0 - HTML-first interactive documents
|
|
1886
2196
|
|
|
1887
2197
|
### Breaking changes
|
package/dist/data/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# SlexKit > Markdown-friendly reactive UI runtime for AI output
|
|
2
2
|
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.2
|
|
4
4
|
|
|
5
5
|
## Machine-readable documentation
|
|
6
6
|
|
|
@@ -29,7 +29,7 @@ Version: 0.5.0
|
|
|
29
29
|
|
|
30
30
|
### Examples
|
|
31
31
|
|
|
32
|
-
- [Artifact Shared
|
|
32
|
+
- [Artifact Shared State Lab](/docs/examples/cross-doc-state-lab.md): Synchronize JSON state between three independent fences in the same artifact.
|
|
33
33
|
- [assistant-ui Integration](/docs/examples/assistant-ui-host.md): assistant-ui adapter for rendering explicit slex fences inside Streamdown text message parts.
|
|
34
34
|
- [Baud Rate Error Calculator](/docs/examples/baud-rate-calculator.md): Enter crystal frequency and target baud rate to calculate UART baud rate error percentage and judge communication reliability.
|
|
35
35
|
- [Branching: Mode Selector](/docs/examples/tabs-and-branching.md): Use select to switch the mode state and render different inputs and results.
|
|
@@ -41,10 +41,10 @@ Version: 0.5.0
|
|
|
41
41
|
- [Project Dashboard](/docs/examples/project-dashboard.md): Build an information dashboard with section + grid — covering Sprint progress, quality metrics, and team health with multi-card coordination.
|
|
42
42
|
- [RC Low-Pass Filter](/docs/examples/rc-low-pass-filter.md): A frequency-selective circuit built with a resistor and capacitor — calculate cutoff frequency and gain attenuation at any frequency.
|
|
43
43
|
- [Search and Filter Table](/docs/examples/search-filter-table.md): A search input filters table rows in real time and uses collapsible for row details.
|
|
44
|
-
- [Semantic Details Layout](/docs/examples/tech-selection-evaluator.md): Use native section and details elements when no documented compound custom element matches the content.
|
|
45
44
|
- [Social Insurance Calculator](/docs/examples/salary-calculator.md): Enter a salary and city to calculate China's social insurance breakdown — showing personal contributions, employer contributions, and take-home pay.
|
|
46
45
|
- [Software Project Cost Estimator](/docs/examples/project-cost-estimator.md): Enter team size, development timeline, and per-person cost to calculate total project cost and monthly burn rate.
|
|
47
46
|
- [Streamdown Integration](/docs/examples/streamdown-host.md): A React/Streamdown adapter that takes over explicit slex fences and leaves ordinary Markdown and code blocks to Streamdown.
|
|
47
|
+
- [Technology Selection Evaluator](/docs/examples/tech-selection-evaluator.md): Compare example technology scores across performance, ecosystem, learning, and maintenance.
|
|
48
48
|
- [Tiptap Editor Integration](/docs/examples/tiptap-host.md): A Tiptap CodeBlock adapter that previews explicit slex blocks while preserving ordinary code blocks and Markdown import/export.
|
|
49
49
|
- [ToolHost Form Question](/docs/examples/form-wizard-steps.md): ToolHost renders a form card during a conversation, collects project fields, and submits structured results.
|
|
50
50
|
- [ToolHost Tool Call UI](/docs/examples/toolhost-demo.md): Render a function_call as an inline tool card, then write the submitted result back as function_call_output.
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slexkit-ai-docs",
|
|
3
3
|
"packageName": "slexkit",
|
|
4
|
-
"version": "0.5.
|
|
5
|
-
"generatedAt": "2026-11-
|
|
4
|
+
"version": "0.5.2",
|
|
5
|
+
"generatedAt": "2026-11-11T04:08:49.598Z",
|
|
6
6
|
"authoring": {
|
|
7
7
|
"sourceType": "html",
|
|
8
8
|
"fenceLanguage": "slex",
|
|
@@ -12,14 +12,14 @@
|
|
|
12
12
|
"llms.txt": {
|
|
13
13
|
"path": "/llms.txt",
|
|
14
14
|
"title": "llms.txt",
|
|
15
|
-
"summary": "Version: 0.5.
|
|
16
|
-
"hash": "
|
|
15
|
+
"summary": "Version: 0.5.2",
|
|
16
|
+
"hash": "797bc6d5"
|
|
17
17
|
},
|
|
18
18
|
"llms-full.txt": {
|
|
19
19
|
"path": "/llms-full.txt",
|
|
20
20
|
"title": "llms-full.txt",
|
|
21
21
|
"summary": "Source: site/content/components/accordion/en-US.md",
|
|
22
|
-
"hash": "
|
|
22
|
+
"hash": "8b7cde2c"
|
|
23
23
|
},
|
|
24
24
|
"llms-components.txt": {
|
|
25
25
|
"path": "/llms-components.txt",
|
|
@@ -386,13 +386,13 @@
|
|
|
386
386
|
{
|
|
387
387
|
"id": "examples/cross-doc-state-lab",
|
|
388
388
|
"group": "Examples",
|
|
389
|
-
"title": "Artifact Shared
|
|
390
|
-
"summary": "
|
|
389
|
+
"title": "Artifact Shared State Lab",
|
|
390
|
+
"summary": "Synchronize JSON state between three independent fences in the same artifact.",
|
|
391
391
|
"href": "/examples/cross-doc-state-lab",
|
|
392
392
|
"rawHref": "/docs/examples/cross-doc-state-lab.md",
|
|
393
393
|
"sourcePath": "site/content/examples/cross-doc-state-lab/en-US.md",
|
|
394
|
-
"body": "
|
|
395
|
-
"hash": "
|
|
394
|
+
"body": "# Artifact Shared State Lab\n\nChange the name, font size, or color in the control panel. The two independent panels below update through shared JSON.\n\n## Control panel\n\n```slex\n<slex-card title=\"Control panel\">\n <slex-grid columns=\"3\">\n <slex-input id=\"name\" label=\"Display name\" value=\"SlexKit\"></slex-input>\n <slex-slider id=\"size\" label=\"Font size\" min=\"12\" max=\"30\" value=\"18\" unit=\"px\"></slex-slider>\n <slex-select id=\"color\" label=\"Text color\"><option value=\"blue\">Blue</option><option value=\"green\">Green</option><option value=\"orange\">Orange</option></slex-select>\n </slex-grid>\n</slex-card>\n<script type=\"module\">\n const get = id => slex.root.querySelector(`#${id}`);\n const controls = [\"name\", \"size\", \"color\"].map(get);\n const publish = () => slex.shared.set(\"profile\", { name: get(\"name\").value, size: Number(get(\"size\").value), color: get(\"color\").value });\n controls.forEach(control => control.addEventListener(\"input\", publish));\n publish();\n slex.onDispose(() => controls.forEach(control => control.removeEventListener(\"input\", publish)));\n</script>\n```\n\n## Live preview\n\nThis panel subscribes to the shared value.\n\n```slex\n<slex-card title=\"Live preview\"><slex-text id=\"message\"></slex-text></slex-card>\n<script type=\"module\">\n const message = slex.root.querySelector(\"#message\");\n const stop = slex.shared.subscribe(\"profile\", profile => {\n if (!profile) return;\n message.text = String(profile.name);\n message.size = Number(profile.size);\n message.color = ({ blue: \"#2563eb\", green: \"#15803d\", orange: \"#c2410c\" })[profile.color] || \"#2563eb\";\n });\n slex.onDispose(stop);\n</script>\n```\n\n## Observer panel\n\nA second independent fence subscribes to the same JSON.\n\n```slex\n<slex-card title=\"Observer panel\"><slex-grid columns=\"2\"><slex-stat id=\"nameValue\" label=\"Current name\"></slex-stat><slex-stat id=\"sizeValue\" label=\"Font size\" unit=\"px\"></slex-stat></slex-grid></slex-card>\n<script type=\"module\">\n const stop = slex.shared.subscribe(\"profile\", profile => {\n if (!profile) return;\n slex.root.querySelector(\"#nameValue\").value = String(profile.name);\n slex.root.querySelector(\"#sizeValue\").value = Number(profile.size);\n });\n slex.onDispose(stop);\n</script>\n```\n\nThe fences share JSON only, not DOM nodes or JavaScript globals. Subscriptions and listeners are cleaned up on disposal.\n",
|
|
395
|
+
"hash": "8da8e094"
|
|
396
396
|
},
|
|
397
397
|
{
|
|
398
398
|
"id": "examples/assistant-ui-host",
|
|
@@ -413,8 +413,8 @@
|
|
|
413
413
|
"href": "/examples/baud-rate-calculator",
|
|
414
414
|
"rawHref": "/docs/examples/baud-rate-calculator.md",
|
|
415
415
|
"sourcePath": "site/content/examples/baud-rate-calculator/en-US.md",
|
|
416
|
-
"body": "\n# Baud Rate Error Calculator\n\nEnter a peripheral clock and divider
|
|
417
|
-
"hash": "
|
|
416
|
+
"body": "\n# Baud Rate Error Calculator\n\nEnter a peripheral clock, target baud rate, and integer divider. The module calculates the actual baud rate and error using 16× oversampling.\n\n```slex\n<slex-card title=\"Baud Rate Error Calculator\"><slex-grid columns=\"3\"><slex-input id=\"clock\" type=\"number\" label=\"Peripheral clock\" unit=\"MHz\" value=\"48\" min=\"0\"></slex-input><slex-input id=\"divider\" type=\"number\" label=\"Divider\" value=\"26\" min=\"1\" step=\"1\"></slex-input><slex-input id=\"target\" type=\"number\" label=\"Target baud\" value=\"115200\" min=\"1\"></slex-input></slex-grid><slex-stat id=\"result\" label=\"Actual baud / error\"></slex-stat></slex-card>\n<script type=\"module\">\n const fields = [\"clock\", \"divider\", \"target\"].map(id => slex.root.querySelector(`#${id}`));\n const result = slex.root.querySelector(\"#result\");\n const update = () => {\n const [clock, divider, target] = fields.map(field => Number(field.value));\n if (!(clock > 0 && target > 0 && Number.isInteger(divider) && divider > 0)) { result.value = \"Enter valid parameters\"; return; }\n const baud = clock * 1e6 / (16 * divider);\n result.value = `${baud.toFixed(0)} / ${((baud / target - 1) * 100).toFixed(2)}%`;\n };\n fields.forEach(field => field.addEventListener(\"input\", update)); update();\n slex.onDispose(() => fields.forEach(field => field.removeEventListener(\"input\", update)));\n</script>\n```\n\nInput values are read from live control properties, and the calculated baud rate and error appear in one stat.\n",
|
|
417
|
+
"hash": "7936ed13"
|
|
418
418
|
},
|
|
419
419
|
{
|
|
420
420
|
"id": "examples/tabs-and-branching",
|
|
@@ -424,8 +424,8 @@
|
|
|
424
424
|
"href": "/examples/tabs-and-branching",
|
|
425
425
|
"rawHref": "/docs/examples/tabs-and-branching.md",
|
|
426
426
|
"sourcePath": "site/content/examples/tabs-and-branching/en-US.md",
|
|
427
|
-
"body": "\n# Branching: Mode Selector\n\
|
|
428
|
-
"hash": "
|
|
427
|
+
"body": "\n# Branching: Mode Selector\n\nChoose a length, weight, or temperature conversion. The input and result update with the selected mode.\n\n```slex\n<slex-card title=\"Unit conversion\">\n <slex-select id=\"mode\" label=\"Conversion mode\"><option value=\"length\">Centimeters → meters</option><option value=\"weight\">Kilograms → pounds</option><option value=\"temperature\">Celsius → Fahrenheit</option></slex-select>\n <slex-input id=\"amount\" type=\"number\" label=\"Value (cm)\" value=\"100\"></slex-input>\n <slex-stat id=\"result\" label=\"Result\"></slex-stat>\n <slex-text id=\"description\"></slex-text>\n</slex-card>\n<script type=\"module\">\n const mode = slex.root.querySelector(\"#mode\");\n const amount = slex.root.querySelector(\"#amount\");\n const result = slex.root.querySelector(\"#result\");\n const description = slex.root.querySelector(\"#description\");\n const modes = {\n length: { label: \"Value (cm)\", description: \"Divide centimeters by 100 to obtain meters.\", convert: n => `${(n / 100).toFixed(2)} m` },\n weight: { label: \"Value (kg)\", description: \"Multiply kilograms by 2.20462 to obtain pounds.\", convert: n => `${(n * 2.20462).toFixed(2)} lb` },\n temperature: { label: \"Value (°C)\", description: \"Multiply Celsius by 9/5, then add 32.\", convert: n => `${(n * 9 / 5 + 32).toFixed(1)} °F` },\n };\n const update = () => {\n const selected = modes[mode.value] || modes.length;\n const number = amount.value === \"\" ? NaN : Number(amount.value);\n amount.label = selected.label;\n description.text = selected.description;\n result.value = Number.isFinite(number) ? selected.convert(number) : \"Enter a number\";\n };\n mode.addEventListener(\"change\", update);\n amount.addEventListener(\"input\", update);\n update();\n slex.onDispose(() => { mode.removeEventListener(\"change\", update); amount.removeEventListener(\"input\", update); });\n</script>\n```\n\nNative events drive the mode and input value; listeners are removed when the document is disposed.\n",
|
|
428
|
+
"hash": "8560ecdc"
|
|
429
429
|
},
|
|
430
430
|
{
|
|
431
431
|
"id": "examples/roi-estimator",
|
|
@@ -435,8 +435,8 @@
|
|
|
435
435
|
"href": "/examples/roi-estimator",
|
|
436
436
|
"rawHref": "/docs/examples/roi-estimator.md",
|
|
437
437
|
"sourcePath": "site/content/examples/roi-estimator/en-US.md",
|
|
438
|
-
"body": "\n# Build vs Buy Decision\n\nCompare
|
|
439
|
-
"hash": "
|
|
438
|
+
"body": "\n# Build vs Buy Decision\n\nCompare feature fit, cost, delivery time, and vendor risk. The scores are illustrative.\n\n```slex\n<slex-card title=\"Build vs Buy Decision\">\n <slex-select id=\"scope\" label=\"Function role\"><option value=\"core\">Core business</option><option value=\"non-core\">Supporting function</option></slex-select>\n <slex-grid columns=\"2\">\n <slex-card title=\"Build\"><slex-slider id=\"buildFit\" label=\"Feature fit\" min=\"0\" max=\"100\" step=\"5\" value=\"60\"></slex-slider><slex-slider id=\"buildCost\" label=\"Cost score (lower is better)\" min=\"0\" max=\"100\" step=\"5\" value=\"80\"></slex-slider><slex-slider id=\"buildTime\" label=\"Time to launch (months)\" min=\"1\" max=\"12\" value=\"6\"></slex-slider></slex-card>\n <slex-card title=\"Buy\"><slex-slider id=\"buyFit\" label=\"Feature fit\" min=\"0\" max=\"100\" step=\"5\" value=\"85\"></slex-slider><slex-slider id=\"buyCost\" label=\"Cost score (lower is better)\" min=\"0\" max=\"100\" step=\"5\" value=\"40\"></slex-slider><slex-slider id=\"buyTime\" label=\"Time to launch (months)\" min=\"1\" max=\"12\" value=\"1\"></slex-slider><slex-slider id=\"buyLock\" label=\"Vendor lock-in risk\" min=\"0\" max=\"100\" step=\"5\" value=\"30\"></slex-slider></slex-card>\n </slex-grid>\n <slex-grid columns=\"2\"><slex-stat id=\"buildScore\" label=\"Build score\"></slex-stat><slex-stat id=\"buyScore\" label=\"Buy score\"></slex-stat></slex-grid>\n <slex-text id=\"advice\" label=\"Decision notes\"></slex-text>\n</slex-card>\n<script type=\"module\">\n const get = id => slex.root.querySelector(`#${id}`);\n const ids = [\"scope\", \"buildFit\", \"buildCost\", \"buildTime\", \"buyFit\", \"buyCost\", \"buyTime\", \"buyLock\"];\n const copy = {\"close\": \"The scores are close; investigate both options further.\", \"buildWins\": \"Build scores higher\", \"buyWins\": \"Buy scores higher\", \"coreNote\": \"For core capabilities, also consider long-term control.\", \"noncoreNote\": \"For supporting capabilities, also consider maintenance cost.\"};\n const update = () => {\n const value = id => Number(get(id).value);\n const timeScore = id => Math.max(0, 100 - value(id) * 10);\n const build = (value(\"buildFit\") + 100 - value(\"buildCost\") + timeScore(\"buildTime\")) / 3;\n const buy = (value(\"buyFit\") + 100 - value(\"buyCost\") + timeScore(\"buyTime\") - value(\"buyLock\") * 0.5) / 3;\n get(\"buildScore\").value = build.toFixed(1); get(\"buyScore\").value = buy.toFixed(1);\n const verdict = Math.abs(build - buy) < 10 ? copy.close : build > buy ? copy.buildWins : copy.buyWins;\n get(\"advice\").text = `${verdict} ${get(\"scope\").value === \"core\" ? copy.coreNote : copy.noncoreNote}`;\n };\n ids.forEach(id => get(id).addEventListener(\"input\", update)); update();\n slex.onDispose(() => ids.forEach(id => get(id).removeEventListener(\"input\", update)));\n</script>\n```\n\nThese adjustable example scores do not replace a real budget, procurement, or risk assessment.\n",
|
|
439
|
+
"hash": "9ded7150"
|
|
440
440
|
},
|
|
441
441
|
{
|
|
442
442
|
"id": "examples/first-interaction",
|
|
@@ -490,8 +490,8 @@
|
|
|
490
490
|
"href": "/examples/project-dashboard",
|
|
491
491
|
"rawHref": "/docs/examples/project-dashboard.md",
|
|
492
492
|
"sourcePath": "site/content/examples/project-dashboard/en-US.md",
|
|
493
|
-
"body": "\n# Project Dashboard\n\nThe dashboard composes cards, grids, controls, and stats while one JavaScript update function coordinates the displayed project metrics.\n\n```slex\n<slex-
|
|
494
|
-
"hash": "
|
|
493
|
+
"body": "\n# Project Dashboard\n\nThe dashboard composes cards, grids, controls, and stats while one JavaScript update function coordinates the displayed project metrics.\n\n```slex\n<slex-section title=\"Sprint dashboard\" subtitle=\"Adjust the inputs to explore progress, quality, and team load.\">\n <slex-grid columns=\"3\">\n <slex-card title=\"Sprint progress\">\n <slex-slider id=\"progress\" label=\"Completion\" value=\"72\" min=\"0\" max=\"100\" unit=\"%\"></slex-slider>\n <slex-progress id=\"progressBar\" label=\"Completion\"></slex-progress>\n <slex-select id=\"scope\" label=\"Scope status\"><option value=\"on-track\">On track</option><option value=\"at-risk\">At risk</option><option value=\"off-track\">Off track</option></slex-select>\n <slex-badge id=\"scopeBadge\"></slex-badge>\n </slex-card>\n <slex-card title=\"Quality\">\n <slex-input id=\"bugs\" type=\"number\" min=\"0\" label=\"Total defects\" value=\"12\"></slex-input>\n <slex-input id=\"resolved\" type=\"number\" min=\"0\" label=\"Resolved\" value=\"9\"></slex-input>\n <slex-stat id=\"remaining\" label=\"Remaining defects\"></slex-stat>\n <slex-progress id=\"fixRate\" label=\"Resolution rate\"></slex-progress>\n </slex-card>\n <slex-card title=\"Team health\">\n <slex-input id=\"workload\" type=\"number\" min=\"0\" label=\"Workload\" value=\"8\"></slex-input>\n <slex-input id=\"team\" type=\"number\" min=\"1\" label=\"Team members\" value=\"6\"></slex-input>\n <slex-stat id=\"load\" label=\"Load index\" unit=\"%\"></slex-stat>\n <slex-text id=\"note\"></slex-text>\n </slex-card>\n </slex-grid>\n <slex-card title=\"Task details\"><slex-table id=\"tasks\"></slex-table></slex-card>\n</slex-section>\n<script type=\"module\">\n const get = id => slex.root.querySelector(`#${id}`);\n const controls = [\"progress\", \"scope\", \"bugs\", \"resolved\", \"workload\", \"team\"].map(get);\n const statuses = { \"on-track\": [\"On track\", \"success\"], \"at-risk\": [\"At risk\", \"warning\"], \"off-track\": [\"Off track\", \"destructive\"] };\n const update = () => {\n const bugs = Math.max(0, Number(get(\"bugs\").value) || 0);\n const resolved = Math.min(bugs, Math.max(0, Number(get(\"resolved\").value) || 0));\n const team = Math.max(1, Number(get(\"team\").value) || 1);\n const load = Math.min(100, Math.max(0, Number(get(\"workload\").value) || 0) / team * 20);\n const [label, tone] = statuses[get(\"scope\").value] || statuses[\"on-track\"];\n get(\"progressBar\").value = Number(get(\"progress\").value);\n get(\"scopeBadge\").label = label; get(\"scopeBadge\").tone = tone;\n get(\"remaining\").value = bugs - resolved;\n get(\"fixRate\").value = bugs ? resolved / bugs * 100 : 0;\n get(\"load\").value = load.toFixed(1);\n get(\"note\").text = load > 80 ? \"Team load is high; consider redistributing work.\" : \"Team load is within the healthy range.\";\n };\n get(\"tasks\").columns = [\"Task\", \"Owner\", \"Status\"];\n get(\"tasks\").rows = [[\"API refactor\", \"Alex\", \"Done\"], [\"UI components\", \"Lee\", \"In progress\"], [\"Integration tests\", \"Sam\", \"Review\"]];\n controls.forEach(control => control.addEventListener(\"input\", update));\n update();\n slex.onDispose(() => controls.forEach(control => control.removeEventListener(\"input\", update)));\n</script>\n```\n\nThe values stay in component properties and ordinary JavaScript; no hidden namespace store or expression evaluator participates.\n",
|
|
494
|
+
"hash": "e129c4dd"
|
|
495
495
|
},
|
|
496
496
|
{
|
|
497
497
|
"id": "examples/rc-low-pass-filter",
|
|
@@ -501,8 +501,8 @@
|
|
|
501
501
|
"href": "/examples/rc-low-pass-filter",
|
|
502
502
|
"rawHref": "/docs/examples/rc-low-pass-filter.md",
|
|
503
503
|
"sourcePath": "site/content/examples/rc-low-pass-filter/en-US.md",
|
|
504
|
-
"body": "\n# RC Low-Pass Filter\n\nThe cutoff calculation is ordinary JavaScript: \\(f_c = 1 / (2\\pi RC)\\). Values are read from live custom-element properties.\n\n```slex\n<
|
|
505
|
-
"hash": "
|
|
504
|
+
"body": "\n# RC Low-Pass Filter\n\nThe cutoff calculation is ordinary JavaScript: \\(f_c = 1 / (2\\pi RC)\\). Values are read from live custom-element properties.\n\n```slex\n<div class=\"rc-filter-demo\">\n <div id=\"inputs\" class=\"rc-filter-grid\">\n <div class=\"rc-filter-field\">\n <slex-input id=\"r\" label=\"Resistance R\" type=\"engineering\" value=\"10kΩ\" placeholder=\"10kΩ\"></slex-input>\n <slex-slider id=\"rControl\" label=\"R\" value=\"10000\" min=\"1000\" max=\"100000\" step=\"1000\" unit=\"Ω\"></slex-slider>\n </div>\n <div class=\"rc-filter-field\">\n <slex-input id=\"c\" label=\"Capacitance C\" type=\"engineering\" value=\"100nF\" placeholder=\"100nF\"></slex-input>\n <slex-slider id=\"cControl\" label=\"C\" value=\"100\" min=\"10\" max=\"1000\" step=\"10\" unit=\"nF\"></slex-slider>\n </div>\n <div class=\"rc-filter-field\">\n <slex-input id=\"f\" label=\"Input frequency f\" type=\"engineering\" value=\"1kHz\" placeholder=\"1kHz\"></slex-input>\n <slex-slider id=\"fControl\" label=\"f\" value=\"1000\" min=\"0\" max=\"5000\" step=\"10\" unit=\"Hz\"></slex-slider>\n </div>\n <div class=\"rc-filter-field\">\n <slex-input id=\"vin\" label=\"Input amplitude Vin\" type=\"engineering\" value=\"1V\" placeholder=\"1V\"></slex-input>\n <slex-slider id=\"vinControl\" label=\"Vin\" value=\"1\" min=\"0\" max=\"5\" step=\"0.1\" unit=\"V\"></slex-slider>\n </div>\n </div>\n\n <p id=\"inputHint\" class=\"rc-filter-muted\">Try 4.7kΩ, 220nF, 10kHz, and 500mV. value keeps the source text; number drives the calculation.</p>\n\n <div id=\"outputs\" class=\"rc-filter-grid\">\n <slex-stat id=\"tau\" label=\"Time constant\" unit=\"ms\" animate-initial></slex-stat>\n <slex-stat id=\"cutoff\" label=\"Cutoff frequency\" unit=\"Hz\" animate-initial></slex-stat>\n <slex-stat id=\"gain\" label=\"Magnitude gain\" animate-initial></slex-stat>\n <slex-stat id=\"output\" label=\"Output amplitude\" unit=\"V\" animate-initial></slex-stat>\n </div>\n\n <div id=\"formula\" class=\"rc-filter-formula\"></div>\n <div class=\"rc-filter-actions\">\n <p id=\"status\" class=\"rc-filter-muted\"></p>\n <slex-button id=\"reset\" label=\"Reset\" variant=\"secondary\"></slex-button>\n </div>\n</div>\n\n<style>\n .rc-filter-demo { display: grid; gap: 1rem; min-width: 0; }\n .rc-filter-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1rem; min-width: 0; }\n @media (min-width: 600px) { .rc-filter-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }\n .rc-filter-field { display: grid; align-content: start; gap: 1rem; min-width: 0; }\n .rc-filter-formula { border: 1px solid var(--border); border-radius: var(--radius); background: var(--muted); padding: .625rem .75rem; font-family: var(--font-mono, monospace); font-weight: 600; line-height: 1.7; }\n .rc-filter-muted { margin: 0; color: var(--muted-foreground); font-size: .875rem; line-height: 1.625; }\n .rc-filter-actions { display: flex; min-width: 0; align-items: center; justify-content: space-between; gap: 1rem; }\n #status { flex: 1 1 24rem; min-width: 0; }\n @media (max-width: 599px) {\n .rc-filter-actions { flex-direction: column; align-items: stretch; }\n #status { flex: 0 1 auto; }\n #reset { width: 100%; }\n }\n</style>\n\n<script type=\"module\">\n const byId = (id) => slex.root.querySelector(`#${id}`);\n const inputs = {\n r: byId(\"r\"),\n c: byId(\"c\"),\n f: byId(\"f\"),\n vin: byId(\"vin\"),\n };\n const sliders = {\n r: byId(\"rControl\"),\n c: byId(\"cControl\"),\n f: byId(\"fControl\"),\n vin: byId(\"vinControl\"),\n };\n const defaults = { r: \"10kΩ\", c: \"100nF\", f: \"1kHz\", vin: \"1V\" };\n const units = { r: \"Ω\", c: \"nF\", f: \"Hz\", vin: \"V\" };\n const sliderScale = { r: 1, c: 1e9, f: 1, vin: 1 };\n const format = (value, digits) => Number.isFinite(value) ? value.toFixed(digits) : \"Invalid\";\n\n const update = (origin) => {\n const r = inputs.r.valueAsNumber;\n const c = inputs.c.valueAsNumber;\n const f = inputs.f.valueAsNumber;\n const vin = inputs.vin.valueAsNumber;\n const valid = [r, c, f, vin].every(Number.isFinite) && r > 0 && c > 0 && f >= 0 && vin >= 0;\n const tau = valid ? r * c : NaN;\n const cutoff = valid && tau > 0 ? 1 / (2 * Math.PI * tau) : NaN;\n const gain = valid && cutoff > 0 ? 1 / Math.sqrt(1 + (f / cutoff) ** 2) : NaN;\n const gainDb = Number.isFinite(gain) && gain > 0 ? 20 * Math.log10(gain) : NaN;\n const output = Number.isFinite(gain) ? vin * gain : NaN;\n\n if (origin !== \"slider\") {\n for (const key of Object.keys(sliders)) {\n const number = inputs[key].valueAsNumber;\n if (Number.isFinite(number)) sliders[key].value = String(number * sliderScale[key]);\n }\n }\n\n byId(\"tau\").value = format(tau * 1000, 3);\n byId(\"cutoff\").value = format(cutoff, 2);\n byId(\"gain\").value = format(gain, 3);\n byId(\"output\").value = format(output, 3);\n byId(\"formula\").textContent = `|H(f)| = ${format(gain, 3)}, Gain = ${format(gainDb, 2)} dB`;\n byId(\"status\").textContent = valid\n ? \"Low frequencies pass through; higher frequencies are attenuated by the first-order RC network.\"\n : \"Check the engineering input format. R and C must be greater than 0; frequency and input amplitude cannot be negative.\";\n };\n\n const onInput = () => update(\"input\");\n const sliderHandlers = Object.fromEntries(Object.keys(sliders).map((key) => [key, () => {\n inputs[key].value = `${sliders[key].value}${units[key]}`;\n update(\"slider\");\n }]));\n const reset = () => {\n for (const [key, value] of Object.entries(defaults)) inputs[key].value = value;\n update(\"input\");\n };\n\n Object.values(inputs).forEach((control) => control.addEventListener(\"input\", onInput));\n for (const [key, control] of Object.entries(sliders)) control.addEventListener(\"input\", sliderHandlers[key]);\n byId(\"reset\").addEventListener(\"click\", reset);\n update(\"input\");\n\n slex.onDispose(() => {\n Object.values(inputs).forEach((control) => control.removeEventListener(\"input\", onInput));\n for (const [key, control] of Object.entries(sliders)) control.removeEventListener(\"input\", sliderHandlers[key]);\n byId(\"reset\").removeEventListener(\"click\", reset);\n });\n</script>\n```\n\nEngineering input values are parsed from the controls and the resulting cutoff/gain values are written as display properties.\n",
|
|
505
|
+
"hash": "293ef1d5"
|
|
506
506
|
},
|
|
507
507
|
{
|
|
508
508
|
"id": "examples/search-filter-table",
|
|
@@ -512,19 +512,8 @@
|
|
|
512
512
|
"href": "/examples/search-filter-table",
|
|
513
513
|
"rawHref": "/docs/examples/search-filter-table.md",
|
|
514
514
|
"sourcePath": "site/content/examples/search-filter-table/en-US.md",
|
|
515
|
-
"body": "\n# Search and Filter Table\n\nThe search input filters an in-memory array and assigns the matching rows to the table's live `.rows` property.\n\n```slex\n<slex-card title=\"Search and Filter Table\"><slex-input id=\"query\" label=\"Filter\"></slex-input><slex-table id=\"results\"></slex-table></slex-card>\n<script type=\"module\">\n const rows = [{ name: \"Ada\", role: \"Engineer\" }, { name: \"Lin\", role: \"Designer\" }]; const query = slex.root.querySelector(\"#query\"); const table = slex.root.querySelector(\"#results\");\n table.columns = [{ key: \"name\", label: \"Name\" }, { key: \"role\", label: \"Role\" }]
|
|
516
|
-
"hash": "
|
|
517
|
-
},
|
|
518
|
-
{
|
|
519
|
-
"id": "examples/tech-selection-evaluator",
|
|
520
|
-
"group": "Examples",
|
|
521
|
-
"title": "Semantic Details Layout",
|
|
522
|
-
"summary": "Use native section and details elements when no documented compound custom element matches the content.",
|
|
523
|
-
"href": "/examples/tech-selection-evaluator",
|
|
524
|
-
"rawHref": "/docs/examples/tech-selection-evaluator.md",
|
|
525
|
-
"sourcePath": "site/content/examples/tech-selection-evaluator/en-US.md",
|
|
526
|
-
"body": "\n# Semantic Details Layout\n\nThis fragment uses semantic native `<section>` and `<details>` elements for a compound disclosure layout that needs no custom component or script.\n\n```slex\n<section><h2>Semantic Details Layout</h2><details open><summary>First section</summary><p>Unsupported compound widgets use semantic native HTML.</p></details><details><summary>Second section</summary><p>Native disclosure behavior needs no custom script.</p></details></section>\n```\n\nNative disclosure behavior remains inside this fence's isolated document and requires no hidden JavaScript state.\n",
|
|
527
|
-
"hash": "cdb346cc"
|
|
515
|
+
"body": "\n# Search and Filter Table\n\nThe search input filters an in-memory array and assigns the matching rows to the table's live `.rows` property.\n\n```slex\n<slex-card title=\"Search and Filter Table\"><slex-input id=\"query\" label=\"Filter\"></slex-input><slex-table id=\"results\"></slex-table><div id=\"details\"></div></slex-card>\n<script type=\"module\">\n const rows = [{ name: \"Ada\", role: \"Engineer\" }, { name: \"Lin\", role: \"Designer\" }]; const query = slex.root.querySelector(\"#query\"); const table = slex.root.querySelector(\"#results\");\n const details = slex.root.querySelector(\"#details\");\n table.columns = [{ key: \"name\", label: \"Name\" }, { key: \"role\", label: \"Role\" }];\n const update = () => {\n const needle = query.value.toLowerCase();\n const matches = rows.filter((row) => Object.values(row).some((value) => value.toLowerCase().includes(needle)));\n table.rows = matches;\n details.replaceChildren(...matches.map((row) => {\n const item = document.createElement(\"slex-collapsible\");\n item.setAttribute(\"trigger\", `${row.name} — details`);\n item.setAttribute(\"content\", `Role: ${row.role}`);\n return item;\n }));\n };\n query.addEventListener(\"input\", update); update(); slex.onDispose(() => query.removeEventListener(\"input\", update));\n</script>\n```\n\nTable data is assigned as arrays through properties rather than encoded into HTML attributes. Expand a matching row's details below the table; text is not parsed as HTML.\n",
|
|
516
|
+
"hash": "48b12231"
|
|
528
517
|
},
|
|
529
518
|
{
|
|
530
519
|
"id": "examples/salary-calculator",
|
|
@@ -534,8 +523,8 @@
|
|
|
534
523
|
"href": "/examples/salary-calculator",
|
|
535
524
|
"rawHref": "/docs/examples/salary-calculator.md",
|
|
536
525
|
"sourcePath": "site/content/examples/salary-calculator/en-US.md",
|
|
537
|
-
"body": "\n# Social Insurance Calculator\n\nAdjust the contribution rate to estimate the employee deduction and remaining pay.\n\n```slex\n<slex-card title=\"Social Insurance Calculator\"><slex-grid columns=\"2\"><slex-input id=\"salary\" type=\"number\" label=\"Monthly salary\" value=\"18000\"></slex-input><slex-slider id=\"rate\" label=\"Employee contribution\" unit=\"%\" min=\"0\" max=\"30\" value=\"10.5\"></slex-slider></slex-grid><slex-grid columns=\"2\"><slex-stat id=\"deduction\" label=\"Deduction\"></slex-stat><slex-stat id=\"remaining\" label=\"Remaining before tax\"></slex-stat></slex-grid></slex-card>\n<script type=\"module\">\n const salary = slex.root.querySelector(\"#salary\"); const rate = slex.root.querySelector(\"#rate\"); const deduction = slex.root.querySelector(\"#deduction\"); const remaining = slex.root.querySelector(\"#remaining\");\n const update = () => { const amount = Number(salary.value) * Number(rate.value) / 100; deduction.value = amount.toFixed(2); remaining.value = (Number(salary.value) - amount).toFixed(2); };\n salary.addEventListener(\"input\", update); rate.addEventListener(\"input\", update); update(); slex.onDispose(() => { salary.removeEventListener(\"input\", update); rate.removeEventListener(\"input\", update); });\n</script>\n```\n\nThe salary and contribution rate remain live control values; recalculation updates only the displayed deduction and remainder.\n",
|
|
538
|
-
"hash": "
|
|
526
|
+
"body": "\n# Social Insurance Calculator\n\nAdjust the contribution rate to estimate the employee deduction and remaining pay.\n\n```slex\n<slex-card title=\"Social Insurance Calculator\"><slex-grid columns=\"2\"><slex-input id=\"salary\" type=\"number\" label=\"Monthly salary\" value=\"18000\"></slex-input><slex-slider id=\"rate\" label=\"Employee contribution\" unit=\"%\" min=\"0\" max=\"30\" step=\"0.1\" value=\"10.5\"></slex-slider></slex-grid><slex-grid columns=\"2\"><slex-stat id=\"deduction\" label=\"Deduction\"></slex-stat><slex-stat id=\"remaining\" label=\"Remaining before tax\"></slex-stat></slex-grid></slex-card>\n<script type=\"module\">\n const salary = slex.root.querySelector(\"#salary\"); const rate = slex.root.querySelector(\"#rate\"); const deduction = slex.root.querySelector(\"#deduction\"); const remaining = slex.root.querySelector(\"#remaining\");\n const update = () => { const amount = Number(salary.value) * Number(rate.value) / 100; deduction.value = amount.toFixed(2); remaining.value = (Number(salary.value) - amount).toFixed(2); };\n salary.addEventListener(\"input\", update); rate.addEventListener(\"input\", update); update(); slex.onDispose(() => { salary.removeEventListener(\"input\", update); rate.removeEventListener(\"input\", update); });\n</script>\n```\n\nThe salary and contribution rate remain live control values; recalculation updates only the displayed deduction and remainder.\n",
|
|
527
|
+
"hash": "7d15f06b"
|
|
539
528
|
},
|
|
540
529
|
{
|
|
541
530
|
"id": "examples/project-cost-estimator",
|
|
@@ -559,6 +548,17 @@
|
|
|
559
548
|
"body": "\n# Streamdown Integration\n\nThe Streamdown renderer handles ordinary Markdown normally and sends only explicit `slex` fence strings to the isolated document host.\n\n```slex\n<slex-card title=\"Streamdown Integration\"><slex-grid columns=\"2\"><slex-input id=\"left\" label=\"Value A\" value=\"10\"></slex-input><slex-slider id=\"right\" label=\"Value B\" min=\"0\" max=\"100\" value=\"20\"></slex-slider></slex-grid><slex-stat id=\"result\" label=\"Result\"></slex-stat></slex-card>\n<script type=\"module\">\n const left = slex.root.querySelector(\"#left\"); const right = slex.root.querySelector(\"#right\"); const result = slex.root.querySelector(\"#result\"); const update = () => { result.value = Number(left.value) + right.valueAsNumber; };\n left.addEventListener(\"input\", update); right.addEventListener(\"input\", update); update(); slex.onDispose(() => { left.removeEventListener(\"input\", update); right.removeEventListener(\"input\", update); });\n</script>\n```\n\n## Host boundary\n\nThe adapter recognizes explicit `slex` fences and passes the raw HTML string to the same isolated document host. The host supplies stable artifact/block IDs, runtime/style URLs, and policy; the payload does not.\n\nThe adapter keeps stable artifact/block IDs and delegates preview versus commit decisions to the document host.\n\n`@slexkit/streamdown` recognizes explicit fences and forwards their HTML source to the isolated document host.\n\n<iframe class=\"slex-example-live-frame\" src=\"/adapter-demos/streamdown/?embed=1\" title=\"Streamdown HTML fence demo\"></iframe>\n\nSource: `examples/streamdown`.\n",
|
|
560
549
|
"hash": "df557438"
|
|
561
550
|
},
|
|
551
|
+
{
|
|
552
|
+
"id": "examples/tech-selection-evaluator",
|
|
553
|
+
"group": "Examples",
|
|
554
|
+
"title": "Technology Selection Evaluator",
|
|
555
|
+
"summary": "Compare example technology scores across performance, ecosystem, learning, and maintenance.",
|
|
556
|
+
"href": "/examples/tech-selection-evaluator",
|
|
557
|
+
"rawHref": "/docs/examples/tech-selection-evaluator.md",
|
|
558
|
+
"sourcePath": "site/content/examples/tech-selection-evaluator/en-US.md",
|
|
559
|
+
"body": "\n# Technology Selection Evaluator\n\nChoose a set of example scores, then adjust each dimension for your team. The weighted result is an illustration, not an objective ranking of frameworks.\n\n```slex\n<slex-card title=\"Technology selection\">\n <slex-select id=\"technology\" label=\"Technology\"><option value=\"react\">React</option><option value=\"vue\">Vue</option><option value=\"svelte\">Svelte</option><option value=\"angular\">Angular</option></slex-select>\n <slex-grid columns=\"2\">\n <slex-slider id=\"performance\" label=\"Performance (30%)\" value=\"85\" min=\"0\" max=\"100\" step=\"5\"></slex-slider>\n <slex-slider id=\"ecosystem\" label=\"Ecosystem (25%)\" value=\"95\" min=\"0\" max=\"100\" step=\"5\"></slex-slider>\n <slex-slider id=\"learning\" label=\"Learning (20%)\" value=\"70\" min=\"0\" max=\"100\" step=\"5\"></slex-slider>\n <slex-slider id=\"maintenance\" label=\"Maintenance (25%)\" value=\"80\" min=\"0\" max=\"100\" step=\"5\"></slex-slider>\n </slex-grid>\n <slex-stat id=\"score\" label=\"Weighted score\" unit=\"points\"></slex-stat>\n <slex-text id=\"recommendation\"></slex-text>\n</slex-card>\n<script type=\"module\">\n const get = id => slex.root.querySelector(`#${id}`);\n const ids = [\"performance\", \"ecosystem\", \"learning\", \"maintenance\"];\n const presets = { react: [85, 95, 70, 80], vue: [80, 85, 85, 85], svelte: [95, 70, 90, 90], angular: [80, 80, 60, 75] };\n const update = () => {\n const values = ids.map(id => Number(get(id).value));\n const score = values[0] * 0.3 + values[1] * 0.25 + values[2] * 0.2 + values[3] * 0.25;\n get(\"score\").value = score.toFixed(1);\n get(\"recommendation\").text = score >= 85 ? \"Example result: strongly recommended\" : score >= 75 ? \"Example result: recommended\" : score >= 60 ? \"Example result: worth considering\" : \"Example result: proceed with caution\";\n };\n const choose = () => { (presets[get(\"technology\").value] || presets.react).forEach((value, i) => { get(ids[i]).value = value; }); update(); };\n get(\"technology\").addEventListener(\"change\", choose);\n ids.forEach(id => get(id).addEventListener(\"input\", update));\n update();\n slex.onDispose(() => { get(\"technology\").removeEventListener(\"change\", choose); ids.forEach(id => get(id).removeEventListener(\"input\", update)); });\n</script>\n```\n\nThe weights are 30%, 25%, 20%, and 25%. The local sample scores can be adjusted to match your own decision criteria.\n",
|
|
560
|
+
"hash": "46a04d79"
|
|
561
|
+
},
|
|
562
562
|
{
|
|
563
563
|
"id": "examples/tiptap-host",
|
|
564
564
|
"group": "Examples",
|
|
@@ -578,8 +578,8 @@
|
|
|
578
578
|
"href": "/examples/form-wizard-steps",
|
|
579
579
|
"rawHref": "/docs/examples/form-wizard-steps.md",
|
|
580
580
|
"sourcePath": "site/content/examples/form-wizard-steps/en-US.md",
|
|
581
|
-
"body": "\n# ToolHost Form Question\n\nToolHost renders trusted host-side form UI and resolves an explicit submitted or ignored structured result; it is separate from display-only `slex` execution.\n\n```
|
|
582
|
-
"hash": "
|
|
581
|
+
"body": "\n# ToolHost Form Question\n\nToolHost renders trusted host-side form UI and resolves an explicit submitted or ignored structured result; it is separate from display-only `slex` execution.\n\n```js\nconst handle = renderToolCall({\n id: \"project-form\",\n name: \"fill-form\",\n arguments: { fields: [{ name: \"name\", label: \"Project name\", type: \"text\", required: true }] },\n}, container);\nconst result = await handle.promise;\n```\n\nThe form below is rendered by ToolHost in the host. Submit or ignore it to see the returned structured result.\n",
|
|
582
|
+
"hash": "1468ec61"
|
|
583
583
|
},
|
|
584
584
|
{
|
|
585
585
|
"id": "examples/toolhost-demo",
|
|
@@ -589,8 +589,8 @@
|
|
|
589
589
|
"href": "/examples/toolhost-demo",
|
|
590
590
|
"rawHref": "/docs/examples/toolhost-demo.md",
|
|
591
591
|
"sourcePath": "site/content/examples/toolhost-demo/en-US.md",
|
|
592
|
-
"body": "\n# ToolHost Tool Call UI\n\nToolHost is a host-side tool-call renderer, not an authoring element inside a `slex` payload. The host selects a registered template from a trusted `function_call` name and passes only the call arguments to that template.\n\n```js\nconst
|
|
593
|
-
"hash": "
|
|
592
|
+
"body": "\n# ToolHost Tool Call UI\n\nToolHost is a host-side tool-call renderer, not an authoring element inside a `slex` payload. The host selects a registered template from a trusted `function_call` name and passes only the call arguments to that template.\n\n```js\nconst handle = renderToolCall({\n name: \"fill-form\",\n id: item.call_id,\n arguments: JSON.parse(item.arguments),\n}, container);\nconst output = await handle.promise;\nresponsesInput.push({ type: \"function_call_output\", call_id: item.call_id, output: JSON.stringify(output) });\n```\n\n## Tool-call boundary\n\nWhen an agent emits a `function_call`, the browser host can render it as an inline ToolHost card. The returned handle's promise resolves after submit or ignore, then the host writes a `function_call_output` using the original call ID. This workflow does not execute a deployment or other domain action by itself.\n",
|
|
593
|
+
"hash": "409e4f3a"
|
|
594
594
|
},
|
|
595
595
|
{
|
|
596
596
|
"id": "examples/voltage-divider",
|
|
@@ -600,8 +600,8 @@
|
|
|
600
600
|
"href": "/examples/voltage-divider",
|
|
601
601
|
"rawHref": "/docs/examples/voltage-divider.md",
|
|
602
602
|
"sourcePath": "site/content/examples/voltage-divider/en-US.md",
|
|
603
|
-
"body": "\n# Voltage Divider Calculator\n\nThe module script implements \\(V_{out} = V_{in} R_2 / (R_1 + R_2)\\) with native `input` events.\n\n```slex\n<slex-card title=\"Voltage Divider Calculator\"><slex-grid columns=\"3\"><slex-input id=\"vin\" type=\"number\" label=\"Input voltage\" value=\"12\"></slex-input><slex-input id=\"r1\" type=\"number\" label=\"R1\" unit=\"kΩ\" value=\"10\"></slex-input><slex-input id=\"r2\" type=\"number\" label=\"R2\" unit=\"kΩ\" value=\"20\"></slex-input></slex-grid><slex-stat id=\"vout\" label=\"Output voltage\" unit=\"V\"></slex-stat></slex-card>\n<script type=\"module\">\n const fields = [\"vin\", \"r1\", \"r2\"].map(id => slex.root.querySelector(`#${id}`)); const vout = slex.root.querySelector(\"#vout\");\n const update = () => { const [vin, r1, r2] = fields.map(field => Number(field.value)); vout.value = (vin * r2 / (r1 + r2)).toFixed(2); };\n fields.forEach(field => field.addEventListener(\"input\", update)); update();\n slex.onDispose(() => fields.forEach(field => field.removeEventListener(\"input\", update)));\n</script>\n```\n\nThe three
|
|
604
|
-
"hash": "
|
|
603
|
+
"body": "\n# Voltage Divider Calculator\n\nThe module script implements \\(V_{out} = V_{in} R_2 / (R_1 + R_2)\\) with native `input` events.\n\n```slex\n<slex-card title=\"Voltage Divider Calculator\"><slex-grid columns=\"3\"><slex-input id=\"vin\" type=\"number\" label=\"Input voltage\" value=\"12\"></slex-input><slex-input id=\"r1\" type=\"number\" label=\"R1\" unit=\"kΩ\" value=\"10\"></slex-input><slex-input id=\"r2\" type=\"number\" label=\"R2\" unit=\"kΩ\" value=\"20\"></slex-input></slex-grid><slex-stat id=\"vout\" label=\"Output voltage\" unit=\"V\"></slex-stat></slex-card>\n<script type=\"module\">\n const fields = [\"vin\", \"r1\", \"r2\"].map(id => slex.root.querySelector(`#${id}`)); const vout = slex.root.querySelector(\"#vout\");\n const update = () => { const [vin, r1, r2] = fields.map(field => Number(field.value)); vout.value = fields.some(field => field.value === \"\") || !Number.isFinite(vin) || r1 < 0 || r2 < 0 || r1 + r2 <= 0 ? \"—\" : (vin * r2 / (r1 + r2)).toFixed(2); };\n fields.forEach(field => field.addEventListener(\"input\", update)); update();\n slex.onDispose(() => fields.forEach(field => field.removeEventListener(\"input\", update)));\n</script>\n```\n\nThe three numeric inputs drive one calculation function, which updates the output voltage. Invalid resistor values display a dash.\n",
|
|
604
|
+
"hash": "ea8f9d0f"
|
|
605
605
|
},
|
|
606
606
|
{
|
|
607
607
|
"id": "guides/ai-agents",
|
|
@@ -787,8 +787,8 @@
|
|
|
787
787
|
"href": "/docs/releases/changelog",
|
|
788
788
|
"rawHref": "/docs/releases/changelog.md",
|
|
789
789
|
"sourcePath": "site/content/releases/changelog/en-US.md",
|
|
790
|
-
"body": "\n# Changelog\n\nAll notable changes to SlexKit.\n\n## v0.5.0 - HTML-first interactive documents\n\n### Breaking changes\n- `slex` fences now contain HTML fragments with standard JavaScript and `slex-*` Web Components. The former object-tree DSL, expression strings, and implicit namespace state are no longer supported.\n- Cross-fence state uses the explicit artifact-local `slex.shared` API. Hosts must configure an isolated runtime URL for generated content.\n\n### Added\n- A reusable Web Components entry, custom-element manifest, theme tokens, and updated Markdown, Streamdown, assistant-ui, Tiptap, and Obsidian integrations.\n- Static, non-executing source inspection and cross-browser, adapter, layout, and lifecycle conformance checks.\n\n### Changed\n- Metric cards adapt numeric precision to available width, preserve the original value, and align automatically in responsive rows.\n- Component documentation now describes the HTML contracts in English and Chinese.\n\n### Fixed\n- Frame initialization timeouts no longer leave artifact updates waiting indefinitely.\n- Long labels, native hidden elements, CSS zoom, and RTL numeric rendering now respect their layout and reading direction.\n\n### Validation status\n- The Obsidian desktop fix remains pending verification in the actual desktop application. Browser tests do not establish desktop compatibility.\n\n## v0.4.0 - Production adapters and ToolHost hardening\n\n### Added\n- `@slexkit/assistant-ui`: React assistant-ui adapter package with secure-frame defaults for `slex` code blocks.\n- Browser-openable Assistant UI host example and documentation pages for adapter integration.\n- Internal ToolHost `step` component for multi-step human-input flows inside one tool call.\n- Theme package coverage for base, per-component, and ToolHost/step CSS exports.\n\n### Changed\n- AI docs and standard artifacts now separate public components from ToolHost-only internals: `submit` and `step` remain renderable runtime components but are no longer counted in the public component catalog.\n- `smoke:release` now logs pack/install/smoke stages, validates packed tarballs through a temporary app, checks CLI conformance, and checks the MCP server before reporting success.\n- ToolHost demo and replay fixtures now use the same step/submit flow expected from production host integrations.\n\n### Fixed\n- Radio group list selection styling no longer uses `:has()` in shipped runtime or theme CSS.\n- Tiptap preview controls preserve focus across embedded SlexKit inputs, selects, and transient controls.\n- `step` and `submit` component docs now include synced SPEC examples and API tables.\n- Release smoke no longer hangs after successful MCP validation on Windows.\n## v0.3.4 - Production documentation polish\n\n### Changed\n- Reworked the documentation site shell labels, language menu, mobile navigation, and theme controls so localized pages no longer expose English-only UI chrome.\n- Polished guide, reference, component, example, package README, and AI-facing documentation copy to remove report-like wording and visible placeholder phrasing.\n- Localized generated Chinese component examples and API descriptions, including Formula props, through the component spec documentation pipeline.\n\n### Fixed\n- Chinese documentation no longer renders copied English UI phrases such as counter labels, ToolHost examples, Obsidian status text, or design-system tone labels.\n- Markdown documentation tests now guard against copied English skeleton headings, visible English-only list rows, double-question-mark replacement corruption, stale generated spec blocks, and previously fixed English UI phrase regressions.\n\n## v0.3.3 - Obsidian input control hardening\n\n### Fixed\n- Slider now renders its visual track outside the native range input while keeping the native input for interaction and accessibility, avoiding square thumb artifacts in Obsidian and other host themes.\n- Input fields with trailing units now reset host input chrome with scoped selectors so unit add-ons stay aligned with the text field in Obsidian dark themes.\n\n## v0.3.2 - Host CSS isolation and repeated layout hardening\n\n### Changed\n- `$for` rendering now uses comment anchors and direct child insertion instead of a wrapper element that depended on `display: contents`.\n- Site-only mobile navigation CSS moved out of the runtime base stylesheet and into the documentation site shell.\n- Component accessors now share one reactive effect across subscribers instead of creating duplicate subscriber fan-out work.\n\n### Fixed\n- Obsidian and other Markdown hosts no longer need to rewrite `$for` wrapper CSS to avoid `display: contents`, preserving grid and row layouts for repeated items.\n- Published runtime base CSS no longer leaks `#mobileNav` or `body[data-mobile-nav-open]` selectors into host pages.\n- Custom renderers that return no element no longer leave invalid `$for` slots behind during diffing or cleanup.\n\n## v0.3.1 - Host stability and control rendering hardening\n\n### Added\n- Runtime style safety tests that block broad `:has()` selectors, `clip-path`, and slider track regressions in shipped CSS.\n- Regression coverage for disabled Switch, Checkbox, and Radio state attributes.\n\n### Changed\n- CI now installs dependencies with `bun install --frozen-lockfile` and runs lint before tests.\n- Disabled Switch, Checkbox, and Radio styling now uses explicit `data-disabled` attributes instead of broad relational selectors.\n- Select and sr-only helper styles avoid `clip-path` for better host and Obsidian CSS compatibility.\n\n### Fixed\n- Slider thumb rendering artifacts caused by painting the range track on the native input box.\n- Input focus visibility after removing custom engineering steppers.\n- Home RC example input labels now use native Input component labels instead of separate text labels.\n- Stat cards no longer clip updated text during cross-document state examples.\n- Markdown calculator examples no longer render duplicate section labels.\n\n## v0.3.0 - Examples overhaul with component audit and i18n\n\n### Added\n- Example gallery: 17 high-quality examples organized by usage scenario (Getting Started, Calculators, Data Browsing, Dashboards, Config Wizards, Decision Support, Platform Features)\n- English translations for all 17 example pages\n- `toolhost-demo`: real `renderToolCall` API with chat-style conversation UI\n- Example rendering infrastructure: `site/routes/examples.js`, `site/pages/examples.slex.js`, `site/data/examples.js`\n- Content discovery: `site/data/content-discovery.js` with locale fallback and allowed-slug filtering\n- `site/data/content-discovery.js`: `discoverExampleMarkdown()` with per-locale discovery\n- SEO metadata for example pages\n- `examples/minimal-cdn/index.html`: zero-build CDN usage example\n- Formula component (`src/components/svelte/content/Formula.svelte`) with KaTeX rendering\n- `src/engine/capabilities.ts`: structured capability docs for AI agents\n- `src/engine/validation.ts`: SPEC contract validation for component specs\n- `src/engine/stdlib.ts`: standard library with `math.clamp`, `math.safeDivide`, and other utilities\n- `src/engine/sandbox-runner.ts`: sandbox runner for secure runtime\n- Component state eval context shadowing test suite (`component-state-shadowing.test.ts`)\n- Collapsible and Callout double-rendering regression tests\n- Slider component name shadowing regression test\n- Tests for content, playground, select, tabs, slider, disclosure, feedback, policy-api\n\n### Changed\n- Examples reduced from 64 to 17 high-quality examples, organized by user story\n- Example source locale: `zh-CN` (with `en-US` translations)\n- `renderChildren` (`helpers.ts`) now clears existing content when children are present\n- Switch component now accepts `checked`/`value` props for initialization consistency with Checkbox\n- Site UI: DocsShell, DocRail, router, shell improvements\n- Components: Input, Select, Tabs, Table, PlaygroundMarkdown refinements\n- CSS: theme-shadcn, text-input, docs-shell styling updates\n- MCP: enhanced with structured capability docs\n\n### Fixed\n- Eval context shadowing: component names `g` and `api` no longer overwrite reserved context keys\n- `renderChildren` double rendering in Collapsible and Callout\n- Voltage divider summary typo (\"输入输入电压\")\n- Salary calculator fallback numbers to match actual calculator output\n- Tabs-and-branching: title and length conversion mismatch\n- 4 pre-existing test failures (ai-docs, page-structure, theme, markdown-content)\n- Toolhost test: added setup import to fix `document is not defined`\n- Badge stretching in grid layout\n- Project-dashboard syntax error\n- Salary-calculator rate configuration\n\n### Removed\n- 47 low-quality/duplicate examples (reduced from 64 to 17)\n- Dead \"Fallback\" copywriting from all example files\n- Post-slex explanatory text from example files\n- Unused `DialogShell.svelte` component\n- Orphaned `test-if` example directory\n- Agent-generated `docs/compose` planning files\n- Temporary `screenshot-*.png` files\n\n## v0.2.0 - First public release\n\n### Added\n- `@slexkit/mcp`: AI Agent Model Context Protocol server with `slexkitDocs`, `slexkitExamples`, `slexkitValidate` tools\n- Protocol marker: `\"slex\": \"0.1\"` required on all Slex expressions and ToolHost templates\n- SPEC contract validation: component specs are now validated against the runtime contract\n- Version sync automation (`scripts/sync-version.ts`) and changelog sync (`scripts/sync-changelog.ts`)\n- AI documentation generation pipeline with structured LLM-friendly output\n- Static site export with SEO metadata engine (`site/data/seo.js`, `site/scripts/export-static.ts`)\n- Chinese documentation for all reference and guide pages\n- Enhanced component state management with lifecycle hooks (`onMount`, `onUnmount`, `onUpdate`)\n\n### Changed\n- Switch component migrated from `checked` to `enabled` state mode\n- Documentation: restructured site content, synced en-US with zh-CN, added reference section\n- Theme: refined select styling, dropdown shadows, footer and info tone polish\n- AI docs generation enhanced with Chinese/English locale awareness\n\n### Fixed\n- Component spec alignment with documentation across all 28 components\n- Site routing and code block highlighting\n- Introduction and quick-start guide wording for clarity\n- Broken links and factual errors in component and reference documentation\n\n## v0.1.9\n\n### Added\n- Icon manager with Phosphor icon system (`registerIcon`, `registerIcons`, `getIcon`, `loadIcon`)\n- Expanded icon support across labeled components (badge, button, callout, etc.)\n- Icon docs page with registration API reference\n\n### Fixed\n- Refined component interactions in static site export\n- Tabs indicator animation restored\n- Callout and toast icon placement in titles\n- Numeric value display formatting\n\n### Changed\n- Site docs shell refactored for static export\n- Site navigation and theme controls alignment\n- Slex naming standardized across codebase\n\n## v0.1.8\n\n### Added\n- CSP-hardened secure runtime sandbox with heartbeat watchdog\n- `mountSecureArtifact()` for isolated iframe rendering\n- `createSlexKitMarkdownRuntimeHost()` for Markdown-hosted SlexKit blocks\n- Streamdown React renderer (`@slexkit/streamdown`)\n- Obsidian plugin adapter (now released through `slexkit/obsidian-slexkit`)\n- Shadcn-compatible CSS theme (`@slexkit/theme-shadcn`)\n- Package boundary wrappers (`@slexkit/runtime`, `@slexkit/components-svelte`)\n- ToolHost with built-in templates: `confirm-action`, `choose-options`, `fill-form`\n\n### Changed\n- Component registration model: side-effect import registers all components\n- Styles reorganized into per-component CSS files\n- Build system: Bun.build with Svelte plugin, split ESM entries\n\n## v0.1.7\n\n### Added\n- `$for` list rendering with keyed reconciliation (delete / add-update-reorder / trim phases)\n- `$if` conditional rendering with enter/leave animation support\n- `$key` strategy: `$value`, property-based, or fallback to index\n- Component instance state modes: `value`, `checked`, `enabled`, `readable`, `none`\n- Lifecycle hooks: `g.onMount_<name>()`, `g.onUnmount_<name>()`, `g.onUpdate_<name>()`\n- Engineering number input with SI prefix parsing\n- Rich error diagnostics with line/column/excerpt display\n\n### Changed\n- Expression evaluation: `new Function()` compilation with reactive dependency tracking\n- Layout tree renderer now supports three rendering paths (normal, `$if`, `$for`)\n- `g` deep-merge preserves keys not present in the new state\n\n## v0.1.6 and earlier\n\n### Added\n- Reactive `g`/`layout` split with expression pipes (`$` read-pipes, `on*` write-pipes)\n- Custom fine-grained reactivity system (~280 lines, no external dependency)\n- Component registry with extensible renderer interface\n- Svelte 5 component adapter (creates stores from props, flushSync DOM)\n- `mount()`, `ingest()`, `boot()` entry points\n- 28 built-in Svelte components across 8 categories\n- `parseSlexSource()` DSL parser with `diagnoseSlexKitSource()` error reporting\n- Documentation site with interactive playground\n",
|
|
791
|
-
"hash": "
|
|
790
|
+
"body": "\n# Changelog\n\nAll notable changes to SlexKit.\n\n## v0.5.2 - Runtime rendering fixes\n\n### Fixed\n- Preserve explicit text, label, and content attributes when custom elements have no light DOM children.\n- Keep the sandbox's CSP hash in sync with the trusted component layout styles so isolated components render correctly without relaxing the policy.\n- Restore interactive website examples and build adapter demos from pinned local dependencies.\n- Keep grids and their cards aligned in embedded previews, preload sandbox styles, and reduce the documentation site's initial asset size.\n\n## @slexkit/assistant-ui v0.5.1\n\n### Fixed\n- Constrain `@assistant-ui/react-streamdown` to versions compatible with `@assistant-ui/react` 0.14 so a fresh npm install resolves its peer dependencies.\n\n## v0.5.0 - HTML-first interactive documents\n\n### Breaking changes\n- `slex` fences now contain HTML fragments with standard JavaScript and `slex-*` Web Components. The former object-tree DSL, expression strings, and implicit namespace state are no longer supported.\n- Cross-fence state uses the explicit artifact-local `slex.shared` API. Hosts must configure an isolated runtime URL for generated content.\n\n### Added\n- A reusable Web Components entry, custom-element manifest, theme tokens, and updated Markdown, Streamdown, assistant-ui, Tiptap, and Obsidian integrations.\n- Static, non-executing source inspection and cross-browser, adapter, layout, and lifecycle conformance checks.\n\n### Changed\n- Metric cards adapt numeric precision to available width, preserve the original value, and align automatically in responsive rows.\n- Component documentation now describes the HTML contracts in English and Chinese.\n\n### Fixed\n- Frame initialization timeouts no longer leave artifact updates waiting indefinitely.\n- Long labels, native hidden elements, CSS zoom, and RTL numeric rendering now respect their layout and reading direction.\n\n### Validation status\n- The Obsidian desktop fix remains pending verification in the actual desktop application. Browser tests do not establish desktop compatibility.\n\n## v0.4.0 - Production adapters and ToolHost hardening\n\n### Added\n- `@slexkit/assistant-ui`: React assistant-ui adapter package with secure-frame defaults for `slex` code blocks.\n- Browser-openable Assistant UI host example and documentation pages for adapter integration.\n- Internal ToolHost `step` component for multi-step human-input flows inside one tool call.\n- Theme package coverage for base, per-component, and ToolHost/step CSS exports.\n\n### Changed\n- AI docs and standard artifacts now separate public components from ToolHost-only internals: `submit` and `step` remain renderable runtime components but are no longer counted in the public component catalog.\n- `smoke:release` now logs pack/install/smoke stages, validates packed tarballs through a temporary app, checks CLI conformance, and checks the MCP server before reporting success.\n- ToolHost demo and replay fixtures now use the same step/submit flow expected from production host integrations.\n\n### Fixed\n- Radio group list selection styling no longer uses `:has()` in shipped runtime or theme CSS.\n- Tiptap preview controls preserve focus across embedded SlexKit inputs, selects, and transient controls.\n- `step` and `submit` component docs now include synced SPEC examples and API tables.\n- Release smoke no longer hangs after successful MCP validation on Windows.\n## v0.3.4 - Production documentation polish\n\n### Changed\n- Reworked the documentation site shell labels, language menu, mobile navigation, and theme controls so localized pages no longer expose English-only UI chrome.\n- Polished guide, reference, component, example, package README, and AI-facing documentation copy to remove report-like wording and visible placeholder phrasing.\n- Localized generated Chinese component examples and API descriptions, including Formula props, through the component spec documentation pipeline.\n\n### Fixed\n- Chinese documentation no longer renders copied English UI phrases such as counter labels, ToolHost examples, Obsidian status text, or design-system tone labels.\n- Markdown documentation tests now guard against copied English skeleton headings, visible English-only list rows, double-question-mark replacement corruption, stale generated spec blocks, and previously fixed English UI phrase regressions.\n\n## v0.3.3 - Obsidian input control hardening\n\n### Fixed\n- Slider now renders its visual track outside the native range input while keeping the native input for interaction and accessibility, avoiding square thumb artifacts in Obsidian and other host themes.\n- Input fields with trailing units now reset host input chrome with scoped selectors so unit add-ons stay aligned with the text field in Obsidian dark themes.\n\n## v0.3.2 - Host CSS isolation and repeated layout hardening\n\n### Changed\n- `$for` rendering now uses comment anchors and direct child insertion instead of a wrapper element that depended on `display: contents`.\n- Site-only mobile navigation CSS moved out of the runtime base stylesheet and into the documentation site shell.\n- Component accessors now share one reactive effect across subscribers instead of creating duplicate subscriber fan-out work.\n\n### Fixed\n- Obsidian and other Markdown hosts no longer need to rewrite `$for` wrapper CSS to avoid `display: contents`, preserving grid and row layouts for repeated items.\n- Published runtime base CSS no longer leaks `#mobileNav` or `body[data-mobile-nav-open]` selectors into host pages.\n- Custom renderers that return no element no longer leave invalid `$for` slots behind during diffing or cleanup.\n\n## v0.3.1 - Host stability and control rendering hardening\n\n### Added\n- Runtime style safety tests that block broad `:has()` selectors, `clip-path`, and slider track regressions in shipped CSS.\n- Regression coverage for disabled Switch, Checkbox, and Radio state attributes.\n\n### Changed\n- CI now installs dependencies with `bun install --frozen-lockfile` and runs lint before tests.\n- Disabled Switch, Checkbox, and Radio styling now uses explicit `data-disabled` attributes instead of broad relational selectors.\n- Select and sr-only helper styles avoid `clip-path` for better host and Obsidian CSS compatibility.\n\n### Fixed\n- Slider thumb rendering artifacts caused by painting the range track on the native input box.\n- Input focus visibility after removing custom engineering steppers.\n- Home RC example input labels now use native Input component labels instead of separate text labels.\n- Stat cards no longer clip updated text during cross-document state examples.\n- Markdown calculator examples no longer render duplicate section labels.\n\n## v0.3.0 - Examples overhaul with component audit and i18n\n\n### Added\n- Example gallery: 17 high-quality examples organized by usage scenario (Getting Started, Calculators, Data Browsing, Dashboards, Config Wizards, Decision Support, Platform Features)\n- English translations for all 17 example pages\n- `toolhost-demo`: real `renderToolCall` API with chat-style conversation UI\n- Example rendering infrastructure: `site/routes/examples.js`, `site/pages/examples.slex.js`, `site/data/examples.js`\n- Content discovery: `site/data/content-discovery.js` with locale fallback and allowed-slug filtering\n- `site/data/content-discovery.js`: `discoverExampleMarkdown()` with per-locale discovery\n- SEO metadata for example pages\n- `examples/minimal-cdn/index.html`: zero-build CDN usage example\n- Formula component (`src/components/svelte/content/Formula.svelte`) with KaTeX rendering\n- `src/engine/capabilities.ts`: structured capability docs for AI agents\n- `src/engine/validation.ts`: SPEC contract validation for component specs\n- `src/engine/stdlib.ts`: standard library with `math.clamp`, `math.safeDivide`, and other utilities\n- `src/engine/sandbox-runner.ts`: sandbox runner for secure runtime\n- Component state eval context shadowing test suite (`component-state-shadowing.test.ts`)\n- Collapsible and Callout double-rendering regression tests\n- Slider component name shadowing regression test\n- Tests for content, playground, select, tabs, slider, disclosure, feedback, policy-api\n\n### Changed\n- Examples reduced from 64 to 17 high-quality examples, organized by user story\n- Example source locale: `zh-CN` (with `en-US` translations)\n- `renderChildren` (`helpers.ts`) now clears existing content when children are present\n- Switch component now accepts `checked`/`value` props for initialization consistency with Checkbox\n- Site UI: DocsShell, DocRail, router, shell improvements\n- Components: Input, Select, Tabs, Table, PlaygroundMarkdown refinements\n- CSS: theme-shadcn, text-input, docs-shell styling updates\n- MCP: enhanced with structured capability docs\n\n### Fixed\n- Eval context shadowing: component names `g` and `api` no longer overwrite reserved context keys\n- `renderChildren` double rendering in Collapsible and Callout\n- Voltage divider summary typo (\"输入输入电压\")\n- Salary calculator fallback numbers to match actual calculator output\n- Tabs-and-branching: title and length conversion mismatch\n- 4 pre-existing test failures (ai-docs, page-structure, theme, markdown-content)\n- Toolhost test: added setup import to fix `document is not defined`\n- Badge stretching in grid layout\n- Project-dashboard syntax error\n- Salary-calculator rate configuration\n\n### Removed\n- 47 low-quality/duplicate examples (reduced from 64 to 17)\n- Dead \"Fallback\" copywriting from all example files\n- Post-slex explanatory text from example files\n- Unused `DialogShell.svelte` component\n- Orphaned `test-if` example directory\n- Agent-generated `docs/compose` planning files\n- Temporary `screenshot-*.png` files\n\n## v0.2.0 - First public release\n\n### Added\n- `@slexkit/mcp`: AI Agent Model Context Protocol server with `slexkitDocs`, `slexkitExamples`, `slexkitValidate` tools\n- Protocol marker: `\"slex\": \"0.1\"` required on all Slex expressions and ToolHost templates\n- SPEC contract validation: component specs are now validated against the runtime contract\n- Version sync automation (`scripts/sync-version.ts`) and changelog sync (`scripts/sync-changelog.ts`)\n- AI documentation generation pipeline with structured LLM-friendly output\n- Static site export with SEO metadata engine (`site/data/seo.js`, `site/scripts/export-static.ts`)\n- Chinese documentation for all reference and guide pages\n- Enhanced component state management with lifecycle hooks (`onMount`, `onUnmount`, `onUpdate`)\n\n### Changed\n- Switch component migrated from `checked` to `enabled` state mode\n- Documentation: restructured site content, synced en-US with zh-CN, added reference section\n- Theme: refined select styling, dropdown shadows, footer and info tone polish\n- AI docs generation enhanced with Chinese/English locale awareness\n\n### Fixed\n- Component spec alignment with documentation across all 28 components\n- Site routing and code block highlighting\n- Introduction and quick-start guide wording for clarity\n- Broken links and factual errors in component and reference documentation\n\n## v0.1.9\n\n### Added\n- Icon manager with Phosphor icon system (`registerIcon`, `registerIcons`, `getIcon`, `loadIcon`)\n- Expanded icon support across labeled components (badge, button, callout, etc.)\n- Icon docs page with registration API reference\n\n### Fixed\n- Refined component interactions in static site export\n- Tabs indicator animation restored\n- Callout and toast icon placement in titles\n- Numeric value display formatting\n\n### Changed\n- Site docs shell refactored for static export\n- Site navigation and theme controls alignment\n- Slex naming standardized across codebase\n\n## v0.1.8\n\n### Added\n- CSP-hardened secure runtime sandbox with heartbeat watchdog\n- `mountSecureArtifact()` for isolated iframe rendering\n- `createSlexKitMarkdownRuntimeHost()` for Markdown-hosted SlexKit blocks\n- Streamdown React renderer (`@slexkit/streamdown`)\n- Obsidian plugin adapter (now released through `slexkit/obsidian-slexkit`)\n- Shadcn-compatible CSS theme (`@slexkit/theme-shadcn`)\n- Package boundary wrappers (`@slexkit/runtime`, `@slexkit/components-svelte`)\n- ToolHost with built-in templates: `confirm-action`, `choose-options`, `fill-form`\n\n### Changed\n- Component registration model: side-effect import registers all components\n- Styles reorganized into per-component CSS files\n- Build system: Bun.build with Svelte plugin, split ESM entries\n\n## v0.1.7\n\n### Added\n- `$for` list rendering with keyed reconciliation (delete / add-update-reorder / trim phases)\n- `$if` conditional rendering with enter/leave animation support\n- `$key` strategy: `$value`, property-based, or fallback to index\n- Component instance state modes: `value`, `checked`, `enabled`, `readable`, `none`\n- Lifecycle hooks: `g.onMount_<name>()`, `g.onUnmount_<name>()`, `g.onUpdate_<name>()`\n- Engineering number input with SI prefix parsing\n- Rich error diagnostics with line/column/excerpt display\n\n### Changed\n- Expression evaluation: `new Function()` compilation with reactive dependency tracking\n- Layout tree renderer now supports three rendering paths (normal, `$if`, `$for`)\n- `g` deep-merge preserves keys not present in the new state\n\n## v0.1.6 and earlier\n\n### Added\n- Reactive `g`/`layout` split with expression pipes (`$` read-pipes, `on*` write-pipes)\n- Custom fine-grained reactivity system (~280 lines, no external dependency)\n- Component registry with extensible renderer interface\n- Svelte 5 component adapter (creates stores from props, flushSync DOM)\n- `mount()`, `ingest()`, `boot()` entry points\n- 28 built-in Svelte components across 8 categories\n- `parseSlexSource()` DSL parser with `diagnoseSlexKitSource()` error reporting\n- Documentation site with interactive playground\n",
|
|
791
|
+
"hash": "c3e7dffd"
|
|
792
792
|
}
|
|
793
793
|
],
|
|
794
794
|
"sandboxSdk": [
|
|
@@ -811,27 +811,27 @@
|
|
|
811
811
|
"standardArtifacts": {
|
|
812
812
|
"slex-html-profile.json": {
|
|
813
813
|
"path": "/standard/slex-html-profile.json",
|
|
814
|
-
"hash": "
|
|
814
|
+
"hash": "1fafb887"
|
|
815
815
|
},
|
|
816
816
|
"slex-custom-elements.catalog.json": {
|
|
817
817
|
"path": "/standard/slex-custom-elements.catalog.json",
|
|
818
|
-
"hash": "
|
|
818
|
+
"hash": "01741649"
|
|
819
819
|
},
|
|
820
820
|
"slex-sandbox-sdk.json": {
|
|
821
821
|
"path": "/standard/slex-sandbox-sdk.json",
|
|
822
|
-
"hash": "
|
|
822
|
+
"hash": "1bec9fd2"
|
|
823
823
|
},
|
|
824
824
|
"slex-static-policy.json": {
|
|
825
825
|
"path": "/standard/slex-static-policy.json",
|
|
826
|
-
"hash": "
|
|
826
|
+
"hash": "95af5056"
|
|
827
827
|
},
|
|
828
828
|
"slex-html-conformance.json": {
|
|
829
829
|
"path": "/standard/slex-html-conformance.json",
|
|
830
|
-
"hash": "
|
|
830
|
+
"hash": "70a5b4c5"
|
|
831
831
|
},
|
|
832
832
|
"slex-standard-manifest.json": {
|
|
833
833
|
"path": "/standard/slex-standard-manifest.json",
|
|
834
|
-
"hash": "
|
|
834
|
+
"hash": "222a972d"
|
|
835
835
|
}
|
|
836
836
|
},
|
|
837
837
|
"components": [
|
|
@@ -2308,26 +2308,26 @@
|
|
|
2308
2308
|
"site/content/components/text/en-US.md": "6f1b8f1a",
|
|
2309
2309
|
"site/content/components/toast/en-US.md": "036841f1",
|
|
2310
2310
|
"site/content/components/step/en-US.md": "62cf9dd1",
|
|
2311
|
-
"site/content/examples/cross-doc-state-lab/en-US.md": "
|
|
2311
|
+
"site/content/examples/cross-doc-state-lab/en-US.md": "8da8e094",
|
|
2312
2312
|
"site/content/examples/assistant-ui-host/en-US.md": "a1ea2d4f",
|
|
2313
|
-
"site/content/examples/baud-rate-calculator/en-US.md": "
|
|
2314
|
-
"site/content/examples/tabs-and-branching/en-US.md": "
|
|
2315
|
-
"site/content/examples/roi-estimator/en-US.md": "
|
|
2313
|
+
"site/content/examples/baud-rate-calculator/en-US.md": "7936ed13",
|
|
2314
|
+
"site/content/examples/tabs-and-branching/en-US.md": "8560ecdc",
|
|
2315
|
+
"site/content/examples/roi-estimator/en-US.md": "9ded7150",
|
|
2316
2316
|
"site/content/examples/first-interaction/en-US.md": "49dfb9cd",
|
|
2317
2317
|
"site/content/examples/hello-slexkit/en-US.md": "e7030a35",
|
|
2318
2318
|
"site/content/examples/network-policy-fetch-card/en-US.md": "b06165d4",
|
|
2319
2319
|
"site/content/examples/multi-input-coordination/en-US.md": "97ea2d7c",
|
|
2320
|
-
"site/content/examples/project-dashboard/en-US.md": "
|
|
2321
|
-
"site/content/examples/rc-low-pass-filter/en-US.md": "
|
|
2322
|
-
"site/content/examples/search-filter-table/en-US.md": "
|
|
2323
|
-
"site/content/examples/
|
|
2324
|
-
"site/content/examples/salary-calculator/en-US.md": "99f370a7",
|
|
2320
|
+
"site/content/examples/project-dashboard/en-US.md": "e129c4dd",
|
|
2321
|
+
"site/content/examples/rc-low-pass-filter/en-US.md": "293ef1d5",
|
|
2322
|
+
"site/content/examples/search-filter-table/en-US.md": "48b12231",
|
|
2323
|
+
"site/content/examples/salary-calculator/en-US.md": "7d15f06b",
|
|
2325
2324
|
"site/content/examples/project-cost-estimator/en-US.md": "a7d0f9d3",
|
|
2326
2325
|
"site/content/examples/streamdown-host/en-US.md": "df557438",
|
|
2326
|
+
"site/content/examples/tech-selection-evaluator/en-US.md": "46a04d79",
|
|
2327
2327
|
"site/content/examples/tiptap-host/en-US.md": "7f3f6252",
|
|
2328
|
-
"site/content/examples/form-wizard-steps/en-US.md": "
|
|
2329
|
-
"site/content/examples/toolhost-demo/en-US.md": "
|
|
2330
|
-
"site/content/examples/voltage-divider/en-US.md": "
|
|
2328
|
+
"site/content/examples/form-wizard-steps/en-US.md": "1468ec61",
|
|
2329
|
+
"site/content/examples/toolhost-demo/en-US.md": "409e4f3a",
|
|
2330
|
+
"site/content/examples/voltage-divider/en-US.md": "ea8f9d0f",
|
|
2331
2331
|
"site/content/guides/ai-agents/en-US.md": "007375bf",
|
|
2332
2332
|
"site/content/guides/design/en-US.md": "87db15d0",
|
|
2333
2333
|
"site/content/guides/quick-start/en-US.md": "46119ea0",
|
|
@@ -2344,6 +2344,6 @@
|
|
|
2344
2344
|
"site/content/reference/standard/en-US.md": "4e9b397d",
|
|
2345
2345
|
"site/content/reference/usage/en-US.md": "29a421ce",
|
|
2346
2346
|
"site/content/reference/toolhost/en-US.md": "0e58d865",
|
|
2347
|
-
"site/content/releases/changelog/en-US.md": "
|
|
2347
|
+
"site/content/releases/changelog/en-US.md": "c3e7dffd"
|
|
2348
2348
|
}
|
|
2349
2349
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "slex-standard-manifest",
|
|
3
3
|
"packageName": "slexkit",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.2",
|
|
5
5
|
"schemaVersion": "2026-11-html",
|
|
6
6
|
"profileVersion": "1",
|
|
7
|
-
"generatedAt": "2026-11-
|
|
7
|
+
"generatedAt": "2026-11-11T04:08:49.614Z",
|
|
8
8
|
"positioning": "HTML-first interactive Markdown artifact",
|
|
9
9
|
"compatibility": {
|
|
10
10
|
"legacyObjectSource": false,
|
|
@@ -13,23 +13,23 @@
|
|
|
13
13
|
"artifacts": {
|
|
14
14
|
"slex-html-profile.json": {
|
|
15
15
|
"path": "/standard/slex-html-profile.json",
|
|
16
|
-
"hash": "
|
|
16
|
+
"hash": "1fafb887"
|
|
17
17
|
},
|
|
18
18
|
"slex-custom-elements.catalog.json": {
|
|
19
19
|
"path": "/standard/slex-custom-elements.catalog.json",
|
|
20
|
-
"hash": "
|
|
20
|
+
"hash": "01741649"
|
|
21
21
|
},
|
|
22
22
|
"slex-sandbox-sdk.json": {
|
|
23
23
|
"path": "/standard/slex-sandbox-sdk.json",
|
|
24
|
-
"hash": "
|
|
24
|
+
"hash": "1bec9fd2"
|
|
25
25
|
},
|
|
26
26
|
"slex-static-policy.json": {
|
|
27
27
|
"path": "/standard/slex-static-policy.json",
|
|
28
|
-
"hash": "
|
|
28
|
+
"hash": "95af5056"
|
|
29
29
|
},
|
|
30
30
|
"slex-html-conformance.json": {
|
|
31
31
|
"path": "/standard/slex-html-conformance.json",
|
|
32
|
-
"hash": "
|
|
32
|
+
"hash": "70a5b4c5"
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|