import type { Alignment } from "@blueprintjs/core"; import type { IconName } from "@blueprintjs/icons"; import type { ButtonPlacement, ButtonVariant } from "components/constants"; import { ButtonPlacementTypes, ButtonVariantTypes } from "components/constants"; import { EventType } from "constants/AppsmithActionConstants/ActionConstants"; import { ValidationTypes } from "constants/WidgetValidation"; import type { Stylesheet } from "entities/AppTheming"; import { get } from "lodash"; import React from "react"; import type { WidgetProps, WidgetState } from "widgets/BaseWidget"; import BaseWidget from "widgets/BaseWidget"; import { MinimumPopupRows } from "widgets/constants"; import ButtonGroupComponent from "../component"; import { getStylesheetValue } from "./helpers"; import { DefaultAutocompleteDefinitions } from "widgets/WidgetUtils"; import type { AutocompletionDefinitions } from "widgets/constants"; class ButtonGroupWidget extends BaseWidget< ButtonGroupWidgetProps, WidgetState > { static getAutocompleteDefinitions(): AutocompletionDefinitions { return { "!doc": "The Button group widget represents a set of buttons in a group. Group can have simple buttons or menu buttons with drop-down items.", "!url": "https://docs.appsmith.com/widget-reference/button-group", isVisible: DefaultAutocompleteDefinitions.isVisible, }; } static getPropertyPaneContentConfig() { return [ { sectionName: "Data", children: [ { helpText: "Group Buttons", propertyName: "groupButtons", controlType: "GROUP_BUTTONS", label: "Buttons", isBindProperty: false, isTriggerProperty: false, dependencies: ["childStylesheet"], panelConfig: { editableTitle: true, titlePropertyName: "label", panelIdPropertyName: "id", updateHook: ( props: any, propertyPath: string, propertyValue: string, ) => { return [ { propertyPath, propertyValue, }, ]; }, contentChildren: [ { sectionName: "Data", children: [ { propertyName: "buttonType", label: "Button type", controlType: "ICON_TABS", fullWidth: true, helpText: "Sets button type", options: [ { label: "Simple", value: "SIMPLE", }, { label: "Menu", value: "MENU", }, ], defaultValue: "SIMPLE", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT, params: { allowedValues: ["SIMPLE", "MENU"], }, }, }, { hidden: ( props: ButtonGroupWidgetProps, propertyPath: string, ) => { const buttonType = get( props, `${propertyPath.split(".", 2).join(".")}.buttonType`, "", ); return buttonType !== "MENU"; }, dependencies: ["groupButtons"], helpText: "Menu items", propertyName: "menuItems", controlType: "MENU_ITEMS", label: "Menu items", isBindProperty: false, isTriggerProperty: false, panelConfig: { editableTitle: true, titlePropertyName: "label", panelIdPropertyName: "id", updateHook: ( props: any, propertyPath: string, propertyValue: string, ) => { return [ { propertyPath, propertyValue, }, ]; }, contentChildren: [ { sectionName: "Label", children: [ { propertyName: "label", helpText: "Sets the label of a menu item", label: "Text", controlType: "INPUT_TEXT", placeholderText: "Enter label", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, { sectionName: "General", children: [ { propertyName: "isVisible", helpText: "Controls the visibility of menu item", label: "Visible", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN, }, }, { propertyName: "isDisabled", helpText: "Disables menu item", label: "Disabled", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN, }, }, ], }, { sectionName: "Events", children: [ { helpText: "when the menu item is clicked", propertyName: "onClick", label: "onClick", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, ], }, ], styleChildren: [ { sectionName: "Icon", children: [ { propertyName: "iconName", label: "Icon", helpText: "Sets the icon to be used for a menu item", controlType: "ICON_SELECT", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "iconAlign", label: "Position", helpText: "Sets the icon alignment of a menu item", controlType: "ICON_TABS", fullWidth: false, options: [ { startIcon: "skip-left-line", value: "left", }, { startIcon: "skip-right-line", value: "right", }, ], defaultValue: "left", isBindProperty: false, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, { sectionName: "Color", children: [ { propertyName: "backgroundColor", helpText: "Sets the background color of a menu item", label: "Background color", controlType: "COLOR_PICKER", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "iconColor", helpText: "Sets the icon color of a menu item", label: "Icon Color", controlType: "COLOR_PICKER", isBindProperty: false, isTriggerProperty: false, }, { propertyName: "textColor", helpText: "Sets the text color of a menu item", label: "Text color", controlType: "COLOR_PICKER", isBindProperty: false, isTriggerProperty: false, }, ], }, ], }, }, ], }, { sectionName: "Label", children: [ { propertyName: "label", helpText: "Sets the label of a menu item", label: "Text", controlType: "INPUT_TEXT", placeholderText: "Enter label", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, { sectionName: "General", children: [ { propertyName: "isVisible", helpText: "Controls the visibility of the widget", label: "Visible", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isDisabled", helpText: "Disables input to the widget", label: "Disabled", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, ], }, { sectionName: "Events", hidden: ( props: ButtonGroupWidgetProps, propertyPath: string, ) => { const buttonType = get( props, `${propertyPath}.buttonType`, "", ); return buttonType === "MENU"; }, children: [ { helpText: "when the button is clicked", propertyName: "onClick", label: "onClick", controlType: "ACTION_SELECTOR", isJSConvertible: true, isBindProperty: true, isTriggerProperty: true, }, ], }, ], styleChildren: [ { sectionName: "Icon", children: [ { propertyName: "iconName", label: "Icon", helpText: "Sets the icon to be used for a button", controlType: "ICON_SELECT", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "iconAlign", label: "Position", helpText: "Sets the icon alignment of a button", controlType: "ICON_TABS", fullWidth: false, options: [ { startIcon: "skip-left-line", value: "left", }, { startIcon: "skip-right-line", value: "right", }, ], defaultValue: "left", isBindProperty: false, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, { propertyName: "placement", label: "Placement", controlType: "DROP_DOWN", helpText: "Sets the space between items", options: [ { label: "Start", value: ButtonPlacementTypes.START, }, { label: "Between", value: ButtonPlacementTypes.BETWEEN, }, { label: "Center", value: ButtonPlacementTypes.CENTER, }, ], defaultValue: ButtonPlacementTypes.CENTER, isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT, params: { allowedValues: [ ButtonPlacementTypes.START, ButtonPlacementTypes.BETWEEN, ButtonPlacementTypes.CENTER, ], default: ButtonPlacementTypes.CENTER, }, }, }, ], }, { sectionName: "Color", children: [ { getStylesheetValue, propertyName: "buttonColor", helpText: "Changes the color of the button", label: "Button color", controlType: "COLOR_PICKER", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, ], }, }, ], }, { sectionName: "General", children: [ { helpText: "Controls the visibility of the widget", propertyName: "isVisible", label: "Visible", controlType: "SWITCH", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { propertyName: "isDisabled", label: "Disabled", controlType: "SWITCH", helpText: "Disables clicks to this widget", isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.BOOLEAN }, }, { 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 }, }, ], }, ]; } static getPropertyPaneStyleConfig() { return [ { sectionName: "General", children: [ { propertyName: "buttonVariant", label: "Button variant", controlType: "ICON_TABS", fullWidth: true, helpText: "Sets the variant of the button", options: [ { label: "Primary", value: ButtonVariantTypes.PRIMARY, }, { label: "Secondary", value: ButtonVariantTypes.SECONDARY, }, { label: "Tertiary", value: ButtonVariantTypes.TERTIARY, }, ], defaultValue: ButtonVariantTypes.PRIMARY, isJSConvertible: true, isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT, params: { allowedValues: [ ButtonVariantTypes.PRIMARY, ButtonVariantTypes.SECONDARY, ButtonVariantTypes.TERTIARY, ], default: ButtonVariantTypes.PRIMARY, }, }, }, { helpText: "Controls widget orientation", propertyName: "orientation", label: "Orientation", controlType: "ICON_TABS", fullWidth: true, options: [ { label: "Horizontal", value: "horizontal", }, { label: "Vertical", value: "vertical", }, ], defaultValue: "horizontal", isBindProperty: true, isTriggerProperty: false, validation: { type: ValidationTypes.TEXT }, }, ], }, { sectionName: "Border and shadow", children: [ { 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 getStylesheetConfig(): Stylesheet { return { borderRadius: "{{appsmith.theme.borderRadius.appBorderRadius}}", boxShadow: "none", childStylesheet: { button: { buttonColor: "{{appsmith.theme.colors.primaryColor}}", }, }, }; } handleClick = (onClick: string | undefined, callback: () => void): void => { if (onClick) { super.executeAction({ triggerPropertyName: "onClick", dynamicString: onClick, event: { type: EventType.ON_CLICK, callback, }, }); } }; getPageView() { const { componentWidth } = this.getComponentDimensions(); const minPopoverWidth = MinimumPopupRows * this.props.parentColumnSpace; return ( ); } static getWidgetType(): string { return "BUTTON_GROUP_WIDGET"; } } export interface ButtonGroupWidgetProps extends WidgetProps { orientation: string; isDisabled: boolean; borderRadius?: string; boxShadow?: string; buttonVariant: ButtonVariant; groupButtons: Record< string, { widgetId: string; id: string; index: number; isVisible?: boolean; isDisabled?: boolean; label?: string; buttonType?: string; buttonColor?: string; iconName?: IconName; iconAlign?: Alignment; placement?: ButtonPlacement; onClick?: string; menuItems: Record< string, { widgetId: string; id: string; index: number; isVisible?: boolean; isDisabled?: boolean; label?: string; backgroundColor?: string; textColor?: string; iconName?: IconName; iconColor?: string; iconAlign?: Alignment; onClick?: string; } >; } >; } export default ButtonGroupWidget;