Skip to content

Commit

Permalink
Merge pull request #4 from pubpub/new-hooks-api
Browse files Browse the repository at this point in the history
update: New Hooks API
  • Loading branch information
idreyn authored Oct 8, 2021
2 parents 026d613 + 8cedfff commit e9d3aec
Show file tree
Hide file tree
Showing 17 changed files with 373 additions and 328 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ module.exports = {
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_+$" }],
"@typescript-eslint/no-use-before-define": 0,
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-use-before-define": 0,
"no-constant-condition": 0,
Expand Down
20 changes: 10 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"name": "@pubpub/prosemirror-reactive",
"version": "0.1.10",
"version": "0.2.0",
"description": "Use reactive, stateful nodes in Prosemirror",
"main": "dist/index.js",
"devDependencies": {
"@types/jest": "^24.0.18",
"@types/node": "^12.7.4",
"@types/prosemirror-model": "^1.7.2",
"@types/prosemirror-state": "^1.2.5",
"@types/prosemirror-view": "^1.15.0",
"@types/prosemirror-model": "^1.13.2",
"@types/prosemirror-state": "^1.2.7",
"@types/prosemirror-view": "^1.19.1",
"@typescript-eslint/eslint-plugin": "^2.19.2",
"@typescript-eslint/parser": "^2.19.2",
"eslint": "^6.0.1",
Expand Down
13 changes: 5 additions & 8 deletions src/examples/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { ReactiveNodeSpec } from "../store/types";
import { Schema } from "prosemirror-model";

import { ReactiveNodeSpec } from "../store/types";
import { useDeferredNode, useState, useEffect, useTransactionState } from "..";

const doc: ReactiveNodeSpec = {
content: "block+",
};
Expand Down Expand Up @@ -70,7 +72,6 @@ export const feedMe: ReactiveNodeSpec = {

reactiveAttrs: {
report: function({ attrs }) {
const { useDeferredNode } = this;
return useDeferredNode(attrs.wantsToEatId, food => `yum, ${food.attrs.color}!`);
},
},
Expand All @@ -83,7 +84,6 @@ export const feedMeMore: ReactiveNodeSpec = {

reactiveAttrs: {
report: function({ attrs }) {
const { useDeferredNode } = this;
return useDeferredNode(
attrs.wantsToEatIds,
(first, second) => `yum, ${first.attrs.color} and ${second.attrs.color}!`
Expand All @@ -109,7 +109,6 @@ export const boxOpener: ReactiveNodeSpec = {
return node.attrs.value;
},
boxValue: function(node) {
const { useDeferredNode } = this;
return useDeferredNode(node.attrs.lookForBoxId, box => box.attrs.value);
},
},
Expand All @@ -132,7 +131,6 @@ export const sheepCounter: ReactiveNodeSpec = {

reactiveAttrs: {
report: function(node) {
const { useState, useEffect } = this;
const [sheepCount, setSheepCount] = useState(0);

useEffect(() => {
Expand All @@ -155,7 +153,7 @@ export const sheepNamer: ReactiveNodeSpec = {
},
reactiveAttrs: {
report: function(node) {
return this.useDeferredNode(node.attrs.sheepId, sheepNode => {
return useDeferredNode(node.attrs.sheepId, sheepNode => {
if (sheepNode) {
return `My sheep is named ${sheepNode.attrs.name}`;
}
Expand All @@ -168,7 +166,6 @@ export const sheepNamer: ReactiveNodeSpec = {
export const statefulSheepNamer: ReactiveNodeSpec = {
reactiveAttrs: {
report: function() {
const { useState, useEffect, useDeferredNode } = this;
const [sheepIndex, setSheepIndex] = useState(0);

useEffect(() => {
Expand All @@ -195,7 +192,7 @@ export const counter: ReactiveNodeSpec = {
},
reactiveAttrs: {
count: function() {
const counterState = this.useTransactionState(["counter"], { count: 0 });
const counterState = useTransactionState(["counter"], { count: 0 });
counterState.count++;
return counterState.count;
},
Expand Down
21 changes: 21 additions & 0 deletions src/globalHooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UseEffect, UseRef, UseState } from "./store/attrStore";
import { Hooks, UseDeferredNode, UseReactiveMap } from "./store/types";

let currentHooks: null | Hooks = null;

export const setCurrentHooks = (hooks: Hooks) => {
currentHooks = hooks;
};

export const useDeferredNode: UseDeferredNode = (nodeIds, callback) =>
currentHooks.useDeferredNode(nodeIds, callback);

export const useDocumentState: UseReactiveMap = (path, initialState) =>
currentHooks.useDocumentState(path, initialState);

export const useTransactionState: UseReactiveMap = (path, initialState) =>
currentHooks.useTransactionState(path, initialState);

export const useState: UseState = initialValue => currentHooks.useState(initialValue);
export const useEffect: UseEffect = (fn, dependencies) => currentHooks.useEffect(fn, dependencies);
export const useRef: UseRef = initialValue => currentHooks.useRef(initialValue);
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
export * from "./plugin";
export { getReactedDoc } from "./doc";
export { addTemporaryIdsToDoc } from "./util";
export {
useState,
useEffect,
useRef,
useDeferredNode,
useTransactionState,
useDocumentState,
} from "./globalHooks";
20 changes: 6 additions & 14 deletions src/store/__tests__/attrStore.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* global it, expect, jest */
import { Node } from "prosemirror-model";

import { useState, useEffect, useRef, useDocumentState } from "../..";
import { createSchema, greeter } from "../../examples/schemas";
import { AttrStore } from "../attrStore";

Expand All @@ -10,8 +11,8 @@ const schema = createSchema({ greeter });

const testNode = Node.fromJSON(schema, { type: "greeter", attrs: { name: "world" } });

const createTestStore = (fn, globalHooks = {}, onInvalidate?) =>
new AttrStore("anything", fn, globalHooks, onInvalidate);
const createTestStore = (fn, documentHooks = {}, onInvalidate?) =>
new AttrStore("anything", fn, documentHooks as any, onInvalidate);

it("runs an attr that can access the current Node value", () => {
const attr = createTestStore(function stateCell(node) {
Expand All @@ -24,17 +25,16 @@ it("runs an attr that can access the current Node value", () => {
it("runs an attr that can access the current global hooks", () => {
const attr = createTestStore(
function stateCell() {
return this.use3();
return useDocumentState(["hey"]);
},
{ use3: () => 3 }
{ useDocumentState: ([val]) => `${val}? yep.` }
);
const result = attr.run(testNode);
expect(result).toEqual(3);
expect(result).toEqual("hey? yep.");
});

it("runs an attr with a useState call", () => {
const attr = createTestStore(function stateCell() {
const { useState } = this;
const [someState] = useState("hello!");
return someState;
});
Expand All @@ -44,7 +44,6 @@ it("runs an attr with a useState call", () => {

it("runs an attr with a useRef call", () => {
const attr = createTestStore(function stateCell() {
const { useRef } = this;
const count = useRef(-1);
count.current += 1;
return count.current;
Expand All @@ -58,7 +57,6 @@ it("runs an attr with a useRef call", () => {

it("runs an attr with a useState and a useEffect call", () => {
const attr = createTestStore(function stateCell() {
const { useState, useEffect } = this;
const [count, setCount] = useState(0);

// In a DocumentStore this would trigger an infinite loop
Expand All @@ -75,7 +73,6 @@ it("runs an attr with a useState and a useEffect call", () => {

it("runs another attr that uses both useState and useEffect", () => {
const attr = createTestStore(function() {
const { useState, useEffect } = this;
const [count, setCount] = useState(37);

useEffect(() => {
Expand All @@ -98,7 +95,6 @@ it("re-runs a useEffect hook only when its dependencies change", () => {
let b = 5;

const attr = createTestStore(function() {
const { useEffect } = this;
useEffect(() => {
callbackFn();
return teardownFn;
Expand Down Expand Up @@ -136,7 +132,6 @@ it("tears down a useEffect hook as expected", () => {
let useFirstTeardown = true;

const attr = createTestStore(function() {
const { useEffect } = this;
useEffect(() => {
return useFirstTeardown ? firstTeardown : secondTeardown;
});
Expand Down Expand Up @@ -164,7 +159,6 @@ it("invalidates when its state changes", () => {

const attr = createTestStore(
function() {
const { useEffect, useState } = this;
const [ready, setReady] = useState(false);

useEffect(() => {
Expand All @@ -187,7 +181,6 @@ it("does not invalidate when setState is called, but does not change the state",

const attr = createTestStore(
function() {
const { useEffect, useState } = this;
const [ready, setReady] = useState(false);

useEffect(() => {
Expand All @@ -210,7 +203,6 @@ it("does not invalidate after it has been destroyed", () => {

const attr = createTestStore(
function() {
const { useEffect, useState } = this;
const [ready, setReady] = useState(false);

useEffect(() => {
Expand Down
Loading

0 comments on commit e9d3aec

Please sign in to comment.