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()
diff --git a/src/components/properties/StrokeSection.vue b/src/components/properties/StrokeSection.vue
index 87478081c..d9d28bdcd 100644
--- a/src/components/properties/StrokeSection.vue
+++ b/src/components/properties/StrokeSection.vue
@@ -1,18 +1,17 @@
@@ -55,7 +54,7 @@ function remove(index: number) {
-
+
-
+
diff --git a/src/components/properties/TypographySection.vue b/src/components/properties/TypographySection.vue
index 1a76cec7e..567d0def8 100644
--- a/src/components/properties/TypographySection.vue
+++ b/src/components/properties/TypographySection.vue
@@ -6,10 +6,7 @@ import ScrubInput from '../ScrubInput.vue'
import { useNodeProps } from '../../composables/use-node-props'
import { listFamilies, loadFont } from '../../engine/fonts'
-import type { SceneNode } from '../../engine/scene-graph'
-
-const { node } = defineProps<{ node: SceneNode }>()
-const { store, updateProp, commitProp } = useNodeProps()
+const { store, node, updateProp, commitProp } = useNodeProps()
const fontPickerOpen = ref(false)
const fontSearch = ref('')
@@ -38,14 +35,14 @@ const WEIGHTS = [
]
const currentWeightLabel = computed(() =>
- WEIGHTS.find((w) => w.value === node.fontWeight)?.label ?? 'Regular'
+ WEIGHTS.find((w) => w.value === node.value.fontWeight)?.label ?? 'Regular'
)
type TextAlign = 'LEFT' | 'CENTER' | 'RIGHT'
async function openFontPicker() {
fontPickerOpen.value = true
- fontSearch.value = node.fontFamily
+ fontSearch.value = node.value.fontFamily
if (fontFamilies.value.length === 0) {
fontFamilies.value = await listFamilies()
}
@@ -57,25 +54,25 @@ async function openFontPicker() {
async function selectFamily(family: string) {
await loadFont(family, currentWeightLabel.value)
- store.updateNodeWithUndo(node.id, { fontFamily: family }, 'Change font')
+ store.updateNodeWithUndo(node.value.id, { fontFamily: family }, 'Change font')
store.requestRender()
fontPickerOpen.value = false
}
async function selectWeight(weight: number) {
const label = WEIGHTS.find((w) => w.value === weight)?.label ?? 'Regular'
- await loadFont(node.fontFamily, label)
- store.updateNodeWithUndo(node.id, { fontWeight: weight }, 'Change font weight')
+ await loadFont(node.value.fontFamily, label)
+ store.updateNodeWithUndo(node.value.id, { fontWeight: weight }, 'Change font weight')
store.requestRender()
}
function setAlign(align: 'LEFT' | 'CENTER' | 'RIGHT') {
- store.updateNodeWithUndo(node.id, { textAlignHorizontal: align }, 'Change text alignment')
+ store.updateNodeWithUndo(node.value.id, { textAlignHorizontal: align }, 'Change text alignment')
store.requestRender()
}
onMounted(async () => {
- await loadFont(node.fontFamily, currentWeightLabel.value)
+ await loadFont(node.value.fontFamily, currentWeightLabel.value)
})
diff --git a/src/composables/use-node-props.ts b/src/composables/use-node-props.ts
index c38602d3f..6ec1984da 100644
--- a/src/composables/use-node-props.ts
+++ b/src/composables/use-node-props.ts
@@ -1,9 +1,13 @@
+import { computed } from 'vue'
+
import { useEditorStore } from '../stores/editor'
import type { SceneNode } from '../engine/scene-graph'
export function useNodeProps() {
const store = useEditorStore()
+ const node = computed(() => store.selectedNode.value!)
+ const nodes = computed(() => store.selectedNodes.value)
function updateProp(key: string, value: number | string) {
if (store.selectedNodes.value.length > 1) {
@@ -29,5 +33,5 @@ export function useNodeProps() {
}
}
- return { store, updateProp, commitProp }
+ return { store, node, nodes, updateProp, commitProp }
}