refactor: extract shared patterns from popup/settings components
- Create useColoris composable (shared Coloris init across 4 files) - Create useLinkedSpacing composable (linked margin/padding logic from TextSettings) - Create BasePopup component (shared popup shell, CSS editor, inheritance button) - Add watchProp helper in ElementPopup (12 watchers → 12 compact lines) - Use extractSpacing for @page margin parsing in PagePopup and PageSettings Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0c682c78c0
commit
69d5ebe7ed
7 changed files with 816 additions and 1187 deletions
34
src/composables/useColoris.js
Normal file
34
src/composables/useColoris.js
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import Coloris from '@melloware/coloris';
|
||||
import '@melloware/coloris/dist/coloris.css';
|
||||
|
||||
const defaultConfig = {
|
||||
el: '[data-coloris]',
|
||||
theme: 'pill',
|
||||
themeMode: 'dark',
|
||||
formatToggle: true,
|
||||
alpha: true,
|
||||
closeButton: true,
|
||||
closeLabel: 'Fermer',
|
||||
clearButton: true,
|
||||
clearLabel: 'Effacer',
|
||||
swatchesOnly: false,
|
||||
inline: false,
|
||||
wrap: true,
|
||||
swatches: [
|
||||
'#264653',
|
||||
'#2a9d8f',
|
||||
'#e9c46a',
|
||||
'#f4a261',
|
||||
'#e76f51',
|
||||
'#d62828',
|
||||
'#023e8a',
|
||||
'#0077b6',
|
||||
'#ffffff',
|
||||
'#000000',
|
||||
],
|
||||
};
|
||||
|
||||
export function initColoris(overrides = {}) {
|
||||
Coloris.init();
|
||||
Coloris({ ...defaultConfig, ...overrides });
|
||||
}
|
||||
146
src/composables/useLinkedSpacing.js
Normal file
146
src/composables/useLinkedSpacing.js
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
import { ref, watch } from 'vue';
|
||||
import { convertUnit } from '../utils/unit-conversion';
|
||||
|
||||
/**
|
||||
* Composable for managing linked/unlinked spacing (margin/padding) with 4 sides.
|
||||
* @param {Object} options
|
||||
* @param {string} options.defaultUnit - Default unit for all sides (default: 'mm')
|
||||
* @param {Object} options.initialValues - Initial values for sides { top, right, bottom, left } each { value, unit }
|
||||
* @param {Function} options.onUpdate - Callback called with the detailed sides when values change
|
||||
* @param {Function} options.isUpdatingFromStore - Function that returns whether we're syncing from store
|
||||
* @param {Function} options.debouncedUpdate - Debounced update function
|
||||
*/
|
||||
export function useLinkedSpacing({ defaultUnit = 'mm', initialValues, onUpdate, isUpdatingFromStore, debouncedUpdate }) {
|
||||
const sides = ref(initialValues || {
|
||||
top: { value: 0, unit: defaultUnit },
|
||||
right: { value: 0, unit: defaultUnit },
|
||||
bottom: { value: 0, unit: defaultUnit },
|
||||
left: { value: 0, unit: defaultUnit },
|
||||
});
|
||||
|
||||
const linked = ref(false);
|
||||
|
||||
const prevValues = ref({
|
||||
top: sides.value.top.value,
|
||||
right: sides.value.right.value,
|
||||
bottom: sides.value.bottom.value,
|
||||
left: sides.value.left.value,
|
||||
});
|
||||
|
||||
const updateUnit = (newUnit) => {
|
||||
const sideNames = ['top', 'right', 'bottom', 'left'];
|
||||
sideNames.forEach((side) => {
|
||||
const s = sides.value[side];
|
||||
s.value = convertUnit(s.value, s.unit, newUnit);
|
||||
s.unit = newUnit;
|
||||
});
|
||||
};
|
||||
|
||||
// When link is toggled on, sync all sides to first non-zero value
|
||||
watch(linked, (isLinked) => {
|
||||
if (!isLinked) return;
|
||||
|
||||
const current = sides.value;
|
||||
const syncValue = current.top.value || current.bottom.value || current.left.value || current.right.value;
|
||||
|
||||
sides.value.top.value = syncValue;
|
||||
sides.value.bottom.value = syncValue;
|
||||
sides.value.left.value = syncValue;
|
||||
sides.value.right.value = syncValue;
|
||||
|
||||
prevValues.value.top = syncValue;
|
||||
prevValues.value.bottom = syncValue;
|
||||
prevValues.value.left = syncValue;
|
||||
prevValues.value.right = syncValue;
|
||||
});
|
||||
|
||||
// Watch side values for linked sync + update callback
|
||||
watch(() => [
|
||||
sides.value.top.value,
|
||||
sides.value.bottom.value,
|
||||
sides.value.left.value,
|
||||
sides.value.right.value,
|
||||
], () => {
|
||||
if (isUpdatingFromStore()) return;
|
||||
|
||||
if (linked.value) {
|
||||
const current = {
|
||||
top: sides.value.top.value,
|
||||
bottom: sides.value.bottom.value,
|
||||
left: sides.value.left.value,
|
||||
right: sides.value.right.value,
|
||||
};
|
||||
|
||||
let changedValue = null;
|
||||
if (current.top !== prevValues.value.top) changedValue = current.top;
|
||||
else if (current.bottom !== prevValues.value.bottom) changedValue = current.bottom;
|
||||
else if (current.left !== prevValues.value.left) changedValue = current.left;
|
||||
else if (current.right !== prevValues.value.right) changedValue = current.right;
|
||||
|
||||
if (changedValue !== null) {
|
||||
sides.value.top.value = changedValue;
|
||||
sides.value.bottom.value = changedValue;
|
||||
sides.value.left.value = changedValue;
|
||||
sides.value.right.value = changedValue;
|
||||
|
||||
prevValues.value.top = changedValue;
|
||||
prevValues.value.bottom = changedValue;
|
||||
prevValues.value.left = changedValue;
|
||||
prevValues.value.right = changedValue;
|
||||
}
|
||||
} else {
|
||||
prevValues.value.top = sides.value.top.value;
|
||||
prevValues.value.bottom = sides.value.bottom.value;
|
||||
prevValues.value.left = sides.value.left.value;
|
||||
prevValues.value.right = sides.value.right.value;
|
||||
}
|
||||
|
||||
if (onUpdate) {
|
||||
debouncedUpdate(() => {
|
||||
onUpdate(sides.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Set all sides from extracted spacing data (from syncFromStore).
|
||||
* Also updates prevValues and optionally sets linked state.
|
||||
*/
|
||||
const setFromSpacing = (spacing) => {
|
||||
if (spacing.simple) {
|
||||
sides.value = {
|
||||
top: { ...spacing.simple },
|
||||
right: { ...spacing.simple },
|
||||
bottom: { ...spacing.simple },
|
||||
left: { ...spacing.simple },
|
||||
};
|
||||
linked.value = true;
|
||||
} else if (spacing.detailed) {
|
||||
sides.value = spacing.detailed;
|
||||
const d = spacing.detailed;
|
||||
const allSame =
|
||||
d.top.value === d.right.value &&
|
||||
d.top.value === d.bottom.value &&
|
||||
d.top.value === d.left.value &&
|
||||
d.top.unit === d.right.unit &&
|
||||
d.top.unit === d.bottom.unit &&
|
||||
d.top.unit === d.left.unit;
|
||||
linked.value = allSame;
|
||||
}
|
||||
|
||||
prevValues.value = {
|
||||
top: sides.value.top.value,
|
||||
right: sides.value.right.value,
|
||||
bottom: sides.value.bottom.value,
|
||||
left: sides.value.left.value,
|
||||
};
|
||||
};
|
||||
|
||||
return {
|
||||
sides,
|
||||
linked,
|
||||
updateUnit,
|
||||
prevValues,
|
||||
setFromSpacing,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue