1
0
mirror of https://github.com/jaandrle/deka-dom-el synced 2025-04-02 20:15:53 +02:00
deka-dom-el/docs/components/ireland.html.js
Jan Andrle f0dfdfde54
v0.9.2 — 🐛 types, on.defer and other small (#36)
* 🔤  T now uses DocumentFragment

* 🔤

* 🔤 

* 🐛 lint

*  cleanup

*  🔤 lib download

*  🔤 ui

*  reorganize files

*  on.host

* 🐛 on.* types

*  🔤 cdn

* 🔤 converter

* 🐛 signal.set(value, force)

*  🔤

* 🔤  converter - convert also comments

*  bs/build

* 🔤 ui p14

* 🔤

* 🔤 Examples

* 🔤

* 🐛 now only el(..., string|number)

* 🐛 fixes #38

* 🔤

*  on.host → on.defer

* 🔤

* 📺
2025-03-16 11:30:42 +01:00

126 lines
3.5 KiB
JavaScript

import { styles } from "../ssr.js";
styles.css`
[data-dde-mark] {
opacity: .5;
filter: grayscale();
@media (prefers-reduced-motion: no-preference) {
animation: fadein 2s infinite ease forwards;;
}
position: relative;
&::after {
content: "Loading Ireland…";
background-color: rgba(0, 0, 0, .5);
color: white;
font-weight: bold;
border-radius: 5px;
padding: 5px 10px;
position: absolute;
top: 3%;
left: 50%;
transform: translateX(-50%);
}
}
@keyframes fadein {
from { opacity: .5; }
to { opacity: .85; }
}
`;
import { el, queue } from "deka-dom-el";
import { addEventListener, registerClientFile } from "../ssr.js";
import { relative } from "node:path";
const dir= new URL("./", import.meta.url).pathname;
const dirFE= "irelands";
// Track all component instances for client-side rehydration
const componentsRegistry = new Map();
/**
* Creates a component that shows code and its runtime output
* with server-side pre-rendering and client-side rehydration
*
* @param {object} attrs
* @param {URL} attrs.src - Path to the file containing the component
* @param {string} [attrs.exportName="default"] - Name of the export to use
* @param {string} attrs.page_id - ID of the current page
* @param {object} [attrs.props={}] - Props to pass to the component
*/
export function ireland({ src, exportName = "default", props = {} }) {
// relative src against the current directory
const path= "./"+relative(dir, src.pathname);
const id = "ireland-" + generateComponentId(src);
const element = el.mark({ type: "later", name: ireland.name });
queue(
import(path)
.then(module => {
const component = module[exportName];
const content= el(component, props, mark(id));
element.replaceWith(content);
content.querySelectorAll("input, textarea, button")
.forEach(el=> el.disabled= true);
})
.catch(console.error)
);
if(!componentsRegistry.size)
addEventListener("oneachrender", registerClientPart);
componentsRegistry.set(id, {
src,
path: dirFE+"/"+path.split("/").pop(),
exportName,
props,
});
return element;
}
function registerClientPart(){
const todo= Array.from(componentsRegistry.entries())
.map(([ id, d ]) => {
registerClientFile(d.src, {
folder: dirFE,
// not all browsers support importmap
replacer(file){
return file
.replaceAll(/ from "deka-dom-el(\/signals)?";/g, ` from "./esm-with-signals.js";`);
}
});
return [ id, d ];
});
const store = JSON.stringify(JSON.stringify(todo));
registerClientFile(new URL("./ireland.js.js", import.meta.url));
registerClientFile(new URL("../../dist/esm-with-signals.js", import.meta.url), { folder: dirFE });
document.head.append(
// not all browsers support importmap
el("script", { type: "importmap" }).append(`
{
"imports": {
"deka-dom-el": "./${dirFE}/esm-with-signals.js",
"deka-dom-el/signals": "./${dirFE}/esm-with-signals.js"
}
}
`.trim())
);
document.body.append(
el("script", { type: "module" }).append(`
import { loadIrelands } from "./ireland.js.js";
loadIrelands(new Map(JSON.parse(${store})));
`.trim())
)
}
function mark(id) { return el=> el.dataset.ddeMark= id; }
const store_prev= new Map();
/** @param {URL} src */
function generateComponentId(src){
const candidate= parseInt(relative((new URL("..", import.meta.url)).pathname, src.pathname)
.split("")
.map(ch=> ch.charCodeAt(0))
.join(""), 10)
.toString(36)
.replace(/000+/g, "");
const count= 1 + ( store_prev.get(candidate) || 0 );
store_prev.set(candidate, count);
return count.toString()+"-"+candidate;
}