1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-07-03 05:02:15 +02:00
This commit is contained in:
2025-03-11 16:55:08 +01:00
parent 97defc5884
commit a8183d1282
26 changed files with 619 additions and 591 deletions

View File

@ -189,6 +189,7 @@ import { el } from "deka-dom-el";
* */
export function code({ id, src, content, language= "js", className= host.slice(1), page_id }){
if(src) content= s.cat(src);
content= normalizeIndentation(content);
let dataJS;
if(page_id){
registerClientPart(page_id);
@ -198,6 +199,10 @@ export function code({ id, src, content, language= "js", className= host.slice(1
el("code", { className: "language-"+language, textContent: content.trim() })
);
}
export function pre({ content }){
content= normalizeIndentation(content);
return el("pre").append(el("code", content.trim()));
}
let is_registered= {};
/** @param {string} page_id */
function registerClientPart(page_id){
@ -218,3 +223,9 @@ function registerClientPart(page_id){
is_registered[page_id]= true;
}
/** @param {string} src */
function normalizeIndentation(src){
const lines= src.split("\n");
const min_indent= Math.min(...lines.map(line=> line.search(/\S/)).filter(i=> i >= 0));
return lines.map(line=> line.slice(min_indent)).join("\n");
}

View File

@ -8,7 +8,8 @@ export class HTMLCustomElement extends HTMLElement{
connectedCallback(){
customElementRender(
this.attachShadow({ mode: "open" }),
ddeComponent
ddeComponent,
this
);
}
set attr(value){ this.setAttribute("attr", value); }

View File

@ -9,7 +9,7 @@ export class HTMLCustomElement extends HTMLElement{
// nice place to render custom element
}
attributeChangedCallback(name, oldValue, newValue){
// listen to attribute changes (see `observedAttributes`)
// listen to attribute changes (see `S.observedAttributes`)
}
disconnectedCallback(){
// nice place to clean up

View File

@ -1,4 +1,4 @@
// Example of reactive element marker
<!--<dde:mark type=\"reactive\" source=\"...\">-->
<!--<dde:mark type="reactive" source="...">-->
<!-- content that updates when signal changes -->
<!--</dde:mark>-->

View File

@ -0,0 +1,19 @@
import { el, on, dispatchEvent, scope } from "deka-dom-el";
document.body.append(
el(component),
);
function component(){
const { host }= scope;
const dispatchExample= dispatchEvent(
"example",
{ bubbles: true },
host
);
return el("div").append(
el("p", "Dispatch events from outside of the component."),
el("button", { textContent: "Dispatch", type: "button" },
on("click", dispatchExample))
);
}

View File

@ -1,5 +1,5 @@
import { el, on } from "deka-dom-el";
const paragraph= el("p", "See live-cycle events in console.",
const paragraph= el("p", "See lifecycle events in console.",
el=> log({ type: "dde:created", detail: el }),
on.connected(log),
on.disconnected(log),

View File

@ -6,9 +6,8 @@ let count = 0;
button.addEventListener('click', () => {
count++;
document.querySelector('p').textContent =
'Clicked ' + count + ' times';
'Clicked ' + count + ' times';
if (count > 10) {
button.disabled = true;
}
if (count > 10)
button.disabled = true;
});

View File

@ -1,4 +1,4 @@
import { el, on } from "deka-dom-el";
import { el } from "deka-dom-el";
import { S } from "deka-dom-el/signals";
// A HelloWorld component using the 3PS pattern
@ -27,4 +27,4 @@ function HelloWorld({ emoji = "🚀" }) {
// Use the component in your app
document.body.append(
el(HelloWorld, { emoji: "🎉" })
);
);

View File

@ -16,7 +16,9 @@ function Counter() {
// THE HOST IS PROBABLY DIFFERENT THAN
// YOU EXPECT AND SIGNAL MAY BE
// UNEXPECTEDLY REMOVED!!!
host().querySelector("button").disabled = count.get() >= 10;
S.on(count, (count)=>
host().querySelector("button").disabled = count >= 10
);
};
setTimeout(()=> {
// ok, BUT consider extract to separate function

View File

@ -1,6 +1,5 @@
// Handling async data in SSR
import { JSDOM } from "jsdom";
import { S } from "deka-dom-el/signals";
import { register, queue } from "deka-dom-el/jsdom";
async function renderWithAsyncData() {
@ -8,23 +7,7 @@ async function renderWithAsyncData() {
const { el } = await register(dom);
// Create a component that fetches data
function AsyncComponent() {
const title= S("-");
const description= S("-");
// Use the queue to track the async operation
queue(fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => {
title.set(data.title);
description.set(data.description);
}));
return el("div", { className: "async-content" }).append(
el("h2", title),
el("p", description)
);
}
const { AsyncComponent } = await import("./components/AsyncComponent.js");
// Render the page
dom.window.document.body.append(
@ -41,3 +24,24 @@ async function renderWithAsyncData() {
}
renderWithAsyncData();
// file: components/AsyncComponent.js
import { el } from "deka-dom-el";
import { S } from "deka-dom-el/signals";
function AsyncComponent() {
const title= S("-");
const description= S("-");
// Use the queue to track the async operation
queue(fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => {
title.set(data.title);
description.set(data.description);
}));
return el("div", { className: "async-content" }).append(
el("h2", title),
el("p", description)
);
}

View File

@ -11,6 +11,7 @@ async function renderPage() {
const { el } = await register(dom);
// Create a simple header component
// can be separated into a separate file and use `import { el } from "deka-dom-el"`
function Header({ title }) {
return el("header").append(
el("h1", title),

View File

@ -17,6 +17,7 @@ async function renderPage() {
const { el } = await register(dom);
// 4. Dynamically import page components
// use `import { el } from "deka-dom-el"`
const { Header } = await import("./components/Header.js");
const { Content } = await import("./components/Content.js");

View File

@ -1,6 +1,6 @@
// Basic jsdom integration example
import { JSDOM } from "jsdom";
import { register, unregister, queue } from "deka-dom-el/jsdom.js";
import { register, unregister, queue } from "deka-dom-el/jsdom";
// Create a jsdom instance
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");

View File

@ -12,7 +12,7 @@ async function buildSite() {
];
// Create output directory
mkdirSync("./dist", { recursive: true });
mkdirSync("./dist/docs", { recursive: true });
// Build each page
for (const page of pages) {
@ -23,6 +23,7 @@ async function buildSite() {
const { el } = await register(dom);
// Import the page component
// use `import { el } from "deka-dom-el"`
const { default: PageComponent } = await import(page.component);
// Render the page with its metadata
@ -35,7 +36,7 @@ async function buildSite() {
// Write the HTML to a file
const html = dom.serialize();
writeFileSync(`./dist/${page.id}.html`, html);
writeFileSync(`./dist/docs/${page.id}.html`, html);
console.log(`Built page: ${page.id}.html`);
}