Fassung 1.6.1: flexible Editorflaeche und passende Blockeigenschaften
This commit is contained in:
1 parent
05ea703655
commit
b783d9d1e5
13 files changed
+276
-11
No files matched your search
@@ -5,7 +5,7 @@
|
||||
* what the server accepts – nothing more, nothing less. Adding a property on the server makes it
|
||||
* appear here without touching this file.
|
||||
*/
|
||||
import { devices, effectiveStyle, hoverStyle, setStyle, resetStyleDevice, clearStyle } from './editor-model.js';
|
||||
import { devices, effectiveStyle, hoverStyle, setStyle, resetStyleDevice, clearStyle, isContainer, relevantProperty } from './editor-model.js';
|
||||
import { openMedia } from './media.js';
|
||||
|
||||
export const GROUPS = {
|
||||
@@ -122,6 +122,8 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
const linkedSides = new Map();
|
||||
// Lives as long as the editor session, so a look can travel between blocks and pages.
|
||||
let clipboard = null;
|
||||
let showAll = false, lastBlockId = null;
|
||||
const openGroups = new Map();
|
||||
|
||||
/** Replaces the styling of a block with a copy, or removes it when nothing is given. */
|
||||
const applyStyle = (doc, id, style) => {
|
||||
@@ -227,7 +229,7 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
return wrap;
|
||||
};
|
||||
|
||||
const lengthControl = (id, value, apply, placeholder) => {
|
||||
const lengthControl = (id, value, apply, placeholder, keywords = []) => {
|
||||
const wrap = element('div', 'length-control');
|
||||
const parts = splitLength(value);
|
||||
const number = document.createElement('input');
|
||||
@@ -245,6 +247,17 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
unit.addEventListener('change', () => { if (number.value !== '') push(); });
|
||||
makeScrubbable(number, { apply: push, step: 1, mergeKey: `scrub-${id}` });
|
||||
wrap.append(number, unit);
|
||||
if (keywords.length) {
|
||||
const mode = document.createElement('select');
|
||||
mode.className = 'length-mode';
|
||||
mode.setAttribute('aria-label', `${schema.properties[id.replace('style-', '')]?.label ?? 'Länge'} Vorgabe`);
|
||||
mode.append(new Option('Eigener Zahlenwert / geerbt', ''));
|
||||
for (const keyword of keywords) mode.append(new Option(keyword === 'none' ? 'Ohne Begrenzung' : 'Automatisch', keyword));
|
||||
mode.value = ['auto', 'none'].includes(value) ? value : '';
|
||||
number.hidden = unit.hidden = mode.value !== '';
|
||||
mode.addEventListener('change', () => apply(mode.value));
|
||||
wrap.prepend(mode);
|
||||
}
|
||||
return wrap;
|
||||
};
|
||||
|
||||
@@ -449,11 +462,16 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
const block = getBlock();
|
||||
const deviceName = getDevice();
|
||||
if (!block) return;
|
||||
if (lastBlockId !== block.id) { showAll = false; lastBlockId = block.id; }
|
||||
|
||||
const scope = element('p', 'design-scope');
|
||||
scope.textContent = `${devices[deviceName]} · ${deviceName === 'desktop' ? 'Basis für alle Geräte' : deviceName === 'tablet' ? 'bis 1024 px, gilt auch für Mobil' : 'bis 767 px'}`;
|
||||
panel.append(scope);
|
||||
panel.append(element('p', 'field-help', 'Leere Felder erben vom größeren Gerät und zuletzt vom Theme. Werte mit eigenem Wert sind hervorgehoben und lassen sich einzeln zurücksetzen.'));
|
||||
const all = element('button', 'secondary design-context-toggle', showAll ? 'Passende Eigenschaften anzeigen' : 'Alle Eigenschaften anzeigen');
|
||||
all.type = 'button'; all.setAttribute('aria-pressed', String(showAll));
|
||||
all.addEventListener('click', () => { showAll = !showAll; onChange(); panel.querySelector('.design-context-toggle')?.focus(); });
|
||||
panel.append(all);
|
||||
|
||||
// A filter over the properties. With more than ninety of them across eight collapsed groups,
|
||||
// "where is the border thickness" is a fair question - so it can be typed instead of hunted.
|
||||
@@ -484,11 +502,16 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
});
|
||||
panel.append(searchLabel, search, found);
|
||||
|
||||
for (const [group, groupLabel] of Object.entries(GROUPS)) {
|
||||
const properties = Object.entries(schema.properties).filter(([, p]) => p.group === group);
|
||||
const priority = ['image', 'gallery', 'logos'].includes(block.type) ? ['image', 'size', 'spacing'] : isContainer(block) ? ['layout', 'size', 'spacing', 'background'] : ['spacer', 'divider', 'embed'].includes(block.type) ? ['size', 'spacing'] : ['text', 'size', 'spacing'];
|
||||
const orderedGroups = [...new Set([...priority, ...Object.keys(GROUPS)])];
|
||||
for (const group of orderedGroups) {
|
||||
const groupLabel = GROUPS[group];
|
||||
const properties = Object.entries(schema.properties).filter(([key, p]) => p.group === group && (showAll || relevantProperty(block, key, p)));
|
||||
if (properties.length === 0) continue;
|
||||
const details = element('details', 'design-group');
|
||||
if (group === 'text' || group === 'spacing') details.open = true;
|
||||
const groupKey = `${block.type}:${group}`;
|
||||
details.open = openGroups.get(groupKey) ?? (group === priority[0] || group === 'spacing');
|
||||
details.addEventListener('toggle', () => { if (details.isConnected) openGroups.set(groupKey, details.open); });
|
||||
details.append(element('summary', null, groupLabel));
|
||||
const body = element('div', 'design-group-body');
|
||||
|
||||
@@ -510,7 +533,7 @@ export function createDesignPanel({ schema, onChange, onSavePreset, getBlock, ge
|
||||
continue;
|
||||
}
|
||||
if (property.type === 'color') control = colorControl(id, own ? current.value : '', apply);
|
||||
else if (property.type === 'length' || property.type === 'length-auto') control = lengthControl(id, own ? current.value : '', apply, current.value ? String(current.value) : 'erbt');
|
||||
else if (property.type === 'length' || property.type === 'length-auto') control = lengthControl(id, own ? current.value : '', apply, current.value ? String(current.value) : 'erbt', property.type === 'length-auto' ? (key.startsWith('max') ? ['none'] : ['auto']) : []);
|
||||
else if (property.type === 'number') control = numberControl(id, own ? current.value : '', property, apply);
|
||||
else if (property.type === 'choice') control = choiceControl(id, own ? current.value : '', property, apply, inheritedText);
|
||||
else if (property.type === 'font') control = fontControl(id, own ? current.value : '', apply, inheritedText);
|
||||
|
||||
Reference in new issue
Block a user