@project-skymap/library 0.7.0 → 0.7.1
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.cjs +83 -16
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +83 -16
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -103,6 +103,7 @@ type StarMapProps = {
|
|
|
103
103
|
onHover?: (node?: SceneNode) => void;
|
|
104
104
|
onArrangementChange?: (arrangement: StarArrangement) => void;
|
|
105
105
|
onFovChange?: (fov: number) => void;
|
|
106
|
+
onLongPress?: (node: SceneNode | null, x: number, y: number) => void;
|
|
106
107
|
};
|
|
107
108
|
type StarMapHandle = {
|
|
108
109
|
getFullArrangement: () => StarArrangement | undefined;
|
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,7 @@ type StarMapProps = {
|
|
|
103
103
|
onHover?: (node?: SceneNode) => void;
|
|
104
104
|
onArrangementChange?: (arrangement: StarArrangement) => void;
|
|
105
105
|
onFovChange?: (fov: number) => void;
|
|
106
|
+
onLongPress?: (node: SceneNode | null, x: number, y: number) => void;
|
|
106
107
|
};
|
|
107
108
|
type StarMapHandle = {
|
|
108
109
|
getFullArrangement: () => StarArrangement | undefined;
|
package/dist/index.js
CHANGED
|
@@ -827,7 +827,8 @@ function createEngine({
|
|
|
827
827
|
onSelect,
|
|
828
828
|
onHover,
|
|
829
829
|
onArrangementChange,
|
|
830
|
-
onFovChange
|
|
830
|
+
onFovChange,
|
|
831
|
+
onLongPress
|
|
831
832
|
}) {
|
|
832
833
|
let hoveredBookId = null;
|
|
833
834
|
let focusedBookId = null;
|
|
@@ -897,13 +898,20 @@ function createEngine({
|
|
|
897
898
|
pinchStartDistance: 0,
|
|
898
899
|
pinchStartFov: ENGINE_CONFIG.defaultFov,
|
|
899
900
|
pinchCenterX: 0,
|
|
900
|
-
pinchCenterY: 0
|
|
901
|
+
pinchCenterY: 0,
|
|
902
|
+
// Double-tap detection
|
|
903
|
+
lastTapTime: 0,
|
|
904
|
+
lastTapX: 0,
|
|
905
|
+
lastTapY: 0,
|
|
906
|
+
// Long-press detection
|
|
907
|
+
longPressTimer: null,
|
|
908
|
+
longPressTriggered: false
|
|
901
909
|
};
|
|
902
910
|
const mouseNDC = new THREE5.Vector2();
|
|
903
911
|
let isMouseInWindow = false;
|
|
904
912
|
let isTouchDevice = false;
|
|
905
913
|
let edgeHoverStart = 0;
|
|
906
|
-
let handlers = { onSelect, onHover, onArrangementChange, onFovChange };
|
|
914
|
+
let handlers = { onSelect, onHover, onArrangementChange, onFovChange, onLongPress };
|
|
907
915
|
let currentConfig;
|
|
908
916
|
const constellationLayer = new ConstellationArtworkLayer(scene);
|
|
909
917
|
function mix(a, b, t) {
|
|
@@ -2396,6 +2404,11 @@ function createEngine({
|
|
|
2396
2404
|
function onTouchStart(e) {
|
|
2397
2405
|
e.preventDefault();
|
|
2398
2406
|
isTouchDevice = true;
|
|
2407
|
+
if (state.longPressTimer) {
|
|
2408
|
+
clearTimeout(state.longPressTimer);
|
|
2409
|
+
state.longPressTimer = null;
|
|
2410
|
+
}
|
|
2411
|
+
state.longPressTriggered = false;
|
|
2399
2412
|
const touches = e.touches;
|
|
2400
2413
|
state.touchCount = touches.length;
|
|
2401
2414
|
if (touches.length === 1) {
|
|
@@ -2411,6 +2424,22 @@ function createEngine({
|
|
|
2411
2424
|
state.isDragging = true;
|
|
2412
2425
|
state.velocityX = 0;
|
|
2413
2426
|
state.velocityY = 0;
|
|
2427
|
+
state.longPressTimer = setTimeout(() => {
|
|
2428
|
+
if (!state.touchMoved && state.touchCount === 1) {
|
|
2429
|
+
state.longPressTriggered = true;
|
|
2430
|
+
const rect = renderer.domElement.getBoundingClientRect();
|
|
2431
|
+
const mX = state.touchStartX - rect.left;
|
|
2432
|
+
const mY = state.touchStartY - rect.top;
|
|
2433
|
+
mouseNDC.x = mX / rect.width * 2 - 1;
|
|
2434
|
+
mouseNDC.y = -(mY / rect.height) * 2 + 1;
|
|
2435
|
+
const syntheticEvent = {
|
|
2436
|
+
clientX: state.touchStartX,
|
|
2437
|
+
clientY: state.touchStartY
|
|
2438
|
+
};
|
|
2439
|
+
const hit = pick(syntheticEvent);
|
|
2440
|
+
handlers.onLongPress?.(hit?.node ?? null, state.touchStartX, state.touchStartY);
|
|
2441
|
+
}
|
|
2442
|
+
}, ENGINE_CONFIG.longPressDelay);
|
|
2414
2443
|
} else if (touches.length === 2) {
|
|
2415
2444
|
const t0 = touches[0];
|
|
2416
2445
|
const t1 = touches[1];
|
|
@@ -2437,6 +2466,10 @@ function createEngine({
|
|
|
2437
2466
|
const totalDy = touch.clientY - state.touchStartY;
|
|
2438
2467
|
if (Math.sqrt(totalDx * totalDx + totalDy * totalDy) > ENGINE_CONFIG.tapMaxDistance) {
|
|
2439
2468
|
state.touchMoved = true;
|
|
2469
|
+
if (state.longPressTimer) {
|
|
2470
|
+
clearTimeout(state.longPressTimer);
|
|
2471
|
+
state.longPressTimer = null;
|
|
2472
|
+
}
|
|
2440
2473
|
}
|
|
2441
2474
|
const speedScale = state.fov / ENGINE_CONFIG.defaultFov;
|
|
2442
2475
|
const rotLock = Math.max(0, Math.min(1, (state.fov - 100) / (ENGINE_CONFIG.maxFov - 100)));
|
|
@@ -2471,11 +2504,21 @@ function createEngine({
|
|
|
2471
2504
|
}
|
|
2472
2505
|
function onTouchEnd(e) {
|
|
2473
2506
|
e.preventDefault();
|
|
2507
|
+
if (state.longPressTimer) {
|
|
2508
|
+
clearTimeout(state.longPressTimer);
|
|
2509
|
+
state.longPressTimer = null;
|
|
2510
|
+
}
|
|
2474
2511
|
const remainingTouches = e.touches.length;
|
|
2475
2512
|
if (remainingTouches === 0) {
|
|
2476
|
-
const
|
|
2477
|
-
const
|
|
2513
|
+
const now = performance.now();
|
|
2514
|
+
const duration = now - state.touchStartTime;
|
|
2515
|
+
const wasTap = !state.touchMoved && duration < ENGINE_CONFIG.tapMaxDuration && !state.longPressTriggered;
|
|
2478
2516
|
if (wasTap) {
|
|
2517
|
+
const timeSinceLastTap = now - state.lastTapTime;
|
|
2518
|
+
const distFromLastTap = Math.sqrt(
|
|
2519
|
+
Math.pow(state.touchStartX - state.lastTapX, 2) + Math.pow(state.touchStartY - state.lastTapY, 2)
|
|
2520
|
+
);
|
|
2521
|
+
const isDoubleTap = timeSinceLastTap < ENGINE_CONFIG.doubleTapMaxDelay && distFromLastTap < ENGINE_CONFIG.doubleTapMaxDistance;
|
|
2479
2522
|
const rect = renderer.domElement.getBoundingClientRect();
|
|
2480
2523
|
const mX = state.touchStartX - rect.left;
|
|
2481
2524
|
const mY = state.touchStartY - rect.top;
|
|
@@ -2486,13 +2529,26 @@ function createEngine({
|
|
|
2486
2529
|
clientY: state.touchStartY
|
|
2487
2530
|
};
|
|
2488
2531
|
const hit = pick(syntheticEvent);
|
|
2489
|
-
if (
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2532
|
+
if (isDoubleTap) {
|
|
2533
|
+
if (hit) {
|
|
2534
|
+
flyTo(hit.node.id, ENGINE_CONFIG.minFov);
|
|
2535
|
+
handlers.onSelect?.(hit.node);
|
|
2536
|
+
}
|
|
2537
|
+
state.lastTapTime = 0;
|
|
2538
|
+
state.lastTapX = 0;
|
|
2539
|
+
state.lastTapY = 0;
|
|
2494
2540
|
} else {
|
|
2495
|
-
|
|
2541
|
+
if (hit) {
|
|
2542
|
+
handlers.onSelect?.(hit.node);
|
|
2543
|
+
constellationLayer.setFocused(hit.node.id);
|
|
2544
|
+
if (hit.node.level === 2) setFocusedBook(hit.node.id);
|
|
2545
|
+
else if (hit.node.level === 3 && hit.node.parent) setFocusedBook(hit.node.parent);
|
|
2546
|
+
} else {
|
|
2547
|
+
setFocusedBook(null);
|
|
2548
|
+
}
|
|
2549
|
+
state.lastTapTime = now;
|
|
2550
|
+
state.lastTapX = state.touchStartX;
|
|
2551
|
+
state.lastTapY = state.touchStartY;
|
|
2496
2552
|
}
|
|
2497
2553
|
}
|
|
2498
2554
|
state.isDragging = false;
|
|
@@ -2511,6 +2567,10 @@ function createEngine({
|
|
|
2511
2567
|
}
|
|
2512
2568
|
function onTouchCancel(e) {
|
|
2513
2569
|
e.preventDefault();
|
|
2570
|
+
if (state.longPressTimer) {
|
|
2571
|
+
clearTimeout(state.longPressTimer);
|
|
2572
|
+
state.longPressTimer = null;
|
|
2573
|
+
}
|
|
2514
2574
|
state.isDragging = false;
|
|
2515
2575
|
state.dragMode = "none";
|
|
2516
2576
|
state.touchCount = 0;
|
|
@@ -2896,8 +2956,14 @@ var init_createEngine = __esm({
|
|
|
2896
2956
|
// Snappier than mouse (0.92)
|
|
2897
2957
|
tapMaxDuration: 300,
|
|
2898
2958
|
// ms
|
|
2899
|
-
tapMaxDistance: 10
|
|
2959
|
+
tapMaxDistance: 10,
|
|
2900
2960
|
// px
|
|
2961
|
+
doubleTapMaxDelay: 300,
|
|
2962
|
+
// ms between taps
|
|
2963
|
+
doubleTapMaxDistance: 30,
|
|
2964
|
+
// px between tap locations
|
|
2965
|
+
longPressDelay: 500
|
|
2966
|
+
// ms to trigger long-press
|
|
2901
2967
|
};
|
|
2902
2968
|
ORDER_REVEAL_CONFIG = {
|
|
2903
2969
|
globalDim: 0.85,
|
|
@@ -2908,7 +2974,7 @@ var init_createEngine = __esm({
|
|
|
2908
2974
|
}
|
|
2909
2975
|
});
|
|
2910
2976
|
var StarMap = forwardRef(
|
|
2911
|
-
({ config, className, onSelect, onHover, onArrangementChange, onFovChange }, ref) => {
|
|
2977
|
+
({ config, className, onSelect, onHover, onArrangementChange, onFovChange, onLongPress }, ref) => {
|
|
2912
2978
|
const containerRef = useRef(null);
|
|
2913
2979
|
const engineRef = useRef(null);
|
|
2914
2980
|
useImperativeHandle(ref, () => ({
|
|
@@ -2931,7 +2997,8 @@ var StarMap = forwardRef(
|
|
|
2931
2997
|
onSelect,
|
|
2932
2998
|
onHover,
|
|
2933
2999
|
onArrangementChange,
|
|
2934
|
-
onFovChange
|
|
3000
|
+
onFovChange,
|
|
3001
|
+
onLongPress
|
|
2935
3002
|
});
|
|
2936
3003
|
engineRef.current.setConfig(config);
|
|
2937
3004
|
engineRef.current.start();
|
|
@@ -2947,8 +3014,8 @@ var StarMap = forwardRef(
|
|
|
2947
3014
|
engineRef.current?.setConfig?.(config);
|
|
2948
3015
|
}, [config]);
|
|
2949
3016
|
useEffect(() => {
|
|
2950
|
-
engineRef.current?.setHandlers?.({ onSelect, onHover, onArrangementChange, onFovChange });
|
|
2951
|
-
}, [onSelect, onHover, onArrangementChange, onFovChange]);
|
|
3017
|
+
engineRef.current?.setHandlers?.({ onSelect, onHover, onArrangementChange, onFovChange, onLongPress });
|
|
3018
|
+
}, [onSelect, onHover, onArrangementChange, onFovChange, onLongPress]);
|
|
2952
3019
|
return /* @__PURE__ */ jsx("div", { ref: containerRef, className, style: { width: "100%", height: "100%" } });
|
|
2953
3020
|
}
|
|
2954
3021
|
);
|