Rewrite Features config drag-drop with pointer/touch events
Replace HTML5 Drag and Drop API with pointer/touch event handling for better mobile support: - Add pointer event handlers for desktop/stylus drag - Add global touch event listeners for mobile drag - Track drag state with refs for consistent behavior - Calculate drop position based on Y coordinate - Improve Cancel to restore from initial snapshot Also improve SwipeTabs to ignore interactive elements (buttons, links, inputs) during swipe detection, and add touch-action: none to order cards for proper touch handling. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,15 @@ const findTouchById = (touches: React.TouchList, id: number): React.Touch | null
|
||||
return touch;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
};
|
||||
|
||||
const resolveSwipeTarget = (target: EventTarget | null): Element | null => {
|
||||
if (!target) return null;
|
||||
const element = target as Element;
|
||||
if (typeof element.closest === 'function') return element;
|
||||
const node = target as Node & { parentElement?: Element | null };
|
||||
return node.parentElement ?? null;
|
||||
};
|
||||
|
||||
export function SwipeTabs<T extends string | number>({
|
||||
@@ -80,8 +88,18 @@ export function SwipeTabs<T extends string | number>({
|
||||
});
|
||||
|
||||
const shouldIgnoreSwipe = useCallback((target: EventTarget | null) => {
|
||||
if (!target || typeof (target as Element).closest !== 'function') return false;
|
||||
return Boolean((target as Element).closest('[data-swipe-ignore="true"]'));
|
||||
const element = resolveSwipeTarget(target);
|
||||
if (!element) return false;
|
||||
if (element.closest(
|
||||
'[data-swipe-ignore="true"], button, a, input, select, textarea, [role="button"], [role="link"], [role="switch"], [contenteditable="true"]'
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
const label = element.closest('label');
|
||||
if (label && label.querySelector('input, select, textarea, button')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}, []);
|
||||
|
||||
const applyTransform = useCallback((offset: number, animate: boolean) => {
|
||||
|
||||
Reference in New Issue
Block a user