@ssaprt/tooltip 1.0.3 → 1.0.4
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/dist/index.js +164 -50
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +164 -50
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -951,6 +951,63 @@ var INTERACTIVE_RECHECK_INTERVAL = 50;
|
|
|
951
951
|
var TOUCH_MOVE_THRESHOLD = 10;
|
|
952
952
|
var TOUCH_MAX_TAP_DURATION = 600;
|
|
953
953
|
var TOUCH_FOCUS_SUPPRESSION = 700;
|
|
954
|
+
var activeTooltipSession = null;
|
|
955
|
+
var inputModality = "pointer";
|
|
956
|
+
var inputModalitySubscribers = 0;
|
|
957
|
+
var handleGlobalPointerDown = () => {
|
|
958
|
+
inputModality = "pointer";
|
|
959
|
+
};
|
|
960
|
+
var keyboardFocusKeys = /* @__PURE__ */ new Set([
|
|
961
|
+
"Tab",
|
|
962
|
+
"Enter",
|
|
963
|
+
" ",
|
|
964
|
+
"ArrowUp",
|
|
965
|
+
"ArrowDown",
|
|
966
|
+
"ArrowLeft",
|
|
967
|
+
"ArrowRight",
|
|
968
|
+
"Home",
|
|
969
|
+
"End",
|
|
970
|
+
"PageUp",
|
|
971
|
+
"PageDown"
|
|
972
|
+
]);
|
|
973
|
+
var handleGlobalKeyDown = (event) => {
|
|
974
|
+
if (event.metaKey || event.ctrlKey || event.altKey || !keyboardFocusKeys.has(event.key)) {
|
|
975
|
+
return;
|
|
976
|
+
}
|
|
977
|
+
inputModality = "keyboard";
|
|
978
|
+
};
|
|
979
|
+
var subscribeInputModality = () => {
|
|
980
|
+
inputModalitySubscribers += 1;
|
|
981
|
+
if (inputModalitySubscribers !== 1) {
|
|
982
|
+
return;
|
|
983
|
+
}
|
|
984
|
+
document.addEventListener("pointerdown", handleGlobalPointerDown, true);
|
|
985
|
+
document.addEventListener("keydown", handleGlobalKeyDown, true);
|
|
986
|
+
};
|
|
987
|
+
var unsubscribeInputModality = () => {
|
|
988
|
+
inputModalitySubscribers = Math.max(0, inputModalitySubscribers - 1);
|
|
989
|
+
if (inputModalitySubscribers !== 0) {
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
document.removeEventListener("pointerdown", handleGlobalPointerDown, true);
|
|
993
|
+
document.removeEventListener("keydown", handleGlobalKeyDown, true);
|
|
994
|
+
};
|
|
995
|
+
var requestTooltipActivation = (session, point) => {
|
|
996
|
+
const currentSession = activeTooltipSession;
|
|
997
|
+
if (currentSession && currentSession.owner !== session.owner) {
|
|
998
|
+
if (point && currentSession.interactive && currentSession.protectsPoint(point)) {
|
|
999
|
+
return false;
|
|
1000
|
+
}
|
|
1001
|
+
currentSession.close();
|
|
1002
|
+
}
|
|
1003
|
+
activeTooltipSession = session;
|
|
1004
|
+
return true;
|
|
1005
|
+
};
|
|
1006
|
+
var clearTooltipActivation = (owner) => {
|
|
1007
|
+
if (activeTooltipSession?.owner === owner) {
|
|
1008
|
+
activeTooltipSession = null;
|
|
1009
|
+
}
|
|
1010
|
+
};
|
|
954
1011
|
var oppositePlacement = {
|
|
955
1012
|
top: "bottom",
|
|
956
1013
|
bottom: "top",
|
|
@@ -1076,6 +1133,7 @@ var useTooltip = ({
|
|
|
1076
1133
|
}) => {
|
|
1077
1134
|
const tooltipRef = useRef(null);
|
|
1078
1135
|
const bodyRef = useRef(null);
|
|
1136
|
+
const ownerRef = useRef(/* @__PURE__ */ Symbol("tooltip"));
|
|
1079
1137
|
const hideTimerRef = useRef(null);
|
|
1080
1138
|
const firstFrameRef = useRef(null);
|
|
1081
1139
|
const secondFrameRef = useRef(null);
|
|
@@ -1088,6 +1146,7 @@ var useTooltip = ({
|
|
|
1088
1146
|
y: Number.NaN,
|
|
1089
1147
|
pointerType: ""
|
|
1090
1148
|
});
|
|
1149
|
+
const interactiveAreaAtPointRef = useRef(() => "outside");
|
|
1091
1150
|
const touchGestureRef = useRef(null);
|
|
1092
1151
|
const suppressFocusUntilRef = useRef(0);
|
|
1093
1152
|
const [mounted, setMounted] = useState(false);
|
|
@@ -1226,7 +1285,7 @@ var useTooltip = ({
|
|
|
1226
1285
|
});
|
|
1227
1286
|
}, [anchor, getAvailableSpace, preferredPlacement]);
|
|
1228
1287
|
const isFocusInsideTooltipRegion = useCallback(() => {
|
|
1229
|
-
if (!anchor || typeof document === "undefined") {
|
|
1288
|
+
if (!anchor || typeof document === "undefined" || inputModality !== "keyboard") {
|
|
1230
1289
|
return false;
|
|
1231
1290
|
}
|
|
1232
1291
|
const activeElement = document.activeElement;
|
|
@@ -1234,50 +1293,60 @@ var useTooltip = ({
|
|
|
1234
1293
|
if (!(activeElement instanceof Node)) {
|
|
1235
1294
|
return false;
|
|
1236
1295
|
}
|
|
1237
|
-
|
|
1238
|
-
return true;
|
|
1239
|
-
}
|
|
1240
|
-
return anchor.contains(activeElement) && activeElement instanceof Element && activeElement.matches(":focus-visible");
|
|
1296
|
+
return anchor.contains(activeElement) || Boolean(interactive && tooltip?.contains(activeElement));
|
|
1241
1297
|
}, [anchor, interactive]);
|
|
1298
|
+
const getInteractivePointerAreaAtPoint = useCallback(
|
|
1299
|
+
(point) => {
|
|
1300
|
+
if (!interactive || !anchor) {
|
|
1301
|
+
return "outside";
|
|
1302
|
+
}
|
|
1303
|
+
const tooltip = tooltipRef.current;
|
|
1304
|
+
if (!tooltip || !Number.isFinite(point.x) || !Number.isFinite(point.y)) {
|
|
1305
|
+
return "outside";
|
|
1306
|
+
}
|
|
1307
|
+
const anchorRect = anchor.getBoundingClientRect();
|
|
1308
|
+
const tooltipRect = tooltip.getBoundingClientRect();
|
|
1309
|
+
if (isPointInsideRect(
|
|
1310
|
+
point,
|
|
1311
|
+
anchorRect,
|
|
1312
|
+
INTERACTIVE_DIRECT_PADDING
|
|
1313
|
+
) || isPointInsideRect(
|
|
1314
|
+
point,
|
|
1315
|
+
tooltipRect,
|
|
1316
|
+
INTERACTIVE_DIRECT_PADDING
|
|
1317
|
+
)) {
|
|
1318
|
+
return "direct";
|
|
1319
|
+
}
|
|
1320
|
+
const bridge = createInteractiveBridge(
|
|
1321
|
+
anchorRect,
|
|
1322
|
+
tooltipRect,
|
|
1323
|
+
placement
|
|
1324
|
+
);
|
|
1325
|
+
return isPointInsidePolygon(point, bridge) ? "bridge" : "outside";
|
|
1326
|
+
},
|
|
1327
|
+
[anchor, interactive, placement]
|
|
1328
|
+
);
|
|
1329
|
+
useLayoutEffect(() => {
|
|
1330
|
+
interactiveAreaAtPointRef.current = getInteractivePointerAreaAtPoint;
|
|
1331
|
+
}, [getInteractivePointerAreaAtPoint]);
|
|
1242
1332
|
const getInteractivePointerArea = useCallback(() => {
|
|
1243
|
-
if (!interactive || !anchor) {
|
|
1244
|
-
return "outside";
|
|
1245
|
-
}
|
|
1246
1333
|
const pointer = pointerRef.current;
|
|
1247
|
-
|
|
1248
|
-
if (!tooltip || pointer.pointerType !== "mouse" && pointer.pointerType !== "pen" || !Number.isFinite(pointer.x) || !Number.isFinite(pointer.y)) {
|
|
1334
|
+
if (pointer.pointerType !== "mouse" && pointer.pointerType !== "pen" || !Number.isFinite(pointer.x) || !Number.isFinite(pointer.y)) {
|
|
1249
1335
|
return "outside";
|
|
1250
1336
|
}
|
|
1251
|
-
|
|
1337
|
+
return getInteractivePointerAreaAtPoint({
|
|
1252
1338
|
x: pointer.x,
|
|
1253
1339
|
y: pointer.y
|
|
1254
|
-
};
|
|
1255
|
-
|
|
1256
|
-
const tooltipRect = tooltip.getBoundingClientRect();
|
|
1257
|
-
if (isPointInsideRect(
|
|
1258
|
-
point,
|
|
1259
|
-
anchorRect,
|
|
1260
|
-
INTERACTIVE_DIRECT_PADDING
|
|
1261
|
-
) || isPointInsideRect(
|
|
1262
|
-
point,
|
|
1263
|
-
tooltipRect,
|
|
1264
|
-
INTERACTIVE_DIRECT_PADDING
|
|
1265
|
-
)) {
|
|
1266
|
-
return "direct";
|
|
1267
|
-
}
|
|
1268
|
-
const bridge = createInteractiveBridge(
|
|
1269
|
-
anchorRect,
|
|
1270
|
-
tooltipRect,
|
|
1271
|
-
placement
|
|
1272
|
-
);
|
|
1273
|
-
return isPointInsidePolygon(point, bridge) ? "bridge" : "outside";
|
|
1274
|
-
}, [anchor, interactive, placement]);
|
|
1340
|
+
});
|
|
1341
|
+
}, [getInteractivePointerAreaAtPoint]);
|
|
1275
1342
|
const removeTooltip = useCallback(() => {
|
|
1276
1343
|
clearHideTimer();
|
|
1277
1344
|
clearEnterFrames();
|
|
1278
1345
|
clearInteractiveFrame();
|
|
1279
1346
|
pendingHideRef.current = false;
|
|
1280
1347
|
interactiveBridgeDeadlineRef.current = 0;
|
|
1348
|
+
clearTooltipActivation(ownerRef.current);
|
|
1349
|
+
setMounted(false);
|
|
1281
1350
|
updatePhase("hidden");
|
|
1282
1351
|
}, [clearEnterFrames, clearHideTimer, clearInteractiveFrame, updatePhase]);
|
|
1283
1352
|
const runHide = useCallback(() => {
|
|
@@ -1353,21 +1422,51 @@ var useTooltip = ({
|
|
|
1353
1422
|
runHide
|
|
1354
1423
|
]
|
|
1355
1424
|
);
|
|
1356
|
-
const showTooltip = useCallback(
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1425
|
+
const showTooltip = useCallback(
|
|
1426
|
+
(activationPoint) => {
|
|
1427
|
+
if (!anchor || disabled) {
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
const activated = requestTooltipActivation(
|
|
1431
|
+
{
|
|
1432
|
+
owner: ownerRef.current,
|
|
1433
|
+
interactive,
|
|
1434
|
+
protectsPoint: (point) => {
|
|
1435
|
+
if (phaseRef.current === "hidden") {
|
|
1436
|
+
return false;
|
|
1437
|
+
}
|
|
1438
|
+
return interactiveAreaAtPointRef.current(point) !== "outside";
|
|
1439
|
+
},
|
|
1440
|
+
close: () => {
|
|
1441
|
+
hideTooltip(true);
|
|
1442
|
+
}
|
|
1443
|
+
},
|
|
1444
|
+
activationPoint
|
|
1445
|
+
);
|
|
1446
|
+
if (!activated) {
|
|
1447
|
+
return;
|
|
1448
|
+
}
|
|
1449
|
+
clearHideTimer();
|
|
1450
|
+
clearEnterFrames();
|
|
1451
|
+
interactiveBridgeDeadlineRef.current = 0;
|
|
1452
|
+
pendingHideRef.current = false;
|
|
1453
|
+
setMounted(true);
|
|
1454
|
+
if (phaseRef.current === "entering" || phaseRef.current === "visible") {
|
|
1455
|
+
return;
|
|
1456
|
+
}
|
|
1457
|
+
updatePhase("preparing");
|
|
1458
|
+
setShowVersion((value) => value + 1);
|
|
1459
|
+
},
|
|
1460
|
+
[
|
|
1461
|
+
anchor,
|
|
1462
|
+
clearEnterFrames,
|
|
1463
|
+
clearHideTimer,
|
|
1464
|
+
disabled,
|
|
1465
|
+
hideTooltip,
|
|
1466
|
+
interactive,
|
|
1467
|
+
updatePhase
|
|
1468
|
+
]
|
|
1469
|
+
);
|
|
1371
1470
|
const keepTooltipOpen = useCallback(() => {
|
|
1372
1471
|
if (!interactive || disabled) {
|
|
1373
1472
|
return;
|
|
@@ -1457,6 +1556,13 @@ var useTooltip = ({
|
|
|
1457
1556
|
showVersion,
|
|
1458
1557
|
updatePhase
|
|
1459
1558
|
]);
|
|
1559
|
+
useEffect(() => {
|
|
1560
|
+
subscribeInputModality();
|
|
1561
|
+
return () => {
|
|
1562
|
+
unsubscribeInputModality();
|
|
1563
|
+
clearTooltipActivation(ownerRef.current);
|
|
1564
|
+
};
|
|
1565
|
+
}, []);
|
|
1460
1566
|
useEffect(() => {
|
|
1461
1567
|
if (!anchor) {
|
|
1462
1568
|
removeTooltip();
|
|
@@ -1474,7 +1580,10 @@ var useTooltip = ({
|
|
|
1474
1580
|
if (event.pointerType === "touch") {
|
|
1475
1581
|
return;
|
|
1476
1582
|
}
|
|
1477
|
-
showTooltip(
|
|
1583
|
+
showTooltip({
|
|
1584
|
+
x: event.clientX,
|
|
1585
|
+
y: event.clientY
|
|
1586
|
+
});
|
|
1478
1587
|
};
|
|
1479
1588
|
const onPointerLeave = (event) => {
|
|
1480
1589
|
updatePointer(event);
|
|
@@ -1546,7 +1655,10 @@ var useTooltip = ({
|
|
|
1546
1655
|
return;
|
|
1547
1656
|
}
|
|
1548
1657
|
if (phaseRef.current === "hidden" || phaseRef.current === "leaving") {
|
|
1549
|
-
showTooltip(
|
|
1658
|
+
showTooltip({
|
|
1659
|
+
x: event.clientX,
|
|
1660
|
+
y: event.clientY
|
|
1661
|
+
});
|
|
1550
1662
|
} else {
|
|
1551
1663
|
hideTooltip(true);
|
|
1552
1664
|
}
|
|
@@ -1643,7 +1755,9 @@ var useTooltip = ({
|
|
|
1643
1755
|
scheduleInteractivePointerProcessing();
|
|
1644
1756
|
};
|
|
1645
1757
|
const onFocusIn = () => {
|
|
1646
|
-
|
|
1758
|
+
if (inputModality === "keyboard") {
|
|
1759
|
+
keepTooltipOpen();
|
|
1760
|
+
}
|
|
1647
1761
|
};
|
|
1648
1762
|
const onFocusOut = (event) => {
|
|
1649
1763
|
const relatedTarget = event.relatedTarget;
|