From 76274fff04c54514230ad2bb0aca362139618411 Mon Sep 17 00:00:00 2001 From: isUnknown Date: Wed, 10 Dec 2025 12:11:53 +0100 Subject: [PATCH] feat: apply field values when unlocking inheritance MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Unlocking now creates CSS block with current field values - Locking removes CSS block to restore general styles - Show commented CSS preview when inheritance is locked - Preview displays what would be applied if unlocked 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/components/ElementPopup.vue | 80 +++++++++++++++++++++++++++++++-- src/components/PagePopup.vue | 66 ++++++++++++++++++++++----- 2 files changed, 133 insertions(+), 13 deletions(-) diff --git a/src/components/ElementPopup.vue b/src/components/ElementPopup.vue index 9d36142..a49dbb0 100644 --- a/src/components/ElementPopup.vue +++ b/src/components/ElementPopup.vue @@ -369,6 +369,62 @@ const elementCss = computed(() => { return stylesheetStore.extractBlock(selector.value) || ''; }); +// Generate a preview CSS block from current field values +const generatePreviewCss = () => { + if (!selector.value) return ''; + + const properties = []; + + if (fontFamily.value.value) { + properties.push(` font-family: ${fontFamily.value.value};`); + } + if (fontStyle.value.italic) { + properties.push(` font-style: italic;`); + } + if (fontWeight.value.value) { + properties.push(` font-weight: ${fontWeight.value.value};`); + } + if (fontSize.value.value) { + properties.push(` font-size: ${fontSize.value.value}${fontSize.value.unit};`); + } + if (textAlign.value.value) { + properties.push(` text-align: ${textAlign.value.value};`); + } + if (color.value.value && color.value.value !== 'rgb(0, 0, 0)') { + properties.push(` color: ${color.value.value};`); + } + if (background.value.value && background.value.value !== 'transparent') { + properties.push(` background: ${background.value.value};`); + } + if (marginOuter.value.value) { + properties.push(` margin: ${marginOuter.value.value}${marginOuter.value.unit};`); + } + if (paddingInner.value.value) { + properties.push(` padding: ${paddingInner.value.value}${paddingInner.value.unit};`); + } + + if (properties.length === 0) return ''; + + return `${selector.value} {\n${properties.join('\n')}\n}`; +}; + +const displayedCss = computed(() => { + if (!selector.value) return ''; + + // If unlocked, show the actual CSS block from stylesheet + if (!inheritanceLocked.value) { + return elementCss.value || generatePreviewCss(); + } + + // If locked, show commented preview of what would be applied + const preview = generatePreviewCss(); + if (!preview) return ''; + + return '/* Héritage verrouillé - déverrouiller pour appliquer */\n/* ' + + preview.split('\n').join('\n ') + + ' */'; +}); + // Remove the element-specific CSS block to restore inheritance const removeElementBlock = () => { if (!selector.value) return; @@ -386,8 +442,8 @@ const removeElementBlock = () => { }; const highlightedCss = computed(() => { - if (!elementCss.value) return ''; - return hljs.highlight(elementCss.value, { language: 'css' }).value; + if (!displayedCss.value) return ''; + return hljs.highlight(displayedCss.value, { language: 'css' }).value; }); // Update functions for each property @@ -436,6 +492,21 @@ const updatePaddingInner = () => { stylesheetStore.updateProperty(selector.value, 'padding', paddingInner.value.value, paddingInner.value.unit); }; +// Apply all current field values to create/update the CSS block +const applyAllStyles = () => { + if (!selector.value) return; + + updateFontFamily(); + updateFontStyle(); + updateFontWeight(); + updateFontSize(); + updateTextAlign(); + updateColor(); + updateBackground(); + updateMarginOuter(); + updatePaddingInner(); +}; + // Watch for changes watch(() => fontFamily.value.value, () => { if (isUpdatingFromStore) return; @@ -695,9 +766,12 @@ const toggleInheritance = () => { } } - // When re-locking, remove the element-specific CSS block to restore inheritance if (inheritanceLocked.value && !wasLocked) { + // Re-locking: remove the element-specific CSS block to restore inheritance removeElementBlock(); + } else if (!inheritanceLocked.value && wasLocked) { + // Unlocking: apply all current field values to create the CSS block + applyAllStyles(); } }; diff --git a/src/components/PagePopup.vue b/src/components/PagePopup.vue index aae5505..d82b8ef 100644 --- a/src/components/PagePopup.vue +++ b/src/components/PagePopup.vue @@ -383,9 +383,9 @@ const removeTemplateBlock = () => { } }; -const updateMargins = () => { - // Only update if inheritance is unlocked - if (inheritanceLocked.value) return; +const updateMargins = (force = false) => { + // Only update if inheritance is unlocked (unless forced) + if (!force && inheritanceLocked.value) return; const marginValue = `${margins.value.top.value}${margins.value.top.unit} ${margins.value.right.value}${margins.value.right.unit} ${margins.value.bottom.value}${margins.value.bottom.unit} ${margins.value.left.value}${margins.value.left.unit}`; @@ -415,9 +415,9 @@ const updateMargins = () => { } }; -const updateBackground = () => { - // Only update if inheritance is unlocked - if (inheritanceLocked.value) return; +const updateBackground = (force = false) => { + // Only update if inheritance is unlocked (unless forced) + if (!force && inheritanceLocked.value) return; if (!background.value.value) return; const currentBlock = getOrCreateTemplateBlock(); @@ -444,6 +444,12 @@ const updateBackground = () => { } }; +// Apply all current field values to create/update the CSS block +const applyAllStyles = () => { + updateMargins(true); + updateBackground(true); +}; + // Watch margin values (number inputs) with debounce watch( () => [ @@ -594,10 +600,11 @@ const toggleInheritance = () => { if (inheritanceLocked.value && !wasLocked) { // Re-locking: remove the template-specific block - // Fields keep their values, but preview returns to @page defaults removeTemplateBlock(); + } else if (!inheritanceLocked.value && wasLocked) { + // Unlocking: apply all current field values to create the CSS block + applyAllStyles(); } - // When unlocking: fields already have values, block will be created on first edit }; const pageCss = computed(() => { @@ -609,9 +616,47 @@ const pageCss = computed(() => { return stylesheetStore.extractBlock('@page') || ''; }); +// Generate a preview CSS block from current field values +const generatePreviewCss = () => { + if (!templateName.value) return ''; + + const properties = []; + + const marginValue = `${margins.value.top.value}${margins.value.top.unit} ${margins.value.right.value}${margins.value.right.unit} ${margins.value.bottom.value}${margins.value.bottom.unit} ${margins.value.left.value}${margins.value.left.unit}`; + properties.push(` margin: ${marginValue};`); + + if (background.value.value) { + properties.push(` background: ${background.value.value};`); + } + + if (properties.length === 0) return ''; + + return `@page ${templateName.value} {\n${properties.join('\n')}\n}`; +}; + +const displayedCss = computed(() => { + // If unlocked, show the actual CSS block from stylesheet + if (!inheritanceLocked.value) { + return pageCss.value; + } + + // If locked, show commented preview of what would be applied + if (!templateName.value) { + // For base @page, just show it normally + return pageCss.value; + } + + const preview = generatePreviewCss(); + if (!preview) return pageCss.value; + + return '/* Héritage verrouillé - déverrouiller pour appliquer */\n/* ' + + preview.split('\n').join('\n ') + + ' */'; +}); + const highlightedCss = computed(() => { - if (!pageCss.value) return ''; - return hljs.highlight(pageCss.value, { language: 'css' }).value; + if (!displayedCss.value) return ''; + return hljs.highlight(displayedCss.value, { language: 'css' }).value; }); let cssDebounceTimer = null; @@ -624,6 +669,7 @@ const handleCssInput = (event) => { } cssDebounceTimer = setTimeout(() => { + // Get the actual CSS block (not the commented preview) const oldBlock = pageCss.value; if (oldBlock) { stylesheetStore.content = stylesheetStore.content.replace(