Skip to content

Commit 824681b

Browse files
committed
feat(SDK): allow setting content in web-components sdk using child elements
1 parent bca496c commit 824681b

7 files changed

Lines changed: 1396 additions & 17 deletions

File tree

.agents/skills/livecodes/framework-wrappers/SKILL.md

Lines changed: 120 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ function App() {
271271
<!-- Basic usage -->
272272
<live-codes template="react"></live-codes>
273273

274-
<!-- With config -->
274+
<!-- With config property -->
275275
<live-codes height="400px"></live-codes>
276276

277277
<script>
@@ -282,6 +282,125 @@ function App() {
282282
</script>
283283
```
284284
285+
### Web Components: Declarative Code via Children
286+
287+
The web component supports providing code declaratively as child elements inside a wrapper `<template>`. This avoids JavaScript string escaping and enables IDE syntax highlighting.
288+
289+
The outer `<template>` makes inner `<style>` and `<script>` elements inert (no side effects on the embedding page).
290+
291+
#### Single-Editor Mode
292+
293+
```html
294+
<live-codes height="400px">
295+
<template>
296+
<template lang="html">
297+
<h1>Hello World</h1>
298+
<p>Welcome to <strong>LiveCodes</strong></p>
299+
</template>
300+
<style lang="scss">
301+
body {
302+
font-family: sans-serif;
303+
h1 {
304+
color: royalblue;
305+
}
306+
}
307+
</style>
308+
<script lang="ts">
309+
console.log('Hello from TypeScript!');
310+
</script>
311+
</template>
312+
</live-codes>
313+
```
314+
315+
If `lang` is omitted, defaults are `html`, `css`, and `javascript`.
316+
317+
<!--
318+
#### Multi-File Mode
319+
320+
Use a `filename` attribute. Language is inferred from the file extension.
321+
322+
```html
323+
<live-codes height="400px">
324+
<template>
325+
<template filename="index.html"><h1>Hello</h1></template>
326+
<style filename="styles.scss">
327+
h1 {
328+
color: royalblue;
329+
}
330+
</style>
331+
<script filename="app.ts">
332+
import { greet } from './utils.ts';
333+
console.log(greet('LiveCodes'));
334+
</script>
335+
<script filename="utils.ts">
336+
export const greet = (name: string): string => `Hello, ${name}!`;
337+
</script>
338+
</template>
339+
</live-codes>
340+
```
341+
-->
342+
343+
#### Active Editor
344+
345+
Use the `active` boolean attribute to set the initially focused editor:
346+
347+
```html
348+
<live-codes>
349+
<template>
350+
<template lang="html"><h1>Hello</h1></template>
351+
<script lang="ts" active>
352+
console.log('focused');
353+
</script>
354+
</template>
355+
</live-codes>
356+
```
357+
358+
#### Config and Params Attributes
359+
360+
Use `config` and `params` HTML attributes as JSON strings for non-code settings:
361+
362+
```html
363+
<live-codes config='{"processors": ["tailwindcss"]}' params='{"console": "open"}'>
364+
<template>
365+
<template lang="html"><h1 class="text-3xl">Hello</h1></template>
366+
</template>
367+
</live-codes>
368+
```
369+
370+
#### Merge Precedence
371+
372+
When combining children, config attribute, and config property:
373+
374+
1. **`config` property** (highest — explicit programmatic override)
375+
2. **Children** (declarative defaults)
376+
3. **`config` attribute** (lowest — inline JSON settings)
377+
378+
Same for `params`: attribute is merged with property, property wins for overlapping keys.
379+
380+
#### Reactivity
381+
382+
Children content is reactive. Changing content inside the wrapper `<template>` programmatically triggers `setConfig()`:
383+
384+
```html
385+
<live-codes id="demo">
386+
<template>
387+
<style lang="css">
388+
h1 {
389+
color: blue;
390+
}
391+
</style>
392+
</template>
393+
</live-codes>
394+
395+
<script>
396+
function changeColor() {
397+
const wrapper = document.querySelector('#demo > template');
398+
wrapper.content.querySelector('style').textContent = 'h1 { color: red; }';
399+
// MutationObserver detects this → setConfig() called
400+
}
401+
</script>
402+
```
403+
285404
## Common Mistakes
286405
287406
### HIGH Not using sdkReady to access SDK in frameworks

docs/docs/contribution/sdk.mdx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,29 @@ const usePlayground = createUsePlayground({ useEffect, useRef });
269269

270270
### Web Components (`web-components.ts`)
271271

272+
The web component supports three ways to provide code, which can be combined:
273+
274+
1. **Declarative children** — code as child elements inside a wrapper `<template>` (parsed by `parseChildren` in `internal.ts`)
275+
2. **`config` attribute** — JSON string, parsed and merged
276+
3. **`config` property** — object or URL string, set via JavaScript
277+
278+
Merge precedence: `config` attribute (lowest) < children < `config` property (highest).
279+
280+
The same pattern applies for `params` (attribute merged with property, property wins for overlapping keys).
281+
282+
A `MutationObserver` watches the wrapper `<template>` content for changes and calls `setConfig()` reactively.
283+
272284
```html
285+
<!-- Declarative code via children -->
286+
<live-codes height="400px" config='{"processors": ["tailwindcss"]}'>
287+
<template>
288+
<template lang="html"><h1>Hello</h1></template>
289+
<style lang="scss">h1 { color: royalblue; }</style>
290+
<script lang="ts">console.log('Hi');</script>
291+
</template>
292+
</live-codes>
293+
294+
<!-- Config via properties -->
273295
<live-codes template="react"></live-codes>
274296

275297
<script type="module">

0 commit comments

Comments
 (0)