From de83a716cd6888cd3fed7c402f7e6fb2d0710174 Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Sat, 28 Feb 2026 09:27:03 +0300 Subject: [PATCH] Remove prop drilling from property sections All sections now get selected node from useNodeProps() composable instead of receiving it as a prop from PropertiesPanel. --- src/components/PropertiesPanel.vue | 14 +++---- .../properties/AppearanceSection.vue | 7 +--- src/components/properties/FillSection.vue | 25 ++++++------ src/components/properties/LayoutSection.vue | 39 +++++++++---------- src/components/properties/PositionSection.vue | 5 +-- src/components/properties/StrokeSection.vue | 31 +++++++-------- .../properties/TypographySection.vue | 19 ++++----- src/composables/use-node-props.ts | 6 ++- 8 files changed, 69 insertions(+), 77 deletions(-) diff --git a/src/components/PropertiesPanel.vue b/src/components/PropertiesPanel.vue index c1526e556..c46418a29 100644 --- a/src/components/PropertiesPanel.vue +++ b/src/components/PropertiesPanel.vue @@ -33,7 +33,7 @@ const multiCount = computed(() => store.selectedNodes.value.length) Mixed {{ multiCount }} layers - + @@ -44,12 +44,12 @@ const multiCount = computed(() => store.selectedNodes.value.length) {{ node.name }} - - - - - - + + + + + +
diff --git a/src/components/properties/AppearanceSection.vue b/src/components/properties/AppearanceSection.vue index d965eb96a..cacd5ddc1 100644 --- a/src/components/properties/AppearanceSection.vue +++ b/src/components/properties/AppearanceSection.vue @@ -2,13 +2,10 @@ import ScrubInput from '../ScrubInput.vue' import { useNodeProps } from '../../composables/use-node-props' -import type { SceneNode } from '../../engine/scene-graph' - -const { node } = defineProps<{ node: SceneNode }>() -const { store, updateProp, commitProp } = useNodeProps() +const { store, node, updateProp, commitProp } = useNodeProps() function toggleVisibility() { - store.updateNodeWithUndo(node.id, { visible: !node.visible }, 'Toggle visibility') + store.updateNodeWithUndo(node.value.id, { visible: !node.value.visible }, 'Toggle visibility') store.requestRender() } diff --git a/src/components/properties/FillSection.vue b/src/components/properties/FillSection.vue index 97de34224..bb389711c 100644 --- a/src/components/properties/FillSection.vue +++ b/src/components/properties/FillSection.vue @@ -1,19 +1,18 @@ @@ -49,7 +48,7 @@ function remove(index: number) {
-
+
() -const { store, updateProp, commitProp } = useNodeProps() +const { store, node, updateProp, commitProp } = useNodeProps() const showIndividualPadding = ref(false) const widthSizingOpen = ref(false) @@ -20,30 +19,30 @@ onClickOutside(widthDimRef, () => { widthSizingOpen.value = false }) onClickOutside(heightDimRef, () => { heightSizingOpen.value = false }) const isInAutoLayout = computed(() => { - if (!node.parentId) return false - const parent = store.graph.getNode(node.parentId) + if (!node.value.parentId) return false + const parent = store.graph.getNode(node.value.parentId) return parent ? parent.layoutMode !== 'NONE' : false }) const widthSizing = computed(() => { - if (node.layoutMode !== 'NONE') { - return node.layoutMode === 'HORIZONTAL' ? node.primaryAxisSizing : node.counterAxisSizing + if (node.value.layoutMode !== 'NONE') { + return node.value.layoutMode === 'HORIZONTAL' ? node.value.primaryAxisSizing : node.value.counterAxisSizing } - if (isInAutoLayout.value && node.layoutGrow > 0) return 'FILL' + if (isInAutoLayout.value && node.value.layoutGrow > 0) return 'FILL' return 'FIXED' }) const heightSizing = computed(() => { - if (node.layoutMode !== 'NONE') { - return node.layoutMode === 'VERTICAL' ? node.primaryAxisSizing : node.counterAxisSizing + if (node.value.layoutMode !== 'NONE') { + return node.value.layoutMode === 'VERTICAL' ? node.value.primaryAxisSizing : node.value.counterAxisSizing } - if (isInAutoLayout.value && node.layoutAlignSelf === 'STRETCH') return 'FILL' + if (isInAutoLayout.value && node.value.layoutAlignSelf === 'STRETCH') return 'FILL' return 'FIXED' }) function setWidthSizing(sizing: LayoutSizing) { - if (node.layoutMode !== 'NONE') { - if (node.layoutMode === 'HORIZONTAL') updateProp('primaryAxisSizing', sizing) + if (node.value.layoutMode !== 'NONE') { + if (node.value.layoutMode === 'HORIZONTAL') updateProp('primaryAxisSizing', sizing) else updateProp('counterAxisSizing', sizing) } else if (isInAutoLayout.value) { updateProp('layoutGrow', sizing === 'FILL' ? 1 : 0) @@ -52,8 +51,8 @@ function setWidthSizing(sizing: LayoutSizing) { } function setHeightSizing(sizing: LayoutSizing) { - if (node.layoutMode !== 'NONE') { - if (node.layoutMode === 'VERTICAL') updateProp('primaryAxisSizing', sizing) + if (node.value.layoutMode !== 'NONE') { + if (node.value.layoutMode === 'VERTICAL') updateProp('primaryAxisSizing', sizing) else updateProp('counterAxisSizing', sizing) } else if (isInAutoLayout.value) { updateProp('layoutAlignSelf', sizing === 'FILL' ? 'STRETCH' : 'AUTO') @@ -68,17 +67,17 @@ function sizingLabel(s: string) { } function hasUniformPadding() { - return node.paddingTop === node.paddingRight && - node.paddingRight === node.paddingBottom && - node.paddingBottom === node.paddingLeft + return node.value.paddingTop === node.value.paddingRight && + node.value.paddingRight === node.value.paddingBottom && + node.value.paddingBottom === node.value.paddingLeft } function setUniformPadding(v: number) { - store.updateNode(node.id, { paddingTop: v, paddingRight: v, paddingBottom: v, paddingLeft: v }) + store.updateNode(node.value.id, { paddingTop: v, paddingRight: v, paddingBottom: v, paddingLeft: v }) } function commitUniformPadding(_value: number, previous: number) { - store.commitNodeUpdate(node.id, { + store.commitNodeUpdate(node.value.id, { paddingTop: previous, paddingRight: previous, paddingBottom: previous, paddingLeft: previous } as unknown as Partial, 'Change padding') } @@ -96,7 +95,7 @@ const ALIGN_GRID: Array<{ primary: LayoutAlign; counter: LayoutCounterAlign }> = ] function setAlignment(primary: LayoutAlign, counter: LayoutCounterAlign) { - store.updateNodeWithUndo(node.id, { primaryAxisAlign: primary, counterAxisAlign: counter }, 'Change alignment') + store.updateNodeWithUndo(node.value.id, { primaryAxisAlign: primary, counterAxisAlign: counter }, 'Change alignment') } diff --git a/src/components/properties/PositionSection.vue b/src/components/properties/PositionSection.vue index 233cb8740..42dabfcf7 100644 --- a/src/components/properties/PositionSection.vue +++ b/src/components/properties/PositionSection.vue @@ -2,10 +2,7 @@ import ScrubInput from '../ScrubInput.vue' import { useNodeProps } from '../../composables/use-node-props' -import type { SceneNode } from '../../engine/scene-graph' - -const { node } = defineProps<{ node: SceneNode }>() -const { updateProp, commitProp } = useNodeProps() +const { node, updateProp, commitProp } = useNodeProps()