@rogieking/figui3 6.6.3 → 6.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components.css +12 -0
- package/dist/components.css +1 -1
- package/dist/fig.css +1 -1
- package/dist/fig.js +18 -18
- package/fig.js +298 -120
- package/package.json +1 -1
package/fig.js
CHANGED
|
@@ -164,6 +164,19 @@ function figUniqueId() {
|
|
|
164
164
|
return Date.now().toString(36) + Math.random().toString(36).substring(2);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
/** Zero-size portal for fixed overlays so they never affect body layout metrics. */
|
|
168
|
+
function figGetOverlayRoot() {
|
|
169
|
+
if (!document.body) return null;
|
|
170
|
+
const attr = "data-figui-overlay-root";
|
|
171
|
+
let root = document.body.querySelector(`:scope > [${attr}]`);
|
|
172
|
+
if (!root) {
|
|
173
|
+
root = document.createElement("div");
|
|
174
|
+
root.setAttribute(attr, "");
|
|
175
|
+
document.body.append(root);
|
|
176
|
+
}
|
|
177
|
+
return root;
|
|
178
|
+
}
|
|
179
|
+
|
|
167
180
|
let _figZCounter = 10000;
|
|
168
181
|
function figGetHighestZIndex() {
|
|
169
182
|
return _figZCounter++;
|
|
@@ -859,13 +872,13 @@ class FigTooltip extends HTMLElement {
|
|
|
859
872
|
// - Without popover support, fall back to today's behavior: nearest open
|
|
860
873
|
// <dialog> ancestor if present, else document.body.
|
|
861
874
|
if (supportsPopover) {
|
|
862
|
-
document.body.append(this.popup);
|
|
875
|
+
(figGetOverlayRoot() ?? document.body).append(this.popup);
|
|
863
876
|
} else {
|
|
864
877
|
const parentDialog = this.closest("dialog");
|
|
865
878
|
if (parentDialog && parentDialog.open) {
|
|
866
879
|
parentDialog.append(this.popup);
|
|
867
880
|
} else {
|
|
868
|
-
document.body.append(this.popup);
|
|
881
|
+
(figGetOverlayRoot() ?? document.body).append(this.popup);
|
|
869
882
|
}
|
|
870
883
|
}
|
|
871
884
|
|
|
@@ -1142,13 +1155,13 @@ class FigTooltip extends HTMLElement {
|
|
|
1142
1155
|
popup.append(content);
|
|
1143
1156
|
|
|
1144
1157
|
if (supportsPopover) {
|
|
1145
|
-
document.body.append(popup);
|
|
1158
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
1146
1159
|
} else {
|
|
1147
1160
|
const parentDialog = anchor.closest?.("dialog");
|
|
1148
1161
|
if (parentDialog && parentDialog.open) {
|
|
1149
1162
|
parentDialog.append(popup);
|
|
1150
1163
|
} else {
|
|
1151
|
-
document.body.append(popup);
|
|
1164
|
+
(figGetOverlayRoot() ?? document.body).append(popup);
|
|
1152
1165
|
}
|
|
1153
1166
|
}
|
|
1154
1167
|
|
|
@@ -2884,10 +2897,150 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2884
2897
|
return "top";
|
|
2885
2898
|
}
|
|
2886
2899
|
|
|
2887
|
-
|
|
2900
|
+
lengthToPx(value, fallback = 0) {
|
|
2901
|
+
const styles = getComputedStyle(this);
|
|
2902
|
+
const raw = String(value || "").trim();
|
|
2903
|
+
const n = parseFloat(raw);
|
|
2904
|
+
if (!Number.isFinite(n)) return fallback;
|
|
2905
|
+
if (raw.endsWith("rem")) {
|
|
2906
|
+
return n * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
2907
|
+
}
|
|
2908
|
+
if (raw.endsWith("em")) {
|
|
2909
|
+
return n * parseFloat(styles.fontSize);
|
|
2910
|
+
}
|
|
2911
|
+
return n;
|
|
2912
|
+
}
|
|
2913
|
+
|
|
2914
|
+
radiusForSide(side) {
|
|
2915
|
+
const styles = getComputedStyle(this);
|
|
2916
|
+
const toPx = (value) => this.lengthToPx(value, 0);
|
|
2917
|
+
if (side === "top") {
|
|
2918
|
+
return Math.max(
|
|
2919
|
+
toPx(styles.borderTopLeftRadius),
|
|
2920
|
+
toPx(styles.borderTopRightRadius),
|
|
2921
|
+
);
|
|
2922
|
+
}
|
|
2923
|
+
if (side === "bottom") {
|
|
2924
|
+
return Math.max(
|
|
2925
|
+
toPx(styles.borderBottomLeftRadius),
|
|
2926
|
+
toPx(styles.borderBottomRightRadius),
|
|
2927
|
+
);
|
|
2928
|
+
}
|
|
2929
|
+
if (side === "left") {
|
|
2930
|
+
return Math.max(
|
|
2931
|
+
toPx(styles.borderTopLeftRadius),
|
|
2932
|
+
toPx(styles.borderBottomLeftRadius),
|
|
2933
|
+
);
|
|
2934
|
+
}
|
|
2935
|
+
if (side === "right") {
|
|
2936
|
+
return Math.max(
|
|
2937
|
+
toPx(styles.borderTopRightRadius),
|
|
2938
|
+
toPx(styles.borderBottomRightRadius),
|
|
2939
|
+
);
|
|
2940
|
+
}
|
|
2941
|
+
return 0;
|
|
2942
|
+
}
|
|
2943
|
+
|
|
2944
|
+
getBeakEdgeInset(beakSide) {
|
|
2945
|
+
const beakWidth = this.lengthToPx(
|
|
2946
|
+
getComputedStyle(this).getPropertyValue("--fig-popup-beak-width"),
|
|
2947
|
+
16,
|
|
2948
|
+
);
|
|
2949
|
+
return Math.max(10, this.radiusForSide(beakSide) + beakWidth / 2);
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
tracksAnchorBeak() {
|
|
2888
2953
|
const variant = this.getAttribute("variant");
|
|
2889
|
-
|
|
2890
|
-
|
|
2954
|
+
return variant === "popover" || variant === "tooltip";
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
getViewportBounds(m) {
|
|
2958
|
+
const vv = window.visualViewport;
|
|
2959
|
+
const width = vv?.width ?? window.innerWidth;
|
|
2960
|
+
const height = vv?.height ?? window.innerHeight;
|
|
2961
|
+
const offsetLeft = vv?.offsetLeft ?? 0;
|
|
2962
|
+
const offsetTop = vv?.offsetTop ?? 0;
|
|
2963
|
+
|
|
2964
|
+
return {
|
|
2965
|
+
minLeft: offsetLeft + m.left,
|
|
2966
|
+
minTop: offsetTop + m.top,
|
|
2967
|
+
maxRight: offsetLeft + width - m.right,
|
|
2968
|
+
maxBottom: offsetTop + height - m.bottom,
|
|
2969
|
+
};
|
|
2970
|
+
}
|
|
2971
|
+
|
|
2972
|
+
clampToViewport(coords, popupRect, m) {
|
|
2973
|
+
const bounds = this.getViewportBounds(m);
|
|
2974
|
+
const maxLeft = bounds.maxRight - popupRect.width;
|
|
2975
|
+
const maxTop = bounds.maxBottom - popupRect.height;
|
|
2976
|
+
|
|
2977
|
+
return {
|
|
2978
|
+
left: Math.min(maxLeft, Math.max(bounds.minLeft, coords.left)),
|
|
2979
|
+
top: Math.min(maxTop, Math.max(bounds.minTop, coords.top)),
|
|
2980
|
+
};
|
|
2981
|
+
}
|
|
2982
|
+
|
|
2983
|
+
resolveCoordsAtViewport(anchorRect, popupRect, coords, placementSide, m) {
|
|
2984
|
+
let { left, top } = this.clampToViewport(coords, popupRect, m);
|
|
2985
|
+
if (!anchorRect || !this.tracksAnchorBeak()) {
|
|
2986
|
+
return { left, top };
|
|
2987
|
+
}
|
|
2988
|
+
|
|
2989
|
+
const beakSide = this.oppositeSide(placementSide);
|
|
2990
|
+
const bounds = this.getViewportBounds(m);
|
|
2991
|
+
const maxLeft = bounds.maxRight - popupRect.width;
|
|
2992
|
+
const minLeft = bounds.minLeft;
|
|
2993
|
+
const maxTop = bounds.maxBottom - popupRect.height;
|
|
2994
|
+
const minTop = bounds.minTop;
|
|
2995
|
+
|
|
2996
|
+
if (beakSide === "top" || beakSide === "bottom") {
|
|
2997
|
+
const inset = this.getBeakEdgeInset(beakSide);
|
|
2998
|
+
const anchorCenterX = anchorRect.left + anchorRect.width / 2;
|
|
2999
|
+
const beakOffset = anchorCenterX - left;
|
|
3000
|
+
if (beakOffset < inset) {
|
|
3001
|
+
left = anchorCenterX - inset;
|
|
3002
|
+
} else if (beakOffset > popupRect.width - inset) {
|
|
3003
|
+
left = anchorCenterX - (popupRect.width - inset);
|
|
3004
|
+
}
|
|
3005
|
+
left = Math.min(maxLeft, Math.max(minLeft, left));
|
|
3006
|
+
} else if (beakSide === "left" || beakSide === "right") {
|
|
3007
|
+
const inset = this.getBeakEdgeInset(beakSide);
|
|
3008
|
+
const anchorCenterY = anchorRect.top + anchorRect.height / 2;
|
|
3009
|
+
const beakOffset = anchorCenterY - top;
|
|
3010
|
+
if (beakOffset < inset) {
|
|
3011
|
+
top = anchorCenterY - inset;
|
|
3012
|
+
} else if (beakOffset > popupRect.height - inset) {
|
|
3013
|
+
top = anchorCenterY - (popupRect.height - inset);
|
|
3014
|
+
}
|
|
3015
|
+
top = Math.min(maxTop, Math.max(minTop, top));
|
|
3016
|
+
}
|
|
3017
|
+
|
|
3018
|
+
return { left, top };
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
canPointAtAnchor(anchorRect, popupRect, left, top, placementSide) {
|
|
3022
|
+
if (!anchorRect || !this.tracksAnchorBeak()) return true;
|
|
3023
|
+
|
|
3024
|
+
const beakSide = this.oppositeSide(placementSide);
|
|
3025
|
+
const inset = this.getBeakEdgeInset(beakSide);
|
|
3026
|
+
|
|
3027
|
+
if (beakSide === "top" || beakSide === "bottom") {
|
|
3028
|
+
const beakOffset = anchorRect.left + anchorRect.width / 2 - left;
|
|
3029
|
+
return (
|
|
3030
|
+
beakOffset >= inset - 0.5 &&
|
|
3031
|
+
beakOffset <= popupRect.width - inset + 0.5
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
const beakOffset = anchorRect.top + anchorRect.height / 2 - top;
|
|
3036
|
+
return (
|
|
3037
|
+
beakOffset >= inset - 0.5 &&
|
|
3038
|
+
beakOffset <= popupRect.height - inset + 0.5
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
updatePopoverBeak(anchorRect, popupRect, left, top, placementSide) {
|
|
3043
|
+
if (!this.tracksAnchorBeak() || !anchorRect) {
|
|
2891
3044
|
this.style.removeProperty("--fig-popup-beak-offset");
|
|
2892
3045
|
this.removeAttribute("data-beak-side");
|
|
2893
3046
|
return;
|
|
@@ -2903,54 +3056,9 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2903
3056
|
measuredRect.width > 0 && measuredRect.height > 0
|
|
2904
3057
|
? measuredRect
|
|
2905
3058
|
: popupRect;
|
|
2906
|
-
// Always use the rendered popup rect so beak alignment matches real final placement.
|
|
2907
3059
|
const resolvedLeft = rect.left;
|
|
2908
3060
|
const resolvedTop = rect.top;
|
|
2909
|
-
const
|
|
2910
|
-
const toPx = (value, fallback = 0) => {
|
|
2911
|
-
const raw = String(value || "").trim();
|
|
2912
|
-
const n = parseFloat(raw);
|
|
2913
|
-
if (!Number.isFinite(n)) return fallback;
|
|
2914
|
-
if (raw.endsWith("rem")) {
|
|
2915
|
-
return n * parseFloat(getComputedStyle(document.documentElement).fontSize);
|
|
2916
|
-
}
|
|
2917
|
-
if (raw.endsWith("em")) {
|
|
2918
|
-
return n * parseFloat(styles.fontSize);
|
|
2919
|
-
}
|
|
2920
|
-
return n;
|
|
2921
|
-
};
|
|
2922
|
-
const radiusForSide = (side) => {
|
|
2923
|
-
if (side === "top") {
|
|
2924
|
-
return Math.max(
|
|
2925
|
-
toPx(styles.borderTopLeftRadius),
|
|
2926
|
-
toPx(styles.borderTopRightRadius),
|
|
2927
|
-
);
|
|
2928
|
-
}
|
|
2929
|
-
if (side === "bottom") {
|
|
2930
|
-
return Math.max(
|
|
2931
|
-
toPx(styles.borderBottomLeftRadius),
|
|
2932
|
-
toPx(styles.borderBottomRightRadius),
|
|
2933
|
-
);
|
|
2934
|
-
}
|
|
2935
|
-
if (side === "left") {
|
|
2936
|
-
return Math.max(
|
|
2937
|
-
toPx(styles.borderTopLeftRadius),
|
|
2938
|
-
toPx(styles.borderBottomLeftRadius),
|
|
2939
|
-
);
|
|
2940
|
-
}
|
|
2941
|
-
if (side === "right") {
|
|
2942
|
-
return Math.max(
|
|
2943
|
-
toPx(styles.borderTopRightRadius),
|
|
2944
|
-
toPx(styles.borderBottomRightRadius),
|
|
2945
|
-
);
|
|
2946
|
-
}
|
|
2947
|
-
return 0;
|
|
2948
|
-
};
|
|
2949
|
-
const beakWidth = toPx(
|
|
2950
|
-
styles.getPropertyValue("--fig-popup-beak-width"),
|
|
2951
|
-
16,
|
|
2952
|
-
);
|
|
2953
|
-
const edgeInset = Math.max(10, radiusForSide(beakSide) + beakWidth / 2);
|
|
3061
|
+
const edgeInset = this.getBeakEdgeInset(beakSide);
|
|
2954
3062
|
|
|
2955
3063
|
let beakOffset;
|
|
2956
3064
|
if (beakSide === "top" || beakSide === "bottom") {
|
|
@@ -2969,15 +3077,14 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2969
3077
|
}
|
|
2970
3078
|
|
|
2971
3079
|
overflowScore(coords, popupRect, m) {
|
|
2972
|
-
const
|
|
2973
|
-
const vh = window.innerHeight;
|
|
3080
|
+
const bounds = this.getViewportBounds(m);
|
|
2974
3081
|
const right = coords.left + popupRect.width;
|
|
2975
3082
|
const bottom = coords.top + popupRect.height;
|
|
2976
3083
|
|
|
2977
|
-
const overflowLeft = Math.max(0,
|
|
2978
|
-
const overflowTop = Math.max(0,
|
|
2979
|
-
const overflowRight = Math.max(0, right -
|
|
2980
|
-
const overflowBottom = Math.max(0, bottom -
|
|
3084
|
+
const overflowLeft = Math.max(0, bounds.minLeft - coords.left);
|
|
3085
|
+
const overflowTop = Math.max(0, bounds.minTop - coords.top);
|
|
3086
|
+
const overflowRight = Math.max(0, right - bounds.maxRight);
|
|
3087
|
+
const overflowBottom = Math.max(0, bottom - bounds.maxBottom);
|
|
2981
3088
|
|
|
2982
3089
|
return overflowLeft + overflowTop + overflowRight + overflowBottom;
|
|
2983
3090
|
}
|
|
@@ -2986,26 +3093,93 @@ class FigPopup extends HTMLDialogElement {
|
|
|
2986
3093
|
return this.overflowScore(coords, popupRect, m) === 0;
|
|
2987
3094
|
}
|
|
2988
3095
|
|
|
2989
|
-
clamp(coords, popupRect, m) {
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3096
|
+
clamp(coords, popupRect, m, anchorRect = null, placementSide = "top") {
|
|
3097
|
+
if (anchorRect) {
|
|
3098
|
+
return this.resolveCoordsAtViewport(
|
|
3099
|
+
anchorRect,
|
|
3100
|
+
popupRect,
|
|
3101
|
+
coords,
|
|
3102
|
+
placementSide,
|
|
3103
|
+
m,
|
|
3104
|
+
);
|
|
3105
|
+
}
|
|
3106
|
+
return this.clampToViewport(coords, popupRect, m);
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
primaryAxisOverflowPenalty(coords, popupRect, m, placementSide) {
|
|
3110
|
+
const bounds = this.getViewportBounds(m);
|
|
3111
|
+
let overflow = 0;
|
|
3112
|
+
|
|
3113
|
+
if (placementSide === "top") {
|
|
3114
|
+
overflow = Math.max(0, bounds.minTop - coords.top);
|
|
3115
|
+
} else if (placementSide === "bottom") {
|
|
3116
|
+
overflow = Math.max(0, coords.top + popupRect.height - bounds.maxBottom);
|
|
3117
|
+
} else if (placementSide === "left") {
|
|
3118
|
+
overflow = Math.max(0, bounds.minLeft - coords.left);
|
|
3119
|
+
} else if (placementSide === "right") {
|
|
3120
|
+
overflow = Math.max(0, coords.left + popupRect.width - bounds.maxRight);
|
|
3121
|
+
}
|
|
3122
|
+
|
|
3123
|
+
return overflow > 0 ? 1000 + overflow : 0;
|
|
3124
|
+
}
|
|
3125
|
+
|
|
3126
|
+
placementScore(anchorRect, popupRect, coords, placementSide, m) {
|
|
3127
|
+
const resolved = this.resolveCoordsAtViewport(
|
|
3128
|
+
anchorRect,
|
|
3129
|
+
popupRect,
|
|
3130
|
+
coords,
|
|
3131
|
+
placementSide,
|
|
3132
|
+
m,
|
|
2995
3133
|
);
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
3134
|
+
let score = this.overflowScore(resolved, popupRect, m);
|
|
3135
|
+
score += this.primaryAxisOverflowPenalty(
|
|
3136
|
+
coords,
|
|
3137
|
+
popupRect,
|
|
3138
|
+
m,
|
|
3139
|
+
placementSide,
|
|
2999
3140
|
);
|
|
3141
|
+
if (
|
|
3142
|
+
anchorRect &&
|
|
3143
|
+
!this.canPointAtAnchor(
|
|
3144
|
+
anchorRect,
|
|
3145
|
+
popupRect,
|
|
3146
|
+
resolved.left,
|
|
3147
|
+
resolved.top,
|
|
3148
|
+
placementSide,
|
|
3149
|
+
)
|
|
3150
|
+
) {
|
|
3151
|
+
score += 10000;
|
|
3152
|
+
}
|
|
3153
|
+
return { score, resolved };
|
|
3154
|
+
}
|
|
3000
3155
|
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3156
|
+
applyPopupPosition(
|
|
3157
|
+
anchorRect,
|
|
3158
|
+
popupRect,
|
|
3159
|
+
coords,
|
|
3160
|
+
placementSide,
|
|
3161
|
+
m,
|
|
3162
|
+
) {
|
|
3163
|
+
const resolved = this.resolveCoordsAtViewport(
|
|
3164
|
+
anchorRect,
|
|
3165
|
+
popupRect,
|
|
3166
|
+
coords,
|
|
3167
|
+
placementSide,
|
|
3168
|
+
m,
|
|
3169
|
+
);
|
|
3170
|
+
this.style.left = `${resolved.left}px`;
|
|
3171
|
+
this.style.top = `${resolved.top}px`;
|
|
3172
|
+
this.updatePopoverBeak(
|
|
3173
|
+
anchorRect,
|
|
3174
|
+
popupRect,
|
|
3175
|
+
resolved.left,
|
|
3176
|
+
resolved.top,
|
|
3177
|
+
placementSide,
|
|
3178
|
+
);
|
|
3005
3179
|
}
|
|
3006
3180
|
|
|
3007
3181
|
positionPopup() {
|
|
3008
|
-
if (!this.open
|
|
3182
|
+
if (!this.open) return;
|
|
3009
3183
|
|
|
3010
3184
|
const popupRect = this.getBoundingClientRect();
|
|
3011
3185
|
const offset = this.parseOffset();
|
|
@@ -3015,14 +3189,16 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3015
3189
|
|
|
3016
3190
|
if (!anchor) {
|
|
3017
3191
|
this.updatePopoverBeak(null, popupRect, 0, 0, "top");
|
|
3192
|
+
const bounds = this.getViewportBounds(m);
|
|
3018
3193
|
const centered = {
|
|
3019
3194
|
left:
|
|
3020
|
-
|
|
3195
|
+
bounds.minLeft +
|
|
3196
|
+
(bounds.maxRight - bounds.minLeft - popupRect.width) / 2,
|
|
3021
3197
|
top:
|
|
3022
|
-
|
|
3023
|
-
(
|
|
3198
|
+
bounds.minTop +
|
|
3199
|
+
(bounds.maxBottom - bounds.minTop - popupRect.height) / 2,
|
|
3024
3200
|
};
|
|
3025
|
-
const clamped = this.
|
|
3201
|
+
const clamped = this.clampToViewport(centered, popupRect, m);
|
|
3026
3202
|
this.style.left = `${clamped.left}px`;
|
|
3027
3203
|
this.style.top = `${clamped.top}px`;
|
|
3028
3204
|
return;
|
|
@@ -3041,69 +3217,63 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3041
3217
|
for (const { v, h, s } of candidates) {
|
|
3042
3218
|
const coords = this.computeCoords(anchorRect, popupRect, v, h, offset, s);
|
|
3043
3219
|
const placementSide = this.getPlacementSide(v, h, s);
|
|
3220
|
+
const { score, resolved } = this.placementScore(
|
|
3221
|
+
anchorRect,
|
|
3222
|
+
popupRect,
|
|
3223
|
+
coords,
|
|
3224
|
+
placementSide,
|
|
3225
|
+
m,
|
|
3226
|
+
);
|
|
3044
3227
|
|
|
3045
3228
|
if (s) {
|
|
3046
|
-
const
|
|
3229
|
+
const bounds = this.getViewportBounds(m);
|
|
3047
3230
|
const primaryFits =
|
|
3048
3231
|
s === "left" || s === "right"
|
|
3049
|
-
? coords.left >=
|
|
3050
|
-
coords.left + popupRect.width <=
|
|
3051
|
-
: coords.top >=
|
|
3052
|
-
coords.top + popupRect.height <=
|
|
3053
|
-
if (primaryFits) {
|
|
3054
|
-
this.
|
|
3055
|
-
this.style.top = `${clamped.top}px`;
|
|
3056
|
-
this.updatePopoverBeak(
|
|
3232
|
+
? coords.left >= bounds.minLeft &&
|
|
3233
|
+
coords.left + popupRect.width <= bounds.maxRight
|
|
3234
|
+
: coords.top >= bounds.minTop &&
|
|
3235
|
+
coords.top + popupRect.height <= bounds.maxBottom;
|
|
3236
|
+
if (primaryFits && score < 10000) {
|
|
3237
|
+
this.applyPopupPosition(
|
|
3057
3238
|
anchorRect,
|
|
3058
3239
|
popupRect,
|
|
3059
|
-
|
|
3060
|
-
clamped.top,
|
|
3240
|
+
coords,
|
|
3061
3241
|
placementSide,
|
|
3242
|
+
m,
|
|
3062
3243
|
);
|
|
3063
3244
|
return;
|
|
3064
3245
|
}
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
placementSide,
|
|
3081
|
-
);
|
|
3082
|
-
return;
|
|
3083
|
-
}
|
|
3084
|
-
const score = this.overflowScore(coords, popupRect, m);
|
|
3085
|
-
if (score < bestScore) {
|
|
3086
|
-
bestScore = score;
|
|
3087
|
-
best = coords;
|
|
3088
|
-
bestSide = placementSide;
|
|
3089
|
-
}
|
|
3246
|
+
} else if (score === 0) {
|
|
3247
|
+
this.applyPopupPosition(
|
|
3248
|
+
anchorRect,
|
|
3249
|
+
popupRect,
|
|
3250
|
+
coords,
|
|
3251
|
+
placementSide,
|
|
3252
|
+
m,
|
|
3253
|
+
);
|
|
3254
|
+
return;
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
if (score < bestScore) {
|
|
3258
|
+
bestScore = score;
|
|
3259
|
+
best = resolved;
|
|
3260
|
+
bestSide = placementSide;
|
|
3090
3261
|
}
|
|
3091
3262
|
}
|
|
3092
3263
|
|
|
3093
|
-
|
|
3094
|
-
this.style.left = `${clamped.left}px`;
|
|
3095
|
-
this.style.top = `${clamped.top}px`;
|
|
3096
|
-
this.updatePopoverBeak(
|
|
3264
|
+
this.applyPopupPosition(
|
|
3097
3265
|
anchorRect,
|
|
3098
3266
|
popupRect,
|
|
3099
|
-
|
|
3100
|
-
clamped.top,
|
|
3267
|
+
best || { left: 0, top: 0 },
|
|
3101
3268
|
bestSide,
|
|
3269
|
+
m,
|
|
3102
3270
|
);
|
|
3103
3271
|
}
|
|
3104
3272
|
|
|
3105
3273
|
queueReposition() {
|
|
3106
|
-
if (!this.open || !this.shouldAutoReposition())
|
|
3274
|
+
if (!this.open || !this.isPopupDisplayed() || !this.shouldAutoReposition()) {
|
|
3275
|
+
return;
|
|
3276
|
+
}
|
|
3107
3277
|
if (this._rafId !== null) return;
|
|
3108
3278
|
|
|
3109
3279
|
this._rafId = requestAnimationFrame(() => {
|
|
@@ -3116,6 +3286,14 @@ class FigPopup extends HTMLDialogElement {
|
|
|
3116
3286
|
if (!(this.drag && this._wasDragged)) return true;
|
|
3117
3287
|
return !this.resolveAnchor();
|
|
3118
3288
|
}
|
|
3289
|
+
|
|
3290
|
+
isPopupDisplayed() {
|
|
3291
|
+
return Boolean(
|
|
3292
|
+
this._isPopupActive ||
|
|
3293
|
+
this.matches?.(":open") ||
|
|
3294
|
+
this.matches?.(":popover-open"),
|
|
3295
|
+
);
|
|
3296
|
+
}
|
|
3119
3297
|
}
|
|
3120
3298
|
figDefineCustomizedBuiltIn("fig-popup", FigPopup, { extends: "dialog" });
|
|
3121
3299
|
|
package/package.json
CHANGED