This commit is contained in:
13
dist/sigpro-ui.css
vendored
13
dist/sigpro-ui.css
vendored
@@ -3509,19 +3509,6 @@
|
|||||||
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='m18 16l4-4l-4-4M6 8l-4 4l4 4m8.5-12l-5 16'/%3E%3C/svg%3E");
|
--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\] {
|
.icon-\[lucide--eye-off\] {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
width: 1em;
|
width: 1em;
|
||||||
|
|||||||
256
dist/sigpro-ui.esm.js
vendored
256
dist/sigpro-ui.esm.js
vendored
@@ -13,9 +13,9 @@ var __export = (target, all) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-ui.js
|
||||||
var exports_sigpro_components = {};
|
var exports_sigpro_ui = {};
|
||||||
__export(exports_sigpro_components, {
|
__export(exports_sigpro_ui, {
|
||||||
Tooltip: () => Tooltip,
|
Tooltip: () => Tooltip,
|
||||||
Toggle: () => Toggle,
|
Toggle: () => Toggle,
|
||||||
Toast: () => Toast,
|
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 rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
||||||
var close = () => document.activeElement?.blur();
|
var close = () => document.activeElement?.blur();
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-ui.js
|
||||||
var Accordion = (p2) => {
|
var Accordion = (p2) => {
|
||||||
const name = p2.name || rand("acc");
|
const name = p2.name || rand("acc");
|
||||||
return K(p2.items, (it) => {
|
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 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);
|
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> `;
|
||||||
|
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> `;
|
||||||
|
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
|
// sigpro-locale.js
|
||||||
var i18n = {
|
var i18n = {
|
||||||
es: {
|
es: {
|
||||||
@@ -1185,7 +1430,8 @@ var tt = (t) => () => i18n[currentLocale()][t] || t;
|
|||||||
|
|
||||||
// index.js
|
// index.js
|
||||||
var Components = {
|
var Components = {
|
||||||
...exports_sigpro_components
|
...exports_sigpro_ui,
|
||||||
|
...exports_sigpro_editor
|
||||||
};
|
};
|
||||||
var Utils = {
|
var Utils = {
|
||||||
Locale,
|
Locale,
|
||||||
|
|||||||
8
dist/sigpro-ui.esm.min.js
vendored
8
dist/sigpro-ui.esm.min.js
vendored
File diff suppressed because one or more lines are too long
260
dist/sigpro-ui.js
vendored
260
dist/sigpro-ui.js
vendored
@@ -38,15 +38,15 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
// index.js
|
// index.js
|
||||||
var exports_sigpro_ui = {};
|
var exports_sigpro_ui2 = {};
|
||||||
__export(exports_sigpro_ui, {
|
__export(exports_sigpro_ui2, {
|
||||||
Utils: () => Utils,
|
Utils: () => Utils,
|
||||||
Components: () => Components
|
Components: () => Components
|
||||||
});
|
});
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-ui.js
|
||||||
var exports_sigpro_components = {};
|
var exports_sigpro_ui = {};
|
||||||
__export(exports_sigpro_components, {
|
__export(exports_sigpro_ui, {
|
||||||
Tooltip: () => Tooltip,
|
Tooltip: () => Tooltip,
|
||||||
Toggle: () => Toggle,
|
Toggle: () => Toggle,
|
||||||
Toast: () => Toast,
|
Toast: () => Toast,
|
||||||
@@ -560,7 +560,7 @@
|
|||||||
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
||||||
var close = () => document.activeElement?.blur();
|
var close = () => document.activeElement?.blur();
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-ui.js
|
||||||
var Accordion = (p2) => {
|
var Accordion = (p2) => {
|
||||||
const name = p2.name || rand("acc");
|
const name = p2.name || rand("acc");
|
||||||
return K(p2.items, (it) => {
|
return K(p2.items, (it) => {
|
||||||
@@ -1191,6 +1191,251 @@
|
|||||||
var Toggle = (p2) => O("input", { ...p2, type: "checkbox", class: cls("toggle", p2.class) });
|
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);
|
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> `;
|
||||||
|
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> `;
|
||||||
|
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
|
// sigpro-locale.js
|
||||||
var i18n = {
|
var i18n = {
|
||||||
es: {
|
es: {
|
||||||
@@ -1216,7 +1461,8 @@
|
|||||||
|
|
||||||
// index.js
|
// index.js
|
||||||
var Components = {
|
var Components = {
|
||||||
...exports_sigpro_components
|
...exports_sigpro_ui,
|
||||||
|
...exports_sigpro_editor
|
||||||
};
|
};
|
||||||
var Utils = {
|
var Utils = {
|
||||||
Locale,
|
Locale,
|
||||||
|
|||||||
2
dist/sigpro-ui.min.css
vendored
2
dist/sigpro-ui.min.css
vendored
File diff suppressed because one or more lines are too long
8
dist/sigpro-ui.min.js
vendored
8
dist/sigpro-ui.min.js
vendored
File diff suppressed because one or more lines are too long
2
docs/sigpro-ui.min.css
vendored
2
docs/sigpro-ui.min.css
vendored
File diff suppressed because one or more lines are too long
8
docs/sigpro-ui.min.js
vendored
8
docs/sigpro-ui.min.js
vendored
File diff suppressed because one or more lines are too long
6
index.js
6
index.js
@@ -1,10 +1,10 @@
|
|||||||
import * as All from './sigpro-components.js';
|
import * as All from './sigpro-ui.js';
|
||||||
// import * as Editor from './sigpro-editor.js';
|
import * as Editor from './sigpro-editor.js';
|
||||||
import { Locale, tt } from './sigpro-locale.js';
|
import { Locale, tt } from './sigpro-locale.js';
|
||||||
|
|
||||||
export const Components = {
|
export const Components = {
|
||||||
...All,
|
...All,
|
||||||
// ...Editor,
|
...Editor,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Utils = {
|
export const Utils = {
|
||||||
|
|||||||
@@ -125,8 +125,8 @@ export const Editor = (p) => {
|
|||||||
// GRUPO 2: LISTAS Y PÁRRAFO
|
// 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("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("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("outdent") }, 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("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("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" }),
|
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" }),
|
h("span", { class: "w-px h-5 bg-base-300 mx-1" }),
|
||||||
|
|
||||||
// GRUPO 4: UTILIDADES
|
// 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") }, h("span", { class: "icon-[lucide--undo-2]" })),
|
||||||
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") }, h("span", { class: "icon-[lucide--redo-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 ${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]" }))
|
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]" }))
|
||||||
|
|||||||
Reference in New Issue
Block a user