mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 21:27:20 +00:00
feat(core): init organize (#7456)
This commit is contained in:
@@ -20,6 +20,9 @@ type DropTargetGetFeedback<D extends DNDData> = Parameters<
|
||||
source: {
|
||||
data: D['draggable'];
|
||||
};
|
||||
} & {
|
||||
treeInstruction: Instruction | null;
|
||||
closestEdge: Edge | null;
|
||||
};
|
||||
|
||||
type DropTargetGet<T, D extends DNDData> =
|
||||
@@ -27,17 +30,60 @@ type DropTargetGet<T, D extends DNDData> =
|
||||
| ((data: DropTargetGetFeedback<D>) => T);
|
||||
|
||||
function dropTargetGet<T, D extends DNDData>(
|
||||
get: T
|
||||
get: T,
|
||||
options: DropTargetOptions<D>
|
||||
): T extends undefined
|
||||
? undefined
|
||||
: T extends DropTargetGet<infer I, D>
|
||||
? (args: DropTargetGetFeedback<D>) => I
|
||||
? (
|
||||
args: Omit<DropTargetGetFeedback<D>, 'treeInstruction' | 'closestEdge'>
|
||||
) => I
|
||||
: never {
|
||||
if (get === undefined) {
|
||||
return undefined as any;
|
||||
}
|
||||
return ((args: DropTargetGetFeedback<D>) =>
|
||||
typeof get === 'function' ? (get as any)(args) : get) as any;
|
||||
return ((
|
||||
args: Omit<DropTargetGetFeedback<D>, 'treeInstruction' | 'closestEdge'>
|
||||
) => {
|
||||
if (typeof get === 'function') {
|
||||
return (get as any)({
|
||||
...args,
|
||||
get treeInstruction() {
|
||||
return options.treeInstruction
|
||||
? extractInstruction(
|
||||
attachInstruction(
|
||||
{},
|
||||
{
|
||||
input: args.input,
|
||||
element: args.element,
|
||||
currentLevel: options.treeInstruction.currentLevel,
|
||||
indentPerLevel: options.treeInstruction.indentPerLevel,
|
||||
mode: options.treeInstruction.mode,
|
||||
block: options.treeInstruction.block,
|
||||
}
|
||||
)
|
||||
)
|
||||
: null;
|
||||
},
|
||||
get closestEdge() {
|
||||
return options.closestEdge
|
||||
? extractClosestEdge(
|
||||
attachClosestEdge(
|
||||
{},
|
||||
{
|
||||
input: args.input,
|
||||
element: args.element,
|
||||
allowedEdges: options.closestEdge.allowedEdges,
|
||||
}
|
||||
)
|
||||
)
|
||||
: null;
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return get;
|
||||
}
|
||||
}) as any;
|
||||
}
|
||||
|
||||
export type DropTargetDropEvent<D extends DNDData> = Parameters<
|
||||
@@ -52,6 +98,8 @@ export type DropTargetDragEvent<D extends DNDData> = Parameters<
|
||||
source: { data: D['draggable'] };
|
||||
};
|
||||
|
||||
export type DropTargetTreeInstruction = Instruction;
|
||||
|
||||
export interface DropTargetOptions<D extends DNDData = DNDData> {
|
||||
data?: DropTargetGet<D['dropTarget'], D>;
|
||||
canDrop?: DropTargetGet<boolean, D>;
|
||||
@@ -80,8 +128,26 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
null
|
||||
);
|
||||
const [closestEdge, setClosestEdge] = useState<Edge | null>(null);
|
||||
const [dropEffect, setDropEffect] = useState<'copy' | 'link' | 'move' | null>(
|
||||
null
|
||||
);
|
||||
const [draggedOverDraggable, setDraggedOverDraggable] = useState<{
|
||||
data: D['draggable'];
|
||||
} | null>(null);
|
||||
const [draggedOverPosition, setDraggedOverPosition] = useState<{
|
||||
/**
|
||||
* relative position to the drop target element top-left corner
|
||||
*/
|
||||
relativeX: number;
|
||||
relativeY: number;
|
||||
clientX: number;
|
||||
clientY: number;
|
||||
}>({ relativeX: 0, relativeY: 0, clientX: 0, clientY: 0 });
|
||||
|
||||
const enableDraggedOver = useRef(false);
|
||||
const enableDraggedOverDraggable = useRef(false);
|
||||
const enableDraggedOverPosition = useRef(false);
|
||||
const enableDropEffect = useRef(false);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const options = useMemo(getOptions, deps);
|
||||
@@ -92,19 +158,36 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
}
|
||||
return dropTargetForElements({
|
||||
element: dropTargetRef.current,
|
||||
canDrop: dropTargetGet(options.canDrop),
|
||||
getDropEffect: dropTargetGet(options.dropEffect),
|
||||
getIsSticky: dropTargetGet(options.isSticky),
|
||||
canDrop: dropTargetGet(options.canDrop, options),
|
||||
getDropEffect: dropTargetGet(options.dropEffect, options),
|
||||
getIsSticky: dropTargetGet(options.isSticky, options),
|
||||
onDrop: args => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable(null);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
setDraggedOverPosition({
|
||||
relativeX: 0,
|
||||
relativeY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
});
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['treeInstruction'];
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
}
|
||||
@@ -120,7 +203,7 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
}
|
||||
},
|
||||
getData: args => {
|
||||
const originData = dropTargetGet(options.data ?? {})(args);
|
||||
const originData = dropTargetGet(options.data ?? {}, options)(args);
|
||||
const { input, element } = args;
|
||||
const withInstruction = options.treeInstruction
|
||||
? attachInstruction(originData, {
|
||||
@@ -141,43 +224,116 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
: withInstruction;
|
||||
return withClosestEdge;
|
||||
},
|
||||
onDragEnter: () => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(true);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['draggedOver'] = 'true';
|
||||
}
|
||||
},
|
||||
onDrag: args => {
|
||||
let instruction = null;
|
||||
let closestEdge = null;
|
||||
if (options.treeInstruction) {
|
||||
instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (
|
||||
args.location.current.dropTargets[0]?.element ===
|
||||
dropTargetRef.current
|
||||
) {
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable({ data: args.source.data });
|
||||
}
|
||||
let instruction = null;
|
||||
let closestEdge = null;
|
||||
if (options.treeInstruction) {
|
||||
instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['treeInstruction'] =
|
||||
instruction?.type;
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
const rect = args.self.element.getBoundingClientRect();
|
||||
const { clientX, clientY } = args.location.current.input;
|
||||
setDraggedOverPosition({
|
||||
relativeX: clientX - rect.x,
|
||||
relativeY: clientY - rect.y,
|
||||
clientX: clientX,
|
||||
clientY: clientY,
|
||||
});
|
||||
}
|
||||
options.onDrag?.({
|
||||
...args,
|
||||
treeInstruction: instruction,
|
||||
closestEdge,
|
||||
} as DropTargetDropEvent<D>);
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
options.onDrag?.({
|
||||
...args,
|
||||
treeInstruction: instruction,
|
||||
closestEdge,
|
||||
} as DropTargetDropEvent<D>);
|
||||
},
|
||||
onDragLeave: () => {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
onDropTargetChange: args => {
|
||||
if (
|
||||
args.location.current.dropTargets[0]?.element ===
|
||||
dropTargetRef.current
|
||||
) {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(true);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
const instruction = extractInstruction(args.self.data);
|
||||
setTreeInstruction(instruction);
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['treeInstruction'] =
|
||||
instruction?.type;
|
||||
}
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
const closestEdge = extractClosestEdge(args.self.data);
|
||||
setClosestEdge(closestEdge);
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable({ data: args.source.data });
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
const rect = args.self.element.getBoundingClientRect();
|
||||
setDraggedOverPosition({
|
||||
relativeX: args.location.current.input.clientX - rect.x,
|
||||
relativeY: args.location.current.input.clientY - rect.y,
|
||||
clientX: args.location.current.input.clientX,
|
||||
clientY: args.location.current.input.clientY,
|
||||
});
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
dropTargetRef.current.dataset['draggedOver'] = 'true';
|
||||
}
|
||||
} else {
|
||||
if (enableDraggedOver.current) {
|
||||
setDraggedOver(false);
|
||||
}
|
||||
if (enableDraggedOverDraggable.current) {
|
||||
setDraggedOverDraggable(null);
|
||||
}
|
||||
if (options.treeInstruction) {
|
||||
setTreeInstruction(null);
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['treeInstruction'];
|
||||
}
|
||||
}
|
||||
if (enableDropEffect.current) {
|
||||
setDropEffect(args.self.dropEffect);
|
||||
}
|
||||
if (enableDraggedOverPosition.current) {
|
||||
setDraggedOverPosition({
|
||||
relativeX: 0,
|
||||
relativeY: 0,
|
||||
clientX: 0,
|
||||
clientY: 0,
|
||||
});
|
||||
}
|
||||
if (options.closestEdge) {
|
||||
setClosestEdge(null);
|
||||
}
|
||||
if (dropTargetRef.current) {
|
||||
delete dropTargetRef.current.dataset['draggedOver'];
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -189,6 +345,18 @@ export const useDropTarget = <D extends DNDData = DNDData>(
|
||||
enableDraggedOver.current = true;
|
||||
return draggedOver;
|
||||
},
|
||||
get draggedOverDraggable() {
|
||||
enableDraggedOverDraggable.current = true;
|
||||
return draggedOverDraggable;
|
||||
},
|
||||
get draggedOverPosition() {
|
||||
enableDraggedOverPosition.current = true;
|
||||
return draggedOverPosition;
|
||||
},
|
||||
get dropEffect() {
|
||||
enableDropEffect.current = true;
|
||||
return dropEffect;
|
||||
},
|
||||
treeInstruction,
|
||||
closestEdge,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user