Skip to content

Instantly share code, notes, and snippets.

@BrianHung
Created October 12, 2022 16:33
Show Gist options
  • Select an option

  • Save BrianHung/b889a1c357dfeea843746e32feb704a9 to your computer and use it in GitHub Desktop.

Select an option

Save BrianHung/b889a1c357dfeea843746e32feb704a9 to your computer and use it in GitHub Desktop.
import { types as t, type IAnyModelType, getSnapshot, onPatch } from "mobx-state-tree"
import invariant from "tiny-invariant";
import { validate as isUUID } from "uuid";
console.log("mobx");
const Cell = t.model("cell", {
id: t.refinement(t.identifier, id => isUUID(id)),
content: t.string,
row: t.reference(t.late((): IAnyModelType => Row)),
col: t.reference(t.late((): IAnyModelType => Col)),
node: t.reference(t.late((): IAnyModelType => Node)),
})
const Row = t.model("row", {
id: t.refinement(t.identifier, id => isUUID(id)),
order: t.string,
node: t.reference(t.late((): IAnyModelType => Node)),
})
const Col = t.model("col", {
id: t.refinement(t.identifier, id => isUUID(id)),
order: t.string,
node: t.reference(t.late((): IAnyModelType => Node)),
})
const Node = t
.model("node", {
id: t.refinement(t.identifier, id => isUUID(id)),
type: t.enumeration("NodeType", ["grid", "doc"]),
name: t.string,
children: t.map(t.reference(t.late((): IAnyModelType => Nodes))),
parentId: t.maybe(t.refinement(t.string, id => isUUID(id))),
layout: t.reference(t.late((): IAnyModelType => Layout)),
})
.actions(self => ({
setLayout: (id: string) => void (self.layout = id),
}))
const GridNode = Node.named("grid")
.props({
type: "grid",
rows: t.array(t.reference(t.late((): IAnyModelType => Row))),
cols: t.array(t.reference(t.late((): IAnyModelType => Col))),
cells: t.array(t.reference(t.late((): IAnyModelType => Cell))),
})
const DocNode = Node.named("doc")
.props({
type: "doc",
sourceId: t.maybe(t.string),
createdAt: t.maybe(t.string),
updatedAt: t.maybe(t.string),
inputs: t.array(t.string),
outputs: t.array(t.string),
})
const View = t.model("view", {
id: t.refinement(t.identifier, id => isUUID(id)),
name: t.string,
})
const Size = t
.model("size", {
width: t.number,
height: t.number,
})
.actions(self => ({
setSize(width: number, height: number) {
self.width = width;
self.height = height;
}
}))
.views(self => ({
get size() {
return {
width: self.width,
height: self.height,
}
}
}))
const Position = t
.model("position", {
x: t.number,
y: t.number,
})
.actions(self => ({
setPosition(x: number, y: number) {
self.x = x;
self.y = y;
}
}))
.views(self => ({
get position() {
return {
x: self.x,
y: self.y,
}
}
}))
const Layout = t
.compose(Size, Position)
.named("layout")
.props({
id: t.refinement(t.identifier, id => isUUID(id)),
view: t.reference(t.late((): IAnyModelType => View)),
node: t.reference(t.late((): IAnyModelType => Node)),
})
const nodeTypes = {
"doc": DocNode,
"grid": GridNode,
}
const Nodes = t.union({ dispatcher: ({type}) => nodeTypes[type] ?? invariant(type, `No type found.`) }, DocNode, GridNode);
const EditorState = t.model("State", {
nodes: t.map(Nodes),
doc: t.reference(DocNode),
views: t.map(View),
layouts: t.map(Layout),
cells: t.map(Cell),
rows: t.map(Row),
cols: t.map(Col),
})
const state = EditorState.create({
doc: "3e55b79e-073b-4d14-a727-bca81af450dd",
nodes: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
type: "doc",
name: "Untitled",
children: ["3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b"],
layout: "3e55b79e-073b-4d14-a727-bca81af450dd"
},
"3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b": {
id: "3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b",
type: "grid",
name: "Grid 1",
children: [],
layout: "3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b",
rows: ["3e55b79e-073b-4d14-a727-bca81af450dd"],
cols: ["3e55b79e-073b-4d14-a727-bca81af450dd"],
cells: ["3e55b79e-073b-4d14-a727-bca81af450dd"],
}
},
layouts: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
node: "3e55b79e-073b-4d14-a727-bca81af450dd",
view: "3e55b79e-073b-4d14-a727-bca81af450dd",
x: 0,
y: 0,
width: Number.POSITIVE_INFINITY,
height: Number.POSITIVE_INFINITY,
},
"3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b": {
id: "3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b",
node: "3fdd16fa-a3a2-4740-906c-b3e03c2e8f3b",
view: "3e55b79e-073b-4d14-a727-bca81af450dd",
x: 0,
y: 0,
width: Number.POSITIVE_INFINITY,
height: Number.POSITIVE_INFINITY,
},
},
views: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
name: "boop",
}
},
rows: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
order: "0",
node: "3e55b79e-073b-4d14-a727-bca81af450dd",
}
},
cols: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
order: "0",
node: "3e55b79e-073b-4d14-a727-bca81af450dd",
}
},
cells: {
"3e55b79e-073b-4d14-a727-bca81af450dd": {
id: "3e55b79e-073b-4d14-a727-bca81af450dd",
content: "Hello World",
row: "3e55b79e-073b-4d14-a727-bca81af450dd",
col: "3e55b79e-073b-4d14-a727-bca81af450dd",
node: "3e55b79e-073b-4d14-a727-bca81af450dd",
},
}
})
const patches = [], inverse = []
onPatch(state, (patch, inversePatch) => {
patches.push(patch);
inverse.push(inversePatch)
})
state.doc.children[0].layout.setPosition(1000, 10220)
state.doc.children[0].setLayout("3e55b79e-073b-4d14-a727-bca81af450dd");
state.doc.children[0].layout.setPosition(1000, 10220)
JSON.stringify(patches, inverse)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment