From 93e715aea780a9e1101fc03880c504fdcd099cfe Mon Sep 17 00:00:00 2001 From: Tim McMackin Date: Mon, 6 Apr 2026 15:08:03 -0400 Subject: [PATCH 1/5] DEVREL-2759: resetAllProps() --- .../elements-generated.d.ts | 1 + src/examples/components.ts | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/designer-extension-typings/elements-generated.d.ts b/src/designer-extension-typings/elements-generated.d.ts index fea7687..5df5ba4 100644 --- a/src/designer-extension-typings/elements-generated.d.ts +++ b/src/designer-extension-typings/elements-generated.d.ts @@ -186,6 +186,7 @@ interface ComponentElement setProps( props: Array ): Promise>; + resetAllProps(): Promise; } interface UnknownElement diff --git a/src/examples/components.ts b/src/examples/components.ts index 204bafd..9040e8f 100644 --- a/src/examples/components.ts +++ b/src/examples/components.ts @@ -297,6 +297,38 @@ export const Components = { await myComponent.setName('My New Component Name') }, + resetAllProps: async () => { + // Get the selected component instance + const instanceEl = await webflow.getSelectedElement(); + + if (instanceEl?.type === 'ComponentInstance') { + // Get the instance's props to find a prop ID to override + const props = await instanceEl.searchProps(); + + if (props.length > 0) { + const firstProp = props[0]; + + // Set an override on the first prop + await instanceEl.setProps([{ propId: firstProp.propId, value: 'Custom value' }]); + + // Confirm the override is applied + const before = await instanceEl.getProps(); + console.log('Has override:', before[0].hasOverride); // true + + // Reset all overrides to component defaults in one call + await instanceEl.resetAllProps(); + + // All props now show defaults, no overrides + const after = await instanceEl.getProps(); + console.log('Has override after reset:', after[0].hasOverride); // false + } else { + console.log('This component instance has no props.'); + } + } else { + console.log('Please select a component instance.'); + } + }, + getComponent: async () => { // Select Component Element on Page const elements = await webflow.getAllElements() From a93966def99a2690986d4525b01b1fb29bc2311e Mon Sep 17 00:00:00 2001 From: Tim McMackin Date: Mon, 6 Apr 2026 15:10:00 -0400 Subject: [PATCH 2/5] DEVREL-2758: setProps() --- src/examples/components.ts | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/examples/components.ts b/src/examples/components.ts index 9040e8f..2038c55 100644 --- a/src/examples/components.ts +++ b/src/examples/components.ts @@ -297,6 +297,40 @@ export const Components = { await myComponent.setName('My New Component Name') }, + setProps: async () => { + // Get the selected component instance + const instanceEl = await webflow.getSelectedElement(); + + if (instanceEl?.type === 'ComponentInstance') { + // Read current prop values (round-trip: read, modify, write back) + const currentProps = await instanceEl.getProps(); + console.log('Current props:', currentProps); + + await instanceEl.setProps([ + // Static value override — set the first prop to a new string value + { propId: currentProps[0].propId, value: 'New Heading' }, + + // Bind to a parent component prop + { propId: 'prop_2', value: { sourceType: 'prop', propId: 'parent_prop_5' } }, + + // Bind to a CMS field + { propId: 'prop_3', value: { sourceType: 'cms', collectionId: 'col_abc', fieldId: 'field_author' } }, + + // Bind to a page field + { propId: 'prop_4', value: { sourceType: 'page', fieldKey: 'seoTitle' } }, + + // Disconnect a binding / reset a prop to its component default + { propId: 'prop_5', value: null }, + ]); + + // Confirm updated values + const updatedProps = await instanceEl.getProps(); + console.log('Updated props:', updatedProps); + } else { + console.log('Please select a component instance.'); + } + }, + resetAllProps: async () => { // Get the selected component instance const instanceEl = await webflow.getSelectedElement(); From 7fc26b0bb559776d61a34ae34f6d0eae21e716c2 Mon Sep 17 00:00:00 2001 From: Tim McMackin Date: Mon, 6 Apr 2026 15:12:01 -0400 Subject: [PATCH 3/5] DEVREL-2757: getResolvedProps() --- .../elements-generated.d.ts | 1 + src/examples/components.ts | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/designer-extension-typings/elements-generated.d.ts b/src/designer-extension-typings/elements-generated.d.ts index 5df5ba4..f6683e9 100644 --- a/src/designer-extension-typings/elements-generated.d.ts +++ b/src/designer-extension-typings/elements-generated.d.ts @@ -179,6 +179,7 @@ interface ComponentElement readonly plugin: ''; getComponent(): Promise; getSlots(): Promise>; + getResolvedProps(): Promise>; getProps(): Promise>; searchProps( options?: SearchInstancePropsOptions diff --git a/src/examples/components.ts b/src/examples/components.ts index 2038c55..0a3927d 100644 --- a/src/examples/components.ts +++ b/src/examples/components.ts @@ -297,6 +297,40 @@ export const Components = { await myComponent.setName('My New Component Name') }, + getResolvedProps: async () => { + // Get the selected component instance + const instanceEl = await webflow.getSelectedElement(); + + if (instanceEl?.type === 'ComponentInstance') { + // Get what each prop actually renders — bindings resolved to their output values + const resolvedProps = await instanceEl.getResolvedProps(); + + for (const prop of resolvedProps) { + console.log(`${prop.propId}: ${prop.value}`); + } + + // Comparison of all three instance prop read APIs: + + // searchProps — full metadata: wrapped value, resolved value, display info, override status + const search = await instanceEl.searchProps(); + console.log(search[0].value); // { sourceType: 'static', value: 'My Custom Title' } + console.log(search[0].resolvedValue); // 'My Custom Title' + console.log(search[0].display); // { label: 'Heading', group: 'Content' } + console.log(search[0].hasOverride); // true + + // getProps — raw values with override status, no display metadata + const props = await instanceEl.getProps(); + console.log(props[0].value); // 'My Custom Title' (bare value) + console.log(props[0].hasOverride); // true + + // getResolvedProps — just the final resolved output, no binding metadata + const resolved = await instanceEl.getResolvedProps(); + console.log(resolved[0].value); // 'My Custom Title' + } else { + console.log('Please select a component instance.'); + } + }, + setProps: async () => { // Get the selected component instance const instanceEl = await webflow.getSelectedElement(); From d5f871a6aadf6ec7e28f5a0c9db15e24b7662486 Mon Sep 17 00:00:00 2001 From: Tim McMackin Date: Mon, 6 Apr 2026 15:13:47 -0400 Subject: [PATCH 4/5] DEVREL-2756: getProps() --- src/examples/components.ts | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/examples/components.ts b/src/examples/components.ts index 0a3927d..3ffd4b8 100644 --- a/src/examples/components.ts +++ b/src/examples/components.ts @@ -297,6 +297,36 @@ export const Components = { await myComponent.setName('My New Component Name') }, + getProps: async () => { + // Get the selected component instance + const instanceEl = await webflow.getSelectedElement(); + + if (instanceEl?.type === 'ComponentInstance') { + const props = await instanceEl.getProps(); + + // Distinguish bound props from static values using the sourceType property + for (const prop of props) { + if (typeof prop.value === 'object' && prop.value !== null && 'sourceType' in prop.value) { + console.log(`${prop.propId}: bound to ${(prop.value as { sourceType: string }).sourceType}`); + } else { + console.log(`${prop.propId}: ${prop.value}${prop.hasOverride ? ' (overridden)' : ''}`); + } + } + + // Round-trip: read current values, modify one, and write them back with setProps + const updatedProps = props.map((prop) => { + if (prop.propId === props[0].propId) { + return { propId: prop.propId, value: 'Updated value' }; + } + return { propId: prop.propId, value: prop.value }; + }); + + await instanceEl.setProps(updatedProps); + } else { + console.log('Please select a component instance.'); + } + }, + getResolvedProps: async () => { // Get the selected component instance const instanceEl = await webflow.getSelectedElement(); From 9149d29854930035f5033ac6eb910bdc6f066c3a Mon Sep 17 00:00:00 2001 From: Tim McMackin Date: Tue, 7 Apr 2026 08:23:35 -0400 Subject: [PATCH 5/5] Apply suggestions from code review Co-authored-by: James Mosier <2854919+jamesmosier@users.noreply.github.com> --- src/examples/components.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/examples/components.ts b/src/examples/components.ts index 3ffd4b8..c7a1c18 100644 --- a/src/examples/components.ts +++ b/src/examples/components.ts @@ -309,7 +309,7 @@ export const Components = { if (typeof prop.value === 'object' && prop.value !== null && 'sourceType' in prop.value) { console.log(`${prop.propId}: bound to ${(prop.value as { sourceType: string }).sourceType}`); } else { - console.log(`${prop.propId}: ${prop.value}${prop.hasOverride ? ' (overridden)' : ''}`); + console.log(`${prop.propId}: ${JSON.stringify(prop.value)}${prop.hasOverride ? ' (overridden)' : ''}`); } } @@ -336,7 +336,7 @@ export const Components = { const resolvedProps = await instanceEl.getResolvedProps(); for (const prop of resolvedProps) { - console.log(`${prop.propId}: ${prop.value}`); + console.log(`${prop.propId}: ${JSON.stringify(prop.value)}`); } // Comparison of all three instance prop read APIs: