Skip to content

Commit 1882499

Browse files
chore: add some resizing structure
1 parent 438208b commit 1882499

3 files changed

Lines changed: 154 additions & 8 deletions

File tree

packages/main/src/Popover.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,30 @@ class Popover extends Popup {
217217
_width?: string;
218218
_height?: string;
219219

220+
_resizeMouseMoveHandler: (e: MouseEvent) => void;
221+
_resizeMouseUpHandler: (e: MouseEvent) => void;
222+
_y?: number;
223+
_x?: number;
224+
_isRTL?: boolean;
225+
_initialX?: number;
226+
_initialY?: number;
227+
_initialWidth?: number;
228+
_initialHeight?: number;
229+
_initialTop?: number;
230+
_initialLeft?: number;
231+
_minWidth?: number;
232+
_cachedMinHeight?: number;
233+
_draggedOrResized = false;
234+
220235
static get VIEWPORT_MARGIN() {
221236
return 10; // px
222237
}
223238

224239
constructor() {
225240
super();
241+
242+
this._resizeMouseMoveHandler = this._onResizeMouseMove.bind(this);
243+
this._resizeMouseUpHandler = this._onResizeMouseUp.bind(this);
226244
}
227245

228246
/**
@@ -873,6 +891,131 @@ class Popover extends Popup {
873891

874892
return this.horizontalAlign;
875893
}
894+
895+
get _showResizeHandle() {
896+
return this.resizable && this.onDesktop;
897+
}
898+
899+
_onResizeMouseDown(e: MouseEvent) {
900+
if (!this.resizable) {
901+
return;
902+
}
903+
904+
e.preventDefault();
905+
906+
const {
907+
top,
908+
left,
909+
} = this.getBoundingClientRect();
910+
const {
911+
width,
912+
height,
913+
minWidth,
914+
} = window.getComputedStyle(this);
915+
916+
this._initialX = e.clientX;
917+
this._initialY = e.clientY;
918+
this._initialWidth = Number.parseFloat(width);
919+
this._initialHeight = Number.parseFloat(height);
920+
this._initialTop = top;
921+
this._initialLeft = left;
922+
this._minWidth = Number.parseFloat(minWidth);
923+
// this._cachedMinHeight = this._minHeight;
924+
925+
Object.assign(this.style, {
926+
top: `${top}px`,
927+
left: `${left}px`,
928+
});
929+
930+
this._draggedOrResized = true;
931+
this._attachMouseResizeHandlers();
932+
}
933+
934+
_onResizeMouseMove(e: MouseEvent) {
935+
const { clientX, clientY } = e;
936+
937+
let newWidth,
938+
newLeft;
939+
940+
if (this._isRTL) {
941+
newWidth = clamp(
942+
this._initialWidth! - (clientX - this._initialX!),
943+
this._minWidth!,
944+
this._initialLeft! + this._initialWidth!,
945+
);
946+
947+
// check if width is changed to avoid "left" jumping when max width is reached
948+
Object.assign(this.style, {
949+
width: `${newWidth}px`,
950+
});
951+
952+
const deltaWidth = newWidth - this.getBoundingClientRect().width;
953+
const rightEdge = this._initialLeft! + this._initialWidth! + deltaWidth;
954+
955+
newLeft = clamp(
956+
rightEdge - newWidth,
957+
0,
958+
rightEdge - this._minWidth!,
959+
);
960+
} else {
961+
newWidth = clamp(
962+
this._initialWidth! + (clientX - this._initialX!),
963+
this._minWidth!,
964+
window.innerWidth - this._initialLeft!,
965+
);
966+
}
967+
968+
const newHeight = clamp(
969+
this._initialHeight! + (clientY - this._initialY!),
970+
this._cachedMinHeight!,
971+
window.innerHeight - this._initialTop!,
972+
);
973+
974+
Object.assign(this.style, {
975+
height: `${newHeight}px`,
976+
width: `${newWidth}px`,
977+
left: this._isRTL ? `${newLeft}px` : undefined,
978+
});
979+
}
980+
981+
_onResizeMouseUp() {
982+
delete this._initialX;
983+
delete this._initialY;
984+
delete this._initialWidth;
985+
delete this._initialHeight;
986+
delete this._initialTop;
987+
delete this._initialLeft;
988+
delete this._minWidth;
989+
delete this._cachedMinHeight;
990+
991+
this._detachMouseResizeHandlers();
992+
}
993+
994+
_handleDragStart(e: DragEvent) {
995+
if (this.draggable) {
996+
e.preventDefault();
997+
}
998+
}
999+
1000+
_attachMouseResizeHandlers() {
1001+
window.addEventListener("mousemove", this._resizeMouseMoveHandler);
1002+
window.addEventListener("mouseup", this._resizeMouseUpHandler);
1003+
this.addEventListener("ui5-before-close", this._revertSize, { once: true });
1004+
}
1005+
1006+
_detachMouseResizeHandlers() {
1007+
window.removeEventListener("mousemove", this._resizeMouseMoveHandler);
1008+
window.removeEventListener("mouseup", this._resizeMouseUpHandler);
1009+
}
1010+
1011+
_revertSize = () => {
1012+
Object.assign(this.style, {
1013+
top: "",
1014+
left: "",
1015+
width: "",
1016+
height: "",
1017+
});
1018+
}
8761019
}
8771020

8781021
const instanceOfPopover = (object: any): object is Popover => {

packages/main/src/PopoverTemplate.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ function afterContent(this: Popover) {
3535
</footer>
3636
}
3737

38-
{this.resizable &&
39-
<div class="ui5-popover-resize-handle">
40-
<Icon name={resizeCorner} class="ui5-popover-resize-handle-icon" mode="Decorative" />
38+
{this._showResizeHandle &&
39+
<div class="ui5-popover-resize-handle"
40+
onMouseDown={this._onResizeMouseDown}
41+
>
42+
<Icon name={resizeCorner} />
4143
</div>
4244
}
4345
</>);

packages/main/src/themes/Popover.css

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@
101101
z-index: 10;
102102
}
103103

104-
.ui5-popover-resize-handle .ui5-popover-resize-handle-icon {
104+
.ui5-popover-resize-handle [ui5-icon] {
105105
position: absolute;
106106
width: 1rem;
107107
height: 1rem;
108108
cursor: inherit;
109+
color: var(--sapButton_Lite_TextColor);
109110
}
110111

111112
.ui5-popover-resize-handle-top-right .ui5-popover-resize-handle {
@@ -114,7 +115,7 @@
114115
cursor: ne-resize;
115116
}
116117

117-
.ui5-popover-resize-handle-top-right .ui5-popover-resize-handle .ui5-popover-resize-handle-icon {
118+
.ui5-popover-resize-handle-top-right .ui5-popover-resize-handle [ui5-icon] {
118119
bottom: 0;
119120
left: 0;
120121
transform: rotate(270deg);
@@ -126,7 +127,7 @@
126127
cursor: nw-resize;
127128
}
128129

129-
.ui5-popover-resize-handle-top-left .ui5-popover-resize-handle .ui5-popover-resize-handle-icon {
130+
.ui5-popover-resize-handle-top-left .ui5-popover-resize-handle [ui5-icon] {
130131
bottom: 0;
131132
right: 0;
132133
transform: rotate(180deg);
@@ -138,7 +139,7 @@
138139
cursor: ne-resize;
139140
}
140141

141-
.ui5-popover-resize-handle-bottom-left .ui5-popover-resize-handle .ui5-popover-resize-handle-icon {
142+
.ui5-popover-resize-handle-bottom-left .ui5-popover-resize-handle [ui5-icon] {
142143
top: 0;
143144
right: 0;
144145
transform: rotate(90deg);
@@ -150,7 +151,7 @@
150151
cursor: nw-resize;
151152
}
152153

153-
.ui5-popover-resize-handle-bottom-right .ui5-popover-resize-handle .ui5-popover-resize-handle-icon {
154+
.ui5-popover-resize-handle-bottom-right .ui5-popover-resize-handle [ui5-icon] {
154155
top: 0;
155156
left: 0;
156157
}

0 commit comments

Comments
 (0)