All shapes now have a Fill in the properties panel; color inputs are now optional (#583)

* Add aditional stroke properties

* Make the colour input optional

* Fix fmt

* Apply code review changes

* Code review nitpicks

* Fix recursion

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
0HyperCube
2022-04-18 09:25:09 +01:00
committed by Keavon Chambers
co-authored by Keavon Chambers
parent a76bded12f
commit 66a100ff52
7 changed files with 157 additions and 70 deletions
@@ -1,6 +1,6 @@
<template>
<div class="floating-menu" :class="[direction.toLowerCase(), type.toLowerCase()]" v-if="open || type === 'Dialog'" ref="floatingMenu">
<div class="tail" v-if="type === 'Popover'"></div>
<div class="tail" v-if="type === 'Popover'" ref="tail"></div>
<div class="floating-menu-container" ref="floatingMenuContainer">
<LayoutCol class="floating-menu-content" data-floating-menu-content :scrollableY="scrollableY" ref="floatingMenuContent" :style="floatingMenuContentStyle">
<slot></slot>
@@ -201,51 +201,74 @@ export default defineComponent({
open: false,
pointerStillDown: false,
containerResizeObserver,
workspaceBounds: new DOMRect(),
floatingMenuBounds: new DOMRect(),
floatingMenuContentBounds: new DOMRect(),
};
},
// Gets the client bounds of the elements and apply relevant styles to them
// TODO: Use the Vue :style attribute more whilst not causing recursive updates
updated() {
const workspace = document.querySelector("[data-workspace]");
const floatingMenuContainer = this.$refs.floatingMenuContainer as HTMLElement;
const floatingMenuContentComponent = this.$refs.floatingMenuContent as typeof LayoutCol;
const floatingMenuContent = floatingMenuContentComponent && (floatingMenuContentComponent.$el as HTMLElement);
const workspace = document.querySelector("[data-workspace]");
const floatingMenu = this.$refs.floatingMenu as HTMLElement;
if (!floatingMenuContainer || !floatingMenuContentComponent || !floatingMenuContent || !workspace) return;
if (!workspace || !floatingMenuContainer || !floatingMenuContentComponent || !floatingMenuContent || !floatingMenu) return;
const workspaceBounds = workspace.getBoundingClientRect();
const floatingMenuBounds = floatingMenuContent.getBoundingClientRect();
this.workspaceBounds = workspace.getBoundingClientRect();
this.floatingMenuBounds = floatingMenu.getBoundingClientRect();
this.floatingMenuContentBounds = floatingMenuContent.getBoundingClientRect();
// Required to correctly position content when scrolled (it has a `position: fixed` to prevent clipping)
const tailOffset = this.type === "Popover" ? 10 : 0;
if (this.direction === "Bottom") floatingMenuContent.style.top = `${tailOffset + this.floatingMenuBounds.top}px`;
if (this.direction === "Top") floatingMenuContent.style.bottom = `${tailOffset + this.floatingMenuBounds.bottom}px`;
if (this.direction === "Right") floatingMenuContent.style.left = `${tailOffset + this.floatingMenuBounds.left}px`;
if (this.direction === "Left") floatingMenuContent.style.right = `${tailOffset + this.floatingMenuBounds.right}px`;
// Required to correctly position content when scrolled (it has a `position: fixed` to prevent clipping)
const tail = this.$refs.tail as HTMLElement;
if (tail) {
if (this.direction === "Bottom") tail.style.top = `${this.floatingMenuBounds.top}px`;
if (this.direction === "Top") tail.style.bottom = `${this.floatingMenuBounds.bottom}px`;
if (this.direction === "Right") tail.style.left = `${this.floatingMenuBounds.left}px`;
if (this.direction === "Left") tail.style.right = `${this.floatingMenuBounds.right}px`;
}
type Edge = "Top" | "Bottom" | "Left" | "Right";
let zeroedBorderDirection1: Edge | undefined;
let zeroedBorderDirection2: Edge | undefined;
let zeroedBorderVertical: Edge | undefined;
let zeroedBorderHorizontal: Edge | undefined;
if (this.direction === "Top" || this.direction === "Bottom") {
zeroedBorderDirection1 = this.direction === "Top" ? "Bottom" : "Top";
zeroedBorderVertical = this.direction === "Top" ? "Bottom" : "Top";
if (floatingMenuBounds.left - this.windowEdgeMargin <= workspaceBounds.left) {
if (this.floatingMenuContentBounds.left - this.windowEdgeMargin <= this.workspaceBounds.left) {
floatingMenuContent.style.left = `${this.windowEdgeMargin}px`;
if (workspaceBounds.left + floatingMenuContainer.getBoundingClientRect().left === 12) zeroedBorderDirection2 = "Left";
if (this.workspaceBounds.left + floatingMenuContainer.getBoundingClientRect().left === 12) zeroedBorderHorizontal = "Left";
}
if (floatingMenuBounds.right + this.windowEdgeMargin >= workspaceBounds.right) {
if (this.floatingMenuContentBounds.right + this.windowEdgeMargin >= this.workspaceBounds.right) {
floatingMenuContent.style.right = `${this.windowEdgeMargin}px`;
if (workspaceBounds.right - floatingMenuContainer.getBoundingClientRect().right === 12) zeroedBorderDirection2 = "Right";
if (this.workspaceBounds.right - floatingMenuContainer.getBoundingClientRect().right === 12) zeroedBorderHorizontal = "Right";
}
}
if (this.direction === "Left" || this.direction === "Right") {
zeroedBorderDirection2 = this.direction === "Left" ? "Right" : "Left";
zeroedBorderHorizontal = this.direction === "Left" ? "Right" : "Left";
if (floatingMenuBounds.top - this.windowEdgeMargin <= workspaceBounds.top) {
if (this.floatingMenuContentBounds.top - this.windowEdgeMargin <= this.workspaceBounds.top) {
floatingMenuContent.style.top = `${this.windowEdgeMargin}px`;
if (workspaceBounds.top + floatingMenuContainer.getBoundingClientRect().top === 12) zeroedBorderDirection1 = "Top";
if (this.workspaceBounds.top + floatingMenuContainer.getBoundingClientRect().top === 12) zeroedBorderVertical = "Top";
}
if (floatingMenuBounds.bottom + this.windowEdgeMargin >= workspaceBounds.bottom) {
if (this.floatingMenuContentBounds.bottom + this.windowEdgeMargin >= this.workspaceBounds.bottom) {
floatingMenuContent.style.bottom = `${this.windowEdgeMargin}px`;
if (workspaceBounds.bottom - floatingMenuContainer.getBoundingClientRect().bottom === 12) zeroedBorderDirection1 = "Bottom";
if (this.workspaceBounds.bottom - floatingMenuContainer.getBoundingClientRect().bottom === 12) zeroedBorderVertical = "Bottom";
}
}
// Remove the rounded corner from where the tail perfectly meets the corner
if (this.type === "Popover" && this.windowEdgeMargin === 6 && zeroedBorderDirection1 && zeroedBorderDirection2) {
switch (`${zeroedBorderDirection1}${zeroedBorderDirection2}`) {
// Remove the rounded corner from the content where the tail perfectly meets the corner
if (this.type === "Popover" && this.windowEdgeMargin === 6 && zeroedBorderVertical && zeroedBorderHorizontal) {
switch (`${zeroedBorderVertical}${zeroedBorderHorizontal}`) {
case "TopLeft":
floatingMenuContent.style.borderTopLeftRadius = "0";
break;
@@ -375,6 +398,7 @@ export default defineComponent({
}
});
}
// Switching from open to closed
if (!newState && oldState) {
window.removeEventListener("pointermove", this.pointerMoveHandler);