reconvert sigpro/ui
This commit is contained in:
2
dist/sigpro.min.js → dist/sigpro.js
vendored
2
dist/sigpro.min.js → dist/sigpro.js
vendored
File diff suppressed because one or more lines are too long
2
dist/sigpro.ui.css
vendored
Normal file
2
dist/sigpro.ui.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
dist/sigpro.ui.js
vendored
Normal file
1
dist/sigpro.ui.js
vendored
Normal file
File diff suppressed because one or more lines are too long
83
dist/sigpro.utils.js
vendored
83
dist/sigpro.utils.js
vendored
@@ -1,82 +1 @@
|
||||
// src/sigpro.utils.js
|
||||
import { h, watch, $, render, isF } from "./sigpro.js";
|
||||
var router = (routes) => {
|
||||
const getHash = () => window.location.hash.slice(1) || "/";
|
||||
const path = $(getHash());
|
||||
const handler = () => path(getHash());
|
||||
window.addEventListener("hashchange", handler);
|
||||
const hook = h("div", { class: "router-hook" });
|
||||
let currentView = null;
|
||||
watch([path], () => {
|
||||
const cur = path();
|
||||
const route = routes.find((r) => {
|
||||
const p1 = r.path.split("/").filter(Boolean);
|
||||
const p2 = cur.split("/").filter(Boolean);
|
||||
return p1.length === p2.length && p1.every((p, i) => p[0] === ":" || p === p2[i]);
|
||||
}) || routes.find((r) => r.path === "*");
|
||||
if (route) {
|
||||
currentView?.destroy();
|
||||
const params = {};
|
||||
route.path.split("/").filter(Boolean).forEach((p, i) => {
|
||||
if (p[0] === ":")
|
||||
params[p.slice(1)] = cur.split("/").filter(Boolean)[i];
|
||||
});
|
||||
router.params(params);
|
||||
currentView = render(() => isF(route.component) ? route.component(params) : route.component);
|
||||
hook.replaceChildren(currentView.container);
|
||||
}
|
||||
});
|
||||
hook.destroy = () => {
|
||||
window.removeEventListener("hashchange", handler);
|
||||
currentView?.destroy();
|
||||
};
|
||||
return hook;
|
||||
};
|
||||
router.params = $({});
|
||||
router.to = (p) => window.location.hash = p.replace(/^#?\/?/, "#/");
|
||||
router.back = () => window.history.back();
|
||||
router.path = () => window.location.hash.replace(/^#/, "") || "/";
|
||||
var db = async (url, data = {}, loading = null) => {
|
||||
if (loading)
|
||||
loading(true);
|
||||
try {
|
||||
const res = await fetch(url, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
credentials: "include"
|
||||
});
|
||||
if (!res.ok) {
|
||||
const errorText = await res.text();
|
||||
throw new Error(`Error ${res.status}: ${errorText}`);
|
||||
}
|
||||
return await res.json();
|
||||
} finally {
|
||||
if (loading)
|
||||
loading(false);
|
||||
}
|
||||
};
|
||||
var currentLocale = $("en");
|
||||
var translations = {};
|
||||
var addLang = (obj) => {
|
||||
for (const locale of Object.keys(obj)) {
|
||||
if (!translations[locale])
|
||||
translations[locale] = {};
|
||||
Object.assign(translations[locale], obj[locale]);
|
||||
}
|
||||
};
|
||||
var setLocale = (locale) => {
|
||||
if (locale && translations[locale]) {
|
||||
currentLocale(locale);
|
||||
}
|
||||
};
|
||||
var t = (key) => {
|
||||
return () => translations[currentLocale()]?.[key] ?? key;
|
||||
};
|
||||
export {
|
||||
t,
|
||||
setLocale,
|
||||
router,
|
||||
db,
|
||||
addLang
|
||||
};
|
||||
import{h as m,watch as x,$ as d,render as b,isF as g}from"./sigpro.js";var l=(t)=>{let e=()=>window.location.hash.slice(1)||"/",o=d(e()),n=()=>o(e());window.addEventListener("hashchange",n);let s=m("div",{class:"router-hook"}),h=null;return x([o],()=>{let f=o(),a=t.find((r)=>{let c=r.path.split("/").filter(Boolean),p=f.split("/").filter(Boolean);return c.length===p.length&&c.every((w,y)=>w[0]===":"||w===p[y])})||t.find((r)=>r.path==="*");if(a){h?.destroy();let r={};a.path.split("/").filter(Boolean).forEach((c,p)=>{if(c[0]===":")r[c.slice(1)]=f.split("/").filter(Boolean)[p]}),l.params(r),h=b(()=>g(a.component)?a.component(r):a.component),s.replaceChildren(h.container)}}),s.destroy=()=>{window.removeEventListener("hashchange",n),h?.destroy()},s};l.params=d({});l.to=(t)=>window.location.hash=t.replace(/^#?\/?/,"#/");l.back=()=>window.history.back();l.path=()=>window.location.hash.replace(/^#/,"")||"/";var v=async(t,e={},o=null)=>{if(o)o(!0);try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),credentials:"include"});if(!n.ok){let s=await n.text();throw Error(`Error ${n.status}: ${s}`)}return await n.json()}finally{if(o)o(!1)}},u=d("en"),i={},E=(t)=>{for(let e of Object.keys(t)){if(!i[e])i[e]={};Object.assign(i[e],t[e])}},L=(t)=>{if(t&&i[t])u(t)},B=(t)=>{return()=>i[u()]?.[t]??t};export{B as t,L as setLocale,l as router,v as db,E as addLang};
|
||||
|
||||
56
dist/sigpro.vite.js
vendored
56
dist/sigpro.vite.js
vendored
@@ -1,52 +1,4 @@
|
||||
// src/sigpro.vite.js
|
||||
function sigproRouter() {
|
||||
const virtualModuleId = "virtual:sigpro-routes";
|
||||
const resolvedVirtualModuleId = "\x00" + virtualModuleId;
|
||||
const getFiles = (dir) => {
|
||||
if (!fs.existsSync(dir))
|
||||
return [];
|
||||
return fs.readdirSync(dir, { recursive: true }).filter((file) => /\.(js|jsx)$/.test(file) && !path.basename(file).startsWith("_")).map((file) => path.resolve(dir, file));
|
||||
};
|
||||
const pathToUrl = (pagesDir, filePath) => {
|
||||
let relative = path.relative(pagesDir, filePath).replace(/\\/g, "/").replace(/\.(js|jsx)$/, "").replace(/\/index$/, "").replace(/^index$/, "");
|
||||
return ("/" + relative).replace(/\/+/g, "/").replace(/\[\.\.\.([^\]]+)\]/g, "*").replace(/\[([^\]]+)\]/g, ":$1").replace(/\/$/, "") || "/";
|
||||
};
|
||||
return {
|
||||
name: "sigpro-router",
|
||||
resolveId(id) {
|
||||
if (id === virtualModuleId)
|
||||
return resolvedVirtualModuleId;
|
||||
},
|
||||
load(id) {
|
||||
if (id !== resolvedVirtualModuleId)
|
||||
return;
|
||||
const root = process.cwd();
|
||||
const pagesDir = path.resolve(root, "src/pages");
|
||||
const files = getFiles(pagesDir).sort((a, b) => {
|
||||
const urlA = pathToUrl(pagesDir, a);
|
||||
const urlB = pathToUrl(pagesDir, b);
|
||||
if (urlA.includes(":") && !urlB.includes(":"))
|
||||
return 1;
|
||||
if (!urlA.includes(":") && urlB.includes(":"))
|
||||
return -1;
|
||||
return urlB.length - urlA.length;
|
||||
});
|
||||
let routeEntries = "";
|
||||
files.forEach((fullPath) => {
|
||||
const urlPath = pathToUrl(pagesDir, fullPath);
|
||||
const relativeImport = "./" + path.relative(root, fullPath).replace(/\\/g, "/");
|
||||
routeEntries += ` { path: '${urlPath}', component: () => import('/${relativeImport}') },
|
||||
`;
|
||||
});
|
||||
if (!routeEntries.includes("path: '*'")) {
|
||||
routeEntries += ` { path: '*', component: () => ({ default: () => document.createTextNode('404 - Not Found') }) },
|
||||
`;
|
||||
}
|
||||
return `export const routes = [
|
||||
${routeEntries}];`;
|
||||
}
|
||||
};
|
||||
}
|
||||
export {
|
||||
sigproRouter
|
||||
};
|
||||
function g(){let u="\x00virtual:sigpro-routes",i=(e)=>{if(!fs.existsSync(e))return[];return fs.readdirSync(e,{recursive:!0}).filter((r)=>/\.(js|jsx)$/.test(r)&&!path.basename(r).startsWith("_")).map((r)=>path.resolve(e,r))},l=(e,r)=>{return("/"+path.relative(e,r).replace(/\\/g,"/").replace(/\.(js|jsx)$/,"").replace(/\/index$/,"").replace(/^index$/,"")).replace(/\/+/g,"/").replace(/\[\.\.\.([^\]]+)\]/g,"*").replace(/\[([^\]]+)\]/g,":$1").replace(/\/$/,"")||"/"};return{name:"sigpro-router",resolveId(e){if(e==="virtual:sigpro-routes")return u},load(e){if(e!==u)return;let r=process.cwd(),t=path.resolve(r,"src/pages"),p=i(t).sort((n,a)=>{let o=l(t,n),c=l(t,a);if(o.includes(":")&&!c.includes(":"))return 1;if(!o.includes(":")&&c.includes(":"))return-1;return c.length-o.length}),s="";if(p.forEach((n)=>{let a=l(t,n),o="./"+path.relative(r,n).replace(/\\/g,"/");s+=` { path: '${a}', component: () => import('/${o}') },
|
||||
`}),!s.includes("path: '*'"))s+=` { path: '*', component: () => ({ default: () => document.createTextNode('404 - Not Found') }) },
|
||||
`;return`export const routes = [
|
||||
${s}];`}}}export{g as sigproRouter};
|
||||
|
||||
@@ -17,4 +17,5 @@
|
||||
* [Tags](api/tags.md)
|
||||
* [Global Store](api/global.md)
|
||||
* [JSX Style](api/jsx.md)
|
||||
* [HTML converter](convert.md)
|
||||
* [HTML converter](convert.md)
|
||||
* [UI](ui.md)
|
||||
@@ -1,6 +1,6 @@
|
||||
// src/convert.js
|
||||
import { $ } from "./sigpro.js";
|
||||
function html2sigpro(h) {
|
||||
function html2sigpro(h, advanced = false) {
|
||||
const B = new Set(["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "defer", "disabled", "formnovalidate", "hidden", "ismap", "itemscope", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "selected", "truespeed"]), esc = (v) => v.replace(/"/g, "\\\""), bP = (el) => {
|
||||
let a = [...el.attributes].map(({ name: n, value: v }) => /^on/i.test(n) ? `${n}: (e) => { ${v.replace(/\s+/g, " ").trim()} }` : B.has(n.toLowerCase()) && (!v || v == n) ? `${n}: true` : `${n}: "${esc(v)}"`);
|
||||
return a.length ? `{ ${a.join(", ")} }` : "";
|
||||
@@ -11,12 +11,48 @@ function html2sigpro(h) {
|
||||
return t.trim() ? `${s}"${esc(t)}"` : "";
|
||||
}
|
||||
if (n.nodeType == 1) {
|
||||
let t = n.tagName.toLowerCase(), p = bP(n), c = [...n.childNodes].map((i) => cN(i, d + 1)).filter(Boolean);
|
||||
if (!c.length)
|
||||
let t = n.tagName.toLowerCase();
|
||||
let classes = [];
|
||||
let otherAttrs = [];
|
||||
if (advanced) {
|
||||
const classAttribute = Array.from(n.attributes).find((attr) => attr.name === "class");
|
||||
if (classAttribute) {
|
||||
classes = classAttribute.value.trim().split(/\s+/).filter((c2) => c2);
|
||||
}
|
||||
otherAttrs = [...n.attributes].filter((attr) => attr.name !== "class");
|
||||
}
|
||||
let p = "";
|
||||
if (advanced && classes.length > 0) {
|
||||
const classChain = classes.map((c2) => `.${c2.replace(/-/g, "_")}`).join("");
|
||||
if (otherAttrs.length > 0) {
|
||||
const otherProps = otherAttrs.map(({ name: n2, value: v }) => /^on/i.test(n2) ? `${n2}: (e) => { ${v.replace(/\s+/g, " ").trim()} }` : B.has(n2.toLowerCase()) && (!v || v == n2) ? `${n2}: true` : `${n2}: "${esc(v)}"`);
|
||||
p = `${classChain}({ ${otherProps.join(", ")} })`;
|
||||
} else {
|
||||
p = classChain;
|
||||
}
|
||||
} else {
|
||||
p = bP(n);
|
||||
}
|
||||
let c = [...n.childNodes].map((i) => cN(i, d + 1)).filter(Boolean);
|
||||
if (!c.length) {
|
||||
if (advanced && classes.length > 0 && otherAttrs.length === 0) {
|
||||
return `${s}${t}${p}`;
|
||||
}
|
||||
return `${s}${t}(${p})`;
|
||||
}
|
||||
if (c.length == 1 && !c[0].includes(`
|
||||
`))
|
||||
`)) {
|
||||
if (advanced && classes.length > 0 && otherAttrs.length === 0 && !p.includes("{")) {
|
||||
return `${s}${t}${p}(${c[0].trim()})`;
|
||||
}
|
||||
return `${s}${t}(${p ? p + ", " : ""}${c[0].trim()})`;
|
||||
}
|
||||
if (advanced && classes.length > 0 && otherAttrs.length === 0 && !p.includes("{")) {
|
||||
return `${s}${t}${p}([
|
||||
${c.join(`,
|
||||
`)}
|
||||
${s}])`;
|
||||
}
|
||||
return `${s}${t}(${p ? p + ", " : ""}[
|
||||
${c.join(`,
|
||||
`)}
|
||||
@@ -34,13 +70,16 @@ var converter = () => {
|
||||
const setInH = (v) => inH(v);
|
||||
const outS = $("");
|
||||
const setOutS = (v) => outS(v);
|
||||
const advanced = $(false);
|
||||
const setAdvanced = (v) => advanced(v);
|
||||
const cnv = () => {
|
||||
try {
|
||||
setOutS(html2sigpro(inH()));
|
||||
setOutS(html2sigpro(inH(), advanced()));
|
||||
} catch (e) {
|
||||
setOutS("Error: " + e.message);
|
||||
}
|
||||
}, txS = "width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical", btS = "padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px";
|
||||
};
|
||||
const txS = "width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical", btS = "padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px";
|
||||
return div({ style: "max-width:900px;margin:20px auto;font-family:sans-serif" }, [
|
||||
h1("HTML → SigPro"),
|
||||
label({ style: "display:block;font-weight:700" }, "HTML:"),
|
||||
@@ -53,12 +92,20 @@ var converter = () => {
|
||||
cnv();
|
||||
}
|
||||
}),
|
||||
div({ style: "margin:10px 0" }, [
|
||||
div({ style: "margin:10px 0;display:flex;align-items:center;gap:10px" }, [
|
||||
button({ style: btS + ";background:#3b82f6;color:#fff", onclick: cnv }, "Convert"),
|
||||
button({ style: btS + ";background:#d1d5db", onclick: () => {
|
||||
setInH("");
|
||||
setOutS("");
|
||||
} }, "Clear")
|
||||
setAdvanced(false);
|
||||
} }, "Clear"),
|
||||
label({ style: "display:flex;align-items:center;gap:5px;cursor:pointer" }, [
|
||||
input({ type: "checkbox", checked: advanced, onchange: (e) => {
|
||||
setAdvanced(e.target.checked);
|
||||
cnv();
|
||||
} }),
|
||||
span("Advanced (dot notation for classes)")
|
||||
])
|
||||
]),
|
||||
div({ style: "display:flex;justify-content:space-between;align-items:center;margin-bottom:5px" }, [
|
||||
span({ style: "font-weight:700" }, "Out:"),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!doctype html>
|
||||
<html lang="es">
|
||||
<html lang="es" data-theme="splight">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>SigPro Docs</title>
|
||||
@@ -10,12 +10,12 @@
|
||||
rel="stylesheet"
|
||||
href="//cdn.jsdelivr.net/npm/docsify/lib/themes/vue.css"
|
||||
/>
|
||||
|
||||
<link
|
||||
<link href="./sigpro.ui.css" rel="stylesheet" type="text/css" />
|
||||
<!-- <link
|
||||
href="https://cdn.jsdelivr.net/npm/daisyui@5"
|
||||
rel="stylesheet"
|
||||
type="text/css"
|
||||
/>
|
||||
/> -->
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
</head>
|
||||
@@ -65,12 +65,17 @@
|
||||
</script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<script type="module">
|
||||
import * as SigPro from "./sigpro.min.js";
|
||||
import * as SigPro from "./sigpro.js";
|
||||
Object.assign(window, SigPro);
|
||||
import("./convert.js").then(() => {
|
||||
import "./sigpro.tags.js";
|
||||
import "./sigpro.ui.js";
|
||||
|
||||
import("./sigpro.convert.js").then(() => {
|
||||
console.log("SigPro y Convert cargados correctamente.");
|
||||
});
|
||||
// document.documentElement.setAttribute("data-theme", "splight");
|
||||
</script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/plugins/search.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify/lib/docsify.min.js"></script>
|
||||
<script src="//cdn.jsdelivr.net/npm/docsify-copy-code/dist/docsify-copy-code.min.js"></script>
|
||||
</body>
|
||||
|
||||
34
docs/sigpro.convert.js
Normal file
34
docs/sigpro.convert.js
Normal file
@@ -0,0 +1,34 @@
|
||||
var{$:x}=window.SigPro;function f(s,l="tags"){let a=new Set(["allowfullscreen","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected","truespeed"]),p=(o)=>o.replace(/"/g,"\\\""),c=(o)=>{let t=[...o.attributes].map(({name:e,value:n})=>/^on/i.test(e)?`${e}: (e) => { ${n.replace(/\s+/g," ").trim()} }`:a.has(e.toLowerCase())&&(!n||n==e)?`${e}: true`:`${e}: "${p(n)}"`);return t.length?`{ ${t.join(", ")} }`:""},m=(o,t=0)=>{let e=" ".repeat(t);if(o.nodeType==3){let n=o.textContent;return n.trim()?`${e}"${p(n)}"`:""}if(o.nodeType==1){let n=o.tagName.toLowerCase(),d=c(o),i=l==="core"?`h('${n}'`:n,r=[...o.childNodes].map((h)=>m(h,t+1)).filter(Boolean),g=!!d;if(l==="core"){if(!r.length)return g?`${e}${i}, ${d})`:`${e}${i})`;if(r.length===1&&!r[0].includes(`
|
||||
`))return g?`${e}${i}, ${d}, ${r[0].trim()})`:`${e}${i}, ${r[0].trim()})`;return g?`${e}${i}, ${d}, [
|
||||
${r.join(`,
|
||||
`)}
|
||||
${e}])`:`${e}${i}, [
|
||||
${r.join(`,
|
||||
`)}
|
||||
${e}])`}else{if(!r.length)return g?`${e}${i}(${d})`:`${e}${i}`;if(r.length===1&&!r[0].includes(`
|
||||
`))return g?`${e}${i}(${d}, ${r[0].trim()})`:`${e}${i}(${r[0].trim()})`;return g?`${e}${i}(${d}, [
|
||||
${r.join(`,
|
||||
`)}
|
||||
${e}])`:`${e}${i}([
|
||||
${r.join(`,
|
||||
`)}
|
||||
${e}])`}}return""},u=[...new DOMParser().parseFromString(s,"text/html").body.childNodes].map((o)=>m(o)).filter(Boolean);return u.length==1?u[0].trim():`[
|
||||
${u.join(`,
|
||||
`)}
|
||||
]`}var b=()=>{let s=x(""),l=x(""),a=x("tags"),p=x(""),c=()=>{try{l(f(s(),a()))}catch(t){l("Error: "+t.message)}p(s())},m=()=>{s(""),l(""),a("tags"),p("")},u="width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical",o="padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px";return div({style:"margin:20px auto;font-family:sans-serif"},[h1("HTML → SigPro"),div({style:"margin-bottom:10px"},[div({style:"display:flex;gap:20px;flex-wrap:wrap;margin-top:5px"},[label({style:"display:flex;align-items:center;gap:6px"},["Core",input({type:"radio",name:"mode",value:"core",checked:a()==="core",onchange:(t)=>{if(t.target.checked)a("core"),c()}}),span("core — h('tag', props, ...)")]),label({style:"display:flex;align-items:center;gap:6px"},["Tags",input({type:"radio",name:"mode",value:"tags",checked:a()==="tags",onchange:(t)=>{if(t.target.checked)a("tags"),c()}}),span("tags — tag({ props }, ...)")])])]),div({style:"margin-top:15px;display:flex;gap:10px"},[button({style:"padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px;background:#3b82f6;color:#fff",onclick:c},"Convert"),button({style:"padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px;background:#d1d5db",onclick:m},"Clear")]),div({style:"display:grid;grid-template-columns:1fr;gap:15px;margin-top:15px;width:100%"},[div({style:"border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column"},[label({style:"font-weight:bold;margin-bottom:8px"},"HTML Input"),textarea({style:"width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical",placeholder:"Paste your HTML here...",value:s,oninput:(t)=>{s(t.target.value),c()}})]),div({style:"border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column"},[div({style:"display:flex;justify-content:space-between;align-items:center;margin-bottom:8px"},[span({style:"font-weight:bold"},"SigPro Output"),button({style:"padding:4px 8px;background:#10b981;color:white;border:none;border-radius:4px;cursor:pointer;font-size:12px",onclick:()=>{navigator.clipboard.writeText(l()),alert("Copied!")}},"Copy")]),textarea({style:"width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical;background:#f9fafb",readonly:!0,value:l,placeholder:"Converted code will appear here..."})]),div({style:"border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column"},[label({style:"font-weight:bold;margin-bottom:8px"},"Live Preview"),iframe({style:"width:100%;height:200px;border:1px solid #e2e8f0;border-radius:4px;background:white;",srcdoc:()=>{return`
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<style>
|
||||
body { padding: 10px; margin: 0; font-family: sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${p()||""}
|
||||
</body>
|
||||
</html>
|
||||
`},sandbox:"allow-same-origin allow-scripts allow-popups allow-forms allow-modals"})])])])};window.html2sigpro=f;window.converter=b;
|
||||
396
docs/sigpro.js
396
docs/sigpro.js
File diff suppressed because one or more lines are too long
1
docs/sigpro.min.js
vendored
1
docs/sigpro.min.js
vendored
File diff suppressed because one or more lines are too long
1
docs/sigpro.tags.js
Normal file
1
docs/sigpro.tags.js
Normal file
@@ -0,0 +1 @@
|
||||
var{h:a}=window.SigPro;if(typeof window<"u")"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video".split(" ").forEach((e)=>{window[e]=(t,s)=>a(e,t,s)});
|
||||
2
docs/sigpro.ui.css
Normal file
2
docs/sigpro.ui.css
Normal file
File diff suppressed because one or more lines are too long
1
docs/sigpro.ui.js
Normal file
1
docs/sigpro.ui.js
Normal file
File diff suppressed because one or more lines are too long
1
docs/sigpro.utils.js
Normal file
1
docs/sigpro.utils.js
Normal file
@@ -0,0 +1 @@
|
||||
import{h as m,watch as x,$ as d,render as b,isF as g}from"./sigpro.js";var l=(t)=>{let e=()=>window.location.hash.slice(1)||"/",o=d(e()),n=()=>o(e());window.addEventListener("hashchange",n);let s=m("div",{class:"router-hook"}),h=null;return x([o],()=>{let f=o(),a=t.find((r)=>{let c=r.path.split("/").filter(Boolean),p=f.split("/").filter(Boolean);return c.length===p.length&&c.every((w,y)=>w[0]===":"||w===p[y])})||t.find((r)=>r.path==="*");if(a){h?.destroy();let r={};a.path.split("/").filter(Boolean).forEach((c,p)=>{if(c[0]===":")r[c.slice(1)]=f.split("/").filter(Boolean)[p]}),l.params(r),h=b(()=>g(a.component)?a.component(r):a.component),s.replaceChildren(h.container)}}),s.destroy=()=>{window.removeEventListener("hashchange",n),h?.destroy()},s};l.params=d({});l.to=(t)=>window.location.hash=t.replace(/^#?\/?/,"#/");l.back=()=>window.history.back();l.path=()=>window.location.hash.replace(/^#/,"")||"/";var v=async(t,e={},o=null)=>{if(o)o(!0);try{let n=await fetch(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e),credentials:"include"});if(!n.ok){let s=await n.text();throw Error(`Error ${n.status}: ${s}`)}return await n.json()}finally{if(o)o(!1)}},u=d("en"),i={},E=(t)=>{for(let e of Object.keys(t)){if(!i[e])i[e]={};Object.assign(i[e],t[e])}},L=(t)=>{if(t&&i[t])u(t)},B=(t)=>{return()=>i[u()]?.[t]??t};export{B as t,L as setLocale,l as router,v as db,E as addLang};
|
||||
4
docs/sigpro.vite.js
Normal file
4
docs/sigpro.vite.js
Normal file
@@ -0,0 +1,4 @@
|
||||
function g(){let u="\x00virtual:sigpro-routes",i=(e)=>{if(!fs.existsSync(e))return[];return fs.readdirSync(e,{recursive:!0}).filter((r)=>/\.(js|jsx)$/.test(r)&&!path.basename(r).startsWith("_")).map((r)=>path.resolve(e,r))},l=(e,r)=>{return("/"+path.relative(e,r).replace(/\\/g,"/").replace(/\.(js|jsx)$/,"").replace(/\/index$/,"").replace(/^index$/,"")).replace(/\/+/g,"/").replace(/\[\.\.\.([^\]]+)\]/g,"*").replace(/\[([^\]]+)\]/g,":$1").replace(/\/$/,"")||"/"};return{name:"sigpro-router",resolveId(e){if(e==="virtual:sigpro-routes")return u},load(e){if(e!==u)return;let r=process.cwd(),t=path.resolve(r,"src/pages"),p=i(t).sort((n,a)=>{let o=l(t,n),c=l(t,a);if(o.includes(":")&&!c.includes(":"))return 1;if(!o.includes(":")&&c.includes(":"))return-1;return c.length-o.length}),s="";if(p.forEach((n)=>{let a=l(t,n),o="./"+path.relative(r,n).replace(/\\/g,"/");s+=` { path: '${a}', component: () => import('/${o}') },
|
||||
`}),!s.includes("path: '*'"))s+=` { path: '*', component: () => ({ default: () => document.createTextNode('404 - Not Found') }) },
|
||||
`;return`export const routes = [
|
||||
${s}];`}}}export{g as sigproRouter};
|
||||
80
docs/ui.md
Normal file
80
docs/ui.md
Normal file
@@ -0,0 +1,80 @@
|
||||
<div id="ui"></div>
|
||||
|
||||
```js
|
||||
// ===== SIGNALS =====
|
||||
const fruta = $("");
|
||||
const color = $("#3b82f6");
|
||||
const fecha = $("");
|
||||
const rango = $({ start: null, end: null });
|
||||
const pais = $("");
|
||||
|
||||
// ===== OPCIONES =====
|
||||
const frutas = ["Manzana", "Pera", "Plátano", "Fresa", "Mango", "Sandía", "Melón", "Uva"];
|
||||
const paises = [
|
||||
{ label: "🇪🇸 España", value: "ES" },
|
||||
{ label: "🇲🇽 México", value: "MX" },
|
||||
{ label: "🇦🇷 Argentina", value: "AR" },
|
||||
{ label: "🇨🇴 Colombia", value: "CO" },
|
||||
{ label: "🇨🇱 Chile", value: "CL" }
|
||||
];
|
||||
|
||||
mount(() =>
|
||||
div({ class: "p-8 max-w-md mx-auto flex flex-col gap-4" }, [
|
||||
h1({ class: "text-2xl font-bold" }, "Field Components"),
|
||||
|
||||
// Autocomplete simple
|
||||
ui.autocomplete({
|
||||
label: "Fruta favorita",
|
||||
items: frutas,
|
||||
value: fruta,
|
||||
placeholder: "Buscar fruta..."
|
||||
}),
|
||||
|
||||
// Autocomplete con objetos
|
||||
ui.autocomplete({
|
||||
label: "País",
|
||||
items: paises,
|
||||
value: pais,
|
||||
placeholder: "Elige un país..."
|
||||
}),
|
||||
|
||||
// Datepicker simple
|
||||
ui.datepicker({
|
||||
label: "Fecha de nacimiento",
|
||||
value: fecha,
|
||||
placeholder: "Selecciona fecha..."
|
||||
}),
|
||||
|
||||
// Datepicker rango
|
||||
ui.datepicker({
|
||||
label: "Estancia",
|
||||
range: true,
|
||||
value: rango,
|
||||
placeholder: "Check-in → Check-out"
|
||||
}),
|
||||
|
||||
// Colorpicker
|
||||
ui.colorpicker({
|
||||
label: "Color favorito",
|
||||
value: color,
|
||||
placeholder: "Elige un color..."
|
||||
}),
|
||||
|
||||
ui.theme(),
|
||||
// Preview
|
||||
div({ class: "bg-base-200 rounded-box p-4 flex flex-col gap-2 text-sm" }, [
|
||||
div({}, () => `🍎 Fruta: ${val(fruta) || "—"}`),
|
||||
div({}, () => `🌍 País: ${val(pais) || "—"}`),
|
||||
div({}, () => `📅 Fecha: ${val(fecha) || "—"}`),
|
||||
div({}, () => {
|
||||
const r = val(rango);
|
||||
return r.start && r.end ? `🏨 Estancia: ${r.start} → ${r.end}` : "🏨 Estancia: —";
|
||||
}),
|
||||
div({ class: "flex items-center gap-2" }, [
|
||||
span({}, "🎨 Color:"),
|
||||
div({ class: "w-6 h-6 rounded border border-base-300", style: () => `background:${val(color)}` })
|
||||
])
|
||||
])
|
||||
])
|
||||
, "#ui");
|
||||
```
|
||||
51
package.json
51
package.json
@@ -8,19 +8,20 @@
|
||||
"email": "sigpro@natxocc.com",
|
||||
"url": "https://sigpro.natxocc.com"
|
||||
},
|
||||
"main": "./dist/sigpro.min.js",
|
||||
"module": "./dist/sigpro.min.js",
|
||||
"unpkg": "./dist/sigpro.min.js",
|
||||
"jsdelivr": "./dist/sigpro.min.js",
|
||||
"main": "./dist/sigpro.js",
|
||||
"module": "./dist/sigpro.js",
|
||||
"unpkg": "./dist/sigpro.js",
|
||||
"jsdelivr": "./dist/sigpro.js",
|
||||
"types": "./sigpro.d.ts",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./sigpro.d.ts",
|
||||
"import": "./dist/sigpro.min.js",
|
||||
"default": "./dist/sigpro.min.js"
|
||||
"import": "./dist/sigpro.js",
|
||||
"default": "./dist/sigpro.js"
|
||||
},
|
||||
"./utils": "./dist/sigpro.utils.js",
|
||||
"./vite": "./dist/sigpro.vite.js"
|
||||
"./vite": "./dist/sigpro.vite.js",
|
||||
"./ui": "./dist/sigpro.ui.js"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
@@ -41,15 +42,35 @@
|
||||
"del": "bun pm cache rm && rm -f bun.lockb && rm -f bun.lock",
|
||||
"clean": "rm -rf dist",
|
||||
"prebuild": "npm run clean",
|
||||
"build:core": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.min.js --format=esm --minify",
|
||||
"build:utils": "bun build ./src/sigpro.utils.js --bundle --outfile=./dist/sigpro.utils.js --format=esm --external ./src/sigpro.js",
|
||||
"build:vite": "bun build ./src/sigpro.vite.js --bundle --outfile=./dist/sigpro.vite.js --format=esm --external fs --external path",
|
||||
"build:convert": "bun build ./src/convert.js --bundle --outfile=./docs/convert.js --format=esm --external ./src/sigpro.js",
|
||||
"build:copy": "cp ./dist/sigpro.min.js ./docs/sigpro.min.js",
|
||||
"build": "bun run build:core && bun run build:utils && bun run build:vite && bun run build:convert && bun run build:copy",
|
||||
"build:core": "bun build ./src/sigpro.js --bundle --outfile=./dist/sigpro.js --format=esm --minify",
|
||||
"build:utils": "bun build ./src/sigpro.utils.js --bundle --outfile=./dist/sigpro.utils.js --format=esm --external ./src/sigpro.js --minify",
|
||||
"build:ui": "bun build ./src/sigpro.ui.js --bundle --outfile=./dist/sigpro.ui.js --format=esm --external ./src/sigpro.js --minify",
|
||||
"build:vite": "bun build ./src/sigpro.vite.js --bundle --outfile=./dist/sigpro.vite.js --format=esm --external fs --external path --minify",
|
||||
"build:css": "tailwindcss -i ./src/sigpro.ui.css -o ./dist/sigpro.ui.css --minify --content './src/tailwind' && du -h ./dist/sigpro.ui.css",
|
||||
"build:convert": "bun build ./src/sigpro.convert.js --bundle --outfile=./docs/sigpro.convert.js --format=esm --external ./src/sigpro.js --minify",
|
||||
"build": "bun run build:core && bun run build:utils && bun run build:ui && bun run build:vite && bun run build:css && bun run build:convert && cp ./dist/* ./docs",
|
||||
"docs": "bun x serve docs"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "^2.2.471",
|
||||
"@iconify/tailwind4": "^1.2.3",
|
||||
"@tailwindcss/cli": "^4.3.0",
|
||||
"daisyui": "^5.5.19",
|
||||
"tailwindcss": "^4.3.0"
|
||||
},
|
||||
"keywords": [
|
||||
"signals", "reactivity", "reactive", "pure", "vanilla", "js", "ui", "dom", "state", "frontend", "spa", "lightweight", "sigpro"
|
||||
"signals",
|
||||
"reactivity",
|
||||
"reactive",
|
||||
"pure",
|
||||
"vanilla",
|
||||
"js",
|
||||
"ui",
|
||||
"dom",
|
||||
"state",
|
||||
"frontend",
|
||||
"spa",
|
||||
"lightweight",
|
||||
"sigpro"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import * as core from "./sigpro.js"
|
||||
import * as utils from "./sigpro.utils.js"
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
const SigPro = { ...core, ...utils };
|
||||
|
||||
window.SigPro = SigPro;
|
||||
|
||||
Object.assign(window, SigPro);
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
import { $ } from "./sigpro.js";
|
||||
|
||||
function html2sigpro(h) {
|
||||
const B = new Set(['allowfullscreen', 'async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'ismap', 'itemscope', 'loop', 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'playsinline', 'readonly', 'required', 'reversed', 'selected', 'truespeed']),
|
||||
esc = v => v.replace(/"/g, '\\"'),
|
||||
bP = el => {
|
||||
let a = [...el.attributes].map(({ name: n, value: v }) =>
|
||||
/^on/i.test(n) ? `${n}: (e) => { ${v.replace(/\s+/g, ' ').trim()} }` :
|
||||
(B.has(n.toLowerCase()) && (!v || v == n)) ? `${n}: true` : `${n}: "${esc(v)}"`
|
||||
);
|
||||
return a.length ? `{ ${a.join(', ')} }` : '';
|
||||
},
|
||||
cN = (n, d = 0) => {
|
||||
let s = ' '.repeat(d);
|
||||
if (n.nodeType == 3) {
|
||||
let t = n.textContent;
|
||||
return t.trim() ? `${s}"${esc(t)}"` : '';
|
||||
}
|
||||
if (n.nodeType == 1) {
|
||||
let t = n.tagName.toLowerCase(), p = bP(n),
|
||||
c = [...n.childNodes].map(i => cN(i, d + 1)).filter(Boolean);
|
||||
if (!c.length) return `${s}${t}(${p})`;
|
||||
if (c.length == 1 && !c[0].includes('\n')) return `${s}${t}(${p ? p + ', ' : ''}${c[0].trim()})`;
|
||||
return `${s}${t}(${p ? p + ', ' : ''}[\n${c.join(',\n')}\n${s}])`;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
r = [...new DOMParser().parseFromString(h, 'text/html').body.childNodes].map(n => cN(n)).filter(Boolean);
|
||||
return r.length == 1 ? r[0].trim() : `[\n${r.join(',\n')}\n]`;
|
||||
}
|
||||
|
||||
const converter = () => {
|
||||
const inH = $('');
|
||||
const setInH = (v) => inH(v);
|
||||
const outS = $('');
|
||||
const setOutS = (v) => outS(v);
|
||||
const cnv = () => { try { setOutS(html2sigpro(inH())) } catch (e) { setOutS('Error: ' + e.message) } },
|
||||
txS = "width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical",
|
||||
btS = "padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px";
|
||||
|
||||
return div({ style: "max-width:900px;margin:20px auto;font-family:sans-serif" }, [
|
||||
h1("HTML → SigPro"),
|
||||
label({ style: "display:block;font-weight:700" }, "HTML:"),
|
||||
textarea({
|
||||
style: txS, placeholder: "HTML...", value: inH,
|
||||
oninput: e => { setInH(e.target.value); cnv() }
|
||||
}),
|
||||
div({ style: "margin:10px 0" }, [
|
||||
button({ style: btS + ";background:#3b82f6;color:#fff", onclick: cnv }, "Convert"),
|
||||
button({ style: btS + ";background:#d1d5db", onclick: () => { setInH(''); setOutS('') } }, "Clear")
|
||||
]),
|
||||
div({ style: "display:flex;justify-content:space-between;align-items:center;margin-bottom:5px" }, [
|
||||
span({ style: "font-weight:700" }, "Out:"),
|
||||
button({ style: btS + ";background:#10b981;color:#fff", onclick: () => { navigator.clipboard.writeText(outS()); alert('Copied!') } }, "Copy")
|
||||
]),
|
||||
textarea({ style: txS + ";background:#f9fafb", readonly: true, value: outS, placeholder: "Result..." })
|
||||
]);
|
||||
}
|
||||
|
||||
window.html2sigpro = html2sigpro;
|
||||
window.converter = converter;
|
||||
146
src/sigpro.convert.js
Normal file
146
src/sigpro.convert.js
Normal file
@@ -0,0 +1,146 @@
|
||||
// src/sigpro.convert.js - Conversor HTML a SigPro con preview
|
||||
var { $ } = window.SigPro;
|
||||
|
||||
function html2sigpro(h, mode = "tags") {
|
||||
const B = new Set(["allowfullscreen", "async", "autofocus", "autoplay", "checked", "controls", "default", "defer", "disabled", "formnovalidate", "hidden", "ismap", "itemscope", "loop", "multiple", "muted", "nomodule", "novalidate", "open", "playsinline", "readonly", "required", "reversed", "selected", "truespeed"]);
|
||||
const esc = v => v.replace(/"/g, '\\"');
|
||||
|
||||
const bP = el => {
|
||||
let a = [...el.attributes].map(({ name: n, value: v }) =>
|
||||
/^on/i.test(n) ? `${n}: (e) => { ${v.replace(/\s+/g, " ").trim()} }` :
|
||||
(B.has(n.toLowerCase()) && (!v || v == n)) ? `${n}: true` : `${n}: "${esc(v)}"`
|
||||
);
|
||||
return a.length ? `{ ${a.join(", ")} }` : "";
|
||||
};
|
||||
|
||||
const cN = (n, d = 0) => {
|
||||
let s = " ".repeat(d);
|
||||
if (n.nodeType == 3) {
|
||||
let t = n.textContent;
|
||||
return t.trim() ? `${s}"${esc(t)}"` : "";
|
||||
}
|
||||
if (n.nodeType == 1) {
|
||||
let tag = n.tagName.toLowerCase();
|
||||
let props = bP(n);
|
||||
let prefix = mode === "core" ? `h('${tag}'` : tag;
|
||||
|
||||
let children = [...n.childNodes].map(i => cN(i, d + 1)).filter(Boolean);
|
||||
const hasProps = !!props;
|
||||
|
||||
if (mode === "core") {
|
||||
if (!children.length) return hasProps ? `${s}${prefix}, ${props})` : `${s}${prefix})`;
|
||||
if (children.length === 1 && !children[0].includes("\n"))
|
||||
return hasProps ? `${s}${prefix}, ${props}, ${children[0].trim()})` : `${s}${prefix}, ${children[0].trim()})`;
|
||||
return hasProps ? `${s}${prefix}, ${props}, [\n${children.join(",\n")}\n${s}])` : `${s}${prefix}, [\n${children.join(",\n")}\n${s}])`;
|
||||
} else {
|
||||
if (!children.length) return hasProps ? `${s}${prefix}(${props})` : `${s}${prefix}`;
|
||||
if (children.length === 1 && !children[0].includes("\n"))
|
||||
return hasProps ? `${s}${prefix}(${props}, ${children[0].trim()})` : `${s}${prefix}(${children[0].trim()})`;
|
||||
return hasProps ? `${s}${prefix}(${props}, [\n${children.join(",\n")}\n${s}])` : `${s}${prefix}([\n${children.join(",\n")}\n${s}])`;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
const r = [...new DOMParser().parseFromString(h, "text/html").body.childNodes].map(n => cN(n)).filter(Boolean);
|
||||
return r.length == 1 ? r[0].trim() : `[\n${r.join(",\n")}\n]`;
|
||||
}
|
||||
|
||||
const converter = () => {
|
||||
const inH = $("");
|
||||
const outS = $("");
|
||||
const mode = $("tags");
|
||||
const previewHtml = $("");
|
||||
|
||||
const cnv = () => {
|
||||
try {
|
||||
outS(html2sigpro(inH(), mode()));
|
||||
} catch (e) {
|
||||
outS("Error: " + e.message);
|
||||
}
|
||||
previewHtml(inH());
|
||||
};
|
||||
|
||||
const clearAll = () => {
|
||||
inH("");
|
||||
outS("");
|
||||
mode("tags");
|
||||
previewHtml("");
|
||||
};
|
||||
|
||||
const txS = "width:100%;height:200px;padding:10px;border:1px solid #ccc;border-radius:4px;font-family:monospace;font-size:14px;box-sizing:border-box;resize:vertical";
|
||||
const btS = "padding:8px 16px;border:none;border-radius:4px;cursor:pointer;margin-right:8px;font-size:14px";
|
||||
|
||||
return div({ style: "margin:20px auto;font-family:sans-serif" }, [
|
||||
h1("HTML → SigPro"),
|
||||
div({ style: "margin-bottom:10px" }, [
|
||||
div({ style: "display:flex;gap:20px;flex-wrap:wrap;margin-top:5px" }, [
|
||||
label({ style: "display:flex;align-items:center;gap:6px" }, [
|
||||
"Core",
|
||||
input({ type: "radio", name: "mode", value: "core", checked: mode() === "core", onchange: e => { if (e.target.checked) { mode("core"); cnv(); } } }),
|
||||
span("core — h('tag', props, ...)")
|
||||
]),
|
||||
label({ style: "display:flex;align-items:center;gap:6px" }, [
|
||||
"Tags",
|
||||
input({ type: "radio", name: "mode", value: "tags", checked: mode() === "tags", onchange: e => { if (e.target.checked) { mode("tags"); cnv(); } } }),
|
||||
span("tags — tag({ props }, ...)")
|
||||
])
|
||||
])
|
||||
]),
|
||||
div({ style: "margin-top:15px;display:flex;gap:10px" }, [
|
||||
button({ style: btS + ";background:#3b82f6;color:#fff", onclick: cnv }, "Convert"),
|
||||
button({ style: btS + ";background:#d1d5db", onclick: clearAll }, "Clear")
|
||||
]),
|
||||
div({ style: "display:grid;grid-template-columns:1fr;gap:15px;margin-top:15px;width:100%" }, [
|
||||
div({ style: "border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column" }, [
|
||||
label({ style: "font-weight:bold;margin-bottom:8px" }, "HTML Input"),
|
||||
textarea({
|
||||
style: txS,
|
||||
placeholder: "Paste your HTML here...",
|
||||
value: inH,
|
||||
oninput: e => { inH(e.target.value); cnv(); }
|
||||
})
|
||||
]),
|
||||
div({ style: "border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column" }, [
|
||||
div({ style: "display:flex;justify-content:space-between;align-items:center;margin-bottom:8px" }, [
|
||||
span({ style: "font-weight:bold" }, "SigPro Output"),
|
||||
button({
|
||||
style: "padding:4px 8px;background:#10b981;color:white;border:none;border-radius:4px;cursor:pointer;font-size:12px",
|
||||
onclick: () => { navigator.clipboard.writeText(outS()); alert("Copied!"); }
|
||||
}, "Copy")
|
||||
]),
|
||||
textarea({ style: txS + ";background:#f9fafb", readonly: true, value: outS, placeholder: "Converted code will appear here..." })
|
||||
]),
|
||||
div({ style: "border:1px solid #ccc;border-radius:8px;padding:10px;display:flex;flex-direction:column" }, [
|
||||
label({ style: "font-weight:bold;margin-bottom:8px" }, "Live Preview"),
|
||||
iframe({
|
||||
style: "width:100%;height:200px;border:1px solid #e2e8f0;border-radius:4px;background:white;",
|
||||
srcdoc: () => {
|
||||
const html = previewHtml() || "";
|
||||
return `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<link href="https://cdn.jsdelivr.net/npm/daisyui@5" rel="stylesheet" type="text/css">
|
||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||
<style>
|
||||
body { padding: 10px; margin: 0; font-family: sans-serif; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${html}
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
},
|
||||
sandbox: "allow-same-origin allow-scripts allow-popups allow-forms allow-modals"
|
||||
})
|
||||
])
|
||||
]),
|
||||
]);
|
||||
};
|
||||
|
||||
window.html2sigpro = html2sigpro;
|
||||
window.converter = converter;
|
||||
@@ -234,7 +234,7 @@ export const each = (s, fn, kF) => {
|
||||
return rt;
|
||||
};
|
||||
|
||||
export const mount = (c, tgt) => {
|
||||
export const mount = (c, tgt) => {
|
||||
let t = typeof tgt == "string" ? doc.querySelector(tgt) : tgt;
|
||||
if (!t) return;
|
||||
if (MOUNTED.has(t)) MOUNTED.get(t)._del();
|
||||
@@ -242,9 +242,13 @@ export const each = (s, fn, kF) => {
|
||||
t.replaceChildren(i._cnt); MOUNTED.set(t, i); return i;
|
||||
};
|
||||
|
||||
const htmlTags = "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video";
|
||||
|
||||
export const SigPro = { $, watch, batch, h, Fragment, render, mount, when, each, onUnmount, val, isA, isF, isO };
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
window.SigPro = SigPro;
|
||||
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video"
|
||||
.split(" ").forEach(t => window[t] = (p, c) => h(t, p, c));
|
||||
htmlTags.split(" ").forEach(tag => {
|
||||
window[tag] = (props, children) => h(tag, props, children);
|
||||
});
|
||||
}
|
||||
@@ -1,7 +1,26 @@
|
||||
import { h } from "./sigpro.js";
|
||||
// export const createTag = (tag, defaultProps = {}) => {
|
||||
// const fn = (p, c) => {
|
||||
// const props = { ...defaultProps, ...p };
|
||||
// return h(tag, props, c);
|
||||
// };
|
||||
|
||||
if (typeof window < "u") {
|
||||
"a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video"
|
||||
.split(" ").forEach(t => window[t] = (p, c) => h(t, p, c));
|
||||
Object.assign(window, { $, watch, h, Fragment, when, each, onUnmount, mount, batch, val, isA, isF, isO })
|
||||
}
|
||||
// return new Proxy(fn, {
|
||||
// get(_, className) {
|
||||
// const realClass = className.replace(/_/g, '-');
|
||||
// return (p, c) => {
|
||||
// const classProp = p?.class ? `${realClass} ${p.class}` : realClass;
|
||||
// return fn({ ...p, class: classProp }, c);
|
||||
// };
|
||||
// }
|
||||
// });
|
||||
// };
|
||||
|
||||
const { h } = window.SigPro;
|
||||
|
||||
const htmlTags = "a abbr article aside audio b blockquote br button canvas caption cite code col colgroup datalist dd del details dfn dialog div dl dt em embed fieldset figcaption figure footer form h1 h2 h3 h4 h5 h6 header hr i iframe img input ins kbd label legend li main mark meter nav object ol optgroup option output p picture pre progress section select slot small source span strong sub summary sup svg table tbody td template textarea tfoot th thead time tr u ul video";
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
htmlTags.split(" ").forEach(tag => {
|
||||
window[tag] = (props, children) => h(tag, props, children);
|
||||
});
|
||||
}
|
||||
|
||||
108
src/sigpro.ui.css
Normal file
108
src/sigpro.ui.css
Normal file
@@ -0,0 +1,108 @@
|
||||
@import "tailwindcss";
|
||||
@plugin "daisyui";
|
||||
@plugin "@iconify/tailwind4";
|
||||
|
||||
@plugin "daisyui/theme" {
|
||||
name: "splight";
|
||||
default: true;
|
||||
prefersdark: false;
|
||||
color-scheme: "light";
|
||||
--color-base-100: oklch(100% 0 0);
|
||||
--color-base-200: oklch(98% 0 0);
|
||||
--color-base-300: oklch(92% 0 0);
|
||||
--color-base-content: oklch(25% 0.006 285);
|
||||
--color-primary: oklch(25% 0.006 285);
|
||||
--color-primary-content: oklch(98% 0 0);
|
||||
--color-secondary: oklch(55% 0.046 257.417);
|
||||
--color-secondary-content: oklch(98% 0 0);
|
||||
--color-accent: oklch(96% 0 0);
|
||||
--color-accent-content: oklch(25% 0.006 285);
|
||||
--color-neutral: oklch(14% 0.005 285.823);
|
||||
--color-neutral-content: oklch(92% 0.004 286.32);
|
||||
--color-info: oklch(74% 0.16 232);
|
||||
--color-success: oklch(62% 0.17 163);
|
||||
--color-warning: oklch(82% 0.18 84);
|
||||
--color-error: oklch(60% 0.25 27);
|
||||
--radius-selector: 0.5rem;
|
||||
--radius-field: 0.5rem;
|
||||
--radius-box: 0.5rem;
|
||||
--size-selector: 0.25rem;
|
||||
--size-field: 0.25rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 0;
|
||||
}
|
||||
|
||||
@plugin "daisyui/theme" {
|
||||
name: "spdark";
|
||||
default: false;
|
||||
prefersdark: true;
|
||||
color-scheme: "dark";
|
||||
--color-base-100: oklch(15% 0.005 285.823);
|
||||
--color-base-200: oklch(20% 0.005 285.823);
|
||||
--color-base-300: oklch(30% 0.005 285.823);
|
||||
--color-base-content: oklch(92% 0.004 286.32);
|
||||
--color-primary: oklch(98% 0 0);
|
||||
--color-primary-content: oklch(15% 0 0);
|
||||
--color-secondary: oklch(65% 0.046 257.417);
|
||||
--color-secondary-content: oklch(15% 0.005 285.823);
|
||||
--color-accent: oklch(25% 0 0);
|
||||
--color-accent-content: oklch(98% 0 0);
|
||||
--color-neutral: oklch(92% 0.004 286.32);
|
||||
--color-neutral-content: oklch(14% 0.005 285.823);
|
||||
--color-info: oklch(70% 0.1 230);
|
||||
--color-success: oklch(65% 0.15 160);
|
||||
--color-warning: oklch(85% 0.15 90);
|
||||
--color-error: oklch(55% 0.2 27);
|
||||
--radius-selector: 0.5rem;
|
||||
--radius-field: 0.5rem;
|
||||
--radius-box: 0.5rem;
|
||||
--size-selector: 0.25rem;
|
||||
--size-field: 0.25rem;
|
||||
--border: 1px;
|
||||
--depth: 1;
|
||||
--noise: 0;
|
||||
}
|
||||
|
||||
:root {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input,
|
||||
.label,
|
||||
.select,
|
||||
.textarea {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:focus,
|
||||
&:focus-within {
|
||||
outline: none !important;
|
||||
box-shadow: 0 0 4px 0px;
|
||||
}
|
||||
|
||||
&:hover:not(:focus) {
|
||||
background-color: oklch(from var(--color-base-100) calc(l - 0.03) c h);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.floating-label span {
|
||||
color: oklch(30% 0.01 260);
|
||||
font-size: 1.1rem;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.floating-label:focus-within span {
|
||||
color: oklch(25% 0.02 260);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.floating-label:has(input:not(:placeholder-shown)) span {
|
||||
color: oklch(28% 0.01 260);
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
/* Solo para la Demo de docsify */
|
||||
.markdown-section progress.progress {
|
||||
all: revert-layer;
|
||||
}
|
||||
320
src/sigpro.ui.js
Normal file
320
src/sigpro.ui.js
Normal file
@@ -0,0 +1,320 @@
|
||||
const { $, h, mount, val, isF, isO } = window.SigPro;
|
||||
|
||||
export const hide = () => document.activeElement?.blur();
|
||||
|
||||
export const ui = {
|
||||
_label: (p, c) => h("label", { class: "floating-label" }, [h("span", {}, p.label ?? null), c]),
|
||||
accordion: (p, c) => h("div", { ...p, class: `collapse ${p.class || ''}` }, [h("input", { type: "radio", name: p.name, checked: p.checked }), c]),
|
||||
accordionTitle: (p, c) => h("div", { ...p, class: `collapse-title ${p.class || ''}` }, c),
|
||||
accordionContent: (p, c) => h("div", { ...p, class: `collapse-content ${p.class || ''}` }, c),
|
||||
alert: (p, c) => h("div", { ...p, class: `alert ${p.class || ''}` }, c),
|
||||
autocomplete: (p) => ui.combo(p, ({ query, close, setValue }) =>
|
||||
h("ul", { class: "menu bg-base-100 w-full" }, () => {
|
||||
const q = String(val(query)).toLowerCase();
|
||||
const list = (val(p.items) || []).filter(i =>
|
||||
(isO(i) ? (i.label ?? i.value) : String(i)).toLowerCase().includes(q)
|
||||
);
|
||||
return list.length
|
||||
? list.map((item, idx) =>
|
||||
h("li", { key: item.value ?? idx },
|
||||
h("a", {
|
||||
onclick: e => {
|
||||
e.preventDefault();
|
||||
const v = item?.value ?? item;
|
||||
setValue(isO(item) ? (item.label ?? item.value) : String(item));
|
||||
if (isF(p.value)) p.value(v); else p.onChange?.(v);
|
||||
close();
|
||||
}
|
||||
}, isO(item) ? (item.label ?? item.value) : item)
|
||||
)
|
||||
)
|
||||
: [h("li", { class: "disabled" }, h("a", {}, "Sin resultados"))];
|
||||
})
|
||||
),
|
||||
avatar: (p, c) => h("div", { ...p, class: `avatar ${p.class || ''}` }, h("div", { class: p.innerClass || '' }, c)),
|
||||
avatarGroup: (p, c) => h("div", { ...p, class: `avatar-group -space-x-6 ${p.class || ''}` }, c),
|
||||
badge: (p, c) => h("span", { ...p, class: `badge ${p.class || ''}` }, c),
|
||||
breadcrumbs: (p, c) => h("div", { ...p, class: `breadcrumbs ${p.class || ''}` }, c),
|
||||
button: (p, c) => h("button", { ...p, class: `btn ${p.class || ''}` }, c),
|
||||
card: (p, c) => h("div", { ...p, class: `card ${p.class || ''}` }, c),
|
||||
cardTitle: (p, c) => h("div", { ...p, class: `card-title ${p.class || ''}` }, c),
|
||||
cardBody: (p, c) => h("div", { ...p, class: `card-body ${p.class || ''}` }, c),
|
||||
cardActions: (p, c) => h("div", { ...p, class: `card-actions ${p.class || ''}` }, c),
|
||||
carousel: (p, c) => h("div", { ...p, class: `carousel ${p.class || ''}` }, c),
|
||||
carouselItem: (p, c) => h("div", { ...p, class: `carousel-item ${p.class || ''}` }, c),
|
||||
chat: (p, c) => h("div", { ...p, class: `chat ${p.class || ''}` }, c),
|
||||
chatImage: (p, c) => h("div", { ...p, class: `chat-image avatar ${p.class || ''}` }, c),
|
||||
chatHeader: (p, c) => h("div", { ...p, class: `chat-header ${p.class || ''}` }, c),
|
||||
chatBubble: (p, c) => h("div", { ...p, class: `chat-bubble ${p.class || ''}` }, c),
|
||||
chatFooter: (p, c) => h("div", { ...p, class: `chat-footer ${p.class || ''}` }, c),
|
||||
checkbox: (p) => h("input", { ...p, type: "checkbox", class: `checkbox ${p.class || ''}` }),
|
||||
colorpicker: (p) => ui.combo({ ...p, style: ()=>`background:${val(p.value) || '#000'}`, custom: () => h("span", {
|
||||
class: "w-4 h-4 rounded border border-base-300",
|
||||
style: `background:${val(p.value) || '#000'}`
|
||||
})
|
||||
}, ({ close, setValue }) =>
|
||||
pallete({ ...p, onchange: (c) => { setValue(c); close(); } })
|
||||
),
|
||||
combo: (p, c) => {
|
||||
const { placeholder = "", class: cls = "" } = p;
|
||||
const query = $("");
|
||||
let inputEl, open = $(false);
|
||||
|
||||
return ui._label({ label: p.label }, [
|
||||
h("div", { class: `dropdown ${cls} ${val(open) ? "dropdown-open" : ""}` }, [
|
||||
h("label", { class: "input" }, [
|
||||
h("span", { class: p.icon ?? "icon-[lucide--search]" }),
|
||||
p.custom ?? null,
|
||||
h("input", {
|
||||
type: "search", placeholder, tabindex: "0",
|
||||
value: query,
|
||||
onfocus: () => open(true),
|
||||
ref: el => inputEl = el
|
||||
})
|
||||
]),
|
||||
h("div", {
|
||||
class: "dropdown-content bg-base-100 rounded-box z-50 w-full p-2 shadow-sm",
|
||||
onmousedown: e => e.preventDefault()
|
||||
}, () => val(open) && typeof c === "function"
|
||||
? c({ query, open, close: () => { open(false); inputEl?.blur(); }, setValue: v => query(v) })
|
||||
: null
|
||||
)
|
||||
])
|
||||
]);
|
||||
},
|
||||
datepicker: (p) => ui.combo(p, ({ close, setValue }) => {
|
||||
const range = p.range;
|
||||
return h("div", { class: "w-80" }, [
|
||||
calendar({
|
||||
...p,
|
||||
class: "w-full",
|
||||
onChange: (v) => {
|
||||
if (isF(p.value)) p.value(v);
|
||||
if (!range) { setValue(v); close(); }
|
||||
else if (v.start && v.end) { setValue(`${v.start} → ${v.end}`); close(); }
|
||||
else if (v.start) setValue(`${v.start} → ...`);
|
||||
}
|
||||
})
|
||||
]);
|
||||
}),
|
||||
divider: (p) => h("div", { ...p, class: `divider ${p.class || ''}` }),
|
||||
drawer: (p, c) => h("div", { ...p, class: `drawer ${p.class || ''}` }, c),
|
||||
drawerToggle: (p) => h("input", { ...p, type: "checkbox", class: `drawer-toggle ${p.class || ''}` }),
|
||||
drawerContent: (p, c) => h("div", { ...p, class: `drawer-content ${p.class || ''}` }, c),
|
||||
drawerSide: (p, c) => h("div", { ...p, class: `drawer-side ${p.class || ''}` }, c),
|
||||
drawerOverlay: (p) => h("label", { ...p, class: `drawer-overlay ${p.class || ''}` }),
|
||||
dropdown: (p, c) => h("div", { ...p, class: `dropdown ${p.class || ''}` }, c),
|
||||
dropdownButton: (p, c) => h("div", { ...p, tabindex: "0", role: "button", class: `btn ${p.class || ''}` }, c),
|
||||
dropdownContent: (p, c) => h("div", { ...p, tabindex: "0", class: `dropdown-content ${p.class || ''}` }, c),
|
||||
fab: (p, c) => h("div", { ...p, class: `fab ${p.class || ''}` }, c),
|
||||
fabButton: (p, c) => h("div", { ...p, tabindex: "0", role: "button", class: `btn ${p.class || ''}` }, c),
|
||||
fieldset: (p, c) => h("fieldset", { class: `fieldset ${p.class || ''}` }, [h("legend", { class: "fieldset-legend" }, p.label), c]),
|
||||
fileInput: (p) => h("input", { ...p, type: "file", class: `file-input ${p.class || ''}` }),
|
||||
fileDrag: (p, c) => h("label", {
|
||||
class: () => `relative flex items-center justify-between h-12 px-4 border-2 border-dashed rounded-lg cursor-pointer transition-all ${p.drag ? 'border-primary bg-primary/10' : 'border-base-content/20 bg-base-100'} ${p.class || ''}`,
|
||||
ondragover: (e) => { e.preventDefault(); p.ondrag?.(true); },
|
||||
ondragleave: () => p.ondrag?.(false),
|
||||
ondrop: (e) => { e.preventDefault(); p.ondrag?.(false); p.ondrop?.(e.dataTransfer.files); }
|
||||
}, c),
|
||||
filePreview: (p) => h("ul", { class: `mt-2 space-y-1 ${p.class || ''}` },
|
||||
(p.files || []).map((f, i) =>
|
||||
h("li", { class: "flex items-center justify-between p-1.5 pl-3 text-xs bg-base-200/50 rounded-md border" }, [
|
||||
h("div", { class: "flex items-center gap-2 truncate opacity-70" }, [
|
||||
h("span", {}, "📄"),
|
||||
h("span", { class: "truncate max-w-[180px]" }, f.name),
|
||||
h("span", { class: "text-[9px] opacity-50" }, `(${~~(f.size / 1024)}KB)`)
|
||||
]),
|
||||
h("button", { class: "btn btn-ghost btn-xs btn-circle", onclick: () => p.onremove?.(i) }, h("span", { class: "icon-[lucide--x]" }))
|
||||
])
|
||||
)
|
||||
),
|
||||
fileError: (p) => h("div", { class: `text-[10px] text-error mt-1 px-1 ${p.class || ''}` }, p.message),
|
||||
icon: (p) => h("span", { class: p || '' }),
|
||||
indicator: (p, c) => h("div", { ...p, class: `indicator ${p.class || ''}` }, [p.value && h("span", { class: `indicator-item badge ${p.badgeClass || ''}` }, p.value), c]),
|
||||
input: (p) => h("input", { ...p, class: `input ${p.class || ''}` }),
|
||||
inputPass: (p) => {
|
||||
const show = $(false);
|
||||
return [
|
||||
ui.input({ ...p, type: () => val(show) ? "text" : "password" }),
|
||||
ui.swap({ class: "ml-2 swap-rotate" }, [
|
||||
ui.checkbox({ checked: show }),
|
||||
ui.swapOn({}, ui.icon("icon-[lucide--eye]")),
|
||||
ui.swapOff({}, ui.icon("icon-[lucide--eye-off]"))
|
||||
])
|
||||
];
|
||||
},
|
||||
kbd: (p, c) => h("kbd", { ...p, class: `kbd ${p.class || ''}` }, c),
|
||||
label: (p, c) => h("span", { ...p, class: `label ${p.class || ''}` }, c),
|
||||
loading: (p) => h("span", { ...p, class: `loading loading-spinner ${p.class || ''}` }),
|
||||
menu: (p, c) => h("ul", { ...p, class: `menu ${p.class || ''}` }, c),
|
||||
menuItems: (p) => (p.items || []).map((i) => {
|
||||
if (i.items) {
|
||||
return h('li', {}, [
|
||||
h('details', { open: i.open || false }, [
|
||||
h('summary', {}, i.label),
|
||||
h('ul', { class: i.submenuClass || '' }, menuItems({ items: i.items }))
|
||||
])
|
||||
]);
|
||||
}
|
||||
return h('li', {}, i.href ? h('a', { href: i.href }, i.label) : i.label);
|
||||
}),
|
||||
modal: (p, c) => h("dialog", { ...p, class: `modal ${p.class || ''}` }, [c, h("form", { method: "dialog", class: "modal-backdrop" }, h("button", {}, "close"))]),
|
||||
modalBox: (p, c) => h("div", { ...p, class: `modal-box ${p.class || ''}` }, [h("form", { method: "dialog" }, h("button", { class: "btn btn-sm btn-circle btn-ghost absolute right-2 top-2" }, "✕")), c]),
|
||||
modalAction: (p, c) => h("div", { ...p, class: `modal-action ${p.class || ''}` }, c),
|
||||
navbar: (p, c) => h("div", { ...p, class: `navbar ${p.class || ''}` }, c),
|
||||
option: (p, c) => h("option", { ...p }, c),
|
||||
progress: (p) => h("progress", { ...p, class: `progress ${p.class || ''}` }),
|
||||
radial: (p) => h("div", { ...p, class: `radial-progress ${p.class || ''}`, style: `--value:${val(p.value) ?? 0}`, role: "progressbar" }, p.value ?? ""),
|
||||
radio: (p) => h("input", { ...p, type: "radio", class: `radio ${p.class || ''}` }),
|
||||
range: (p) => h("input", { ...p, type: "range", class: `range ${p.class || ''}` }),
|
||||
rating: (p) => h("div", { class: `rating ${p.class || ''}` },
|
||||
[...Array(p.count || 5)].map((_, i) =>
|
||||
h("input", {
|
||||
class: `mask ${p.mask || 'mask-star'} ${p.itemClass || ''}`,
|
||||
name: p.name,
|
||||
type: "radio",
|
||||
checked: () => val(p.value) === (p.offset ? i + p.offset : i),
|
||||
onclick: () => isF(p.value) ? p.value(i) : p.onChange?.(i)
|
||||
})
|
||||
)
|
||||
),
|
||||
search: (p) => ui.text({ ...p, type: "search", icon: p.icon ?? "icon-[lucide--search]" }),
|
||||
select: (p, c) => h("select", { ...p, class: `select ${p.class || ''}` }, c),
|
||||
stack: (p, c) => h("div", { ...p, class: `stack ${p.class || ''}` }, c),
|
||||
stat: (p, c) => h("div", { ...p, class: `stat ${p.class || ''}` }, c),
|
||||
statFigure: (p, c) => h("div", { ...p, class: `stat-figure ${p.class || ''}` }, c),
|
||||
statTitle: (p, c) => h("div", { ...p, class: `stat-title ${p.class || ''}` }, c),
|
||||
statValue: (p, c) => h("div", { ...p, class: `stat-value ${p.class || ''}` }, c),
|
||||
statDesc: (p, c) => h("div", { ...p, class: `stat-desc ${p.class || ''}` }, c),
|
||||
steps: (p, c) => h("ul", { ...p, class: `steps ${p.class || ''}` }, c),
|
||||
step: (p, c) => h("li", { ...p, class: `step ${p.class || ''}`, "data-content": p.dataContent }, c),
|
||||
swap: (p, c) => h("label", { ...p, class: `swap ${p.class || ''}` }, c),
|
||||
swapOn: (p, c) => h("div", { ...p, class: `swap-on ${p.class || ''}` }, c),
|
||||
swapOff: (p, c) => h("div", { ...p, class: `swap-off ${p.class || ''}` }, c),
|
||||
table: (p, c) => h("table", { ...p, class: `table ${p.class || ''}` }, c),
|
||||
tableHead: (p, c) => h("thead", { ...p, class: p.class || '' }, c),
|
||||
tableBody: (p, c) => h("tbody", { ...p, class: p.class || '' }, c),
|
||||
tableFoot: (p, c) => h("tfoot", { ...p, class: p.class || '' }, c),
|
||||
tableRow: (p, c) => h("tr", { ...p, class: p.class || '' }, c),
|
||||
tableTh: (p, c) => h("th", { ...p, class: p.class || '' }, c),
|
||||
tableTd: (p, c) => h("td", { ...p, class: p.class || '' }, c),
|
||||
tabs: (p) => h("div", { style: "display:contents" },
|
||||
h("div", { class: `tabs ${p.class || ''}` },
|
||||
(p.items || []).map((item, i) => [
|
||||
h("input", {
|
||||
type: "radio",
|
||||
name: p.name,
|
||||
class: `tab ${item.class || ''}`,
|
||||
"aria-label": item.label,
|
||||
checked: () => val(p.value) === i,
|
||||
onclick: () => isF(p.value) ? p.value(i) : p.onChange?.(i)
|
||||
}),
|
||||
item.closable && h("span", {
|
||||
class: "cursor-pointer text-xs",
|
||||
onclick: (e) => { e.stopPropagation(); isF(p.items) && p.items(p.items().filter((_, idx) => idx !== i)); }
|
||||
}, " ✕")
|
||||
])
|
||||
),
|
||||
h("div", { class: `tab-content ${p.contentClass || ''}` }, p.items[val(p.value)]?.content)
|
||||
),
|
||||
textarea: (p) => h("textarea", { ...p, class: `textarea ${p.class || ''}` }),
|
||||
textrotate: (p, c) => h("span", { ...p, class: `text-rotate ${p.class || ''}` }, h("span", {}, c)),
|
||||
theme: (p) => ui.toggle({ value: p?.value || "spdark", class: "theme-controller" }),
|
||||
timeline: (p, c) => h("ul", { ...p, class: `timeline ${p.class || ''}` }, c),
|
||||
timelineStart: (p, c) => h("div", { ...p, class: `timeline-start ${p.class || ''}` }, c),
|
||||
timelineMiddle: (p, c) => h("div", { ...p, class: `timeline-middle ${p.class || ''}` }, c),
|
||||
timelineEnd: (p, c) => h("div", { ...p, class: `timeline-end ${p.class || ''}` }, c),
|
||||
toggle: (p) => h("input", { ...p, type: "checkbox", class: `toggle ${p.class || ''}` }),
|
||||
tooltip: (p, c) => h('div', { class: `tooltip ${p.class || ''}`, "data-tip": p.tip }, c),
|
||||
validator: (p, c) => h("div", { ...p, class: `validator-hint ${p.class || ''}` }, c),
|
||||
};
|
||||
|
||||
export const calendar = p => {
|
||||
let [d, hv, sh, eh] = [$(new Date()), $(0), $(0), $(0)], now = new Date(),
|
||||
F = v => v?.toISOString().slice(0, 10),
|
||||
P = n => (n < 10 ? '0' : '') + n,
|
||||
M = (m, y = 0) => d(new Date(d().getFullYear() + y, d().getMonth() + m, 1)),
|
||||
V = () => typeof p.value == 'function' ? p.value() : p.value,
|
||||
G = () => typeof p.range == 'function' ? p.range() : p.range,
|
||||
L = dt => {
|
||||
let s = F(dt), v = V(), r = G();
|
||||
if (!r) return p.onChange?.(p.hour ? `${s}T${P(sh())}:00:00` : s);
|
||||
if (!v?.start || v.end) return p.onChange?.({ start: s, end: null, ...(p.hour && { startHour: sh() }) });
|
||||
let nv = s < v.start ? { start: s, end: v.start } : { start: v.start, end: s };
|
||||
p.onChange?.({ ...nv, ...(p.hour && { startHour: v.startHour ?? sh(), endHour: eh() }) });
|
||||
},
|
||||
I = ({ v, on }) => h('div', { class: 'flex-1 flex gap-2 items-center' }, [
|
||||
h('input', { type: 'range', min: 0, max: 23, value: v, class: 'range range-xs', oninput: e => on(+e.target.value) }),
|
||||
h('span', { class: 'text-sm font-mono' }, () => P(v()) + ':00')
|
||||
]);
|
||||
|
||||
return h('div', { class: `p-4 bg-base-100 border shadow-2xl rounded-box w-80 select-none ${p.class || ''}` }, [
|
||||
h('div', { class: 'flex justify-between items-center mb-4' }, [
|
||||
h('div', { class: 'flex' }, [['-1y', -1, 1], ['-1m', -1, 0]].map(([_, m, y]) => h('button', { class: 'btn btn-ghost btn-xs', onclick: () => M(m, y) }, h('span', { class: `icon-[lucide--chevron${y ? 's' : ''}-left]` })))),
|
||||
h('span', { class: 'font-bold uppercase' }, () => d().toLocaleString('es', { month: 'short', year: 'numeric' })),
|
||||
h('div', { class: 'flex' }, [[1, 0], [1, 1]].map(([m, y]) => h('button', { class: 'btn btn-ghost btn-xs', onclick: () => M(m, y) }, h('span', { class: `icon-[lucide--chevron${y ? 's' : ''}-right]` }))))
|
||||
]),
|
||||
h('div', { class: 'grid grid-cols-7 gap-1', onmouseleave: () => hv(null) }, [
|
||||
...'LMXJVSD'.split('').map(l => h('div', { class: 'text-[10px] opacity-40 font-bold text-center' }, l)),
|
||||
() => {
|
||||
let y = d().getFullYear(), m = d().getMonth(), first = (new Date(y, m, 1).getDay() + 6) % 7;
|
||||
return [...Array(first).fill(h('div')), ...Array(new Date(y, m + 1, 0).getDate()).keys()].map(i => {
|
||||
if (typeof i != 'number') return i;
|
||||
let day = i + 1, ds = F(new Date(y, m, day)), today = F(now) == ds;
|
||||
return h('button', {
|
||||
type: 'button', onclick: () => L(new Date(y, m, day)), onmouseenter: () => G() && hv(ds),
|
||||
class: () => {
|
||||
let v = V(), hov = hv(), s = v?.start || (typeof v == 'string' ? v.slice(0, 10) : 0),
|
||||
isE = v?.end == ds, isS = s == ds,
|
||||
inR = G() && v?.start && (v.end ? (ds > v.start && ds < v.end) : (hov && ((ds > s && ds <= hov) || (ds < s && ds >= hov))));
|
||||
return `btn btn-xs p-0 aspect-square min-h-0 h-auto font-normal relative ${isS || isE ? 'btn-primary z-10' : inR ? 'bg-primary/20 border-none rounded-none' : 'btn-ghost'} ${today ? 'ring-1 ring-primary font-black' : ''}`
|
||||
}
|
||||
}, day)
|
||||
})
|
||||
}
|
||||
]),
|
||||
p.hour && h('div', { class: 'mt-3 pt-2 border-t flex gap-4' }, G() ? [I({ v: sh, on: sh }), I({ v: eh, on: eh })] : [I({ v: sh, on: sh })])
|
||||
])
|
||||
}
|
||||
|
||||
export const pallete = p => {
|
||||
let L = s => (s || '').toLowerCase(),
|
||||
C = ['#000', '#1A1A1A', '#333', '#4D4D4D', '#666', '#808080', '#B3B3B3', '#FFF', '#450a0a', '#7f1d1d', '#991b1b', '#b91c1c', '#dc2626', '#ef4444', '#f87171', '#fca5a5', '#431407', '#7c2d12', '#9a3412', '#c2410c', '#ea580c', '#f97316', '#fb923c', '#ffedd5', '#713f12', '#a16207', '#ca8a04', '#eab308', '#facc15', '#fde047', '#fef08a', '#fff9c4', '#064e3b', '#065f46', '#059669', '#10b981', '#34d399', '#4ade80', '#84cc16', '#d9f99d', '#082f49', '#075985', '#0284c7', '#0ea5e9', '#38bdf8', '#7dd3fc', '#22d3ee', '#cffafe', '#1e1b4b', '#312e81', '#4338ca', '#4f46e5', '#6366f1', '#818cf8', '#a5b4fc', '#e0e7ff', '#2e1065', '#4c1d95', '#6d28d9', '#7c3aed', '#8b5cf6', '#a855f7', '#d946ef', '#fae8ff'];
|
||||
|
||||
return h('div', { class: `p-3 bg-base-100 rounded-box shadow w-64 ${p.class || ''}` },
|
||||
h('div', { class: 'grid grid-cols-8 gap-1' },
|
||||
C.map(c => h('button', {
|
||||
type: 'button',
|
||||
style: `background:${c}`,
|
||||
onclick: () => (isF(p.value) ? p.value(c) : p.onchange?.(c), hide()),
|
||||
class: () => `size-6 rounded-sm transition-all hover:scale-125 hover:z-10 active:scale-95 border border-black/5 p-0 min-h-0 ${L(val(p.value)) == L(c) ? 'ring-2 ring-offset-1 ring-primary z-10 scale-110' : ''}`
|
||||
}))
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const toast = (m, t = "alert-success", d = 3500) => {
|
||||
let C = document.getElementById("stc"), T, E, w = h("div", { style: "display:contents" });
|
||||
if (!C) document.body.append(C = h("div", { id: "stc", class: "fixed top-0 right-0 z-[9999] p-4 flex flex-col items-end gap-2 pointer-events-none" }));
|
||||
C.append(w);
|
||||
|
||||
const i = mount(() => {
|
||||
let v = $(0), l = $(0);
|
||||
E = () => l() || (l(1), clearTimeout(T), setTimeout(() => (i.destroy(), w.remove(), C.firstChild || C.remove()), 300));
|
||||
setTimeout(() => v(1));
|
||||
return h("div", {
|
||||
class: () => `alert alert-soft ${t} shadow-lg transition-all duration-300 inline-flex w-auto pointer-events-auto ${l() ? 'translate-x-full opacity-0' : v() ? 'translate-x-0 opacity-100' : 'translate-x-10 opacity-0'}`
|
||||
}, [
|
||||
typeof m == 'function' ? m() : typeof m == 'string' ? h("span", m) : m,
|
||||
h("button", { class: "btn btn-xs btn-circle btn-ghost", onclick: E }, h("span", { class: "icon-[lucide--x]" }))
|
||||
])
|
||||
}, w);
|
||||
|
||||
if (d > 0) T = setTimeout(E, d);
|
||||
return E;
|
||||
};
|
||||
|
||||
window.ui = ui;
|
||||
window.toast = toast;
|
||||
window.calendar = calendar;
|
||||
window.pallete = pallete
|
||||
117
src/tailwind
Normal file
117
src/tailwind
Normal file
@@ -0,0 +1,117 @@
|
||||
const layout = [
|
||||
'join', 'join-vertical', 'lg:join-horizontal',
|
||||
'divider', 'divider-horizontal',
|
||||
'validator', 'validator-hint',
|
||||
'glass'
|
||||
]
|
||||
|
||||
const icons = [
|
||||
'icon-[lucide--calendar]', 'icon-[lucide--chevrons-left]',
|
||||
'icon-[lucide--chevron-left]', 'icon-[lucide--chevron-right]',
|
||||
'icon-[lucide--chevrons-right]', 'icon-[lucide--info]',
|
||||
'icon-[lucide--check-circle]', 'icon-[lucide--alert-triangle]',
|
||||
'icon-[lucide--alert-circle]', 'icon-[lucide--heart]',
|
||||
'icon-[lucide--upload]', 'icon-[lucide--x]', 'icon-[lucide--text]',
|
||||
'icon-[lucide--lock]', 'icon-[lucide--hash]', 'icon-[lucide--mail]',
|
||||
'icon-[lucide--search]', 'icon-[lucide--phone]', 'icon-[lucide--link]',
|
||||
'icon-[lucide--eye-off]', 'icon-[lucide--eye]'
|
||||
]
|
||||
|
||||
const inputs = [
|
||||
'input', 'input-bordered', 'input-ghost',
|
||||
'input-primary', 'input-secondary', 'input-accent',
|
||||
'input-info', 'input-success', 'input-warning', 'input-error',
|
||||
'input-xs', 'input-sm', 'input-md', 'input-lg',
|
||||
'floating-label'
|
||||
]
|
||||
|
||||
const alerts = [
|
||||
'alert', 'alert-info', 'alert-success', 'alert-warning', 'alert-error',
|
||||
'alert-soft', 'alert-outline', 'alert-dash'
|
||||
]
|
||||
|
||||
const avatars = [
|
||||
'avatar', 'avatar-group', 'avatar-online', 'avatar-offline', 'avatar-placeholder'
|
||||
]
|
||||
|
||||
const badges = [
|
||||
'badge', 'badge-primary', 'badge-secondary', 'badge-accent',
|
||||
'badge-info', 'badge-success', 'badge-warning', 'badge-error',
|
||||
'badge-outline', 'badge-soft', 'badge-dash',
|
||||
'badge-xs', 'badge-sm', 'badge-md', 'badge-lg'
|
||||
]
|
||||
|
||||
const buttons = [
|
||||
'btn', 'btn-primary', 'btn-secondary', 'btn-accent',
|
||||
'btn-ghost', 'btn-info', 'btn-success', 'btn-warning',
|
||||
'btn-error', 'btn-neutral',
|
||||
'btn-xs', 'btn-sm', 'btn-md', 'btn-lg', 'btn-xl',
|
||||
'btn-outline', 'btn-soft', 'btn-dash', 'btn-link',
|
||||
'btn-circle', 'btn-square', 'btn-wide', 'btn-block',
|
||||
'btn-active', 'btn-disabled'
|
||||
]
|
||||
|
||||
const checkboxes = [
|
||||
'checkbox', 'checkbox-primary', 'checkbox-secondary', 'checkbox-accent',
|
||||
'checkbox-info', 'checkbox-success', 'checkbox-warning', 'checkbox-error',
|
||||
'checkbox-xs', 'checkbox-sm', 'checkbox-md', 'checkbox-lg'
|
||||
]
|
||||
|
||||
const toggles = [
|
||||
'toggle', 'toggle-primary', 'toggle-secondary', 'toggle-accent',
|
||||
'toggle-xs', 'toggle-sm', 'toggle-md', 'toggle-lg'
|
||||
]
|
||||
|
||||
const chats = [
|
||||
'chat', 'chat-end', 'chat-start', 'chat-image',
|
||||
'chat-header', 'chat-footer', 'chat-bubble'
|
||||
]
|
||||
|
||||
const drawers = [
|
||||
'drawer', 'drawer-end', 'drawer-toggle', 'drawer-content',
|
||||
'drawer-side', 'drawer-overlay'
|
||||
]
|
||||
|
||||
const dropdowns = [
|
||||
'dropdown', 'dropdown-content', 'dropdown-end',
|
||||
'dropdown-top', 'dropdown-bottom', 'dropdown-left', 'dropdown-right'
|
||||
]
|
||||
|
||||
const misc = [
|
||||
'breadcrumbs', 'fab', 'fieldset', 'fieldset-legend',
|
||||
'indicator', 'indicator-item', 'menu', 'menu-dropdown', 'menu-dropdown-show',
|
||||
'kbd', 'kbd-xs', 'kbd-sm', 'kbd-md', 'kbd-lg', 'kbd-xl',
|
||||
'list', 'list-row', 'list-bullet', 'list-image', 'list-none',
|
||||
'mask', 'mask-star', 'mask-star-2', 'mask-heart', 'mask-circle',
|
||||
'modal', 'modal-box', 'modal-action', 'modal-backdrop',
|
||||
'modal-open', 'modal-middle', 'modal-top', 'modal-bottom',
|
||||
'navbar', 'navbar-start', 'navbar-center', 'navbar-end',
|
||||
'progress', 'progress-neutral', 'progress-primary', 'progress-secondary',
|
||||
'progress-accent', 'progress-info', 'progress-success',
|
||||
'progress-warning', 'progress-error', 'radial-progress',
|
||||
'radio', 'radio-primary', 'radio-secondary', 'radio-accent',
|
||||
'radio-info', 'radio-success', 'radio-warning', 'radio-error',
|
||||
'radio-xs', 'radio-sm', 'radio-md', 'radio-lg',
|
||||
'range', 'range-primary', 'range-secondary', 'range-accent',
|
||||
'range-info', 'range-success', 'range-warning', 'range-error',
|
||||
'range-xs', 'range-sm', 'range-md', 'range-lg',
|
||||
'rating', 'rating-half', 'rating-hidden',
|
||||
'select', 'select-bordered', 'select-primary', 'select-secondary',
|
||||
'select-accent', 'select-info', 'select-success',
|
||||
'select-warning', 'select-error',
|
||||
'select-xs', 'select-sm', 'select-md', 'select-lg',
|
||||
'stack', 'stack-top', 'stack-bottom', 'stack-start', 'stack-end',
|
||||
'stat', 'stat-figure', 'stat-title', 'stat-value', 'stat-desc',
|
||||
'swap', 'swap-on', 'swap-off', 'swap-active',
|
||||
'swap-rotate', 'swap-flip', 'swap-indeterminate',
|
||||
'table', 'table-zebra', 'table-pin-rows', 'table-pin-cols',
|
||||
'table-xs', 'table-sm', 'table-md', 'table-lg',
|
||||
'tabs', 'tabs-box', 'tabs-lift', 'tabs-border', 'tab', 'tab-content',
|
||||
'timeline', 'timeline-vertical', 'timeline-horizontal',
|
||||
'timeline-compact', 'timeline-start', 'timeline-middle',
|
||||
'timeline-end', 'timeline-box',
|
||||
'tooltip', 'tooltip-top', 'tooltip-bottom', 'tooltip-left', 'tooltip-right',
|
||||
'tooltip-primary', 'tooltip-secondary', 'tooltip-accent',
|
||||
'tooltip-info', 'tooltip-success', 'tooltip-warning', 'tooltip-error',
|
||||
'tooltip-open'
|
||||
]
|
||||
Reference in New Issue
Block a user