Include Editor
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 7s

This commit is contained in:
2026-04-27 18:09:59 +02:00
parent 953fae7bbc
commit 670e9fd8fe
11 changed files with 534 additions and 38 deletions

13
dist/sigpro-ui.css vendored
View File

@@ -3509,19 +3509,6 @@
mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m18 16l4-4l-4-4M6 8l-4 4l4 4m8.5-12l-5 16'/%3E%3C/svg%3E");
}
.icon-\[lucide--eraser\] {
display: inline-block;
width: 1em;
height: 1em;
background-color: currentColor;
-webkit-mask-image: var(--svg);
mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
--svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' width='24' height='24'%3E%3Cpath fill='none' stroke='black' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M21 21H8a2 2 0 0 1-1.42-.587l-3.994-3.999a2 2 0 0 1 0-2.828l10-10a2 2 0 0 1 2.829 0l5.999 6a2 2 0 0 1 0 2.828L12.834 21m-7.752-9.91l8.828 8.828'/%3E%3C/svg%3E");
}
.icon-\[lucide--eye-off\] {
display: inline-block;
width: 1em;

256
dist/sigpro-ui.esm.js vendored
View File

@@ -13,9 +13,9 @@ var __export = (target, all) => {
});
};
// sigpro-components.js
var exports_sigpro_components = {};
__export(exports_sigpro_components, {
// sigpro-ui.js
var exports_sigpro_ui = {};
__export(exports_sigpro_ui, {
Tooltip: () => Tooltip,
Toggle: () => Toggle,
Toast: () => Toast,
@@ -529,7 +529,7 @@ var filterBy = (items, query, field = "label", q2 = String(query).toLowerCase())
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
var close = () => document.activeElement?.blur();
// sigpro-components.js
// sigpro-ui.js
var Accordion = (p2) => {
const name = p2.name || rand("acc");
return K(p2.items, (it) => {
@@ -1160,6 +1160,251 @@ var Toast = (message, type = "alert-success", duration = 3500) => {
var Toggle = (p2) => O("input", { ...p2, type: "checkbox", class: cls("toggle", p2.class) });
var Tooltip = (p2, c) => O("div", { ...p2, class: cls("tooltip", p2.class), "data-tip": p2.tip }, c);
// sigpro-editor.js
var exports_sigpro_editor = {};
__export(exports_sigpro_editor, {
Editor: () => Editor
});
var Editor = (p2) => {
const { value, class: extraClass } = p2;
let editorRef = null;
let savedRange = null;
const isSource = S(false);
const source = S("");
const count = S(0);
const refreshTick = S(0);
const showEmojis = S(false);
const emojis = ["\uD83D\uDE00", "\uD83D\uDE0A", "\uD83D\uDE09", "\uD83E\uDDD0", "\uD83D\uDE2E", "\uD83E\uDD14", "\uD83D\uDE05", "\uD83D\uDE02", "\uD83D\uDE0D", "\uD83D\uDE18", "\uD83E\uDD70", "\uD83D\uDC4D", "\uD83D\uDC4E", "\uD83D\uDC4C", "\uD83E\uDD1D", "\uD83E\uDD1E", "\uD83D\uDC4B", "\uD83D\uDC4F", "\uD83D\uDE4C", "\uD83D\uDE4F", "\uD83D\uDCAA", "☝️", "\uD83D\uDC47", "\uD83D\uDC48", "\uD83D\uDC49", "\uD83D\uDD95", "✅", "⚠️", "\uD83D\uDE80", "\uD83D\uDCE2", "✉️", "❤️"];
const saveSelection = () => {
const sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount)
savedRange = sel.getRangeAt(0);
};
const restoreSelection = () => {
if (savedRange) {
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(savedRange);
}
};
const triggerRefresh = () => {
refreshTick(refreshTick() + 1);
if (editorRef)
count(editorRef.innerText.length);
};
const notify = () => {
if (!editorRef)
return;
const html = editorRef.innerHTML;
if (isFn(value))
value(html);
else
p2.onchange?.(html);
triggerRefresh();
};
const exec = (cmd, val = null) => {
if (!editorRef)
return;
editorRef.focus();
if (savedRange)
restoreSelection();
document.execCommand(cmd, false, val);
savedRange = null;
notify();
};
const openLightbox = (src) => {
const overlay = document.createElement("div");
overlay.style = `position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:9999;display:flex;align-items:center;justify-content:center;cursor:zoom-out;`;
const img = document.createElement("img");
img.src = src;
img.style = `max-width:95%;max-height:95%;box-shadow:0 0 30px rgba(0,0,0,0.5);border-radius:4px;`;
overlay.onclick = () => document.body.removeChild(overlay);
overlay.appendChild(img);
document.body.appendChild(overlay);
};
const handleUpload = (file) => {
if (!file)
return;
const reader = new FileReader;
reader.onload = (re) => {
if (file.type.startsWith("image/")) {
const imgHtml = `<div style="display:inline-block; resize:both; overflow:hidden; vertical-align:bottom; line-height:0; width:200px; height:auto; border:1px dashed #ccc; padding:2px; cursor:pointer;" class="resizable-img-container"><img src="${re.target.result}" style="width:100%; height:100%; object-fit:contain; pointer-events:none;"></div>&nbsp;`;
exec("insertHTML", imgHtml);
} else {
const linkHtml = `<a href="${re.target.result}" download="${file.name}" contenteditable="false" style="display:inline-flex; align-items:center; gap:5px; padding:4px 8px; border:1px solid #ccc; border-radius:4px; background:#f9f9f9; text-decoration:none; color:#333; font-size:12px; margin:2px; cursor:pointer;"><span class="icon-[lucide--paperclip] w-3 h-3"></span>${file.name}</a>&nbsp;`;
exec("insertHTML", linkHtml);
}
};
reader.readAsDataURL(file);
};
const queryState = (cmd, val = null) => {
refreshTick();
if (!editorRef || isSource())
return false;
try {
if (cmd === "formatBlock") {
let node = window.getSelection().getRangeAt(0).commonAncestorContainer;
while (node && node !== editorRef) {
if (node.nodeType === 1 && node.tagName === val)
return true;
node = node.parentNode;
}
return false;
}
return document.queryCommandState(cmd);
} catch (e) {
return false;
}
};
const toolbar = O("div", { class: "flex flex-wrap items-center gap-1 p-2 border-b border-base-300 bg-base-200 sticky top-0 z-20" }, [
O("div", { class: "flex flex-wrap gap-1 flex-1 items-center" }, [
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("bold") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("bold") }, O("span", { class: "icon-[lucide--bold]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("italic") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("italic") }, O("span", { class: "icon-[lucide--italic]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("underline") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("underline") }, O("span", { class: "icon-[lucide--underline]" })),
O("input", { type: "color", class: "w-5 h-5 p-0 border-0 bg-transparent cursor-pointer", oninput: (e) => exec("foreColor", e.target.value) }),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyLeft")
}, O("span", { class: "icon-[lucide--align-left]" })),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyCenter")
}, O("span", { class: "icon-[lucide--align-center]" })),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyRight")
}, O("span", { class: "icon-[lucide--align-right]" })),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertUnorderedList") }, O("span", { class: "icon-[lucide--list]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertOrderedList") }, O("span", { class: "icon-[lucide--list-ordered]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("outdent") }, O("span", { class: "icon-[lucide--indent-decrease]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("indent") }, O("span", { class: "icon-[lucide--indent-increase]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("formatBlock", "BLOCKQUOTE") ? "btn-active" : ""}`, onclick: () => exec("formatBlock", queryState("formatBlock", "BLOCKQUOTE") ? "P" : "BLOCKQUOTE") }, O("span", { class: "icon-[lucide--quote]" })),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => {
const url = window.prompt("URL:");
if (url)
exec("createLink", url);
} }, O("span", { class: "icon-[lucide--link]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => {
const input2 = document.createElement("input");
input2.type = "file";
input2.onchange = (e) => handleUpload(e.target.files[0]);
input2.click();
} }, O("span", { class: "icon-[lucide--paperclip]" })),
O("div", { class: "relative" }, [
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: (e) => {
e.stopPropagation();
saveSelection();
showEmojis(!showEmojis());
} }, O("span", { class: "icon-[lucide--smile]" })),
O("div", { class: "absolute top-full left-0 mt-1 p-2 bg-base-100 border border-base-300 shadow-xl rounded-box w-52 z-50 flex flex-wrap gap-1", style: () => showEmojis() ? "display:flex" : "display:none" }, emojis.map((emo) => O("span", { class: "cursor-pointer hover:bg-base-200 p-1 rounded text-lg", onclick: (e) => {
e.stopPropagation();
exec("insertText", emo);
showEmojis(false);
} }, emo)))
]),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("undo") }, O("span", { class: "icon-[lucide--undo-2]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("redo") }, O("span", { class: "icon-[lucide--redo-2]" }))
]),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${isSource() ? "btn-active" : ""}`, onclick: () => {
if (!isSource())
source(editorRef?.innerHTML || "");
else if (editorRef) {
editorRef.innerHTML = source();
notify();
}
isSource(!isSource());
} }, O("span", { class: "icon-[lucide--code-2]" }))
]);
if (typeof document !== "undefined" && !document.getElementById("editor-styles")) {
const style = document.createElement("style");
style.id = "editor-styles";
style.textContent = `
[contenteditable="true"] div,
[contenteditable="true"] p {
margin: 0;
padding: 0;
}
`;
document.head.appendChild(style);
}
return O("div", { class: cls("border border-base-300 rounded-box bg-base-100 overflow-hidden shadow-sm flex flex-col", extraClass) }, [
toolbar,
O("div", { class: "relative flex-1 flex flex-col", onclick: () => showEmojis(false) }, [
O("div", {
ref: (el) => {
if (!editorRef && el) {
editorRef = el;
el.innerHTML = get(value) || "";
document.execCommand("defaultParagraphSeparator", false, "br");
el.addEventListener("click", (e) => {
const container = e.target.closest(".resizable-img-container");
if (container) {
const img = container.querySelector("img");
if (img)
openLightbox(img.src);
}
});
}
},
style: () => `min-height:22rem;${isSource() ? "display:none" : ""}`,
class: "p-4 outline-none text-base-content leading-relaxed [&>div]:m-0 [&>p]:m-0 [&>div]:min-h-[1em] [&_.resizable-img-container]:hover:border-primary [&_blockquote]:border-l-4 [&_blockquote]:border-base-300 [&_blockquote]:pl-4 [&_blockquote]:italic [&_ul]:list-disc [&_ul]:pl-8 [&_ol]:list-decimal [&_ol]:pl-8",
contenteditable: "true",
oninput: notify,
onkeydown: (e) => {
if (e.key === "Tab") {
e.preventDefault();
exec("indent");
}
},
onkeyup: () => {
triggerRefresh();
saveSelection();
},
onclick: (e) => {
triggerRefresh();
saveSelection();
e.stopPropagation();
},
onmouseup: () => {
notify();
saveSelection();
},
onpaste: (e) => {
e.preventDefault();
const text = e.clipboardData.getData("text/plain");
exec("insertText", text);
},
ondragover: (e) => e.preventDefault(),
ondrop: (e) => {
e.preventDefault();
handleUpload(e.dataTransfer.files[0]);
}
}),
O("textarea", {
class: "w-full flex-1 min-h-[22rem] p-4 outline-none font-mono text-sm bg-base-200 border-0",
style: () => isSource() ? "" : "display:none",
value: source,
oninput: (e) => {
source(e.target.value);
if (editorRef)
editorRef.innerHTML = e.target.value;
p2.onchange?.(e.target.value);
}
})
]),
O("div", { class: "px-3 py-1 border-t border-base-300 bg-base-100/50 text-[10px] text-right text-base-content/60 italic" }, [
O("span", () => `${count()} caracteres`)
])
]);
};
// sigpro-locale.js
var i18n = {
es: {
@@ -1185,7 +1430,8 @@ var tt = (t) => () => i18n[currentLocale()][t] || t;
// index.js
var Components = {
...exports_sigpro_components
...exports_sigpro_ui,
...exports_sigpro_editor
};
var Utils = {
Locale,

File diff suppressed because one or more lines are too long

260
dist/sigpro-ui.js vendored
View File

@@ -38,15 +38,15 @@
};
// index.js
var exports_sigpro_ui = {};
__export(exports_sigpro_ui, {
var exports_sigpro_ui2 = {};
__export(exports_sigpro_ui2, {
Utils: () => Utils,
Components: () => Components
});
// sigpro-components.js
var exports_sigpro_components = {};
__export(exports_sigpro_components, {
// sigpro-ui.js
var exports_sigpro_ui = {};
__export(exports_sigpro_ui, {
Tooltip: () => Tooltip,
Toggle: () => Toggle,
Toast: () => Toast,
@@ -560,7 +560,7 @@
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
var close = () => document.activeElement?.blur();
// sigpro-components.js
// sigpro-ui.js
var Accordion = (p2) => {
const name = p2.name || rand("acc");
return K(p2.items, (it) => {
@@ -1191,6 +1191,251 @@
var Toggle = (p2) => O("input", { ...p2, type: "checkbox", class: cls("toggle", p2.class) });
var Tooltip = (p2, c) => O("div", { ...p2, class: cls("tooltip", p2.class), "data-tip": p2.tip }, c);
// sigpro-editor.js
var exports_sigpro_editor = {};
__export(exports_sigpro_editor, {
Editor: () => Editor
});
var Editor = (p2) => {
const { value, class: extraClass } = p2;
let editorRef = null;
let savedRange = null;
const isSource = S(false);
const source = S("");
const count = S(0);
const refreshTick = S(0);
const showEmojis = S(false);
const emojis = ["\uD83D\uDE00", "\uD83D\uDE0A", "\uD83D\uDE09", "\uD83E\uDDD0", "\uD83D\uDE2E", "\uD83E\uDD14", "\uD83D\uDE05", "\uD83D\uDE02", "\uD83D\uDE0D", "\uD83D\uDE18", "\uD83E\uDD70", "\uD83D\uDC4D", "\uD83D\uDC4E", "\uD83D\uDC4C", "\uD83E\uDD1D", "\uD83E\uDD1E", "\uD83D\uDC4B", "\uD83D\uDC4F", "\uD83D\uDE4C", "\uD83D\uDE4F", "\uD83D\uDCAA", "☝️", "\uD83D\uDC47", "\uD83D\uDC48", "\uD83D\uDC49", "\uD83D\uDD95", "✅", "⚠️", "\uD83D\uDE80", "\uD83D\uDCE2", "✉️", "❤️"];
const saveSelection = () => {
const sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount)
savedRange = sel.getRangeAt(0);
};
const restoreSelection = () => {
if (savedRange) {
const sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(savedRange);
}
};
const triggerRefresh = () => {
refreshTick(refreshTick() + 1);
if (editorRef)
count(editorRef.innerText.length);
};
const notify = () => {
if (!editorRef)
return;
const html = editorRef.innerHTML;
if (isFn(value))
value(html);
else
p2.onchange?.(html);
triggerRefresh();
};
const exec = (cmd, val = null) => {
if (!editorRef)
return;
editorRef.focus();
if (savedRange)
restoreSelection();
document.execCommand(cmd, false, val);
savedRange = null;
notify();
};
const openLightbox = (src) => {
const overlay = document.createElement("div");
overlay.style = `position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.9);z-index:9999;display:flex;align-items:center;justify-content:center;cursor:zoom-out;`;
const img = document.createElement("img");
img.src = src;
img.style = `max-width:95%;max-height:95%;box-shadow:0 0 30px rgba(0,0,0,0.5);border-radius:4px;`;
overlay.onclick = () => document.body.removeChild(overlay);
overlay.appendChild(img);
document.body.appendChild(overlay);
};
const handleUpload = (file) => {
if (!file)
return;
const reader = new FileReader;
reader.onload = (re) => {
if (file.type.startsWith("image/")) {
const imgHtml = `<div style="display:inline-block; resize:both; overflow:hidden; vertical-align:bottom; line-height:0; width:200px; height:auto; border:1px dashed #ccc; padding:2px; cursor:pointer;" class="resizable-img-container"><img src="${re.target.result}" style="width:100%; height:100%; object-fit:contain; pointer-events:none;"></div>&nbsp;`;
exec("insertHTML", imgHtml);
} else {
const linkHtml = `<a href="${re.target.result}" download="${file.name}" contenteditable="false" style="display:inline-flex; align-items:center; gap:5px; padding:4px 8px; border:1px solid #ccc; border-radius:4px; background:#f9f9f9; text-decoration:none; color:#333; font-size:12px; margin:2px; cursor:pointer;"><span class="icon-[lucide--paperclip] w-3 h-3"></span>${file.name}</a>&nbsp;`;
exec("insertHTML", linkHtml);
}
};
reader.readAsDataURL(file);
};
const queryState = (cmd, val = null) => {
refreshTick();
if (!editorRef || isSource())
return false;
try {
if (cmd === "formatBlock") {
let node = window.getSelection().getRangeAt(0).commonAncestorContainer;
while (node && node !== editorRef) {
if (node.nodeType === 1 && node.tagName === val)
return true;
node = node.parentNode;
}
return false;
}
return document.queryCommandState(cmd);
} catch (e) {
return false;
}
};
const toolbar = O("div", { class: "flex flex-wrap items-center gap-1 p-2 border-b border-base-300 bg-base-200 sticky top-0 z-20" }, [
O("div", { class: "flex flex-wrap gap-1 flex-1 items-center" }, [
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("bold") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("bold") }, O("span", { class: "icon-[lucide--bold]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("italic") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("italic") }, O("span", { class: "icon-[lucide--italic]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("underline") ? "btn-active bg-primary/20" : ""}`, onclick: () => exec("underline") }, O("span", { class: "icon-[lucide--underline]" })),
O("input", { type: "color", class: "w-5 h-5 p-0 border-0 bg-transparent cursor-pointer", oninput: (e) => exec("foreColor", e.target.value) }),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyLeft")
}, O("span", { class: "icon-[lucide--align-left]" })),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyCenter")
}, O("span", { class: "icon-[lucide--align-center]" })),
O("button", {
type: "button",
class: "btn btn-ghost btn-xs",
onclick: () => exec("justifyRight")
}, O("span", { class: "icon-[lucide--align-right]" })),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertUnorderedList") }, O("span", { class: "icon-[lucide--list]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertOrderedList") }, O("span", { class: "icon-[lucide--list-ordered]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("outdent") }, O("span", { class: "icon-[lucide--indent-decrease]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("indent") }, O("span", { class: "icon-[lucide--indent-increase]" })),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState("formatBlock", "BLOCKQUOTE") ? "btn-active" : ""}`, onclick: () => exec("formatBlock", queryState("formatBlock", "BLOCKQUOTE") ? "P" : "BLOCKQUOTE") }, O("span", { class: "icon-[lucide--quote]" })),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => {
const url = window.prompt("URL:");
if (url)
exec("createLink", url);
} }, O("span", { class: "icon-[lucide--link]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => {
const input2 = document.createElement("input");
input2.type = "file";
input2.onchange = (e) => handleUpload(e.target.files[0]);
input2.click();
} }, O("span", { class: "icon-[lucide--paperclip]" })),
O("div", { class: "relative" }, [
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: (e) => {
e.stopPropagation();
saveSelection();
showEmojis(!showEmojis());
} }, O("span", { class: "icon-[lucide--smile]" })),
O("div", { class: "absolute top-full left-0 mt-1 p-2 bg-base-100 border border-base-300 shadow-xl rounded-box w-52 z-50 flex flex-wrap gap-1", style: () => showEmojis() ? "display:flex" : "display:none" }, emojis.map((emo) => O("span", { class: "cursor-pointer hover:bg-base-200 p-1 rounded text-lg", onclick: (e) => {
e.stopPropagation();
exec("insertText", emo);
showEmojis(false);
} }, emo)))
]),
O("span", { class: "w-px h-5 bg-base-300 mx-1" }),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("undo") }, O("span", { class: "icon-[lucide--undo-2]" })),
O("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("redo") }, O("span", { class: "icon-[lucide--redo-2]" }))
]),
O("button", { type: "button", class: () => `btn btn-ghost btn-xs ${isSource() ? "btn-active" : ""}`, onclick: () => {
if (!isSource())
source(editorRef?.innerHTML || "");
else if (editorRef) {
editorRef.innerHTML = source();
notify();
}
isSource(!isSource());
} }, O("span", { class: "icon-[lucide--code-2]" }))
]);
if (typeof document !== "undefined" && !document.getElementById("editor-styles")) {
const style = document.createElement("style");
style.id = "editor-styles";
style.textContent = `
[contenteditable="true"] div,
[contenteditable="true"] p {
margin: 0;
padding: 0;
}
`;
document.head.appendChild(style);
}
return O("div", { class: cls("border border-base-300 rounded-box bg-base-100 overflow-hidden shadow-sm flex flex-col", extraClass) }, [
toolbar,
O("div", { class: "relative flex-1 flex flex-col", onclick: () => showEmojis(false) }, [
O("div", {
ref: (el) => {
if (!editorRef && el) {
editorRef = el;
el.innerHTML = get(value) || "";
document.execCommand("defaultParagraphSeparator", false, "br");
el.addEventListener("click", (e) => {
const container = e.target.closest(".resizable-img-container");
if (container) {
const img = container.querySelector("img");
if (img)
openLightbox(img.src);
}
});
}
},
style: () => `min-height:22rem;${isSource() ? "display:none" : ""}`,
class: "p-4 outline-none text-base-content leading-relaxed [&>div]:m-0 [&>p]:m-0 [&>div]:min-h-[1em] [&_.resizable-img-container]:hover:border-primary [&_blockquote]:border-l-4 [&_blockquote]:border-base-300 [&_blockquote]:pl-4 [&_blockquote]:italic [&_ul]:list-disc [&_ul]:pl-8 [&_ol]:list-decimal [&_ol]:pl-8",
contenteditable: "true",
oninput: notify,
onkeydown: (e) => {
if (e.key === "Tab") {
e.preventDefault();
exec("indent");
}
},
onkeyup: () => {
triggerRefresh();
saveSelection();
},
onclick: (e) => {
triggerRefresh();
saveSelection();
e.stopPropagation();
},
onmouseup: () => {
notify();
saveSelection();
},
onpaste: (e) => {
e.preventDefault();
const text = e.clipboardData.getData("text/plain");
exec("insertText", text);
},
ondragover: (e) => e.preventDefault(),
ondrop: (e) => {
e.preventDefault();
handleUpload(e.dataTransfer.files[0]);
}
}),
O("textarea", {
class: "w-full flex-1 min-h-[22rem] p-4 outline-none font-mono text-sm bg-base-200 border-0",
style: () => isSource() ? "" : "display:none",
value: source,
oninput: (e) => {
source(e.target.value);
if (editorRef)
editorRef.innerHTML = e.target.value;
p2.onchange?.(e.target.value);
}
})
]),
O("div", { class: "px-3 py-1 border-t border-base-300 bg-base-100/50 text-[10px] text-right text-base-content/60 italic" }, [
O("span", () => `${count()} caracteres`)
])
]);
};
// sigpro-locale.js
var i18n = {
es: {
@@ -1216,7 +1461,8 @@
// index.js
var Components = {
...exports_sigpro_components
...exports_sigpro_ui,
...exports_sigpro_editor
};
var Utils = {
Locale,

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,10 +1,10 @@
import * as All from './sigpro-components.js';
// import * as Editor from './sigpro-editor.js';
import * as All from './sigpro-ui.js';
import * as Editor from './sigpro-editor.js';
import { Locale, tt } from './sigpro-locale.js';
export const Components = {
...All,
// ...Editor,
...Editor,
};
export const Utils = {

View File

@@ -125,8 +125,8 @@ export const Editor = (p) => {
// GRUPO 2: LISTAS Y PÁRRAFO
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertUnorderedList") }, h("span", { class: "icon-[lucide--list]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("insertOrderedList") }, h("span", { class: "icon-[lucide--list-ordered]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("outdent"), title: "Mover izquierda" }, h("span", { class: "icon-[lucide--indent-decrease]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("indent"), title: "Mover derecha (Tab)" }, h("span", { class: "icon-[lucide--indent-increase]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("outdent") }, h("span", { class: "icon-[lucide--indent-decrease]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("indent") }, h("span", { class: "icon-[lucide--indent-increase]" })),
h("button", { type: "button", class: () => `btn btn-ghost btn-xs ${queryState('formatBlock', 'BLOCKQUOTE') ? 'btn-active' : ''}`, onclick: () => exec("formatBlock", queryState('formatBlock', 'BLOCKQUOTE') ? 'P' : 'BLOCKQUOTE') }, h("span", { class: "icon-[lucide--quote]" })),
h("span", { class: "w-px h-5 bg-base-300 mx-1" }),
@@ -144,9 +144,8 @@ export const Editor = (p) => {
h("span", { class: "w-px h-5 bg-base-300 mx-1" }),
// GRUPO 4: UTILIDADES
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("removeFormat") }, h("span", { class: "icon-[lucide--eraser]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("undo"), title: "Deshacer" }, h("span", { class: "icon-[lucide--undo-2]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("redo"), title: "Rehacer" }, h("span", { class: "icon-[lucide--redo-2]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("undo") }, h("span", { class: "icon-[lucide--undo-2]" })),
h("button", { type: "button", class: "btn btn-ghost btn-xs", onclick: () => exec("redo") }, h("span", { class: "icon-[lucide--redo-2]" })),
]),
h("button", { type: "button", class: () => `btn btn-ghost btn-xs ${isSource() ? 'btn-active' : ''}`, onclick: () => { if (!isSource()) source(editorRef?.innerHTML || ""); else if (editorRef) { editorRef.innerHTML = source(); notify(); }; isSource(!isSource()) } }, h("span", { class: "icon-[lucide--code-2]" }))