typescript

This commit is contained in:
2025-11-13 01:07:55 +01:00
parent b812d748ea
commit ada089c05b
147 changed files with 7427 additions and 2534 deletions
@@ -0,0 +1,178 @@
import { safeInvoke } from '../events';
export const CLICK_ACTIONS = {
selectSingle: 'selectSingle',
openDetail: 'openDetail',
addCard: 'addCard',
addStack: 'addStack',
none: 'none',
} as const;
export const DRAG_ACTIONS = {
dragSelectSingle: 'dragSelectSingle',
dragSelection: 'dragSelection',
dragSelectStack: 'dragSelectStack',
none: 'none',
} as const;
export type ClickAction = (typeof CLICK_ACTIONS)[keyof typeof CLICK_ACTIONS];
export type DragAction = (typeof DRAG_ACTIONS)[keyof typeof DRAG_ACTIONS];
export const STACK_HIT_EPSILON = 4;
export const POINTER_DRAG_THRESHOLD_SQUARED = 16;
export const LONG_PRESS_DURATION_MS = 450;
export const withinThreshold = (dx: number, dy: number, thresholdSquared: number): boolean => (dx * dx + dy * dy) <= thresholdSquared;
interface PointerIntentArgs {
doc: { id: string | number };
entryDescriptor: unknown;
selectedDocumentIds: Array<string | number>;
metaKey: boolean;
pointerButton?: number;
pointerType?: string;
stackHits?: string[] | null;
}
export interface PointerIntent {
docId: string | number;
entryDescriptor: unknown;
pointerType?: string;
pointerButton?: number;
selectedAtDown: boolean;
selectionCountAtDown: number;
metaKey: boolean;
clickAction: ClickAction;
dragAction: DragAction;
stackDocIdsForDrag: string[] | null;
stackDocIdsForClick: string[] | null;
stackReplaceOnClick: boolean;
stackReplaceOnDrag: boolean;
clickSelectionApplied: boolean;
stackSelectionApplied: boolean;
longPressTriggered: boolean;
}
export const createPointerIntent = ({
doc,
entryDescriptor,
selectedDocumentIds,
metaKey,
pointerButton,
pointerType,
stackHits,
}: PointerIntentArgs): PointerIntent => {
const alreadySelected = selectedDocumentIds.includes(doc.id);
const selectionCount = Array.isArray(selectedDocumentIds) ? selectedDocumentIds.length : 0;
let clickAction = CLICK_ACTIONS.none;
let dragAction = DRAG_ACTIONS.none;
if (metaKey) {
clickAction = CLICK_ACTIONS.addStack;
dragAction = DRAG_ACTIONS.dragSelectStack;
} else if (alreadySelected) {
clickAction = CLICK_ACTIONS.selectSingle;
dragAction = selectionCount > 1 ? DRAG_ACTIONS.dragSelection : DRAG_ACTIONS.dragSelectSingle;
} else {
clickAction = CLICK_ACTIONS.selectSingle;
dragAction = DRAG_ACTIONS.dragSelectSingle;
}
const stackList = Array.isArray(stackHits) && stackHits.length > 0
? stackHits.slice()
: [String(doc.id)];
const stackDocIdsForDrag = dragAction === DRAG_ACTIONS.dragSelectStack ? stackList : null;
const stackDocIdsForClick = clickAction === CLICK_ACTIONS.addStack ? stackList : null;
return {
docId: doc.id,
entryDescriptor,
pointerType,
pointerButton,
selectedAtDown: alreadySelected,
selectionCountAtDown: selectionCount,
metaKey,
clickAction,
dragAction,
stackDocIdsForDrag,
stackDocIdsForClick,
stackReplaceOnClick: clickAction === CLICK_ACTIONS.addStack,
stackReplaceOnDrag: dragAction === DRAG_ACTIONS.dragSelectStack,
clickSelectionApplied: false,
stackSelectionApplied: false,
longPressTriggered: false,
};
};
export const applyClickPlanImmediately = ({ intent, event, onEntryPointer, onDocumentStackSelect }: {
intent: PointerIntent;
event?: unknown;
onEntryPointer?: (descriptor: unknown, event?: unknown) => void;
onDocumentStackSelect?: (docIds: string[], event?: unknown, options?: { replace?: boolean }) => void;
}) => {
switch (intent.clickAction) {
case CLICK_ACTIONS.selectSingle:
case CLICK_ACTIONS.addCard:
safeInvoke(onEntryPointer, intent.entryDescriptor, event);
intent.clickSelectionApplied = true;
break;
case CLICK_ACTIONS.addStack:
if (Array.isArray(intent.stackDocIdsForClick) && intent.stackDocIdsForClick.length > 0) {
safeInvoke(
onDocumentStackSelect,
intent.stackDocIdsForClick,
event,
{ replace: intent.stackReplaceOnClick },
);
intent.clickSelectionApplied = true;
intent.stackSelectionApplied = true;
}
break;
case CLICK_ACTIONS.openDetail:
default:
intent.clickSelectionApplied = true;
break;
}
};
export const finalizeClickSelection = ({ intent, event, onEntryPointer, onDocumentStackSelect }: {
intent: PointerIntent;
event?: unknown;
onEntryPointer?: (descriptor: unknown, event?: unknown) => void;
onDocumentStackSelect?: (docIds: string[], event?: unknown, options?: { replace?: boolean }) => void;
}) => {
if (!intent || intent.clickSelectionApplied) {
return;
}
applyClickPlanImmediately({ intent, event, onEntryPointer, onDocumentStackSelect });
};
export const applyLongPressSelection = ({ intent, stackDocIds, syntheticEvent, onDocumentStackSelect }: {
intent: PointerIntent;
stackDocIds?: string[] | null;
syntheticEvent?: unknown;
onDocumentStackSelect?: (docIds: string[], event?: unknown, options?: { replace?: boolean }) => void;
}) => {
if (!intent) {
return;
}
const stackCopy = Array.isArray(stackDocIds) && stackDocIds.length > 0
? stackDocIds.slice()
: [intent.docId];
safeInvoke(onDocumentStackSelect, stackCopy, syntheticEvent, { replace: true });
intent.clickAction = CLICK_ACTIONS.addStack;
intent.dragAction = DRAG_ACTIONS.dragSelectStack;
intent.stackDocIdsForClick = stackCopy;
intent.stackDocIdsForDrag = stackCopy;
intent.stackReplaceOnClick = true;
intent.stackReplaceOnDrag = true;
intent.clickSelectionApplied = true;
intent.stackSelectionApplied = true;
intent.longPressTriggered = true;
};