interface Component { readonly [brand]: 'Component'; readonly id: ComponentId; /** * Whether this component is read-only through the Designer Extension API. * Library components and code components without site source are read-only. */ readonly readOnly: boolean; /** Library info when this component comes from an installed library. */ readonly library: ComponentLibraryInfo | null; /** Whether this component is backed by a code component render. */ readonly codeComponent: false; /** * Get the name of a specific component. * @returns A Promise that resolves to a string representing the name of a component. * @example * ```ts * const myComponentName = "Hero-Component"; * const components = await webflow.getAllComponents(); * * // Check if component exists * for (const c in components) { * const currentComponentName = await components[c].getName(); * if (componentName === currentComponentName) { * console.log("Found Hero Component"); * } * } * ``` */ getName(): Promise; /** * Set component name to the provided string. Components can be renamed, and the update happens immediately, * without requiring an explicit save() invocation. * @returns A Promise that resolves when the name change is successful. * @example * ```ts * await component.setName("She-ro Component") * ``` */ setName(name: string): Promise; /** * Get the root element for an editable site component. * Rejects for library components because their implementation is read-only. */ getRootElement(): Promise; /** * Get the number of instances of this component across the site. * Returns the same instance count displayed in the Components panel. * @returns A Promise resolving to the number of instances. * @example * ```ts * const component = (await webflow.getAllComponents())[0]; * const count = await component.getInstanceCount(); * console.log(`This component is used ${count} times`); * ``` */ getInstanceCount(): Promise; /** * Get all variants for this component, including the base variant. * Variants are returned in display order: base variant first (always `id: 'base'`), * followed by style variants in the order they appear in the component's variant field. * * @returns A Promise resolving to an array of Variant objects. Each variant includes: * - `id`: The unique identifier for the variant * - `name`: The display name of the variant * - `isSelected`: Indicates which variant is currently active in the Designer's editing context. * * @example * ```ts * const component = (await webflow.getAllComponents())[0]; * const variants = await component.getVariants(); * console.log(variants); * // [{ id: 'base', name: 'Primary', isSelected: true }, { id: 'xxxx', name: 'Secondary', isSelected: false }] * * // Find which variant is currently being edited * const activeVariant = variants.find(v => v.isSelected); * console.log(`Currently editing: ${activeVariant.name}`); * ``` */ getVariants(): Promise; /** * Create a new variant for this component. * @param name - The name for the new variant * @returns A promise that resolves to the newly created Variant. * @example * ```ts * const quickVariant = await heroComponent.createVariant("Dark Mode"); * const variant = await heroComponent.createVariant({ name: "Dark Mode" }); * console.log(quickVariant.name); // "Dark Mode" * console.log(variant.name); // "Dark Mode" * ``` */ createVariant(name: string): Promise; /** * Create a new variant for this component. * @param options - The name for the new variant and optional selection behavior * @returns A promise that resolves to the newly created Variant. * @example * ```ts * const variant = await heroComponent.createVariant({ name: "Dark Mode" }); * console.log(variant.name); // "Dark Mode" * ``` */ createVariant(options: CreateVariantOptions): Promise; /** * Duplicate an existing variant. Overload: pass sourceVariantId as second argument. * @param options - Options for the duplicate (name base, isSelected) * @param sourceVariantId - The variant ID to duplicate, or 'base' to duplicate the base variant * @returns A promise that resolves to the newly created duplicate Variant. * @example * ```ts * const duplicate = await heroComponent.createVariant({ name: "Copy" }, variants[1].id); * const baseCopy = await heroComponent.createVariant({ name: "Base Copy" }, "base"); * ``` */ createVariant( options: CreateVariantOptions, sourceVariantId: string ): Promise; /** * Get the currently selected variant for this component. * The selected variant reflects the Designer's current editing * context (which variant frame is active in Component Canvas). * * @returns A promise that resolves to the currently selected Variant. * If no variant is explicitly selected, returns the base variant. * Note: The returned variant will always have `isSelected: true` * * @example * ```ts * const variant = await heroComponent.getSelectedVariant(); * console.log(variant.name); // "Primary" * console.log(variant.isSelected); // always true * ``` */ getSelectedVariant(): Promise; /** * Set the selected variant for this component in the Designer. * Accepts an options object ({ name } or { id }) or a string shorthand for variant ID. * Use 'base' or { id: 'base' } to select the base variant. * @param options - Variant to select by name, by id, or string shorthand for id * @returns A promise that resolves when the variant is selected. * @example * ```ts * await heroComponent.setSelectedVariant('variant-dark'); * await heroComponent.setSelectedVariant({ name: 'Dark Mode' }); * await heroComponent.setSelectedVariant({ id: 'base' }); * ``` */ setSelectedVariant( options: SetSelectedVariantOptions | string ): Promise; /** * Reorder variants on this component by specifying an array of variant IDs * in the desired order. Accepts variant IDs or `'base'`. * * When a partial list is provided, the listed variants are repositioned * relative to the first item in the list while unlisted variants keep their * existing relative order. * * @param variantIds - Array of variant IDs (or `'base'`) in the desired order. * @returns A Promise that resolves when the reorder is complete. * @example * ```ts * // Full reorder * await component.reorderVariants(['base', 'variant-2', 'variant-1', 'variant-3']); * * // Partial reorder — move variant-1 and variant-3 together * // Before: base, variant-1, variant-2, variant-3 * await component.reorderVariants(['variant-1', 'variant-3']); * // After: base, variant-1, variant-3, variant-2 * ``` */ reorderVariants(variantIds: string[]): Promise; /** * Delete a variant from this component by ID. * The base variant cannot be deleted. * * @param options - An object containing the `id` of the variant to delete. * @returns A promise that resolves when the variant has been deleted. * @example * ```ts * await heroComponent.deleteVariant({ id: 'variant-456' }); * ``` */ deleteVariant(options: DeleteVariantOptions): Promise; /** * Get a single variant by ID. * Use `'base'` to retrieve the base variant. * @param variantId - The variant ID, or `'base'` for the base variant * @returns A Promise resolving to the Variant object. * @example * ```ts * const variant = await component.getVariant('variant-123'); * console.log(variant.name); // "Dark Mode" * * const base = await component.getVariant('base'); * console.log(base.name); // "Primary" * ``` */ getVariant(variantId: string): Promise; /** * Update settings on a variant. Currently only `name` is supported. * Use `'base'` as the variant ID to rename the base variant. * * @param variantId - The variant ID, or `'base'` for the base variant * @param settings - An object with the properties to update * @returns A Promise resolving to the updated Variant object. * @example * ```ts * // Two-argument form * const updated = await component.setVariant('variant-123', { name: 'Foo' }); * * // Rename the base variant * const base = await component.setVariant('base', { name: 'Default' }); * ``` */ setVariant(variantId: string, settings: {name: string}): Promise; /** * Update settings on a variant using an options object. * Currently only `name` is supported. * * @param options - An object containing the variant `id` and properties to update * @returns A Promise resolving to the updated Variant object. * @example * ```ts * const updated = await component.setVariant({ id: 'variant-123', name: 'Foo' }); * ``` */ setVariant(options: SetVariantOptions): Promise; /** * Get the settings (name, group, description) of a component. * @returns A Promise resolving to the component's settings. * @example * ```ts * const settings = await component.getSettings(); * console.log(settings.name); // 'Hero Section' * console.log(settings.group); // 'Sections' * console.log(settings.description); // 'A reusable hero' * ``` */ getSettings(): Promise; /** * Update one or more settings on a component. All fields are optional. * Updates happen immediately without requiring an explicit save(). * @param settings - A partial object of settings to update. * @returns A Promise that resolves when the update is complete. * @example * ```ts * await component.setSettings({ group: 'Legacy' }); // Set the group * await component.setSettings({ name: 'Hero v2', description: 'Redesigned hero' }); // Set the name and description * ``` */ setSettings(settings: Partial): Promise; /** * Get all prop definitions on this component. * Returns all prop types including variant, visibility, filter, sort, selectedItems, * and booleanFilter — not only the creatable types. * Props are returned in panel display order: ungrouped first, then grouped. * @returns A Promise resolving to an array of prop definitions. */ getProps(): Promise; /** * * Get a single prop definition by its ID. * @param propId - The unique ID of the prop. * @returns A Promise resolving to the prop definition. */ getProp(propId: string): Promise; /** * Get a prop definition by its display name. * Matches only ungrouped props. * Use the `groupName` overload for grouped props. * @param name - The display name of the prop. * @returns A Promise resolving to the prop definition. */ getPropByName(name: string): Promise; /** * Get a prop definition by its group and display name. * @param groupName - The group the prop belongs to. * @param name - The display name of the prop within that group. * @returns A Promise resolving to the prop definition. */ getPropByName(groupName: string, name: string): Promise; /** * Create a new prop on this component. * * Supports all 10 creatable prop types. Name conflicts within the same group * are auto-incremented (e.g., "Heading" → "Heading 2"). The returned `Prop` * includes computed fields (`id`, `valueType`, `bindableTo`) so callers don't * need a follow-up `getProps()` call. * * @param options - The prop definition including type, name, and optional settings. * @returns A Promise resolving to the created prop with computed binding metadata. * * @example * ```ts * const prop = await component.createProp({ * type: 'textContent', * name: 'Heading', * group: 'Content', * defaultValue: 'Welcome', * }); * ``` */ createProp(options: CreatePropOptions): Promise; /** * Create multiple props on this component in a single transaction. * If any prop fails validation, no props are created. * @param options - An array of prop definitions, each using the same shape as createProp. * @returns A Promise resolving to an array of created props, in the same order as the input. */ createProps(options: CreatePropOptions[]): Promise; /** * Update an existing prop's settings. * * Accepts a partial update object — only the fields being changed need to be * provided. Cannot change a prop's `type` (immutable after creation). * Name conflicts within the target group are auto-incremented. Setting a field * to `null` clears it where applicable. * * @param propId - The ID of the prop to update. * @param updates - A partial object with the fields to change. * @returns A Promise resolving to the full updated prop. * * @example * ```ts * const updated = await component.setProp(prop.id, { * name: 'Hero Heading', * tooltip: 'The main headline for the hero section', * }); * ``` */ setProp(propId: string, updates: SetPropOptions): Promise; /** * Update an existing prop's settings. * * @param updates - A partial object with `id` and the fields to change. * @returns A Promise resolving to the full updated prop. * * @example * ```ts * const updated = await component.setProp({ * id: prop.id, * name: 'Hero Heading', * }); * ``` */ setProp(updates: SetPropOptionsWithId): Promise; /** * Remove a prop from this component. * @param propId - The ID of the prop to remove. * @returns A Promise that resolves when the prop has been removed. * @example * ```ts * const props = await component.getProps(); * const unused = props.find(p => p.name === 'Old Heading'); * await component.removeProp(unused.id); * ``` */ removeProp(propId: string): Promise; } interface CodeComponent extends Omit { readonly readOnly: false; readonly codeComponent: true; } interface ReadOnlyCodeComponent extends Omit< Component, 'readOnly' | 'codeComponent' > { readonly readOnly: true; readonly codeComponent: true; } type AnyComponent = Component | CodeComponent | ReadOnlyCodeComponent; /** * Options for creating a new variant or duplicating an existing one. */ interface CreateVariantOptions { /** The name for the new variant (required for create, optional base for duplicate) */ name: string; /** Whether to select this variant after creation (optional, defaults to false) */ isSelected?: boolean; } /** Select variant by display name. */ interface SetSelectedVariantByName { name: string; } /** Select variant by ID. */ interface SetSelectedVariantById { id: string; } /** Options for setSelectedVariant — select by name or by id. */ type SetSelectedVariantOptions = | SetSelectedVariantByName | SetSelectedVariantById; /** Options for deleting a variant by ID. */ interface DeleteVariantOptions { /** The ID of the variant to delete. The base variant ('base') cannot be deleted. */ id: string; } /** Options for setVariant — update variant settings by ID. */ interface SetVariantOptions { /** The variant ID, or `'base'` for the base variant. */ id: string; /** The new display name for the variant. */ name: string; } interface Variant { /** The variant ID. The base variant always has id 'base'. */ readonly id: string; /** The display name of the variant. */ readonly name: string; /** * Indicates which variant is currently active in the Designer's editing context. * This reflects global Designer state (which variant frame is selected in Component Canvas), * not the component definition. * The base variant has `isSelected: true` when no variant is active. */ readonly isSelected: boolean; } /** * A prop definition on a component. * * `type` and `valueType` describe the same prop from two different angles: * - `type` is the prop's structural category in the component definition * (e.g. `'image'` for image asset props). * - `valueType` is the data-binding value type used when binding a CMS field * or variable to this prop (e.g. `'imageAsset'` for the same image prop). * For most prop types these are identical. The only current exception is image * asset props, where `type === 'image'` and `valueType === 'imageAsset'`. */ interface Prop { /** The field ID from the component's WFDL data type. */ readonly id: string; /** * The prop's structural category (e.g. `'string'`, `'boolean'`, `'image'`, * `'variant'`, `'slot'`). Use this to determine which optional fields * (`min`/`max`/`decimals`, `trueLabel`/`falseLabel`, `multiline`) are present. */ readonly type: PropType; /** * The data-binding value type for this prop (e.g. `'string'`, `'boolean'`, * `'imageAsset'`, `'variant'`). Use this when filtering which CMS fields or * variables are compatible with this prop via `bindableTo`. * Identical to `type` for all prop types except image asset props * (`type: 'image'`, `valueType: 'imageAsset'`). */ readonly valueType: BindableValueType; /** The data-binding target types this prop can accept. */ readonly bindableTo: readonly BindableValueType[]; /** The display name for this prop (derived from its label). */ name: string; /** The group name this prop belongs to, or null if ungrouped. */ group: string | null; /** A tooltip description for this prop, or null if not set. */ tooltip: string | null; /** * The default value for this prop, or null if not set or not applicable. * * The shape depends on `valueType`: * - `'string'` | `'number'` | `'id'` | `'altText'` → the raw primitive value * - `'boolean'` → `true` or `false` * - `'imageAsset'` → the asset ID string * - `'link'` → `{ mode: string; to?: string | object; openInNewTab?: boolean; rel?: string }` * - `'video'` → `{ src?: string; title?: string }` * - `'textContent'` → the plain-text string extracted from the default children * - `'richText'` → `{ innerText: string }` * - `'variant'` | `'visibility'` | `'filter'` | `'sort'` | `'selectedItems'` * → always `null` */ readonly defaultValue: ResolvedValue | null; /** Whether the text input allows multiple lines. Present on string and textContent props. */ multiline?: boolean; /** The minimum allowed value. Present on number props, otherwise null when unset. */ min?: number | null; /** The maximum allowed value. Present on number props, otherwise null when unset. */ max?: number | null; /** The number of decimal places (precision) allowed. Present on number props, otherwise null when unset. */ decimals?: number | null; /** The label shown when the boolean is true. Present on boolean props. */ trueLabel?: string; /** The label shown when the boolean is false. Present on boolean props. */ falseLabel?: string; } // --------------------------------------------------------------------------- // createProp input types (discriminated union on `type`) // --------------------------------------------------------------------------- /** * Fields shared between creating and updating props. * Used as the base interface for both {@link CreatePropCommon} and {@link SetPropOptions}. */ interface PropSettingsCommon { /** Display name for the prop. */ name?: string; /** Group/folder name. Props with the same group appear together. `null` to ungroup. */ group?: string | null; /** Tooltip text shown on hover. `null` to remove. */ tooltip?: string | null; /** The default value for this prop (shape depends on type). `null` to clear. */ defaultValue?: ResolvedValue | null; } /** Common fields shared by all prop types when creating. */ interface CreatePropCommon extends PropSettingsCommon { /** Display name for the prop. Auto-incremented on conflicts within the same group. */ name: string; /** Group/folder name. Props with the same group appear together in the props panel. */ group?: string; /** Tooltip text shown on hover in the props panel. */ tooltip?: string; } interface TextContentPropInput extends CreatePropCommon { type: 'textContent'; /** Whether the text input supports multiple lines. */ multiline?: boolean; defaultValue?: string; } interface StringPropInput extends CreatePropCommon { type: 'string'; defaultValue?: string; } interface RichTextPropInput extends CreatePropCommon { type: 'richText'; defaultValue?: RichTextResolvedValue; } interface ImagePropInput extends CreatePropCommon { type: 'image'; /** Default asset ID. */ defaultValue?: string; } interface LinkPropInput extends CreatePropCommon { type: 'link'; defaultValue?: LinkResolvedValue; } interface VideoPropInput extends CreatePropCommon { type: 'video'; defaultValue?: VideoResolvedValue; } interface NumberPropInput extends CreatePropCommon { type: 'number'; min?: number; max?: number; /** Number of decimal places allowed. */ decimals?: number; defaultValue?: number; } interface BooleanPropInput extends CreatePropCommon { type: 'boolean'; /** Label shown when the value is true (e.g., "Visible"). */ trueLabel?: string; /** Label shown when the value is false (e.g., "Hidden"). */ falseLabel?: string; defaultValue?: boolean; } interface IdPropInput extends CreatePropCommon { type: 'id'; /** * Default ID value. Normalized on the host side — invalid characters are * stripped, spaces become hyphens, result is lowercased. The response returns * the normalized value. Error if normalization produces an empty string. */ defaultValue?: string; } interface AltTextPropInput extends CreatePropCommon { type: 'altText'; /** * Default alt text value. The special strings `"decorative"` (marks image as * decorative) and `"inherit"` (inherit from asset) have semantic meaning. */ defaultValue?: string | null; } /** Options for creating a new prop on a component. Discriminated on `type`. */ type CreatePropOptions = | TextContentPropInput | StringPropInput | RichTextPropInput | ImagePropInput | LinkPropInput | VideoPropInput | NumberPropInput | BooleanPropInput | IdPropInput | AltTextPropInput; // --------------------------------------------------------------------------- // setProp input types // --------------------------------------------------------------------------- /** * Options for updating an existing prop on a component. * All fields are optional — only the fields being changed need to be provided. * Cannot change a prop's `type` (immutable after creation). * Setting a field to `null` clears it where applicable. */ interface SetPropOptions extends PropSettingsCommon { /** Whether the text input supports multiple lines. textContent only. */ multiline?: boolean; /** Minimum allowed value. number only. `null` clears the constraint. */ min?: number | null; /** Maximum allowed value. number only. `null` clears the constraint. */ max?: number | null; /** Number of decimal places allowed. number only. `null` clears the constraint. */ decimals?: number | null; /** Label shown when the value is true (e.g., "Visible"). boolean only. `null` clears. */ trueLabel?: string | null; /** Label shown when the value is false (e.g., "Hidden"). boolean only. `null` clears. */ falseLabel?: string | null; } /** {@link SetPropOptions} with an inline `id` for the single-argument overload. */ interface SetPropOptionsWithId extends SetPropOptions { /** The ID of the prop to update. */ id: string; } /** * Settings for a component, including name, group, and description. */ interface ComponentSettings { /** The name of the component */ name: string; /** The group/folder the component belongs to (empty string if not set) */ group: string; /** The description of the component (empty string if not set) */ description: string; } type ComponentId = string; /** Library info for an imported library component. */ interface ComponentLibraryInfo { /** The library's display name. */ name: string | null; /** The library's identifier. */ id: string; } /** A single result returned by {@link webflow.searchComponents}. */ interface ComponentSearchResult { /** The component's unique identifier. */ id: ComponentId; /** Display name of the component. */ name: string; /** Group/folder the component belongs to. */ group: string; /** Component description. */ description: string; /** Number of instances used across the site. */ instances: number; /** * Whether the current user can edit this component. * Always `false` for library components and read-only code components. * For native site components and editable site code components, depends on * the user's `canModifyComponents` permission. */ canEdit: boolean; /** Library info if this is an imported library component, otherwise `null`. */ library: ComponentLibraryInfo | null; } /** Options for {@link webflow.searchComponents}. */ interface SearchComponentsOptions { /** * Optional search query. * Uses the same fuzzy search (FlexSearch, `tokenize: 'full'`) as the Components panel. * When omitted, all components are returned in panel order. */ q?: string; } /** * Options for creating a blank component. */ interface ComponentOptions { /** The name of the component (required) */ name: string; /** The group/folder to place the component in (optional) */ group?: string; /** A description for the component (optional) */ description?: string; /** * Determines if the source element is replaced in the canvas by a * new instance of the created component after conversion. * Only applies when a canvas element is supplied as the `root` argument. * @default true */ replace?: boolean; }