forked from mem9-ai/mem9
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathui-dialog-layout.ts
More file actions
86 lines (73 loc) · 2.43 KB
/
ui-dialog-layout.ts
File metadata and controls
86 lines (73 loc) · 2.43 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
export type PixelFarmDialogTail = "bottom-left" | "bottom-right";
export interface PixelFarmDialogPlacementInput {
viewportWidth: number;
viewportHeight: number;
anchorX: number;
anchorY: number;
dialogWidth: number;
dialogHeight: number;
marginX: number;
marginTop: number;
marginBottom: number;
offsetAboveAnchor: number;
}
export interface PixelFarmDialogPlacement {
mode: "anchor" | "safe-area";
x: number;
y: number;
tail: PixelFarmDialogTail;
}
function clamp(value: number, min: number, max: number): number {
return Math.min(Math.max(value, min), max);
}
function isWithinBounds(
value: number,
min: number,
max: number,
): boolean {
return value >= min && value <= max;
}
function chooseTail(anchorX: number, centerX: number): PixelFarmDialogTail {
return anchorX <= centerX ? "bottom-left" : "bottom-right";
}
function chooseSafeAreaX(input: PixelFarmDialogPlacementInput): number {
const safeMinX = input.marginX;
const safeMaxX = input.viewportWidth - input.marginX - input.dialogWidth;
const centeredX = Math.round((input.viewportWidth - input.dialogWidth) * 0.5);
if (centeredX >= safeMinX && centeredX <= safeMaxX) {
return centeredX;
}
const anchoredX = Math.round(input.anchorX - input.dialogWidth * 0.5);
return clamp(anchoredX, safeMinX, safeMaxX);
}
export function computePixelFarmDialogPlacement(
input: PixelFarmDialogPlacementInput,
): PixelFarmDialogPlacement {
const safeMinX = input.marginX;
const safeMaxX = input.viewportWidth - input.marginX - input.dialogWidth;
const safeMinY = input.marginTop;
const safeMaxY = input.viewportHeight - input.marginBottom - input.dialogHeight;
const anchoredX = Math.round(input.anchorX - input.dialogWidth * 0.5);
const anchoredY = Math.round(input.anchorY - input.dialogHeight - input.offsetAboveAnchor);
const anchoredFits =
isWithinBounds(anchoredX, safeMinX, safeMaxX) &&
isWithinBounds(anchoredY, safeMinY, safeMaxY);
if (anchoredFits) {
const centerX = anchoredX + input.dialogWidth * 0.5;
return {
mode: "anchor",
x: anchoredX,
y: anchoredY,
tail: chooseTail(input.anchorX, centerX),
};
}
const safeX = chooseSafeAreaX(input);
const safeY = safeMinY > safeMaxY ? safeMinY : safeMinY;
const centerX = safeX + input.dialogWidth * 0.5;
return {
mode: "safe-area",
x: Math.round(safeX),
y: Math.round(safeY),
tail: chooseTail(input.anchorX, centerX),
};
}