react-modal-sheet 5.4.1 → 5.5.0
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 +140 -88
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +140 -88
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/constants.ts +1 -1
- package/src/sheet.tsx +21 -57
- package/src/snap.ts +205 -102
package/dist/index.mjs
CHANGED
|
@@ -130,7 +130,7 @@ var REDUCED_MOTION_TWEEN_CONFIG = {
|
|
|
130
130
|
duration: 0.01
|
|
131
131
|
};
|
|
132
132
|
var DEFAULT_DRAG_CLOSE_THRESHOLD = 0.6;
|
|
133
|
-
var DEFAULT_DRAG_VELOCITY_THRESHOLD =
|
|
133
|
+
var DEFAULT_DRAG_VELOCITY_THRESHOLD = 1200;
|
|
134
134
|
|
|
135
135
|
// src/utils.ts
|
|
136
136
|
function applyStyles(styles2, unstyled) {
|
|
@@ -1150,73 +1150,145 @@ function computeSnapPoints({
|
|
|
1150
1150
|
// Y value is inverted as `y = 0` means sheet is at the top
|
|
1151
1151
|
}));
|
|
1152
1152
|
}
|
|
1153
|
-
function
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1153
|
+
function clamp(value, min, max) {
|
|
1154
|
+
return Math.min(Math.max(value, min), max);
|
|
1155
|
+
}
|
|
1156
|
+
function sign(value) {
|
|
1157
|
+
if (value > 0) return 1;
|
|
1158
|
+
if (value < 0) return -1;
|
|
1159
|
+
return 0;
|
|
1160
|
+
}
|
|
1161
|
+
function toAscendingYSnaps(snapPoints) {
|
|
1162
|
+
return snapPoints.slice().sort((a, b) => a.snapValueY - b.snapValueY);
|
|
1163
|
+
}
|
|
1164
|
+
function findNearestSnapByY(snapPoints, y) {
|
|
1157
1165
|
return snapPoints.reduce(
|
|
1158
|
-
(closest, snap) => Math.abs(snap.snapValueY -
|
|
1166
|
+
(closest, snap) => Math.abs(snap.snapValueY - y) < Math.abs(closest.snapValueY - y) ? snap : closest
|
|
1159
1167
|
);
|
|
1160
1168
|
}
|
|
1161
|
-
function
|
|
1169
|
+
function findNearestSnapAboveY(snapPoints, y) {
|
|
1170
|
+
const snaps = toAscendingYSnaps(snapPoints);
|
|
1171
|
+
for (let i = snaps.length - 1; i >= 0; i--) {
|
|
1172
|
+
if (snaps[i].snapValueY < y) {
|
|
1173
|
+
return snaps[i];
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1176
|
+
return null;
|
|
1177
|
+
}
|
|
1178
|
+
function findNearestSnapBelowY(snapPoints, y) {
|
|
1179
|
+
const snaps = toAscendingYSnaps(snapPoints);
|
|
1180
|
+
for (let i = 0; i < snaps.length; i++) {
|
|
1181
|
+
if (snaps[i].snapValueY > y) {
|
|
1182
|
+
return snaps[i];
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
return null;
|
|
1186
|
+
}
|
|
1187
|
+
function resolveDirection({
|
|
1188
|
+
offsetY,
|
|
1189
|
+
velocityY,
|
|
1190
|
+
deltaY
|
|
1191
|
+
}) {
|
|
1192
|
+
if (Math.abs(velocityY) > 50) return sign(velocityY);
|
|
1193
|
+
const offsetDirection = sign(offsetY);
|
|
1194
|
+
if (offsetDirection !== 0) return offsetDirection;
|
|
1195
|
+
return sign(deltaY);
|
|
1196
|
+
}
|
|
1197
|
+
function classifyDragEnd({
|
|
1162
1198
|
y,
|
|
1199
|
+
info,
|
|
1200
|
+
sheetHeight,
|
|
1163
1201
|
snapPoints,
|
|
1164
|
-
|
|
1202
|
+
dragVelocityThreshold,
|
|
1203
|
+
dragCloseThreshold
|
|
1165
1204
|
}) {
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1205
|
+
const flickVelocity = dragVelocityThreshold;
|
|
1206
|
+
const strongFlickVelocity = Math.max(2e3, flickVelocity);
|
|
1207
|
+
const distanceCommitRatio = 0.35;
|
|
1208
|
+
const predictionTime = 0.2;
|
|
1209
|
+
const minDragDistance = 20;
|
|
1210
|
+
const snapStickiness = 24;
|
|
1211
|
+
const minY = 0;
|
|
1212
|
+
const maxY = sheetHeight;
|
|
1213
|
+
const offsetY = info.offset.y;
|
|
1214
|
+
const deltaY = info.delta.y;
|
|
1215
|
+
const velocityY = info.velocity.y;
|
|
1216
|
+
const predictedY = clamp(y + velocityY * predictionTime, minY, maxY);
|
|
1217
|
+
const absVelocity = Math.abs(velocityY);
|
|
1218
|
+
const direction = resolveDirection({ offsetY, velocityY, deltaY });
|
|
1219
|
+
const isStrongFlick = absVelocity > strongFlickVelocity;
|
|
1220
|
+
const isFlick = absVelocity > flickVelocity;
|
|
1221
|
+
if (snapPoints.length === 0) {
|
|
1222
|
+
if (isFlick) {
|
|
1223
|
+
return {
|
|
1224
|
+
yTo: direction < 0 ? minY : maxY,
|
|
1225
|
+
snapIndex: void 0
|
|
1226
|
+
};
|
|
1227
|
+
}
|
|
1228
|
+
const midpoint = minY + (maxY - minY) * dragCloseThreshold;
|
|
1229
|
+
return {
|
|
1230
|
+
yTo: predictedY < midpoint ? minY : maxY,
|
|
1231
|
+
snapIndex: void 0
|
|
1232
|
+
};
|
|
1170
1233
|
}
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
dragDirection,
|
|
1174
|
-
snapPoints
|
|
1175
|
-
}) {
|
|
1176
|
-
const bottomSnapPoint = snapPoints[0];
|
|
1177
|
-
const topSnapPoint = snapPoints[snapPoints.length - 1];
|
|
1178
|
-
if (dragDirection === "down") {
|
|
1234
|
+
const nearestSnap = findNearestSnapByY(snapPoints, y);
|
|
1235
|
+
if (!isFlick && Math.abs(offsetY) < minDragDistance) {
|
|
1179
1236
|
return {
|
|
1180
|
-
yTo:
|
|
1181
|
-
snapIndex:
|
|
1237
|
+
yTo: nearestSnap.snapValueY,
|
|
1238
|
+
snapIndex: nearestSnap.snapIndex
|
|
1182
1239
|
};
|
|
1183
1240
|
}
|
|
1184
|
-
|
|
1185
|
-
yTo: topSnapPoint.snapValueY,
|
|
1186
|
-
snapIndex: topSnapPoint.snapIndex
|
|
1187
|
-
};
|
|
1188
|
-
}
|
|
1189
|
-
function handleLowVelocityDrag({
|
|
1190
|
-
currentSnapPoint,
|
|
1191
|
-
currentY,
|
|
1192
|
-
dragDirection,
|
|
1193
|
-
snapPoints,
|
|
1194
|
-
velocity
|
|
1195
|
-
}) {
|
|
1196
|
-
const closestSnapRelativeToCurrentY = findClosestSnapPoint({
|
|
1197
|
-
snapPoints,
|
|
1198
|
-
currentY
|
|
1199
|
-
});
|
|
1200
|
-
if (Math.abs(velocity) < 20) {
|
|
1241
|
+
if (!isFlick && Math.abs(y - nearestSnap.snapValueY) < snapStickiness) {
|
|
1201
1242
|
return {
|
|
1202
|
-
yTo:
|
|
1203
|
-
snapIndex:
|
|
1243
|
+
yTo: nearestSnap.snapValueY,
|
|
1244
|
+
snapIndex: nearestSnap.snapIndex
|
|
1204
1245
|
};
|
|
1205
1246
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
snapPoints,
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1247
|
+
if (isStrongFlick) {
|
|
1248
|
+
const target = direction < 0 ? minY : maxY;
|
|
1249
|
+
const targetSnap = findNearestSnapByY(snapPoints, target);
|
|
1250
|
+
return {
|
|
1251
|
+
yTo: target,
|
|
1252
|
+
snapIndex: targetSnap.snapIndex
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
if (isFlick) {
|
|
1256
|
+
const nextSnap2 = direction < 0 ? findNearestSnapAboveY(snapPoints, y) : findNearestSnapBelowY(snapPoints, y);
|
|
1257
|
+
const fallbackY = direction < 0 ? minY : maxY;
|
|
1258
|
+
const fallbackSnap = findNearestSnapByY(snapPoints, fallbackY);
|
|
1259
|
+
const targetSnap = nextSnap2 ?? fallbackSnap;
|
|
1260
|
+
return {
|
|
1261
|
+
yTo: targetSnap.snapValueY,
|
|
1262
|
+
snapIndex: targetSnap.snapIndex
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
const firstSnap = toAscendingYSnaps(snapPoints)[0];
|
|
1266
|
+
const lastSnap = toAscendingYSnaps(snapPoints)[snapPoints.length - 1];
|
|
1267
|
+
const prevSnap = findNearestSnapAboveY(snapPoints, y) ?? firstSnap;
|
|
1268
|
+
const nextSnap = findNearestSnapBelowY(snapPoints, y) ?? lastSnap;
|
|
1269
|
+
if (prevSnap.snapIndex === nextSnap.snapIndex) {
|
|
1212
1270
|
return {
|
|
1213
|
-
yTo:
|
|
1214
|
-
snapIndex:
|
|
1271
|
+
yTo: prevSnap.snapValueY,
|
|
1272
|
+
snapIndex: prevSnap.snapIndex
|
|
1215
1273
|
};
|
|
1216
1274
|
}
|
|
1275
|
+
const range = nextSnap.snapValueY - prevSnap.snapValueY;
|
|
1276
|
+
const progress = range > 0 ? (y - prevSnap.snapValueY) / range : 0;
|
|
1277
|
+
let selectedSnap = nearestSnap;
|
|
1278
|
+
if (direction > 0) {
|
|
1279
|
+
selectedSnap = progress > distanceCommitRatio ? nextSnap : prevSnap;
|
|
1280
|
+
} else if (direction < 0) {
|
|
1281
|
+
selectedSnap = progress < 1 - distanceCommitRatio ? prevSnap : nextSnap;
|
|
1282
|
+
}
|
|
1283
|
+
if (absVelocity > 200) {
|
|
1284
|
+
const predictedSnap = findNearestSnapByY(snapPoints, predictedY);
|
|
1285
|
+
if (Math.abs(predictedSnap.snapValueY - y) < Math.abs(selectedSnap.snapValueY - y)) {
|
|
1286
|
+
selectedSnap = predictedSnap;
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1217
1289
|
return {
|
|
1218
|
-
yTo:
|
|
1219
|
-
snapIndex:
|
|
1290
|
+
yTo: selectedSnap.snapValueY,
|
|
1291
|
+
snapIndex: selectedSnap.snapIndex
|
|
1220
1292
|
};
|
|
1221
1293
|
}
|
|
1222
1294
|
|
|
@@ -1363,45 +1435,25 @@ var Sheet = forwardRef(
|
|
|
1363
1435
|
blurActiveInput();
|
|
1364
1436
|
onDragEndProp == null ? void 0 : onDragEndProp(event, info);
|
|
1365
1437
|
const currentY = y.get();
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
currentSnapPoint,
|
|
1381
|
-
currentY,
|
|
1382
|
-
dragDirection: dragOffsetDirection,
|
|
1383
|
-
snapPoints,
|
|
1384
|
-
velocity: info.velocity.y
|
|
1385
|
-
});
|
|
1386
|
-
}
|
|
1387
|
-
yTo = result.yTo;
|
|
1388
|
-
if (disableDismiss && yTo + 1 >= sheetHeight) {
|
|
1389
|
-
const bottomSnapPoint = snapPoints.find((s) => s.snapValue > 0);
|
|
1390
|
-
if (bottomSnapPoint) {
|
|
1391
|
-
yTo = bottomSnapPoint.snapValueY;
|
|
1392
|
-
updateSnap(bottomSnapPoint.snapIndex);
|
|
1393
|
-
} else {
|
|
1394
|
-
yTo = currentY;
|
|
1395
|
-
}
|
|
1396
|
-
} else if (result.snapIndex !== void 0) {
|
|
1397
|
-
updateSnap(result.snapIndex);
|
|
1398
|
-
}
|
|
1399
|
-
} else if (info.velocity.y > dragVelocityThreshold || currentY > sheetHeight * dragCloseThreshold) {
|
|
1400
|
-
if (disableDismiss) {
|
|
1401
|
-
yTo = 0;
|
|
1438
|
+
const result = classifyDragEnd({
|
|
1439
|
+
y: currentY,
|
|
1440
|
+
info,
|
|
1441
|
+
sheetHeight,
|
|
1442
|
+
dragCloseThreshold,
|
|
1443
|
+
snapPoints,
|
|
1444
|
+
dragVelocityThreshold
|
|
1445
|
+
});
|
|
1446
|
+
let yTo = result.yTo;
|
|
1447
|
+
if (disableDismiss && yTo + 1 >= sheetHeight) {
|
|
1448
|
+
const bottomSnapPoint = snapPoints.find((s) => s.snapValue > 0);
|
|
1449
|
+
if (bottomSnapPoint) {
|
|
1450
|
+
yTo = bottomSnapPoint.snapValueY;
|
|
1451
|
+
updateSnap(bottomSnapPoint.snapIndex);
|
|
1402
1452
|
} else {
|
|
1403
|
-
yTo =
|
|
1453
|
+
yTo = currentY;
|
|
1404
1454
|
}
|
|
1455
|
+
} else if (result.snapIndex !== void 0) {
|
|
1456
|
+
updateSnap(result.snapIndex);
|
|
1405
1457
|
}
|
|
1406
1458
|
animate(y, yTo, animationOptions);
|
|
1407
1459
|
if (yTo + 1 >= sheetHeight && !disableDismiss) {
|