Commit 0c5bf2ca authored by jan.koester's avatar jan.koester
Browse files

test

parent ed718019
Loading
Loading
Loading
Loading
+123 −0
Original line number Diff line number Diff line
@@ -395,6 +395,129 @@ body {
    padding-top: 4px;
}

/* Rich Text Editor */
.rte-wrap {
    border: 1px solid var(--border);
    border-radius: 3px;
    overflow: hidden;
}

.rte-toolbar {
    display: flex;
    flex-wrap: wrap;
    gap: 1px;
    padding: 3px;
    background: var(--bg-tertiary);
    border-bottom: 1px solid var(--border);
    align-items: center;
}

.rte-btn {
    background: none;
    border: 1px solid transparent;
    color: var(--text-primary);
    cursor: pointer;
    padding: 2px 5px;
    font-size: 12px;
    border-radius: 2px;
    min-width: 24px;
    height: 24px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: inherit;
}

.rte-btn:hover {
    background: var(--bg-primary);
    border-color: var(--border);
}

.rte-btn.active {
    background: var(--accent);
    color: var(--bg-primary);
}

.rte-sep {
    width: 1px;
    height: 18px;
    background: var(--border);
    margin: 0 2px;
    display: inline-block;
}

.rte-editor {
    min-height: 120px;
    max-height: 400px;
    overflow-y: auto;
    padding: 8px;
    background: var(--bg-primary);
    color: var(--text-primary);
    font-size: 13px;
    line-height: 1.5;
    outline: none;
}

.rte-editor:focus {
    box-shadow: inset 0 0 0 1px var(--accent);
}

.rte-editor table {
    border-collapse: collapse;
    width: 100%;
    margin: 4px 0;
}

.rte-editor th,
.rte-editor td {
    border: 1px solid var(--border);
    padding: 4px 6px;
    min-width: 30px;
}

.rte-editor th {
    background: var(--bg-tertiary);
    font-weight: 600;
}

.rte-editor h1, .rte-editor h2, .rte-editor h3, .rte-editor h4 {
    margin: 0.3em 0;
}

.rte-editor ul, .rte-editor ol {
    padding-left: 1.5em;
    margin: 0.3em 0;
}

.rte-editor a {
    color: var(--accent);
}

.rte-source {
    width: 100%;
    min-height: 120px;
    padding: 8px;
    background: var(--bg-primary);
    color: var(--text-primary);
    border: none;
    font-family: monospace;
    font-size: 12px;
    resize: vertical;
    box-sizing: border-box;
}

.rte-color-input {
    position: absolute;
    left: 0;
    top: 100%;
    width: 0;
    height: 0;
    padding: 0;
    border: 0;
    opacity: 0;
    pointer-events: none;
}

/* Dialogs */
dialog {
    background: var(--bg-secondary);
+185 −1
Original line number Diff line number Diff line
@@ -193,10 +193,194 @@ var PropertiesPanel = (function() {
                    input.value = value;
                    input.placeholder = field.placeholder || '#000000 oder var(--name)';
                } else if (field.type === 'html' || field.type === 'richtext') {
                    var rteWrap = document.createElement('div');
                    rteWrap.className = 'rte-wrap';

                    // Toolbar
                    var toolbar = document.createElement('div');
                    toolbar.className = 'rte-toolbar';

                    var toolbarDefs = [
                        { cmd: 'bold', icon: 'B', title: 'Fett', style: 'font-weight:bold' },
                        { cmd: 'italic', icon: 'I', title: 'Kursiv', style: 'font-style:italic' },
                        { cmd: 'underline', icon: 'U', title: 'Unterstrichen', style: 'text-decoration:underline' },
                        { cmd: 'strikeThrough', icon: 'S', title: 'Durchgestrichen', style: 'text-decoration:line-through' },
                        { sep: true },
                        { cmd: 'formatBlock', val: 'h1', icon: 'H1', title: 'Überschrift 1' },
                        { cmd: 'formatBlock', val: 'h2', icon: 'H2', title: 'Überschrift 2' },
                        { cmd: 'formatBlock', val: 'h3', icon: 'H3', title: 'Überschrift 3' },
                        { cmd: 'formatBlock', val: 'h4', icon: 'H4', title: 'Überschrift 4' },
                        { cmd: 'formatBlock', val: 'p', icon: 'P', title: 'Absatz' },
                        { sep: true },
                        { cmd: 'insertUnorderedList', icon: '\u2022', title: 'Aufzählung' },
                        { cmd: 'insertOrderedList', icon: '1.', title: 'Nummerierung' },
                        { sep: true },
                        { cmd: 'justifyLeft', icon: '\u2261', title: 'Links' },
                        { cmd: 'justifyCenter', icon: '\u2263', title: 'Zentriert' },
                        { cmd: 'justifyRight', icon: '\u2262', title: 'Rechts' },
                        { sep: true },
                        { cmd: 'createLink', icon: '\uD83D\uDD17', title: 'Link einfügen', prompt: true },
                        { cmd: 'unlink', icon: '\u2718', title: 'Link entfernen' },
                        { sep: true },
                        { custom: 'foreColor', icon: 'A\u25BC', title: 'Textfarbe' },
                        { custom: 'table', icon: '\u25A6', title: 'Tabelle einfügen' },
                        { sep: true },
                        { cmd: 'removeFormat', icon: '\u2205', title: 'Formatierung entfernen' },
                        { custom: 'source', icon: '</>', title: 'Quelltext' }
                    ];

                    var editorDiv = document.createElement('div');
                    editorDiv.className = 'rte-editor';
                    editorDiv.contentEditable = 'true';
                    editorDiv.innerHTML = value;

                    var hiddenInput = document.createElement('input');
                    hiddenInput.type = 'hidden';
                    hiddenInput.name = field.key;
                    hiddenInput.value = value;

                    var sourceMode = false;
                    var sourceArea = document.createElement('textarea');
                    sourceArea.className = 'rte-source';
                    sourceArea.style.display = 'none';
                    sourceArea.rows = 8;

                    // Sync editor -> hidden input
                    editorDiv.addEventListener('input', function() {
                        hiddenInput.value = editorDiv.innerHTML;
                    });
                    sourceArea.addEventListener('input', function() {
                        hiddenInput.value = sourceArea.value;
                    });

                    for (var ti = 0; ti < toolbarDefs.length; ti++) {
                        var def = toolbarDefs[ti];
                        if (def.sep) {
                            var sep = document.createElement('span');
                            sep.className = 'rte-sep';
                            toolbar.appendChild(sep);
                            continue;
                        }
                        var btn = document.createElement('button');
                        btn.type = 'button';
                        btn.className = 'rte-btn';
                        btn.innerHTML = def.icon;
                        btn.title = def.title;
                        if (def.style) btn.setAttribute('style', def.style);

                        if (def.custom === 'foreColor') {
                            (function(b, ed, hi) {
                                // Color picker with RGBA support
                                var colorWrap = document.createElement('span');
                                colorWrap.style.position = 'relative';
                                colorWrap.style.display = 'inline-block';
                                var colorInput = document.createElement('input');
                                colorInput.type = 'color';
                                colorInput.className = 'rte-color-input';
                                colorInput.value = '#000000';
                                colorInput.addEventListener('input', function() {
                                    ed.focus();
                                    document.execCommand('foreColor', false, colorInput.value);
                                    hi.value = ed.innerHTML;
                                });
                                b.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    colorInput.click();
                                });
                                colorWrap.appendChild(b);
                                colorWrap.appendChild(colorInput);
                                toolbar.appendChild(colorWrap);
                            })(btn, editorDiv, hiddenInput);
                            continue;
                        } else if (def.custom === 'table') {
                            (function(b, ed, hi) {
                                b.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    var rows = prompt('Zeilen:', '3');
                                    if (!rows) return;
                                    var cols = prompt('Spalten:', '3');
                                    if (!cols) return;
                                    rows = parseInt(rows, 10) || 3;
                                    cols = parseInt(cols, 10) || 3;
                                    var html = '<table border="1" style="border-collapse:collapse;width:100%">';
                                    for (var r = 0; r < rows; r++) {
                                        html += '<tr>';
                                        for (var c = 0; c < cols; c++) {
                                            var tag = r === 0 ? 'th' : 'td';
                                            html += '<' + tag + ' style="padding:4px;border:1px solid #999">&nbsp;</' + tag + '>';
                                        }
                                        html += '</tr>';
                                    }
                                    html += '</table>';
                                    ed.focus();
                                    document.execCommand('insertHTML', false, html);
                                    hi.value = ed.innerHTML;
                                });
                            })(btn, editorDiv, hiddenInput);
                        } else if (def.custom === 'source') {
                            (function(b, ed, sa, hi) {
                                b.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    sourceMode = !sourceMode;
                                    if (sourceMode) {
                                        sa.value = ed.innerHTML;
                                        ed.style.display = 'none';
                                        sa.style.display = '';
                                        b.classList.add('active');
                                    } else {
                                        ed.innerHTML = sa.value;
                                        hi.value = sa.value;
                                        sa.style.display = 'none';
                                        ed.style.display = '';
                                        b.classList.remove('active');
                                    }
                                });
                            })(btn, editorDiv, sourceArea, hiddenInput);
                        } else if (def.prompt) {
                            (function(b, d, ed, hi) {
                                b.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    var url = prompt('URL:', 'https://');
                                    if (url) {
                                        ed.focus();
                                        document.execCommand(d.cmd, false, url);
                                        hi.value = ed.innerHTML;
                                    }
                                });
                            })(btn, def, editorDiv, hiddenInput);
                        } else {
                            (function(b, d, ed, hi) {
                                b.addEventListener('click', function(e) {
                                    e.preventDefault();
                                    ed.focus();
                                    if (d.val) {
                                        document.execCommand(d.cmd, false, d.val);
                                    } else {
                                        document.execCommand(d.cmd, false, null);
                                    }
                                    hi.value = ed.innerHTML;
                                });
                            })(btn, def, editorDiv, hiddenInput);
                        }

                        if (!def.custom || def.custom !== 'foreColor') {
                            toolbar.appendChild(btn);
                        }
                    }

                    rteWrap.appendChild(toolbar);
                    rteWrap.appendChild(editorDiv);
                    rteWrap.appendChild(sourceArea);
                    rteWrap.appendChild(hiddenInput);
                    group.appendChild(rteWrap);
                    panel.appendChild(group);
                    continue;
                } else if (field.type === 'textarea') {
                    input = document.createElement('textarea');
                    input.name = field.key;
                    input.value = value;
                    input.rows = 6;
                    input.rows = 4;
                    input.style.fontFamily = 'monospace';
                    if (field.placeholder) input.placeholder = field.placeholder;
                } else if (field.type === 'media_browse') {
                    var wrapper = document.createElement('div');
+11 −0
Original line number Diff line number Diff line
@@ -240,6 +240,17 @@ extern "C" {
                    json_object *hf = json_object_array_get_idx(arr, json_object_array_length(arr) - 1);
                    json_object_object_add(hf, "default", json_object_new_boolean(false));
                }
                // Mobile overrides
                addField("m_width", "Width", "text", "e.g. 100%", "mobile");
                addField("m_height", "Height", "text", "e.g. auto", "mobile");
                addField("m_font_size", "Font Size", "text", "e.g. 14px", "mobile");
                addField("m_font_color", "Font Color", "color_var", nullptr, "mobile");
                addField("m_text_align", "Text Align", "select", nullptr, "mobile", mkOpts({"left","center","right","justify"}));
                addField("m_hidden", "Hidden", "checkbox", nullptr, "mobile");
                {
                    json_object *hf = json_object_array_get_idx(arr, json_object_array_length(arr) - 1);
                    json_object_object_add(hf, "default", json_object_new_boolean(false));
                }
                addField("custom_css", "Custom CSS", "textarea", ".we-xxx { color: red; }");
                return arr;
            }