import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { ValidationTypes } from "constants/WidgetValidation"; import type { SetterConfig, Stylesheet } from "entities/AppTheming"; import React from "react"; import type { WidgetState } from "widgets/BaseWidget"; import BaseWidget from "widgets/BaseWidget"; import IframeComponent from "../component"; import type { IframeWidgetProps } from "../constants"; import { generateTypeDef } from "utils/autocomplete/dataTreeTypeDefCreator"; import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils"; import type { AutocompletionDefinitions } from "WidgetProvider/constants"; import { ResponsiveBehavior } from "layoutSystems/autolayout/utils/constants"; import IconSVG from "../icon.svg"; import { isAirgapped } from "@appsmith/utils/airgapHelpers"; import type { SnipingModeProperty, PropertyUpdates, } from "WidgetProvider/constants"; import { WIDGET_TAGS } from "constants/WidgetConstants"; const isAirgappedInstance = isAirgapped(); const DEFAULT_IFRAME_SOURCE = !isAirgappedInstance ? "https://www.example.com" : ""; class IframeWidget extends BaseWidget { static type = "IFRAME_WIDGET"; static getConfig() { return { name: "Iframe", iconSVG: IconSVG, tags: [WIDGET_TAGS.DISPLAY], needsMeta: true, searchTags: ["embed"], }; } static getDefaults() { return { source: DEFAULT_IFRAME_SOURCE, borderOpacity: 100, borderWidth: 1, rows: 32, columns: 24, widgetName: "Iframe", version: 1, animateLoading: true, responsiveBehavior: ResponsiveBehavior.Fill, }; } static getMethods() { return { getSnipingModeUpdates: ( propValueMap: SnipingModeProperty, ): PropertyUpdates[] => { return [ { propertyPath: "source", propertyValue: propValueMap.data, isDynamicPropertyPath: true, }, ]; }, }; } static getAutoLayoutConfig() { return { widgetSize: [ { viewportMinWidth: 0, configuration: () => { return { minWidth: "280px", minHeight: "300px", }; }, }, ], }; } static getAutocompleteDefinitions(): AutocompletionDefinitions { return (widget: IframeWidgetProps) => ({ "!doc": "Iframe widget is used to display iframes in your app.", "!url": "https://docs.appsmith.com/widget-reference/iframe", isVisible: DefaultAutocompleteDefinitions.isVisible, source: "string", title: "string", message: generateTypeDef(widget.message), messageMetadata: generateTypeDef(widget.messageMetadata), }); } static getSetterConfig(): SetterConfig { return { __setters: { setVisibility: { path: "isVisible", type: "boolean", }, setURL: { path: "source", type: "string", }, }, }; } static getPropertyPaneContentConfig() { return [ { sectionName: "Data", children: [ { propertyName: "source", helpText: "The URL of the page to embed", label: "URL", controlType: "INPUT_TEXT", placeholderText: "https://docs.appsmith.com", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.SAFE_URL, params: { default: "https://www.example.com", }, }, }, { propertyName: "srcDoc", helpText: "Inline HTML to embed, overriding the src attribute", label: "srcDoc", controlType: "INPUT_TEXT", placeholderText: "

Inline HTML

", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT, }, }, ], }, { sectionName: "General", children: [ { propertyName: "title", helpText: "Label the content of the page to embed", label: "Title", controlType: "INPUT_TEXT", placeholderText: "Documentation", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "animateLoading", label: "Animate loading", controlType: "SWITCH", helpText: "Controls the loading of the widget", defaultValue: true, isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, ], }, { sectionName: "Events", children: [ { helpText: "when the source URL is changed", propertyName: "onURLChanged", label: "onURLChanged", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, { helpText: "when the srcDoc is changed", propertyName: "onSrcDocChanged", label: "onSrcDocChanged", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, { helpText: "when a message event is received", propertyName: "onMessageReceived", label: "onMessageReceived", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, ], }, ]; } static getPropertyPaneStyleConfig() { return [ { sectionName: "Color", children: [ { propertyName: "borderColor", label: "Border color", helpText: "Controls the color of the border", controlType: "COLOR_PICKER", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, { sectionName: "Border and shadow", children: [ { propertyName: "borderWidth", label: "Border width (px)", helpText: "Controls the size of the border in px", controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, inputType: "NUMBER", validation: { type: ValidationTypes.NUMBER, params: { min: 0, default: 1 }, }, }, { propertyName: "borderOpacity", label: "Border opacity (%)", helpText: "Controls the opacity of the border in percentage", controlType: "INPUT_TEXT", isBindProperty: true, isTriggerProperty: false, inputType: "NUMBER", validation: { type: ValidationTypes.NUMBER, params: { min: 0, max: 100, default: 100 }, }, }, { propertyName: "borderRadius", label: "Border radius", helpText: "Rounds the corners of the icon button's outer border edge", controlType: "BORDER_RADIUS_OPTIONS", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "boxShadow", label: "Box shadow", helpText: "Enables you to cast a drop shadow from the frame of the widget", controlType: "BOX_SHADOW_OPTIONS", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, ]; } static getMetaPropertiesMap(): Record { return { message: undefined, messageMetadata: undefined, }; } static getStylesheetConfig(): Stylesheet { return { borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}", boxShadow: "{{appsmith.theme.boxShadow.appBoxShadow}}", }; } handleUrlChange = (url: string) => { if (url && this.props.onURLChanged) { super.executeAction({ triggerPropertyName: "onURLChanged", dynamicString: this.props.onURLChanged, event: { type: EventType.ON_IFRAME_URL_CHANGED, }, }); } }; handleSrcDocChange = (srcDoc?: string) => { if (srcDoc && this.props.onSrcDocChanged) { super.executeAction({ triggerPropertyName: "onSrcDocChanged", dynamicString: this.props.onSrcDocChanged, event: { type: EventType.ON_IFRAME_SRC_DOC_CHANGED, }, }); } }; handleMessageReceive = ({ data, lastEventId, origin, ports, }: MessageEvent) => { this.props.updateWidgetMetaProperty("messageMetadata", { lastEventId, origin, ports, }); this.props.updateWidgetMetaProperty("message", data, { triggerPropertyName: "onMessageReceived", dynamicString: this.props.onMessageReceived, event: { type: EventType.ON_IFRAME_MESSAGE_RECEIVED, }, }); }; getWidgetView() { const { borderColor, borderOpacity, borderWidth, renderMode, source, srcDoc, title, widgetId, widgetName, } = this.props; return ( ); } } export default IframeWidget;