Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
feat: refactor API (prevwong#74)
Browse files Browse the repository at this point in the history
* Add prepush hook, some small nits to the craft project setup (#1)

* add test staged

* add prepush hook

* Add onStateChanged hook (#2)

* improve unit tests setup, refactor and move some unit tests. Also add a callback for nodes

* add pull request template

* add unit tests for frame, improve handling of frame

* Editor state get & set (#3)

* Adds nodes state get and set methods

* Fixes over-shadowing bug

* Add private @candulabs scope for release

* Switches whole repo to point to @candulabs fork

* Updates tests

* Bumps up core version

* Update README.md

Adds warning about using this fork instead of official release

* Sync changes from main repo (#4)

* add test staged

* add prepush hook

* run prettier

* change unit test matcher

* ignore Canvas root id test

Caused by Subscriber, to be fixed

* v0.1.0-beta.4

* Update contributing

* update naming

* update version number

* package naming

Co-authored-by: Prev Wong <prevwong@gmail.com>

* Adds github workflow (#5)

* Adds test workflow

* Fixes shell linter

* Refactors flow to use node step

* Adds build step

* Corrects dep version

* Removes bad dependency

* Fixes potential case sensitive typo

* Configures lerna version

* Reset fork versions for lerna

* v0.1.5

* Adds optional publish step

* Adds better name to workflow

* Removes redundant job name

* Improves naming further

* Actions - second attempt (#6)

* Adds test workflow

* Fixes shell linter

* Refactors flow to use node step

* Adds build step

* Corrects dep version

* Removes bad dependency

* Fixes potential case sensitive typo

* Configures lerna version

* Reset fork versions for lerna

* v0.1.5

* Adds optional publish step

* Adds better name to workflow

* Removes redundant job name

* Improves naming further

* Introduces split workflow

* v0.1.6

* Adds npmrc

* Moves env to job level

* v0.1.7

* Sync changes from main repo (#8)

* add test staged

* add prepush hook

* run prettier

* change unit test matcher

* ignore Canvas root id test

Caused by Subscriber, to be fixed

* v0.1.0-beta.4

* Update contributing

* fix: allow Subscriber to collect state when created (prevwong#52)

* fix: add types for subscriber

* docs: update styling

* docs: fix typos

* docs: add example for drop indicator colours

* chore: add open collective

* docs: add layers gif

* chore: update README

* docs: fix Frame props description

Co-authored-by: Michele Riccardo Esposito <mresposito5@gmail.com>
Co-authored-by: Prev Wong <prevwong@gmail.com>

* v0.1.8

* expose use node context (#9)

* v0.1.9

* Rewrite actions.delete and actions.add plus unit tests (#10)

* tidy up the style inside actions

* add unit tests for action

* improve actions.add and actions.delete functions

* fix drag selection

* v0.1.10

* Refactor event handler to add more unit tests and make it more readable (#11)

* couple small style improvements

* refactor event handlers

* sort the query methods by name

* v0.1.11

* Local development with yalc (#12)

* Adds setup for local development with yalc

* Adds nodemon config file to npmignore

* v0.1.12

* Parse entire tree when dropping a node (#13)

* change query to create and parse a tree, small code style nits

* parse an entire tree from jsx instead of just a single node

* implement adding the tree recursively

* fix dropping shadow

* improve the renderNode function to render nodes among children if there are any

* prevent nodes from being stripped from state if they are not in a canvas node

* v0.1.13

* Adds check if resolver has isCanvas set (#14)

* v0.1.14

* fix: use Subscriber to handle onStateChange (#15)

* v0.1.15

* add enzyme deps

* pr review

* feat: add deprecation util

* feat: add normaliser to createNode/transformJSX

* feat: refactor actions

* feat: refactor rendering

* feat: deprecate Canvas with Element

* cleanup

* fix: render node bug when node deleted

* fix tests

* fix: remove timeout hack

* feat: deprecate adding array of Nodes

* fix: simplify RenderNode

* nit: cleanup unused vars

* nit: remove comments

* chore: add yalc

* fix: Element rehydration

* chore: refactor parseNodeDataFromJSX

* fix: api scheme

* chore: remove capture/debounce handlers

* chore: handle deprecated _childNodes

* chore: hidden => isHidden

* chore: _childCanvas => linkedNodes

* nit: cleanup

* feat: add hydrationTimestamp

* chore: cleanup

* nit: rename Tree => NodeTree

* fix: deprecate decendants

* feat: move connectors to context

* fix: RenderNode

* fix: deserialisation

* feat: update hooks exposed actions

* fix: update action

* chore: cleanup

* chore: update api in test

* feat: refactor NodeHelpers

* nit: update element isCanvas => canvas

* fix: typo

* fix: NodeHelpers

* feat: refactor queries

* chore: cleanup

* fix: remove drag

* chore: update docs

* fix: remove drag

* feat: rename addTree => addNodeTree

* chore: rename onStateChange => onNodesChange

* feat: update linkednode parent

* chore: update docs

* feat: change to click event

* feat: remove id prefix and rename root node

* cleanup

* chore

* chore: remove isHidden

* chore: cleanup API

* chore: add test watch command

* chore: fix docs

* nit

* nit: cleanup

* nit: pr

* feat: deprecate craft name/defaultProps

* feat: ensure dragged element is selected

* chore: update docs

* fix: ensure events exist

* nit(layers): use updated API

* fix: existing node in element

* nit: cleanup

* nit: cleanup

Co-authored-by: Michele Riccardo Esposito <mresposito5@gmail.com>
Co-authored-by: Mateusz Drulis <mateusz.drulis@gmail.com>
Co-authored-by: GitHub Action <action@github.com>
  • Loading branch information
4 people authored Jun 12, 2020
1 parent a2da0f6 commit da714eb
Show file tree
Hide file tree
Showing 62 changed files with 2,181 additions and 1,537 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"prettier": "prettier --write .",
"release": "run-s lint clean build test release:npm",
"release:npm": "lerna publish",
"test:watch": "jest --watch",
"test": "jest",
"test:watch": "cross-env NODE_ENV=test jest --watchAll",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx"
},
"devDependencies": {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/editor/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useEditorStore } from "./store";
import { EditorContext } from "./EditorContext";

export const withDefaults = (options: Partial<Options> = {}) => ({
onStateChange: () => null,
onNodesChange: () => null,
onRender: ({ render }) => render,
resolver: {},
nodes: null,
Expand Down Expand Up @@ -41,7 +41,7 @@ export const Editor: React.FC<Partial<Options>> = ({
json: context.query.serialize(),
}),
({ json }) => {
context.query.getOptions().onStateChange(JSON.parse(json));
context.query.getOptions().onNodesChange(JSON.parse(json));
}
);
}, [context]);
Expand Down
217 changes: 217 additions & 0 deletions packages/core/src/editor/NodeHelpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { EditorState, Node, NodeId } from "@craftjs/core";
import invariant from "tiny-invariant";
import {
deprecationWarning,
ERROR_CANNOT_DRAG,
ERROR_DUPLICATE_NODEID,
ERROR_INVALID_NODE_ID,
ERROR_MOVE_INCOMING_PARENT,
ERROR_MOVE_NONCANVAS_CHILD,
ERROR_MOVE_OUTGOING_PARENT,
ERROR_MOVE_TO_DESCENDANT,
ERROR_MOVE_TO_NONCANVAS_PARENT,
ERROR_MOVE_TOP_LEVEL_NODE,
ROOT_NODE,
} from "@craftjs/utils";
import { serializeNode } from "../utils/serializeNode";
import { mergeTrees } from "../utils/mergeTrees";

export function NodeHelpers(state: EditorState, id: NodeId) {
invariant(typeof id == "string", ERROR_INVALID_NODE_ID);

const node = state.nodes[id];

const nodeHelpers = (id) => NodeHelpers(state, id);

const getNodeFromIdOrNode = (node: NodeId | Node) =>
typeof node === "string" ? state.nodes[node] : node;

return {
isCanvas() {
return !!node.data.isCanvas;
},
isRoot() {
return node.id === ROOT_NODE;
},
isLinkedNode() {
return (
node.data.parent &&
nodeHelpers(node.data.parent).linkedNodes().includes(node.id)
);
},
isTopLevelNode() {
return this.isRoot() || this.isLinkedNode();
},
isDeletable() {
return !this.isTopLevelNode();
},
isParentOfTopLevelNodes: () => !!node.data.linkedNodes,
isParentOfTopLevelCanvas() {
deprecationWarning("query.node(id).isParentOfTopLevelCanvas", {
suggest: "query.node(id).isParentOfTopLevelNodes",
});
return this.isParentOfTopLevelNodes();
},
get() {
return node;
},
ancestors(deep = false) {
function appendParentNode(
id: NodeId,
result: NodeId[] = [],
depth: number = 0
) {
result.push(id);
const node = state.nodes[id];
if (!node.data.parent) {
return result;
}

if (deep || (!deep && depth === 0)) {
result = appendParentNode(node.data.parent, result, depth + 1);
}
return result;
}
return appendParentNode(node.data.parent);
},
descendants(deep = false) {
function appendChildNode(
id: NodeId,
result: NodeId[] = [],
depth: number = 0
) {
const node = state.nodes[id];
if (deep || (!deep && depth === 0)) {
// Include linkedNodes if any
const linkedNodes = nodeHelpers(id).linkedNodes();

linkedNodes.forEach((nodeId) => {
result.push(nodeId);
result = appendChildNode(nodeId, result, depth + 1);
});

const childNodes = node.data.nodes;

if (!childNodes) {
return result;
}

// Include child Nodes if any
if (childNodes) {
childNodes.forEach((nodeId) => {
result.push(nodeId);
result = appendChildNode(nodeId, result, depth + 1);
});
}
}
return result;
}
return appendChildNode(id);
},
linkedNodes() {
return Object.values(node.data.linkedNodes || {});
},
isDraggable(onError?: (err: string) => void) {
try {
const targetNode = node;
invariant(!this.isTopLevelNode(), ERROR_MOVE_TOP_LEVEL_NODE);
invariant(
NodeHelpers(state, targetNode.data.parent).isCanvas(),
ERROR_MOVE_NONCANVAS_CHILD
);
invariant(
targetNode.rules.canDrag(targetNode, nodeHelpers),
ERROR_CANNOT_DRAG
);
return true;
} catch (err) {
if (onError) {
onError(err);
}
return false;
}
},
isDroppable(target: NodeId | Node, onError?: (err: string) => void) {
const isNewNode = typeof target == "object" && !state.nodes[target.id];
const targetNode = getNodeFromIdOrNode(target),
newParentNode = node;
try {
// If target is a NodeId (thus it's already in the state), check if it's a top-level node
if (typeof target === "string") {
invariant(
!nodeHelpers(target).isTopLevelNode(),
ERROR_MOVE_TOP_LEVEL_NODE
);
}

invariant(this.isCanvas(), ERROR_MOVE_TO_NONCANVAS_PARENT);
invariant(
newParentNode.rules.canMoveIn(targetNode, newParentNode, nodeHelpers),
ERROR_MOVE_INCOMING_PARENT
);

if (isNewNode) {
return true;
}

const currentParentNode =
targetNode.data.parent && state.nodes[targetNode.data.parent];

invariant(currentParentNode.data.isCanvas, ERROR_MOVE_NONCANVAS_CHILD);

invariant(
currentParentNode ||
(!currentParentNode && !state.nodes[targetNode.id]),
ERROR_DUPLICATE_NODEID
);

const targetDeepNodes = nodeHelpers(targetNode.id).descendants();

invariant(
!targetDeepNodes.includes(newParentNode.id) &&
newParentNode.id !== targetNode.id,
ERROR_MOVE_TO_DESCENDANT
);
invariant(
currentParentNode.rules.canMoveOut(
targetNode,
currentParentNode,
nodeHelpers
),
ERROR_MOVE_OUTGOING_PARENT
);

return true;
} catch (err) {
if (onError) {
onError(err);
}
return false;
}
},
toSerializedNode() {
return serializeNode(node.data, state.options.resolver);
},
toNodeTree() {
const childNodes = (node.data.nodes || []).map((childNodeId) => {
return NodeHelpers(state, childNodeId).toNodeTree();
});

return mergeTrees(node, childNodes);
},

/**
Deprecated NodeHelpers
**/

decendants(deep = false) {
deprecationWarning("query.node(id).decendants", {
suggest: "query.node(id).descendants",
});
return this.descendants(deep);
},
isTopLevelCanvas() {
return !this.isRoot() && !node.data.parent;
},
};
}
Loading

0 comments on commit da714eb

Please sign in to comment.