Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge changes from candulabs/craft.js #69

Merged
merged 31 commits into from
May 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
f61c311
Add prepush hook, some small nits to the craft project setup (#1)
mresposito Mar 25, 2020
663958e
Add onStateChanged hook (#2)
mresposito Mar 28, 2020
28a20de
Editor state get & set (#3)
matdru Mar 28, 2020
06fa0a8
Sync changes from main repo (#4)
mresposito Mar 31, 2020
64159fd
Adds github workflow (#5)
matdru Apr 1, 2020
da5787c
Actions - second attempt (#6)
matdru Apr 1, 2020
8b95a6e
v0.1.6
actions-user Apr 1, 2020
3ef647f
Adds npmrc
matdru Apr 1, 2020
f55a6bf
Moves env to job level
matdru Apr 1, 2020
6450d98
v0.1.7
actions-user Apr 1, 2020
39b1458
Sync changes from main repo (#8)
matdru Apr 2, 2020
1687460
v0.1.8
actions-user Apr 2, 2020
894b4b0
expose use node context (#9)
mresposito Apr 3, 2020
99557af
v0.1.9
actions-user Apr 3, 2020
ab593ff
Rewrite actions.delete and actions.add plus unit tests (#10)
mresposito Apr 8, 2020
559ee2c
v0.1.10
actions-user Apr 8, 2020
03188b2
Refactor event handler to add more unit tests and make it more readab…
mresposito Apr 9, 2020
3f2f209
v0.1.11
actions-user Apr 9, 2020
8d800de
Local development with yalc (#12)
matdru Apr 9, 2020
514be31
v0.1.12
actions-user Apr 9, 2020
9fc2b6a
Parse entire tree when dropping a node (#13)
mresposito Apr 12, 2020
3c7d13f
v0.1.13
actions-user Apr 12, 2020
844c6bf
Adds check if resolver has isCanvas set (#14)
matdru Apr 14, 2020
56a1c25
v0.1.14
actions-user Apr 14, 2020
b836815
fix: use Subscriber to handle onStateChange (#15)
Apr 21, 2020
9d85e4e
v0.1.15
actions-user Apr 21, 2020
36bfbf0
merge all the changes from candulabs craft
mresposito Apr 26, 2020
c744ec8
add enzyme deps
mresposito Apr 27, 2020
b19607d
pr review
mresposito Apr 29, 2020
f51eeaa
feat: Improvements to PR-69 (#72)
prevwong May 14, 2020
2fcd8df
Merge branch 'master' into michele-actions
mresposito May 14, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Refactor event handler to add more unit tests and make it more readab…
…le (#11)

* couple small style improvements

* refactor event handlers

* sort the query methods by name
  • Loading branch information
mresposito authored Apr 9, 2020
commit 03188b2e8dab942c7bd37c8c3c0a8c5a6e550d05
65 changes: 34 additions & 31 deletions packages/core/src/editor/query.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,44 +41,22 @@ export function QueryMethods(Editor: EditorState) {
typeof node === "string" ? Editor.nodes[node] : node;

return {
/**
* Get the current Editor options
*/
getOptions(): Options {
return options;
},
/**
* Get a Node representing the specified React Element
* @param child
* @param reactElement
* @param extras
*/
createNode(child: React.ReactElement | string, extras?: any) {
const node = transformJSXToNode(child, extras);
createNode(reactElement: React.ReactElement | string, extras?: any) {
const node = transformJSXToNode(reactElement, extras);

const name = resolveComponent(options.resolver, node.data.type);
invariant(name !== null, ERRROR_NOT_IN_RESOLVER);
node.data.displayName = node.data.displayName
? node.data.displayName
: name;

node.data.displayName = node.data.displayName || name;
prevwong marked this conversation as resolved.
Show resolved Hide resolved
node.data.name = name;

return node;
},

getState(): Record<NodeId, SerializedNodeData> {
return Object.keys(Editor.nodes).reduce((result: any, id: NodeId) => {
const {
data: { ...data },
} = Editor.nodes[id];
result[id] = serializeNode({ ...data }, options.resolver);
return result;
}, {});
},
/**
* Retrieve the JSON representation of the editor's Nodes
*/
serialize(): string {
return JSON.stringify(this.getState());
},
/**
* Determine the best possible location to drop the source Node relative to the target Node
*/
Expand Down Expand Up @@ -124,9 +102,9 @@ export function QueryMethods(Editor: EditorState) {
pos.x,
pos.y
);
const currentNode = targetParentNodes.length
? Editor.nodes[targetParentNodes[dropAction.index]]
: null;
const currentNode =
targetParentNodes.length &&
Editor.nodes[targetParentNodes[dropAction.index]];

const output: Indicator = {
placement: {
Expand All @@ -150,6 +128,24 @@ export function QueryMethods(Editor: EditorState) {

return output;
},

/**
* Get the current Editor options
*/
getOptions(): Options {
return options;
},

getState(): Record<NodeId, SerializedNodeData> {
prevwong marked this conversation as resolved.
Show resolved Hide resolved
return Object.keys(Editor.nodes).reduce((result: any, id: NodeId) => {
const {
data: { ...data },
} = Editor.nodes[id];
result[id] = serializeNode({ ...data }, options.resolver);
return result;
}, {});
},

/**
* Helper methods to describe the specified Node
* @param id
Expand Down Expand Up @@ -256,5 +252,12 @@ export function QueryMethods(Editor: EditorState) {
},
};
},

/**
* Retrieve the JSON representation of the editor's Nodes
*/
serialize(): string {
return JSON.stringify(this.getState());
},
};
}
4 changes: 1 addition & 3 deletions packages/core/src/events/EventContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,4 @@ import { EventHandlers } from "./EventHandlers";

export const EventHandlerContext = createContext<EventHandlers>(null);

export const useEventHandler = () => {
return useContext(EventHandlerContext);
};
export const useEventHandler = () => useContext(EventHandlerContext);
190 changes: 87 additions & 103 deletions packages/core/src/events/EventHandlers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,22 @@
import { createShadow } from "./createShadow";
import { NodeId, Node, Indicator } from "../interfaces";
import { Handlers, ConnectorsForHandlers } from "@candulabs/craft-utils";
import { debounce } from "debounce";
import { EditorStore } from "../editor/store";

type DraggedElement = NodeId | Node;

const event = ({
prevwong marked this conversation as resolved.
Show resolved Hide resolved
name,
handler,
capture,
}: {
name: string;
handler: (e: MouseEvent, id: any) => void;
capture?: boolean;
}) => (capture ? [name, handler, capture] : [name, handler]);
const rapidDebounce = (f) => debounce(f, 1);

/**
* Specifies Editor-wide event handlers and connectors
*/
Expand All @@ -16,145 +28,139 @@ export class EventHandlers extends Handlers<
static events: { indicator: Indicator };

handlers() {
let handlers = {
return {
select: {
init: () => {
return () => {
this.store.actions.setNodeEvent("selected", null);
};
},
init: () => () => this.store.actions.setNodeEvent("selected", null),
events: [
[
"mousedown",
debounce((_, id: NodeId) => {
this.store.actions.setNodeEvent("selected", id);
}, 1),
true,
],
event({
name: "mousedown",
handler: rapidDebounce((_, id: NodeId) =>
this.store.actions.setNodeEvent("selected", id)
),
capture: true,
}),
],
},
hover: {
init: () => {
return () => {
this.store.actions.setNodeEvent("hovered", null);
};
},
init: () => () => this.store.actions.setNodeEvent("hovered", null),
events: [
[
"mouseover",
debounce((_, id: NodeId) => {
this.store.actions.setNodeEvent("hovered", id);
}, 1),
true,
],
event({
name: "mouseover",
handler: rapidDebounce((_, id: NodeId) =>
this.store.actions.setNodeEvent("hovered", id)
),
capture: true,
}),
],
},
drop: {
events: [
[
"dragover",
(e: MouseEvent, id: NodeId) => {
event({
name: "dragover",
handler: (e: MouseEvent) => {
e.preventDefault();
e.stopPropagation();
},
],
[
"dragenter",
(e: MouseEvent, id: NodeId) => {
}),
event({
name: "dragenter",
handler: (e: MouseEvent, id: NodeId) => {
e.preventDefault();
e.stopPropagation();

if (!EventHandlers.draggedElement) return;
if (!EventHandlers.draggedElement) {
return;
}

const getPlaceholder = this.store.query.getDropPlaceholder(
const { clientX: x, clientY: y } = e;
const indicator = this.store.query.getDropPlaceholder(
EventHandlers.draggedElement,
id,
{
x: e.clientX,
y: e.clientY,
}
{ x, y }
);

if (getPlaceholder) {
this.store.actions.setIndicator(getPlaceholder);
EventHandlers.events = {
indicator: getPlaceholder,
};
if (!indicator) {
return;
}
this.store.actions.setIndicator(indicator);
EventHandlers.events = { indicator };
},
],
}),
],
},

drag: {
init: (node) => {
node.setAttribute("draggable", true);
return () => {
node.setAttribute("draggable", false);
};
init: (el) => {
el.setAttribute("draggable", true);
return () => el.setAttribute("draggable", false);
},
events: [
[
"dragstart",
(e: DragEvent, id: NodeId) => {
event({
name: "dragstart",
handler: (e: DragEvent, id: NodeId) => {
e.stopPropagation();
e.stopImmediatePropagation();

this.store.actions.setNodeEvent("dragged", id);
EventHandlers.createShadow(e, id);

EventHandlers.draggedElementShadow = createShadow(e);
EventHandlers.draggedElement = id;
},
],
[
"dragend",
(e: DragEvent) => {
}),
event({
name: "dragend",
handler: (e: DragEvent) => {
e.stopPropagation();
this.dropElement((draggedElement, placement) => {

const onDropElement = (draggedElement, placement) =>
this.store.actions.move(
draggedElement as NodeId,
placement.parent.id,
placement.index + (placement.where === "after" ? 1 : 0)
);
});
this.dropElement(onDropElement);
},
],
}),
],
},
create: {
init: (el) => {
el.setAttribute("draggable", true);
return () => {
el.removeAttribute("draggable");
};
return () => el.removeAttribute("draggable");
},
events: [
[
"dragstart",
(e: DragEvent, userElement: React.ElementType) => {
event({
name: "dragstart",
handler: (e: DragEvent, userElement: React.ElementType) => {
e.stopPropagation();
e.stopImmediatePropagation();

const node = this.store.query.createNode(userElement);
EventHandlers.createShadow(e, node);

EventHandlers.draggedElementShadow = createShadow(e);
EventHandlers.draggedElement = node;
},
],
[
"dragend",
(e: DragEvent) => {
}),
event({
name: "dragend",
handler: (e: DragEvent) => {
e.stopPropagation();
this.dropElement((draggedElement, placement) => {

const onDropElement = (draggedElement, placement) => {
const index =
placement.index + (placement.where === "after" ? 1 : 0);
this.store.actions.addNodeAtIndex(
draggedElement,
placement.parent.id,
index
);
});
};
this.dropElement(onDropElement);
},
],
}),
],
},
};

return handlers;
}

private dropElement(
Expand All @@ -163,20 +169,14 @@ export class EventHandlers extends Handlers<
placement: Indicator["placement"]
) => void
) {
const events = EventHandlers.events;
if (
EventHandlers.draggedElement &&
events.indicator &&
!events.indicator.error
) {
const { draggedElement, draggedElementShadow, events } = EventHandlers;
if (draggedElement && events.indicator && !events.indicator.error) {
const { placement } = events.indicator;
onDropNode(EventHandlers.draggedElement, placement);
onDropNode(draggedElement, placement);
}

if (EventHandlers.draggedElementShadow) {
EventHandlers.draggedElementShadow.parentNode.removeChild(
EventHandlers.draggedElementShadow
);
if (draggedElementShadow) {
draggedElementShadow.parentNode.removeChild(draggedElementShadow);
EventHandlers.draggedElementShadow = null;
}

Expand All @@ -185,22 +185,6 @@ export class EventHandlers extends Handlers<
this.store.actions.setNodeEvent("dragged", null);
}

static createShadow(e: DragEvent, node?: DraggedElement) {
const shadow = (e.target as HTMLElement).cloneNode(true) as HTMLElement;
const { width, height } = (e.target as HTMLElement).getBoundingClientRect();
shadow.style.width = `${width}px`;
shadow.style.height = `${height}px`;
shadow.style.position = "fixed";
shadow.style.left = "-100%";
shadow.style.top = "-100%";

document.body.appendChild(shadow);
e.dataTransfer.setDragImage(shadow, 0, 0);

EventHandlers.draggedElementShadow = shadow;
EventHandlers.draggedElement = node;
}

/**
* Create a new instance of Handlers with reference to the current EventHandlers
* @param type A class that extends DerivedEventHandlers
Expand Down
Loading