/ok-to-test tags="@tag.Anvil" <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new `PropertyControlFactory` class for managing property controls. - Added new properties to the `PropertyPaneControlConfig` interface, enhancing customization and validation options. - Implemented methods for creating and registering control builders, improving the flexibility of property controls. - **Documentation** - Enhanced JSDoc comments for existing properties and methods, providing clearer guidance on their usage. - Updated documentation for the `PropertyPaneSectionConfig`, `PropertyPaneControlConfig`, and `ValidationConfigParams` interfaces to clarify their functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai --> <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/11716829822> > Commit: 62df82621a44126f2d876c77a892010265ec53d3 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=11716829822&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.Anvil` > Spec: > <hr>Thu, 07 Nov 2024 05:15:44 UTC <!-- end of auto-generated comment: Cypress test results -->
436 lines
14 KiB
TypeScript
436 lines
14 KiB
TypeScript
import { getPropertyControlTypes } from "components/propertyControls";
|
|
import type {
|
|
ValidationResponse,
|
|
ValidationTypes,
|
|
} from "constants/WidgetValidation";
|
|
import type { EvaluationSubstitutionType } from "entities/DataTree/dataTreeFactory";
|
|
import type { CodeEditorExpected } from "components/editorComponents/CodeEditor";
|
|
import type { UpdateWidgetPropertyPayload } from "actions/controlActions";
|
|
import type { AdditionalDynamicDataTree } from "utils/autocomplete/customTreeTypeDefCreator";
|
|
import type { Stylesheet } from "entities/AppTheming";
|
|
import type { ReduxActionType } from "ee/constants/ReduxActionConstants";
|
|
import type { PropertyUpdates } from "WidgetProvider/constants";
|
|
import type { WidgetProps } from "widgets/BaseWidget";
|
|
|
|
const ControlTypes = getPropertyControlTypes();
|
|
|
|
export type ControlType = (typeof ControlTypes)[keyof typeof ControlTypes];
|
|
|
|
export interface PropertyPaneSectionConfig {
|
|
/**
|
|
* Title displayed at the top of a collapsible section in the property pane.
|
|
*/
|
|
sectionName: string;
|
|
/**
|
|
* Unique identifier for the section. Used for:
|
|
* - Managing section collapse/expand state in Redux
|
|
* - Navigation and search functionality in the property pane
|
|
* - React rendering optimization (as key)
|
|
*
|
|
* If not provided, it will be auto-generated during widget initialization.
|
|
*/
|
|
id?: string;
|
|
/**
|
|
* Array of properties that should go inside the section.
|
|
*/
|
|
children: PropertyPaneConfig[];
|
|
/**
|
|
* If false, the section will not be collapsible.
|
|
*/
|
|
collapsible?: boolean;
|
|
/**
|
|
* A unique id generated by combining the ids of all the children.
|
|
* Mainly used in memoization to prevent unnecessary re-renders of property sections ( PropertySection.tsx )
|
|
*/
|
|
childrenId?: string;
|
|
/**
|
|
* Callback function to determine if the section should be hidden.
|
|
*
|
|
* @param props - Current widget properties
|
|
* @param propertyPath - Path to the widget property
|
|
* @returns - True if the section should be hidden, false otherwise
|
|
*/
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
hidden?: (props: any, propertyPath: string) => boolean;
|
|
/**
|
|
* when true, the section will be open by default.
|
|
* Note: Seems like this is not used anywhere.
|
|
*/
|
|
isDefaultOpen?: boolean;
|
|
propertySectionPath?: string;
|
|
/**
|
|
* Used to show a tag right after the section name (usedonly in the search results)
|
|
*/
|
|
tag?: string;
|
|
/**
|
|
* Indicates whether this section contains properties that need to be generated dynamically at runtime.
|
|
* Used in conjunction with generateDynamicProperties.
|
|
*
|
|
* Common use cases:
|
|
* - Dynamic event handlers ( CustomWidget's )
|
|
* - Properties that depend on user configuration
|
|
* - Properties that need to be generated based on widget state
|
|
*/
|
|
hasDynamicProperties?: boolean;
|
|
/**
|
|
* Function to generate property controls dynamically at runtime.
|
|
* Called when hasDynamicProperties is true.
|
|
*
|
|
* @param widget - Current widget properties
|
|
* @returns Array of dynamically generated property controls
|
|
*
|
|
* @example
|
|
* Used in CustomWidget and ExternalWidget to dynamically generate event handler properties
|
|
* based on available events.
|
|
*/
|
|
generateDynamicProperties?: (
|
|
widget: WidgetProps,
|
|
) => PropertyPaneControlConfig[];
|
|
expandedByDefault?: boolean;
|
|
}
|
|
|
|
export interface PanelConfig {
|
|
editableTitle: boolean;
|
|
titlePropertyName: string;
|
|
panelIdPropertyName: string;
|
|
children?: PropertyPaneConfig[];
|
|
contentChildren?: PropertyPaneConfig[];
|
|
styleChildren?: PropertyPaneConfig[];
|
|
searchConfig?: PropertyPaneConfig[]; // A combination of contentChildren and contentChildren which will be used to display search results
|
|
updateHook: (
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
props: any,
|
|
propertyPath: string,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
propertyValue: any,
|
|
) => Array<PropertyUpdates> | undefined;
|
|
}
|
|
|
|
export interface PropertyPaneControlConfig {
|
|
/**
|
|
* Unique identifier for the control. Used for internal tracking and debugging.
|
|
* It added by `addPropertyConfigIds` function in `WidgetProvider/factory/helpers.ts`.
|
|
*/
|
|
id?: string;
|
|
/**
|
|
* Label shown above the control.
|
|
*/
|
|
label: string;
|
|
/**
|
|
* Human-readable slugified name of the property. Used to identify the property in the widget properties.
|
|
*/
|
|
propertyName: string;
|
|
/**
|
|
* Used to provide more context about the property. Appears as tooltip when we hover over the label of the property.
|
|
* Note: This is different from `helperText` which appears below the property input.
|
|
*/
|
|
helpText?: string;
|
|
/**
|
|
* Dynamic text that appears below the property input.
|
|
*/
|
|
helperText?: ((props: unknown) => React.ReactNode) | React.ReactNode;
|
|
/**
|
|
* If true, transform the property input into plain input where js can be written..
|
|
*/
|
|
isJSConvertible?: boolean;
|
|
/**
|
|
* Used in special cases where we want to custom control instead regular text input control.
|
|
* For example: `COMPUTE_VALUE` control is used in table widget provides access to currentRow in controls in the table columns.
|
|
*/
|
|
customJSControl?: string;
|
|
/**
|
|
* Type of the property control.
|
|
* Full list of supported controls can be found in `app/client/src/components/propertyControls/index.ts`.
|
|
*/
|
|
controlType: ControlType;
|
|
/** @deprecated. Not used anywhere. */
|
|
validationMessage?: string;
|
|
/**
|
|
* path that is used to get evaluated value for the property.
|
|
*/
|
|
dataTreePath?: string;
|
|
/**
|
|
* There is no requirement to define children for a control. This is just done to suffice types
|
|
* in places where controlConfig and sectionConfig are not differentiated.
|
|
*/
|
|
children?: PropertyPaneConfig[];
|
|
panelConfig?: PanelConfig;
|
|
/**
|
|
* Callback function to update related widget properties.
|
|
*
|
|
* @param propertyName - Path to the widget property
|
|
* @param propertyValue - New value of the property
|
|
* @param props - Current widget properties
|
|
* @returns - Array of property updates
|
|
*
|
|
* @example Used in tabs widget to update the label of the tab.
|
|
*/
|
|
updateRelatedWidgetProperties?: (
|
|
propertyName: string,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
propertyValue: any,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
props: any,
|
|
) => UpdateWidgetPropertyPayload[];
|
|
/**
|
|
* Function that is called when the property is updated, it is mainly used to update other properties
|
|
*
|
|
* @param props - Current widget properties
|
|
* @param propertyName - Path to the widget property
|
|
* @param propertyValue - New value of the property
|
|
*
|
|
* @returns - Array of property updates
|
|
*/
|
|
updateHook?: (
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
props: any,
|
|
propertyName: string,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
propertyValue: any,
|
|
) => Array<PropertyUpdates> | undefined;
|
|
/**
|
|
* callback function to determine if the property should be hidden.
|
|
|
|
* @param props - Current widget properties
|
|
* @param propertyPath - Path to the widget property
|
|
* @returns - True if the property should be hidden, false otherwise
|
|
*/
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
hidden?: (props: any, propertyPath: string) => boolean;
|
|
/**
|
|
* If true, the property is hidden.
|
|
* Note: hidden and invisible do the same thing but differently. hidden uses a callback to determine if the property should be hidden.
|
|
* invisible is a boolean flag to hide the property.
|
|
*/
|
|
invisible?: boolean;
|
|
isBindProperty: boolean;
|
|
/**
|
|
* If true, it means the property triggers a widget action.
|
|
*
|
|
* @example
|
|
* OnClick property in Button widget is a trigger property that can trigger an action.
|
|
*/
|
|
isTriggerProperty: boolean;
|
|
/**
|
|
* Validation configuration for the property
|
|
*/
|
|
validation?: ValidationConfig;
|
|
/**
|
|
* Callback function to provide additional autocomplete data for the autocomplete list.
|
|
*
|
|
* @param props - Current widget properties
|
|
* @returns - Additional autocomplete data
|
|
*/
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
additionalAutoComplete?: (props: any) => AdditionalDynamicDataTree;
|
|
evaluationSubstitutionType?: EvaluationSubstitutionType;
|
|
/**
|
|
* All properties that current property is dependent on.
|
|
* All of these properties becomes available in `widgetProperties` in the property control..
|
|
*/
|
|
dependencies?: string[];
|
|
/**
|
|
* It is same as `dependencies` but these dependencies are not statically defined in the widget.
|
|
* The callback is called during rendering of the property control to get the latest dependencies.
|
|
*
|
|
* @example
|
|
* Used in CustomWidget to dynamically get the dependencies based on the current state of the widget.
|
|
*/
|
|
dynamicDependencies?: (widget: WidgetProps) => string[];
|
|
/**
|
|
* Dependencies to be picked from the __evaluated__ object
|
|
*/
|
|
evaluatedDependencies?: string[];
|
|
expected?: CodeEditorExpected;
|
|
/**
|
|
* Used to get value of the property from stylesheet config. Used in app theming v1 ( Not needed in anvil )
|
|
*
|
|
* @param props - Current widget properties
|
|
* @param propertyPath - Path to the widget property
|
|
* @param stylesheet - Stylesheet config
|
|
* @returns - Value of the property
|
|
*/
|
|
getStylesheetValue?: (
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
props: any,
|
|
propertyPath: string,
|
|
stylesheet?: Stylesheet,
|
|
) => Stylesheet[string];
|
|
/**
|
|
* Options for certain controls like Dropdown Control
|
|
* Note: This should be moved to controlConfig instead of being a top level property.
|
|
*/
|
|
// TODO(abhinav): To fix this, rename the options property of the controls which use this
|
|
// Alternatively, create a new structure
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
options?: any;
|
|
// The following should ideally be used internally
|
|
postUpdateAction?: ReduxActionType;
|
|
/**
|
|
* If true, the property is a panel property ( that is nested property pane )
|
|
*/
|
|
isPanelProperty?: boolean;
|
|
// Switch mode ( JS -> Text )
|
|
shouldSwitchToNormalMode?: (
|
|
isDynamic: boolean,
|
|
isToggleDisabled: boolean,
|
|
triggerFlag?: boolean,
|
|
) => boolean;
|
|
/**
|
|
* `controlConfig` is a generic record that can be used to pass additional configuration
|
|
* options to the property control. The specific structure and contents of this record
|
|
* will depend on the control type and its individual requirements.
|
|
*/
|
|
controlConfig?: Record<string, unknown>;
|
|
/**
|
|
* The default value of the property.
|
|
*/
|
|
defaultValue?: unknown;
|
|
/**
|
|
* If the property is marked reusable, on the next drop it will use the value of the last dropped widget.
|
|
*/
|
|
isReusable?: boolean;
|
|
}
|
|
|
|
interface ValidationConfigParams {
|
|
/**
|
|
* Minimum allowed value for a number.
|
|
*/
|
|
min?: number;
|
|
/**
|
|
* Maximum allowed value for a number.
|
|
*/
|
|
max?: number;
|
|
/**
|
|
* If true, the value must be a positive integer.
|
|
*/
|
|
natural?: boolean;
|
|
/**
|
|
* Default value for any type.
|
|
*/
|
|
default?: unknown;
|
|
/**
|
|
* If true or an array of strings, the value must be unique in an array.
|
|
* If an array of strings is provided, it specifies particular paths that must be unique.
|
|
*/
|
|
unique?: boolean | string[];
|
|
/**
|
|
* If true, the value is required.
|
|
* Now used to check if the value is an empty string.
|
|
*/
|
|
required?: boolean;
|
|
/**
|
|
* If true, the key is required.
|
|
*/
|
|
requiredKey?: boolean;
|
|
/**
|
|
* Validator regex for text type.
|
|
*/
|
|
regex?: RegExp;
|
|
/**
|
|
* Allowed keys in an object type.
|
|
*/
|
|
allowedKeys?: Array<{
|
|
name: string;
|
|
type: ValidationTypes;
|
|
params?: ValidationConfigParams;
|
|
}>;
|
|
/**
|
|
* Allowed values in a string and array type.
|
|
*/
|
|
allowedValues?: unknown[];
|
|
/**
|
|
* Children configurations in an ARRAY or OBJECT_ARRAY type.
|
|
*/
|
|
children?: ValidationConfig;
|
|
/**
|
|
* Validation function for FUNCTION type.
|
|
*
|
|
* @param value - The value to validate
|
|
* @param props - Current widget properties
|
|
* @param _ - Additional parameter (unused)
|
|
* @param moment - Moment.js instance
|
|
* @returns - Validation response
|
|
*/
|
|
fn?: (
|
|
value: unknown,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
props: any,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
_?: any,
|
|
// TODO: Fix this the next time the file is edited
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
moment?: any,
|
|
) => ValidationResponse;
|
|
/**
|
|
* AUTO GENERATED, SHOULD NOT BE SET BY WIDGET DEVELOPER
|
|
*/
|
|
fnString?: string;
|
|
/**
|
|
* FUNCTION type expected type and example.
|
|
*/
|
|
expected?: CodeEditorExpected;
|
|
/**
|
|
* If true, enables strict string validation of TEXT type.
|
|
*/
|
|
strict?: boolean;
|
|
/**
|
|
* If true, ignores the case of keys.
|
|
*/
|
|
ignoreCase?: boolean;
|
|
/**
|
|
* Used for ValidationType.ARRAY_OF_TYPE_OR_TYPE to define sub type.
|
|
*/
|
|
type?: ValidationTypes;
|
|
/**
|
|
* Used for ValidationType.UNION to define sub types.
|
|
*/
|
|
types?: ValidationConfig[];
|
|
/**
|
|
* Used for ValidationType.ARRAY_OF_TYPE_OR_TYPE to define sub type params.
|
|
*/
|
|
params?: ValidationConfigParams;
|
|
/**
|
|
* Used for ValidationType.NUMBER to allow 0 to be passed through. Default value is true.
|
|
*/
|
|
passThroughOnZero?: boolean;
|
|
/**
|
|
* Used for ValidationType.TEXT to limit line breaks in a large JSON object.
|
|
*/
|
|
limitLineBreaks?: boolean;
|
|
/**
|
|
* Used for ValidationType.UNION when none of the union type validations succeed.
|
|
*/
|
|
defaultValue?: unknown;
|
|
/**
|
|
* Used for ValidationType.UNION when none of the union type validations succeed.
|
|
*/
|
|
defaultErrorMessage?: string;
|
|
}
|
|
|
|
export interface ValidationConfig {
|
|
type: ValidationTypes;
|
|
params?: ValidationConfigParams;
|
|
}
|
|
|
|
export type PropertyPaneConfig =
|
|
| PropertyPaneSectionConfig
|
|
| PropertyPaneControlConfig;
|
|
|
|
export interface ActionValidationConfigMap {
|
|
[configProperty: string]: ValidationConfig;
|
|
}
|