fix: Button group widget's pop-over/drop-down enlarged along the width of the parent (#11804)
* fix: Button group widget's pop-over/drop-down enlarged along the width -- Implement dynamic width calculation * fix: Button group widget's pop-over/drop-down enlarged along the width -- Add corresponding Cypress test cases * fix: Button group widget's pop-over/drop-down enlarged along the width -- Add min-width CSS property for popover * fix: Button group widget's pop-over/drop-down enlarged along the width -- Add a comment for minPopoverWidth * fix: Button group widget's pop-over/drop-down enlarged along the width -- Remove the comment for minPopoverWidth * feat: Button group widget's pop-over/drop-down enlarged along the width -- update the state variable, itemWidths inside setTimeout to access the updated DOM * fix: Button gruop widget's pop-over/drop-down enlarged along the width -- Refine update logic * fix: Button group widget's pop-over/drop-down enlarged along the width -- Make code DRY by creating createMenuButtonRefs and getMenuButtonWidths methods * fix: Button group widget's popover/dropdown enlarged along the width -- Make every popover class name unique * fix: Button group widget's pop-over/drop-down enlarged along the width -- Rewrite Cypress test * fix: Button group widget's pop-over/drop-down enlarged along the width -- Eliminate unnecessary test case from ButtonGroup_spec
This commit is contained in:
parent
42bdb6c2ab
commit
35b1546f78
|
|
@ -0,0 +1,326 @@
|
||||||
|
{
|
||||||
|
"dsl": {
|
||||||
|
"widgetName": "MainContainer",
|
||||||
|
"backgroundColor": "none",
|
||||||
|
"rightColumn": 1160,
|
||||||
|
"snapColumns": 64,
|
||||||
|
"detachFromLayout": true,
|
||||||
|
"widgetId": "0",
|
||||||
|
"topRow": 0,
|
||||||
|
"bottomRow": 680,
|
||||||
|
"containerStyle": "none",
|
||||||
|
"snapRows": 125,
|
||||||
|
"parentRowSpace": 1,
|
||||||
|
"type": "CANVAS_WIDGET",
|
||||||
|
"canExtend": true,
|
||||||
|
"version": 54,
|
||||||
|
"minHeight": 690,
|
||||||
|
"parentColumnSpace": 1,
|
||||||
|
"dynamicBindingPathList": [],
|
||||||
|
"leftColumn": 0,
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"widgetName": "ButtonGroup1",
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"rightColumn": 50,
|
||||||
|
"isCanvas": false,
|
||||||
|
"displayName": "Button Group",
|
||||||
|
"iconSVG": "/static/media/icon.d6773218.svg",
|
||||||
|
"widgetId": "t5l24fccio",
|
||||||
|
"topRow": 15,
|
||||||
|
"bottomRow": 19,
|
||||||
|
"parentRowSpace": 10,
|
||||||
|
"isVisible": true,
|
||||||
|
"groupButtons": {
|
||||||
|
"groupButton1": {
|
||||||
|
"label": "Favorite",
|
||||||
|
"iconName": "heart",
|
||||||
|
"id": "groupButton1",
|
||||||
|
"widgetId": "",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton2": {
|
||||||
|
"label": "Add",
|
||||||
|
"iconName": "add",
|
||||||
|
"id": "groupButton2",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton3": {
|
||||||
|
"label": "More",
|
||||||
|
"iconName": "more",
|
||||||
|
"id": "groupButton3",
|
||||||
|
"buttonType": "MENU",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2,
|
||||||
|
"menuItems": {
|
||||||
|
"menuItem1": {
|
||||||
|
"label": "First Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem1",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"menuItem2": {
|
||||||
|
"label": "Second Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem2",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"menuItem3": {
|
||||||
|
"label": "Delete",
|
||||||
|
"iconName": "trash",
|
||||||
|
"iconColor": "#FFFFFF",
|
||||||
|
"iconAlign": "right",
|
||||||
|
"textColor": "#FFFFFF",
|
||||||
|
"backgroundColor": "#DD4B34",
|
||||||
|
"id": "menuItem3",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "BUTTON_GROUP_WIDGET",
|
||||||
|
"version": 1,
|
||||||
|
"hideCard": false,
|
||||||
|
"parentId": "0",
|
||||||
|
"renderMode": "CANVAS",
|
||||||
|
"isLoading": false,
|
||||||
|
"animateLoading": true,
|
||||||
|
"parentColumnSpace": 17.9375,
|
||||||
|
"leftColumn": 1,
|
||||||
|
"buttonVariant": "PRIMARY",
|
||||||
|
"key": "qxtmv7r8yb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgetName": "ButtonGroup2",
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"rightColumn": 25,
|
||||||
|
"isCanvas": false,
|
||||||
|
"displayName": "Button Group",
|
||||||
|
"iconSVG": "/static/media/icon.d6773218.svg",
|
||||||
|
"widgetId": "yxjq5sck7d",
|
||||||
|
"topRow": 4,
|
||||||
|
"bottomRow": 8,
|
||||||
|
"parentRowSpace": 10,
|
||||||
|
"isVisible": true,
|
||||||
|
"groupButtons": {
|
||||||
|
"groupButton1": {
|
||||||
|
"label": "Favorite",
|
||||||
|
"iconName": "heart",
|
||||||
|
"id": "groupButton1",
|
||||||
|
"widgetId": "",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton2": {
|
||||||
|
"label": "Add",
|
||||||
|
"iconName": "add",
|
||||||
|
"id": "groupButton2",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton3": {
|
||||||
|
"label": "More",
|
||||||
|
"iconName": "more",
|
||||||
|
"id": "groupButton3",
|
||||||
|
"buttonType": "MENU",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2,
|
||||||
|
"menuItems": {
|
||||||
|
"menuItem1": {
|
||||||
|
"label": "First Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem1",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"menuItem2": {
|
||||||
|
"label": "Second Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem2",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"menuItem3": {
|
||||||
|
"label": "Delete",
|
||||||
|
"iconName": "trash",
|
||||||
|
"iconColor": "#FFFFFF",
|
||||||
|
"iconAlign": "right",
|
||||||
|
"textColor": "#FFFFFF",
|
||||||
|
"backgroundColor": "#DD4B34",
|
||||||
|
"id": "menuItem3",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "BUTTON_GROUP_WIDGET",
|
||||||
|
"version": 1,
|
||||||
|
"hideCard": false,
|
||||||
|
"parentId": "0",
|
||||||
|
"renderMode": "CANVAS",
|
||||||
|
"isLoading": false,
|
||||||
|
"animateLoading": true,
|
||||||
|
"parentColumnSpace": 17.9375,
|
||||||
|
"leftColumn": 1,
|
||||||
|
"buttonVariant": "PRIMARY",
|
||||||
|
"key": "qxtmv7r8yb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgetName": "ButtonGroup3",
|
||||||
|
"isCanvas": false,
|
||||||
|
"displayName": "Button Group",
|
||||||
|
"iconSVG": "/static/media/icon.d6773218.svg",
|
||||||
|
"topRow": 29,
|
||||||
|
"bottomRow": 55,
|
||||||
|
"parentRowSpace": 10,
|
||||||
|
"groupButtons": {
|
||||||
|
"groupButton1": {
|
||||||
|
"label": "Favorite",
|
||||||
|
"iconName": "heart",
|
||||||
|
"id": "groupButton1",
|
||||||
|
"widgetId": "",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton2": {
|
||||||
|
"label": "Add",
|
||||||
|
"iconName": "add",
|
||||||
|
"id": "groupButton2",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"buttonType": "SIMPLE",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1,
|
||||||
|
"menuItems": {}
|
||||||
|
},
|
||||||
|
"groupButton3": {
|
||||||
|
"label": "More",
|
||||||
|
"iconName": "more",
|
||||||
|
"id": "groupButton3",
|
||||||
|
"buttonType": "MENU",
|
||||||
|
"placement": "CENTER",
|
||||||
|
"buttonColor": "#03B365",
|
||||||
|
"widgetId": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2,
|
||||||
|
"menuItems": {
|
||||||
|
"menuItem1": {
|
||||||
|
"label": "First Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem1",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 0
|
||||||
|
},
|
||||||
|
"menuItem2": {
|
||||||
|
"label": "Second Option",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"id": "menuItem2",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 1
|
||||||
|
},
|
||||||
|
"menuItem3": {
|
||||||
|
"label": "Delete",
|
||||||
|
"iconName": "trash",
|
||||||
|
"iconColor": "#FFFFFF",
|
||||||
|
"iconAlign": "right",
|
||||||
|
"textColor": "#FFFFFF",
|
||||||
|
"backgroundColor": "#DD4B34",
|
||||||
|
"id": "menuItem3",
|
||||||
|
"widgetId": "",
|
||||||
|
"onClick": "",
|
||||||
|
"isVisible": true,
|
||||||
|
"isDisabled": false,
|
||||||
|
"index": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"type": "BUTTON_GROUP_WIDGET",
|
||||||
|
"hideCard": false,
|
||||||
|
"animateLoading": true,
|
||||||
|
"parentColumnSpace": 17.9375,
|
||||||
|
"dynamicTriggerPathList": [],
|
||||||
|
"leftColumn": 1,
|
||||||
|
"dynamicBindingPathList": [],
|
||||||
|
"key": "qxtmv7r8yb",
|
||||||
|
"orientation": "horizontal",
|
||||||
|
"rightColumn": 50,
|
||||||
|
"widgetId": "mr048y04aq",
|
||||||
|
"isVisible": true,
|
||||||
|
"version": 1,
|
||||||
|
"parentId": "0",
|
||||||
|
"renderMode": "CANVAS",
|
||||||
|
"isLoading": false,
|
||||||
|
"buttonVariant": "PRIMARY"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
const dsl = require("../../../../fixtures/ButtonGroup_MenuButton_Width_dsl.json");
|
||||||
|
|
||||||
|
const widgetName = "buttongroupwidget";
|
||||||
|
|
||||||
|
describe("In a button group widget, menu button width", function() {
|
||||||
|
before(() => {
|
||||||
|
cy.addDsl(dsl);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("If target width is smaller than min-width, The menu button popover width should be set to minimum width", () => {
|
||||||
|
const minWidth = 12 * 11.9375;
|
||||||
|
const widgetId = "yxjq5sck7d";
|
||||||
|
const menuButtonId = "groupButton3";
|
||||||
|
// Get the default menu button
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.last()
|
||||||
|
.as("target");
|
||||||
|
// Open popover
|
||||||
|
cy.get("@target").click();
|
||||||
|
// Get the target width
|
||||||
|
cy.get("@target")
|
||||||
|
.invoke("outerWidth")
|
||||||
|
.then((targetWidth) => {
|
||||||
|
expect(targetWidth).to.be.lessThan(minWidth);
|
||||||
|
// Check if popover width is set to its target width
|
||||||
|
cy.get(
|
||||||
|
`.bp3-popover2.menu-button-width-${widgetId}-${menuButtonId}`,
|
||||||
|
).should("have.css", "width", `${minWidth}px`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("If target width is bigger than min width, The menu button popover width should always be the same as the target width", () => {
|
||||||
|
const minWidth = 12 * 11.9375;
|
||||||
|
const widgetId = "t5l24fccio";
|
||||||
|
const menuButtonId = "groupButton3";
|
||||||
|
|
||||||
|
// Get the default menu button
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.last()
|
||||||
|
.as("target");
|
||||||
|
// Open popover
|
||||||
|
cy.get("@target").click();
|
||||||
|
// Get the target width
|
||||||
|
cy.get("@target")
|
||||||
|
.invoke("outerWidth")
|
||||||
|
.then((targetWidth) => {
|
||||||
|
expect(targetWidth).to.be.greaterThan(minWidth);
|
||||||
|
// Check if popover width is set to its target width
|
||||||
|
cy.get(
|
||||||
|
`.bp3-popover2.menu-button-width-${widgetId}-${menuButtonId}`,
|
||||||
|
).should("have.css", "width", `${targetWidth}px`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("After converting a simple button to a menu button, The menu button popover width should always be the same as the target width", () => {
|
||||||
|
const minWidth = 12 * 11.9375;
|
||||||
|
const widgetId = "t5l24fccio";
|
||||||
|
const menuButtonId = "groupButton1";
|
||||||
|
// Change the first button type to menu
|
||||||
|
cy.editColumn(menuButtonId);
|
||||||
|
cy.selectDropdownValue(".t--property-control-buttontype", "Menu");
|
||||||
|
cy.get(".t--add-menu-item-btn").click();
|
||||||
|
// Get the newly converted menu button
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.first()
|
||||||
|
.as("target");
|
||||||
|
// Open popover
|
||||||
|
cy.get("@target").click();
|
||||||
|
// Get the target width
|
||||||
|
cy.get("@target")
|
||||||
|
.invoke("outerWidth")
|
||||||
|
.then((targetWidth) => {
|
||||||
|
expect(targetWidth).to.be.greaterThan(minWidth);
|
||||||
|
// Check if popover width is set to its target width
|
||||||
|
cy.get(
|
||||||
|
`.bp3-popover2.menu-button-width-${widgetId}-${menuButtonId}`,
|
||||||
|
).should("have.css", "width", `${targetWidth}px`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("If an existing menu button width changes, its popover width should always be the same as the changed target width", () => {
|
||||||
|
const minWidth = 12 * 11.9375;
|
||||||
|
const widgetId = "t5l24fccio";
|
||||||
|
const menuButtonId = "groupButton1";
|
||||||
|
cy.get(".t--property-pane-back-btn").click();
|
||||||
|
// Change the first button text
|
||||||
|
cy.get(".t--property-pane-section-buttons input")
|
||||||
|
.first()
|
||||||
|
.type("increase width");
|
||||||
|
cy.wait("@updateLayout").should(
|
||||||
|
"have.nested.property",
|
||||||
|
"response.body.responseMeta.status",
|
||||||
|
200,
|
||||||
|
);
|
||||||
|
// Get the menu button with its width changed
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.first()
|
||||||
|
.as("target");
|
||||||
|
// Open popover
|
||||||
|
cy.get("@target").click();
|
||||||
|
// Get the target width
|
||||||
|
cy.get("@target")
|
||||||
|
.invoke("outerWidth")
|
||||||
|
.then((targetWidth) => {
|
||||||
|
expect(targetWidth).to.be.greaterThan(minWidth);
|
||||||
|
// Check if popover width is set to its target width
|
||||||
|
cy.get(
|
||||||
|
`.bp3-popover2.menu-button-width-${widgetId}-${menuButtonId}`,
|
||||||
|
).should("have.css", "width", `${targetWidth}px`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("After changing the orientation to vertical , The menu button popover width should always be the same as the target width", () => {
|
||||||
|
const widgetId = "mr048y04aq";
|
||||||
|
const menuButtonId = "groupButton3";
|
||||||
|
// Open property pane of ButtonGroup3
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.first()
|
||||||
|
.click();
|
||||||
|
// Change its orientation to vetical
|
||||||
|
cy.selectDropdownValue(".t--property-control-orientation", "Vertical");
|
||||||
|
// Get the default menu button
|
||||||
|
cy.get(`.appsmith_widget_${widgetId} div.t--buttongroup-widget`)
|
||||||
|
.children()
|
||||||
|
.last()
|
||||||
|
.as("target");
|
||||||
|
// Open popover
|
||||||
|
cy.get("@target").click();
|
||||||
|
// Get the target width
|
||||||
|
cy.get("@target")
|
||||||
|
.invoke("outerWidth")
|
||||||
|
.then((targetWidth) => {
|
||||||
|
// Check if popover width is set to its target width
|
||||||
|
cy.get(
|
||||||
|
`.bp3-popover2.menu-button-width-${widgetId}-${menuButtonId}`,
|
||||||
|
).should("have.css", "width", `${targetWidth}px`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
after(() => {
|
||||||
|
// clean up after done
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
const explorer = require("../../../../locators/explorerlocators.json");
|
const explorer = require("../../../../locators/explorerlocators.json");
|
||||||
|
|
||||||
|
const widgetName = "buttongroupwidget";
|
||||||
|
|
||||||
describe("Button Group Widget Functionality", function() {
|
describe("Button Group Widget Functionality", function() {
|
||||||
before(() => {
|
before(() => {
|
||||||
// no dsl required
|
// no dsl required
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React from "react";
|
import React, { RefObject, createRef } from "react";
|
||||||
import { sortBy, uniqueId } from "lodash";
|
import { sortBy } from "lodash";
|
||||||
import {
|
import {
|
||||||
Alignment,
|
Alignment,
|
||||||
Icon,
|
Icon,
|
||||||
|
|
@ -29,12 +29,40 @@ import {
|
||||||
getCustomBorderColor,
|
getCustomBorderColor,
|
||||||
getCustomTextColor,
|
getCustomTextColor,
|
||||||
getCustomJustifyContent,
|
getCustomJustifyContent,
|
||||||
WidgetContainerDiff,
|
|
||||||
} from "widgets/WidgetUtils";
|
} from "widgets/WidgetUtils";
|
||||||
import { RenderMode, RenderModes } from "constants/WidgetConstants";
|
import { RenderMode, RenderModes } from "constants/WidgetConstants";
|
||||||
import { DragContainer } from "widgets/ButtonWidget/component/DragContainer";
|
import { DragContainer } from "widgets/ButtonWidget/component/DragContainer";
|
||||||
import { buttonHoverActiveStyles } from "../../ButtonWidget/component/utils";
|
import { buttonHoverActiveStyles } from "../../ButtonWidget/component/utils";
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
interface ButtonData {
|
||||||
|
id?: string;
|
||||||
|
type?: string;
|
||||||
|
label?: string;
|
||||||
|
iconName?: string;
|
||||||
|
}
|
||||||
|
// Extract props influencing to width change
|
||||||
|
const getButtonData = (
|
||||||
|
groupButtons: Record<string, GroupButtonProps>,
|
||||||
|
): ButtonData[] => {
|
||||||
|
const buttonData = Object.keys(groupButtons).reduce(
|
||||||
|
(acc: ButtonData[], id) => {
|
||||||
|
return [
|
||||||
|
...acc,
|
||||||
|
{
|
||||||
|
id,
|
||||||
|
type: groupButtons[id].buttonType,
|
||||||
|
label: groupButtons[id].label,
|
||||||
|
iconName: groupButtons[id].iconName,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return buttonData as ButtonData[];
|
||||||
|
};
|
||||||
|
|
||||||
interface WrapperStyleProps {
|
interface WrapperStyleProps {
|
||||||
isHorizontal: boolean;
|
isHorizontal: boolean;
|
||||||
borderRadius?: ButtonBorderRadius;
|
borderRadius?: ButtonBorderRadius;
|
||||||
|
|
@ -96,26 +124,19 @@ const MenuButtonWrapper = styled.div<{ renderMode: RenderMode }>`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const PopoverStyles = createGlobalStyle<{
|
const PopoverStyles = createGlobalStyle<{
|
||||||
parentWidth: number;
|
minPopoverWidth: number;
|
||||||
menuDropDownWidth: number;
|
popoverTargetWidth?: number;
|
||||||
id: string;
|
id: string;
|
||||||
}>`
|
}>`
|
||||||
.menu-button-popover > .${Classes.POPOVER2_CONTENT} {
|
.menu-button-popover > .${Classes.POPOVER2_CONTENT} {
|
||||||
background: none;
|
background: none;
|
||||||
}
|
}
|
||||||
${({ id, menuDropDownWidth, parentWidth }) => `
|
${({ id, minPopoverWidth, popoverTargetWidth }) => `
|
||||||
.menu-button-width-${id} {
|
.menu-button-width-${id} {
|
||||||
|
${popoverTargetWidth && `width: ${popoverTargetWidth}px`};
|
||||||
max-width: ${
|
min-width: ${minPopoverWidth}px;
|
||||||
menuDropDownWidth > parentWidth
|
}
|
||||||
? `${menuDropDownWidth}px`
|
`}
|
||||||
: `${parentWidth}px`
|
|
||||||
} !important;
|
|
||||||
min-width: ${
|
|
||||||
parentWidth > menuDropDownWidth ? parentWidth : menuDropDownWidth
|
|
||||||
}px !important;
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
interface ButtonStyleProps {
|
interface ButtonStyleProps {
|
||||||
|
|
@ -398,8 +419,128 @@ function PopoverContent(props: PopoverContentProps) {
|
||||||
return <StyledMenu>{listItems}</StyledMenu>;
|
return <StyledMenu>{listItems}</StyledMenu>;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ButtonGroupComponent extends React.Component<ButtonGroupComponentProps> {
|
class ButtonGroupComponent extends React.Component<
|
||||||
onButtonClick = (onClick?: string) => {
|
ButtonGroupComponentProps,
|
||||||
|
ButtonGroupComponentState
|
||||||
|
> {
|
||||||
|
private timer?: number;
|
||||||
|
|
||||||
|
constructor(props: ButtonGroupComponentProps) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
itemRefs: {},
|
||||||
|
itemWidths: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState(() => {
|
||||||
|
return {
|
||||||
|
...this.state,
|
||||||
|
itemRefs: this.createMenuButtonRefs(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.setState(() => {
|
||||||
|
return {
|
||||||
|
...this.state,
|
||||||
|
itemWidths: this.getMenuButtonWidths(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate(
|
||||||
|
prevProps: ButtonGroupComponentProps,
|
||||||
|
prevState: ButtonGroupComponentState,
|
||||||
|
) {
|
||||||
|
if (
|
||||||
|
this.state.itemRefs !== prevState.itemRefs ||
|
||||||
|
this.props.width !== prevProps.width ||
|
||||||
|
this.props.orientation !== prevProps.orientation
|
||||||
|
) {
|
||||||
|
if (this.timer) {
|
||||||
|
clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
this.timer = setTimeout(() => {
|
||||||
|
this.setState(() => {
|
||||||
|
return {
|
||||||
|
...this.state,
|
||||||
|
itemWidths: this.getMenuButtonWidths(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Reset refs array if
|
||||||
|
// * A button is added/removed or changed into a menu button
|
||||||
|
// * A label is changed or icon is newly added or removed
|
||||||
|
let isWidthChanged = false;
|
||||||
|
const buttons = getButtonData(this.props.groupButtons);
|
||||||
|
const menuButtons = buttons.filter((button) => button.type === "MENU");
|
||||||
|
const prevButtons = getButtonData(prevProps.groupButtons);
|
||||||
|
const prevMenuButtons = prevButtons.filter(
|
||||||
|
(button) => button.type === "MENU",
|
||||||
|
);
|
||||||
|
|
||||||
|
if (buttons.length !== prevButtons.length) {
|
||||||
|
isWidthChanged = true;
|
||||||
|
} else if (menuButtons.length > prevMenuButtons.length) {
|
||||||
|
isWidthChanged = true;
|
||||||
|
} else {
|
||||||
|
isWidthChanged = buttons.some((button) => {
|
||||||
|
const prevButton = prevButtons.find((btn) => btn.id === button.id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
button.label !== prevButton?.label ||
|
||||||
|
(button.iconName && !prevButton?.iconName) ||
|
||||||
|
(!button.iconName && prevButton?.iconName)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWidthChanged) {
|
||||||
|
this.setState(() => {
|
||||||
|
return {
|
||||||
|
...this.state,
|
||||||
|
itemRefs: this.createMenuButtonRefs(),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearTimeout(this.timer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get widths of menu buttons
|
||||||
|
getMenuButtonWidths = () =>
|
||||||
|
Object.keys(this.props.groupButtons).reduce((acc, id) => {
|
||||||
|
if (this.props.groupButtons[id].buttonType === "MENU") {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[id]: this.state.itemRefs[id].current?.getBoundingClientRect().width,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Create refs of menu buttons
|
||||||
|
createMenuButtonRefs = () =>
|
||||||
|
Object.keys(this.props.groupButtons).reduce((acc, id) => {
|
||||||
|
if (this.props.groupButtons[id].buttonType === "MENU") {
|
||||||
|
return {
|
||||||
|
...acc,
|
||||||
|
[id]: createRef(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
onButtonClick = (onClick: string | undefined) => () => {
|
||||||
this.props.buttonClickHandler(onClick);
|
this.props.buttonClickHandler(onClick);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -408,9 +549,9 @@ class ButtonGroupComponent extends React.Component<ButtonGroupComponentProps> {
|
||||||
buttonVariant,
|
buttonVariant,
|
||||||
groupButtons,
|
groupButtons,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
menuDropDownWidth,
|
minPopoverWidth,
|
||||||
orientation,
|
orientation,
|
||||||
width,
|
widgetId,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const isHorizontal = orientation === "horizontal";
|
const isHorizontal = orientation === "horizontal";
|
||||||
|
|
||||||
|
|
@ -435,17 +576,16 @@ class ButtonGroupComponent extends React.Component<ButtonGroupComponentProps> {
|
||||||
|
|
||||||
if (button.buttonType === "MENU" && !isButtonDisabled) {
|
if (button.buttonType === "MENU" && !isButtonDisabled) {
|
||||||
const { menuItems } = button;
|
const { menuItems } = button;
|
||||||
const id = uniqueId();
|
const popoverId = `${widgetId}-${button.id}`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuButtonWrapper
|
<MenuButtonWrapper
|
||||||
key={button.id}
|
key={button.id}
|
||||||
renderMode={this.props.renderMode}
|
renderMode={this.props.renderMode}
|
||||||
>
|
>
|
||||||
<PopoverStyles
|
<PopoverStyles
|
||||||
id={id}
|
id={popoverId}
|
||||||
menuDropDownWidth={menuDropDownWidth}
|
minPopoverWidth={minPopoverWidth}
|
||||||
parentWidth={width - WidgetContainerDiff}
|
popoverTargetWidth={this.state.itemWidths[button.id]}
|
||||||
/>
|
/>
|
||||||
<Popover2
|
<Popover2
|
||||||
content={
|
content={
|
||||||
|
|
@ -458,7 +598,7 @@ class ButtonGroupComponent extends React.Component<ButtonGroupComponentProps> {
|
||||||
fill
|
fill
|
||||||
minimal
|
minimal
|
||||||
placement="bottom-end"
|
placement="bottom-end"
|
||||||
popoverClassName={`menu-button-popover menu-button-width-${id}`}
|
popoverClassName={`menu-button-popover menu-button-width-${popoverId}`}
|
||||||
>
|
>
|
||||||
<DragContainer
|
<DragContainer
|
||||||
buttonColor={button.buttonColor}
|
buttonColor={button.buttonColor}
|
||||||
|
|
@ -477,6 +617,7 @@ class ButtonGroupComponent extends React.Component<ButtonGroupComponentProps> {
|
||||||
isHorizontal={isHorizontal}
|
isHorizontal={isHorizontal}
|
||||||
isLabel={!!button.label}
|
isLabel={!!button.label}
|
||||||
key={button.id}
|
key={button.id}
|
||||||
|
ref={this.state.itemRefs[button.id]}
|
||||||
>
|
>
|
||||||
<StyledButtonContent
|
<StyledButtonContent
|
||||||
iconAlign={button.iconAlign || "left"}
|
iconAlign={button.iconAlign || "left"}
|
||||||
|
|
@ -579,10 +720,16 @@ export interface ButtonGroupComponentProps {
|
||||||
buttonClickHandler: (onClick: string | undefined) => void;
|
buttonClickHandler: (onClick: string | undefined) => void;
|
||||||
groupButtons: Record<string, GroupButtonProps>;
|
groupButtons: Record<string, GroupButtonProps>;
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
menuDropDownWidth: number;
|
|
||||||
orientation: string;
|
orientation: string;
|
||||||
renderMode: RenderMode;
|
renderMode: RenderMode;
|
||||||
width: number;
|
width: number;
|
||||||
|
minPopoverWidth: number;
|
||||||
|
widgetId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ButtonGroupComponentState {
|
||||||
|
itemRefs: Record<string, RefObject<HTMLButtonElement>>;
|
||||||
|
itemWidths: Record<string, number>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ButtonGroupComponent;
|
export default ButtonGroupComponent;
|
||||||
|
|
|
||||||
|
|
@ -536,7 +536,7 @@ class ButtonGroupWidget extends BaseWidget<
|
||||||
|
|
||||||
getPageView() {
|
getPageView() {
|
||||||
const { componentWidth } = this.getComponentDimensions();
|
const { componentWidth } = this.getComponentDimensions();
|
||||||
const menuDropDownWidth = MinimumPopupRows * this.props.parentColumnSpace;
|
const minPopoverWidth = MinimumPopupRows * this.props.parentColumnSpace;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ButtonGroupComponent
|
<ButtonGroupComponent
|
||||||
|
|
@ -547,9 +547,10 @@ class ButtonGroupWidget extends BaseWidget<
|
||||||
buttonVariant={this.props.buttonVariant}
|
buttonVariant={this.props.buttonVariant}
|
||||||
groupButtons={this.props.groupButtons}
|
groupButtons={this.props.groupButtons}
|
||||||
isDisabled={this.props.isDisabled}
|
isDisabled={this.props.isDisabled}
|
||||||
menuDropDownWidth={menuDropDownWidth}
|
minPopoverWidth={minPopoverWidth}
|
||||||
orientation={this.props.orientation}
|
orientation={this.props.orientation}
|
||||||
renderMode={this.props.renderMode}
|
renderMode={this.props.renderMode}
|
||||||
|
widgetId={this.props.widgetId}
|
||||||
width={componentWidth}
|
width={componentWidth}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user