diff --git a/packages/vue/src/PositionControls/PositionControlsRoot.vue b/packages/vue/src/PositionControls/PositionControlsRoot.vue new file mode 100644 index 000000000..ac79b996e --- /dev/null +++ b/packages/vue/src/PositionControls/PositionControlsRoot.vue @@ -0,0 +1,64 @@ + + + diff --git a/packages/vue/src/PositionControls/index.ts b/packages/vue/src/PositionControls/index.ts new file mode 100644 index 000000000..9fb0f748a --- /dev/null +++ b/packages/vue/src/PositionControls/index.ts @@ -0,0 +1 @@ +export { default as PositionControlsRoot } from './PositionControlsRoot.vue' diff --git a/packages/vue/src/PropertyList/PropertyListItem.vue b/packages/vue/src/PropertyList/PropertyListItem.vue new file mode 100644 index 000000000..40229a3be --- /dev/null +++ b/packages/vue/src/PropertyList/PropertyListItem.vue @@ -0,0 +1,18 @@ + + + diff --git a/packages/vue/src/PropertyList/PropertyListRoot.vue b/packages/vue/src/PropertyList/PropertyListRoot.vue new file mode 100644 index 000000000..c94850ae7 --- /dev/null +++ b/packages/vue/src/PropertyList/PropertyListRoot.vue @@ -0,0 +1,111 @@ + + + diff --git a/packages/vue/src/PropertyList/context.ts b/packages/vue/src/PropertyList/context.ts new file mode 100644 index 000000000..cacbd06d8 --- /dev/null +++ b/packages/vue/src/PropertyList/context.ts @@ -0,0 +1,32 @@ +import { type InjectionKey, inject, provide } from 'vue' + +import type { Editor } from '@open-pencil/core/editor' +import type { SceneNode } from '@open-pencil/core' +import type { ComputedRef } from 'vue' + +type ArrayPropKey = 'fills' | 'strokes' | 'effects' + +export interface PropertyListContext { + editor: Editor + propKey: ArrayPropKey + items: ComputedRef + isMixed: ComputedRef + activeNode: ComputedRef + isMulti: ComputedRef + add: (defaults: unknown) => void + remove: (index: number) => void + update: (index: number, item: unknown) => void + toggleVisibility: (index: number) => void +} + +export const PROPERTY_LIST_KEY: InjectionKey = Symbol('property-list') + +export function providePropertyList(ctx: PropertyListContext) { + provide(PROPERTY_LIST_KEY, ctx) +} + +export function usePropertyList(): PropertyListContext { + const ctx = inject(PROPERTY_LIST_KEY) + if (!ctx) throw new Error('[open-pencil] usePropertyList() called outside ') + return ctx +} diff --git a/packages/vue/src/PropertyList/index.ts b/packages/vue/src/PropertyList/index.ts new file mode 100644 index 000000000..f089cbd75 --- /dev/null +++ b/packages/vue/src/PropertyList/index.ts @@ -0,0 +1,4 @@ +export { default as PropertyListRoot } from './PropertyListRoot.vue' +export { default as PropertyListItem } from './PropertyListItem.vue' +export { usePropertyList } from './context' +export type { PropertyListContext } from './context' diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts index 5f6ab8141..5eb4d84d5 100644 --- a/packages/vue/src/index.ts +++ b/packages/vue/src/index.ts @@ -27,6 +27,11 @@ export { export type { ScrubInputContext } from './ScrubInput' export { CanvasRoot, CanvasSurface, useCanvasContext } from './Canvas' + +export { PropertyListRoot, PropertyListItem, usePropertyList } from './PropertyList' +export type { PropertyListContext } from './PropertyList' + +export { PositionControlsRoot } from './PositionControls' export type { CanvasContext } from './Canvas' export { ToolbarRoot, ToolbarItem, useToolbar } from './Toolbar' diff --git a/src/components/properties/FillSection.vue b/src/components/properties/FillSection.vue index be22e1b74..85bc1a69c 100644 --- a/src/components/properties/FillSection.vue +++ b/src/components/properties/FillSection.vue @@ -15,45 +15,31 @@ import { import FillPicker from '@/components/FillPicker.vue' import ScrubInput from '@/components/ScrubInput.vue' -import { useNodeProps } from '@open-pencil/vue' +import { PropertyListRoot } from '@open-pencil/vue' +import { useEditorStore } from '@/stores/editor' import { DEFAULT_SHAPE_FILL } from '@/constants' import { colorToCSS, colorToHexRaw } from '@open-pencil/core' + import type { Fill, Variable } from '@open-pencil/core' -const { - store, - isMulti, - active, - activeNode, - targetNodes, - isArrayMixed, - updateArrayItem, - removeArrayItem, - toggleArrayVisibility -} = useNodeProps() - -const fillsAreMixed = computed(() => isArrayMixed('fills')) +const store = useEditorStore() const colorVariables = computed(() => store.graph.getVariablesByType('COLOR')) -function getBoundVariable(index: number): Variable | undefined { - const n = activeNode.value +function getBoundVariable(nodeId: string, index: number): Variable | undefined { + const n = store.graph.getNode(nodeId) if (!n) return undefined const varId = n.boundVariables[`fills/${index}/color`] return varId ? store.graph.variables.get(varId) : undefined } -function bindVariable(index: number, variableId: string) { - const n = activeNode.value - if (!n) return - store.graph.bindVariable(n.id, `fills/${index}/color`, variableId) +function bindVariable(nodeId: string, index: number, variableId: string) { + store.graph.bindVariable(nodeId, `fills/${index}/color`, variableId) store.requestRender() } -function unbindVariable(index: number) { - const n = activeNode.value - if (!n) return - store.graph.unbindVariable(n.id, `fills/${index}/color`) +function unbindVariable(nodeId: string, index: number) { + store.graph.unbindVariable(nodeId, `fills/${index}/color`) store.requestRender() } @@ -63,36 +49,6 @@ function resolvedSwatchStyle(variable: Variable): string { return `background: ${colorToCSS(color)}` } -function updateFill(index: number, fill: Fill) { - updateArrayItem('fills', index, fill, 'Change fill') -} - -function updateOpacity(index: number, opacity: number) { - updateArrayItem( - 'fills', - index, - { opacity: Math.max(0, Math.min(1, opacity / 100)) }, - 'Change fill' - ) -} - -function toggleVisibility(index: number) { - toggleArrayVisibility('fills', index) -} - -function add() { - for (const n of targetNodes()) { - const fills = isMulti.value - ? [{ ...DEFAULT_SHAPE_FILL }] - : [...n.fills, { ...DEFAULT_SHAPE_FILL }] - store.updateNodeWithUndo(n.id, { fills }, isMulti.value ? 'Set fill' : 'Add fill') - } -} - -function remove(index: number) { - removeArrayItem('fills', index, 'Remove fill') -} - const searchTerm = ref('') const { contains } = useFilter({ sensitivity: 'base' }) const filteredVariables = computed(() => { @@ -102,119 +58,132 @@ const filteredVariables = computed(() => {