chore: hydrate widgets properties from session on drop (#32934)
This PR adds a ability for anvil widgets ( mainly buttons, icon buttons, heading, paragraph and inline buttons ) to use values from session on creation on drop. /ok-to-test tags="@tag.Anvil" <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced logic to maintain button appearance using session storage values. - Added functionality to mark properties as reusable, enhancing widget configuration flexibility. - **Bug Fixes** - Corrected a syntax error in `WidgetCard.tsx` to ensure proper class name generation. - **Enhancements** - Improved widget creation process by saving and retrieving properties from session storage, ensuring consistency across sessions. <!-- 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/8936335019> > Commit: fbe155c1165c7e99d837474a7baf56b1430e880a > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=8936335019&attempt=1" target="_blank">Click here!</a> <!-- end of auto-generated comment: Cypress test results --> --------- Co-authored-by: Pawan Kumar <pawankumar@Pawans-MacBook-Pro-2.local>
This commit is contained in:
parent
a5edfb025a
commit
905e5b7338
|
|
@ -2,7 +2,6 @@ import React from "react";
|
||||||
import type { ControlProps } from "./BaseControl";
|
import type { ControlProps } from "./BaseControl";
|
||||||
import BaseControl from "./BaseControl";
|
import BaseControl from "./BaseControl";
|
||||||
import { generateReactKey } from "utils/generators";
|
import { generateReactKey } from "utils/generators";
|
||||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
|
||||||
import orderBy from "lodash/orderBy";
|
import orderBy from "lodash/orderBy";
|
||||||
import isString from "lodash/isString";
|
import isString from "lodash/isString";
|
||||||
import isUndefined from "lodash/isUndefined";
|
import isUndefined from "lodash/isUndefined";
|
||||||
|
|
@ -178,17 +177,13 @@ class ButtonListControl extends BaseControl<
|
||||||
let groupButtons = this.props.propertyValue;
|
let groupButtons = this.props.propertyValue;
|
||||||
const groupButtonsArray = this.getMenuItems();
|
const groupButtonsArray = this.getMenuItems();
|
||||||
const newGroupButtonId = generateReactKey({ prefix: "groupButton" });
|
const newGroupButtonId = generateReactKey({ prefix: "groupButton" });
|
||||||
const newGroupButtonLabel = getNextEntityName(
|
|
||||||
"Group Button ",
|
|
||||||
groupButtonsArray.map((groupButton: any) => groupButton.label),
|
|
||||||
);
|
|
||||||
|
|
||||||
groupButtons = {
|
groupButtons = {
|
||||||
...groupButtons,
|
...groupButtons,
|
||||||
[newGroupButtonId]: {
|
[newGroupButtonId]: {
|
||||||
id: newGroupButtonId,
|
id: newGroupButtonId,
|
||||||
index: groupButtonsArray.length,
|
index: groupButtonsArray.length,
|
||||||
label: isSeparator ? "Separator" : newGroupButtonLabel,
|
label: isSeparator ? "Separator" : "Do Something",
|
||||||
widgetId: generateReactKey(),
|
widgetId: generateReactKey(),
|
||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
itemType: isSeparator ? "SEPARATOR" : "BUTTON",
|
itemType: isSeparator ? "SEPARATOR" : "BUTTON",
|
||||||
|
|
@ -216,9 +211,23 @@ class ButtonListControl extends BaseControl<
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the widget is a WDS_INLINE_BUTTONS_WIDGET, and button already have filled button variant in groupButtons,
|
|
||||||
// then we should add a secondary button ( outlined button ) instead of simple button
|
|
||||||
if (this.props.widgetProperties.type === "WDS_INLINE_BUTTONS_WIDGET") {
|
if (this.props.widgetProperties.type === "WDS_INLINE_BUTTONS_WIDGET") {
|
||||||
|
// if buttonVariant and buttonColor values ar present in session storage, then we should use those values
|
||||||
|
const buttonVariantSessionValue = sessionStorage.getItem(
|
||||||
|
"WDS_INLINE_BUTTONS_WIDGET.buttonVariant",
|
||||||
|
);
|
||||||
|
const buttonColorSessionValue = sessionStorage.getItem(
|
||||||
|
"WDS_INLINE_BUTTONS_WIDGET.buttonColor",
|
||||||
|
);
|
||||||
|
|
||||||
|
groupButtons[newGroupButtonId] = {
|
||||||
|
...groupButtons[newGroupButtonId],
|
||||||
|
buttonVariant: buttonVariantSessionValue || "filled",
|
||||||
|
buttonColor: buttonColorSessionValue || "accent",
|
||||||
|
};
|
||||||
|
|
||||||
|
// if the widget is a WDS_INLINE_BUTTONS_WIDGET, and button already have filled button variant in groupButtons,
|
||||||
|
// then we should add a secondary button ( outlined button ) instead of simple button
|
||||||
const filledButtonVariant = groupButtonsArray.find(
|
const filledButtonVariant = groupButtonsArray.find(
|
||||||
(groupButton: any) => groupButton.buttonVariant === "filled",
|
(groupButton: any) => groupButton.buttonVariant === "filled",
|
||||||
);
|
);
|
||||||
|
|
@ -226,7 +235,7 @@ class ButtonListControl extends BaseControl<
|
||||||
if (filledButtonVariant) {
|
if (filledButtonVariant) {
|
||||||
groupButtons[newGroupButtonId] = {
|
groupButtons[newGroupButtonId] = {
|
||||||
...groupButtons[newGroupButtonId],
|
...groupButtons[newGroupButtonId],
|
||||||
buttonVariant: "outlined",
|
buttonVariant: buttonVariantSessionValue || "outlined",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,8 @@ export interface PropertyPaneControlConfig {
|
||||||
*/
|
*/
|
||||||
controlConfig?: Record<string, unknown>;
|
controlConfig?: Record<string, unknown>;
|
||||||
defaultValue?: unknown;
|
defaultValue?: unknown;
|
||||||
|
/** used to mark a property as reusable so that it can be reused in next dropping widget */
|
||||||
|
isReusable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ValidationConfigParams {
|
interface ValidationConfigParams {
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,8 @@ import type { PropertyUpdates } from "WidgetProvider/constants";
|
||||||
import { getIsOneClickBindingOptionsVisibility } from "selectors/oneClickBindingSelectors";
|
import { getIsOneClickBindingOptionsVisibility } from "selectors/oneClickBindingSelectors";
|
||||||
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
|
||||||
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
|
||||||
|
import { savePropertyInSessionStorageIfRequired } from "./helpers";
|
||||||
|
import { getParentWidget } from "selectors/widgetSelectors";
|
||||||
|
|
||||||
const ResetIcon = importSvg(
|
const ResetIcon = importSvg(
|
||||||
async () => import("assets/icons/control/undo_2.svg"),
|
async () => import("assets/icons/control/undo_2.svg"),
|
||||||
|
|
@ -99,6 +101,9 @@ const PropertyControl = memo((props: Props) => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const widgetProperties: WidgetProperties = useSelector(propsSelector, equal);
|
const widgetProperties: WidgetProperties = useSelector(propsSelector, equal);
|
||||||
|
const parentWidget = useSelector((state) =>
|
||||||
|
getParentWidget(state, widgetProperties.widgetId),
|
||||||
|
);
|
||||||
|
|
||||||
// get the dataTreePath and apply enhancement if exists
|
// get the dataTreePath and apply enhancement if exists
|
||||||
let dataTreePath: string | undefined =
|
let dataTreePath: string | undefined =
|
||||||
|
|
@ -574,6 +579,15 @@ const PropertyControl = memo((props: Props) => {
|
||||||
// updating properties of a widget(s) should be done only once when property value changes.
|
// updating properties of a widget(s) should be done only once when property value changes.
|
||||||
// to make sure dsl updates are atomic which is a necessity for undo/redo.
|
// to make sure dsl updates are atomic which is a necessity for undo/redo.
|
||||||
onBatchUpdatePropertiesOfMultipleWidgets(allPropertiesToUpdates);
|
onBatchUpdatePropertiesOfMultipleWidgets(allPropertiesToUpdates);
|
||||||
|
|
||||||
|
savePropertyInSessionStorageIfRequired({
|
||||||
|
isReusable: !!props.isReusable,
|
||||||
|
widgetProperties,
|
||||||
|
propertyName,
|
||||||
|
propertyValue,
|
||||||
|
parentWidgetId: parentWidget?.widgetId,
|
||||||
|
parentWidgetType: parentWidget?.type,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import { Callout } from "design-system";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import WidgetFactory from "WidgetProvider/factory";
|
import WidgetFactory from "WidgetProvider/factory";
|
||||||
import type { WidgetCallout } from "WidgetProvider/constants";
|
import type { WidgetCallout } from "WidgetProvider/constants";
|
||||||
|
import { isDynamicValue } from "utils/DynamicBindingUtils";
|
||||||
|
|
||||||
export function useSearchText(initialVal: string) {
|
export function useSearchText(initialVal: string) {
|
||||||
const [searchText, setSearchText] = useState(initialVal);
|
const [searchText, setSearchText] = useState(initialVal);
|
||||||
|
|
@ -127,3 +128,59 @@ export function renderWidgetCallouts(props: WidgetProps): JSX.Element[] {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* saves property value incase it is a reusable property in the session storage so that we can re-use
|
||||||
|
* the property value when we create widget on drop.
|
||||||
|
*
|
||||||
|
* Note: these values that we are storing will be used in widgetAddtionSaga to hydrate the widget properties when
|
||||||
|
* we create widget on drop
|
||||||
|
*/
|
||||||
|
export function savePropertyInSessionStorageIfRequired(props: {
|
||||||
|
isReusable: boolean;
|
||||||
|
widgetProperties: any;
|
||||||
|
propertyName: string;
|
||||||
|
propertyValue: string;
|
||||||
|
parentWidgetId?: string;
|
||||||
|
parentWidgetType?: string;
|
||||||
|
}) {
|
||||||
|
const {
|
||||||
|
isReusable,
|
||||||
|
parentWidgetId,
|
||||||
|
parentWidgetType,
|
||||||
|
propertyName,
|
||||||
|
propertyValue,
|
||||||
|
widgetProperties,
|
||||||
|
} = props;
|
||||||
|
|
||||||
|
if (isReusable && isDynamicValue(propertyValue) === false) {
|
||||||
|
let widgetType = widgetProperties.type;
|
||||||
|
let widgetPropertyName = propertyName;
|
||||||
|
|
||||||
|
// in case of type is WDS_ICON_BUTTON_WIDGET, we need to use key WDS_BUTTON_WIDGET, reason being
|
||||||
|
// we want to reuse the property values of icon button for button as well when we create button widget on drop
|
||||||
|
if (widgetType === "WDS_ICON_BUTTON_WIDGET") {
|
||||||
|
widgetType = "WDS_BUTTON_WIDGET";
|
||||||
|
}
|
||||||
|
|
||||||
|
// in case of type is WDS_INLINE_BUTTONS_WIDGET, we want to just store the property that is being changed, not the whole property path
|
||||||
|
if (widgetType === "WDS_INLINE_BUTTONS_WIDGET") {
|
||||||
|
widgetPropertyName = propertyName.split(".").pop() as string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if case of type is ZONE_WIDGET, we need to store the property value with parent widget id as well
|
||||||
|
// parent id is required because we want to hydrate value of property of the new zone widget only if the parent widget is same
|
||||||
|
if (widgetType === "ZONE_WIDGET") {
|
||||||
|
if (!(parentWidgetType && parentWidgetId)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
widgetPropertyName = `${parentWidgetId}.${widgetPropertyName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStorage.setItem(
|
||||||
|
`${widgetType}.${widgetPropertyName}`,
|
||||||
|
propertyValue,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,7 @@ import {
|
||||||
import { getPropertiesToUpdate } from "./WidgetOperationSagas";
|
import { getPropertiesToUpdate } from "./WidgetOperationSagas";
|
||||||
import { getWidget, getWidgets } from "./selectors";
|
import { getWidget, getWidgets } from "./selectors";
|
||||||
import { addBuildingBlockToCanvasSaga } from "./BuildingBlockAdditionSagas";
|
import { addBuildingBlockToCanvasSaga } from "./BuildingBlockAdditionSagas";
|
||||||
|
import { getCurrentlyOpenAnvilDetachedWidgets } from "layoutSystems/anvil/integrations/modalSelectors";
|
||||||
|
|
||||||
const WidgetTypes = WidgetFactory.widgetTypes;
|
const WidgetTypes = WidgetFactory.widgetTypes;
|
||||||
|
|
||||||
|
|
@ -86,8 +87,13 @@ function* getChildWidgetProps(
|
||||||
]);
|
]);
|
||||||
const themeDefaultConfig =
|
const themeDefaultConfig =
|
||||||
WidgetFactory.getWidgetStylesheetConfigMap(type) || {};
|
WidgetFactory.getWidgetStylesheetConfigMap(type) || {};
|
||||||
|
const widgetSessionValues = getWidgetSessionValues(type, parent);
|
||||||
const mainCanvasWidth: number = yield select(getCanvasWidth);
|
const mainCanvasWidth: number = yield select(getCanvasWidth);
|
||||||
const isMobile: boolean = yield select(getIsAutoLayoutMobileBreakPoint);
|
const isMobile: boolean = yield select(getIsAutoLayoutMobileBreakPoint);
|
||||||
|
const detachedWidgets: string[] = yield select(
|
||||||
|
getCurrentlyOpenAnvilDetachedWidgets,
|
||||||
|
);
|
||||||
|
const isModalOpen = detachedWidgets && detachedWidgets.length > 0;
|
||||||
|
|
||||||
if (!widgetName) {
|
if (!widgetName) {
|
||||||
const widgetNames = Object.keys(widgets).map((w) => widgets[w].widgetName);
|
const widgetNames = Object.keys(widgets).map((w) => widgets[w].widgetName);
|
||||||
|
|
@ -116,6 +122,12 @@ function* getChildWidgetProps(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in case we are creating zone inside zone, we want to use the parent's column space, we want
|
||||||
|
// to make sure the elevateBackground is set to false
|
||||||
|
if (type === "ZONE_WIDGET" && isModalOpen) {
|
||||||
|
props = { ...props, elevatedBackground: false };
|
||||||
|
}
|
||||||
|
|
||||||
const isAutoLayout = isStack(widgets, parent);
|
const isAutoLayout = isStack(widgets, parent);
|
||||||
const isFillWidget =
|
const isFillWidget =
|
||||||
restDefaultConfig?.responsiveBehavior === ResponsiveBehavior.Fill;
|
restDefaultConfig?.responsiveBehavior === ResponsiveBehavior.Fill;
|
||||||
|
|
@ -130,6 +142,7 @@ function* getChildWidgetProps(
|
||||||
widgetId: newWidgetId,
|
widgetId: newWidgetId,
|
||||||
renderMode: RenderModes.CANVAS,
|
renderMode: RenderModes.CANVAS,
|
||||||
...themeDefaultConfig,
|
...themeDefaultConfig,
|
||||||
|
...widgetSessionValues,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { minWidth } = getWidgetMinMaxDimensionsInPixel(
|
const { minWidth } = getWidgetMinMaxDimensionsInPixel(
|
||||||
|
|
@ -516,3 +529,50 @@ export default function* widgetAdditionSagas() {
|
||||||
takeEvery(ReduxActionTypes.WIDGET_ADD_NEW_TAB_CHILD, addNewTabChildSaga),
|
takeEvery(ReduxActionTypes.WIDGET_ADD_NEW_TAB_CHILD, addNewTabChildSaga),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* retrieves the values from session storage for the widget properties
|
||||||
|
* for hydration of the widget when we create widget on drop
|
||||||
|
*/
|
||||||
|
export function getWidgetSessionValues(
|
||||||
|
type: string,
|
||||||
|
parent: FlattenedWidgetProps,
|
||||||
|
) {
|
||||||
|
// For WDS_INLINE_BUTTONS_WIDGET, we want to hydation only to work when we add more items to the inline button group.
|
||||||
|
// So we don't want to hydrate the values when we drop the widget on the canvas.
|
||||||
|
if (["WDS_INLINE_BUTTONS_WIDGET"].includes(type)) return;
|
||||||
|
|
||||||
|
let widgetType = type;
|
||||||
|
const configMap = WidgetFactory.widgetConfigMap.get(type);
|
||||||
|
const widgetSessionValues: any = {};
|
||||||
|
|
||||||
|
// in case we are dropping WDS_ICON_BUTTON_WIDGET, we want to reuse the values of BUTTON_WIDGET
|
||||||
|
if (type === "WDS_ICON_BUTTON_WIDGET") {
|
||||||
|
widgetType = "WDS_BUTTON_WIDGET";
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const key in configMap) {
|
||||||
|
if (configMap[key]) {
|
||||||
|
let sessionStorageKey = `${widgetType}.${key}`;
|
||||||
|
|
||||||
|
if (type === "ZONE_WIDGET") {
|
||||||
|
sessionStorageKey = `${widgetType}.${parent.widgetId}.${key}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let valueFromSession: any = sessionStorage.getItem(sessionStorageKey);
|
||||||
|
|
||||||
|
// parse "true" as true and "false" as false
|
||||||
|
if (valueFromSession === "true") {
|
||||||
|
valueFromSession = true;
|
||||||
|
} else if (valueFromSession === "false") {
|
||||||
|
valueFromSession = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (valueFromSession !== undefined && valueFromSession !== null) {
|
||||||
|
widgetSessionValues[key] = valueFromSession;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return widgetSessionValues;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ export const propertyPaneStyle = [
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.BOOLEAN,
|
type: ValidationTypes.BOOLEAN,
|
||||||
},
|
},
|
||||||
|
isReusable: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -40,6 +41,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -40,6 +41,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,7 @@ export const propertyPaneContentConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -125,6 +126,7 @@ export const propertyPaneContentConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -69,6 +70,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: {
|
validation: {
|
||||||
type: ValidationTypes.TEXT,
|
type: ValidationTypes.TEXT,
|
||||||
params: {
|
params: {
|
||||||
|
|
@ -95,6 +97,7 @@ export const propertyPaneStyleConfig = [
|
||||||
isJSConvertible: true,
|
isJSConvertible: true,
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
isReusable: true,
|
||||||
validation: { type: ValidationTypes.TEXT },
|
validation: { type: ValidationTypes.TEXT },
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export const propertyPaneContentConfig = [
|
||||||
helpText: "Sets a default selected option",
|
helpText: "Sets a default selected option",
|
||||||
propertyName: "defaultOptionValue",
|
propertyName: "defaultOptionValue",
|
||||||
label: "Default selected value",
|
label: "Default selected value",
|
||||||
placeholderText: "Y",
|
placeholderText: "L",
|
||||||
controlType: "INPUT_TEXT",
|
controlType: "INPUT_TEXT",
|
||||||
isBindProperty: true,
|
isBindProperty: true,
|
||||||
isTriggerProperty: false,
|
isTriggerProperty: false,
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ export const defaultsConfig = {
|
||||||
widgetId: "",
|
widgetId: "",
|
||||||
id: "separator",
|
id: "separator",
|
||||||
index: 2,
|
index: 2,
|
||||||
|
label: "Separator",
|
||||||
itemType: "SEPARATOR",
|
itemType: "SEPARATOR",
|
||||||
},
|
},
|
||||||
button4: {
|
button4: {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user