From ab1ba02c942dae47044be6b2b76ceb019b08a2de Mon Sep 17 00:00:00 2001 From: Danila Poyarkov Date: Mon, 4 May 2026 12:47:38 +0300 Subject: [PATCH] feat(app): extend variable binding to more inspector fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add VariableScrubInput — reusable wrapper that combines ScrubInput with variable binding picker and detach button. Wire it into: - Corner radius (uniform + 4 independent corners) - Opacity - Auto-layout gap (primary + cross axis) - Padding (horizontal/vertical + 4 individual sides) - Font size All fields get bind, detach, create, search, and detach-on-edit behavior automatically through the shared component. --- .../controls/number-variable-binding/use.ts | 21 +++- packages/vue/src/index.ts | 1 + .../properties/AppearanceSection.vue | 57 +++++++-- .../properties/LayoutSection/FlexControls.vue | 13 +- .../LayoutSection/PaddingControls.vue | 20 ++-- .../properties/TypographySection.vue | 5 +- .../properties/VariableScrubInput.vue | 113 ++++++++++++++++++ 7 files changed, 208 insertions(+), 22 deletions(-) create mode 100644 src/components/properties/VariableScrubInput.vue diff --git a/packages/vue/src/controls/number-variable-binding/use.ts b/packages/vue/src/controls/number-variable-binding/use.ts index 366caeb7b..b1228b676 100644 --- a/packages/vue/src/controls/number-variable-binding/use.ts +++ b/packages/vue/src/controls/number-variable-binding/use.ts @@ -6,7 +6,26 @@ import type { VariableCollection } from '@open-pencil/core/scene-graph' const FALLBACK_NUMBER_VARIABLE_NAME = 'New number' -type NumberBindingPath = 'width' | 'height' +export type NumberBindingPath = + | 'width' + | 'height' + | 'minWidth' + | 'maxWidth' + | 'minHeight' + | 'maxHeight' + | 'cornerRadius' + | 'topLeftRadius' + | 'topRightRadius' + | 'bottomLeftRadius' + | 'bottomRightRadius' + | 'itemSpacing' + | 'counterAxisSpacing' + | 'paddingTop' + | 'paddingRight' + | 'paddingBottom' + | 'paddingLeft' + | 'opacity' + | 'fontSize' export function useNumberVariableBinding(path: NumberBindingPath) { const binding = useVariableBinding({ diff --git a/packages/vue/src/index.ts b/packages/vue/src/index.ts index 9f63ddf73..24cb89719 100644 --- a/packages/vue/src/index.ts +++ b/packages/vue/src/index.ts @@ -56,6 +56,7 @@ export type { ExportFormatId } from '#vue/document/export/use' export { useFillControls } from '#vue/controls/fill/use' export { useColorVariableBinding } from '#vue/controls/color-variable-binding/use' export { useNumberVariableBinding } from '#vue/controls/number-variable-binding/use' +export type { NumberBindingPath } from '#vue/controls/number-variable-binding/use' export { useVariableBinding } from '#vue/controls/variable-binding/use' export type { VariableBindingState, diff --git a/src/components/properties/AppearanceSection.vue b/src/components/properties/AppearanceSection.vue index df3bd796b..04ba6d02b 100644 --- a/src/components/properties/AppearanceSection.vue +++ b/src/components/properties/AppearanceSection.vue @@ -4,6 +4,7 @@ import { computed, ref } from 'vue' import { useAppearance, useI18n } from '@open-pencil/vue' import ScrubInput from '@/components/ScrubInput.vue' +import VariableScrubInput from '@/components/properties/VariableScrubInput.vue' import Tip from '@/components/ui/Tip.vue' import { useSectionUI } from '@/components/ui/section' @@ -65,7 +66,23 @@ function onToggleCorners() {
+ + + - - + @@ -158,11 +193,13 @@ function onToggleCorners() { - - + @@ -177,11 +214,13 @@ function onToggleCorners() { - - + @@ -196,7 +235,7 @@ function onToggleCorners() { - +
diff --git a/src/components/properties/LayoutSection/FlexControls.vue b/src/components/properties/LayoutSection/FlexControls.vue index 5442f38b4..72aadf705 100644 --- a/src/components/properties/LayoutSection/FlexControls.vue +++ b/src/components/properties/LayoutSection/FlexControls.vue @@ -13,6 +13,7 @@ import { import AppSelect from '@/components/ui/AppSelect.vue' import ScrubInput from '@/components/ScrubInput.vue' +import VariableScrubInput from '@/components/properties/VariableScrubInput.vue' import ClipContentControl from '@/components/properties/LayoutSection/ClipContentControl.vue' import PaddingControls from '@/components/properties/LayoutSection/PaddingControls.vue' import { useSelectUI } from '@/components/ui/select' @@ -57,12 +58,14 @@ function isAlignmentActive(primary: LayoutAlign, counter: string) {
- - + @@ -90,7 +95,7 @@ function isAlignmentActive(primary: LayoutAlign, counter: string) { /> - + - +
diff --git a/src/components/properties/TypographySection.vue b/src/components/properties/TypographySection.vue index d3bc1b6dc..257b87d0b 100644 --- a/src/components/properties/TypographySection.vue +++ b/src/components/properties/TypographySection.vue @@ -5,6 +5,7 @@ import { TypographyControlsRoot, useI18n } from '@open-pencil/vue' import FontPicker from '@/components/FontPicker.vue' import ScrubInput from '@/components/ScrubInput.vue' +import VariableScrubInput from '@/components/properties/VariableScrubInput.vue' import AppSelect from '@/components/ui/AppSelect.vue' import Tip from '@/components/ui/Tip.vue' import { useSectionUI } from '@/components/ui/section' @@ -47,11 +48,13 @@ const sectionCls = useSectionUI() :options="ctx.weights" @update:model-value="ctx.setWeight(+$event)" /> - diff --git a/src/components/properties/VariableScrubInput.vue b/src/components/properties/VariableScrubInput.vue new file mode 100644 index 000000000..022fb9799 --- /dev/null +++ b/src/components/properties/VariableScrubInput.vue @@ -0,0 +1,113 @@ + + +