slate#createEditor TypeScript Examples

The following examples show how to use slate#createEditor. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: MessageFormatEditor.tsx    From project-loved-web with MIT License 6 votes vote down vote up
export default function MessageFormatEditor({
  className,
  readOnly,
  setValue,
  value,
  ...props
}: MessageFormatEditorProps & TextareaHTMLAttributes<HTMLDivElement>) {
  const editor = useMemo(() => withReact(createEditor()), []);

  return (
    <Slate
      editor={editor}
      onChange={(value) => {
        if (!readOnly) {
          setValue!(((value[0] as Element).children[0] as Text).text);
        }
      }}
      value={[{ children: [{ text: value, type: 0 }] }]}
    >
      <Editable
        {...props}
        className={`slate-editor${readOnly ? '' : ' editable'} ${className ?? ''}`}
        decorate={decorate}
        onKeyDown={onKeyDown}
        readOnly={readOnly}
        renderLeaf={renderLeaf}
      />
    </Slate>
  );
}
Example #2
Source File: fuzzer.ts    From slate-ot with MIT License 6 votes vote down vote up
/**
 * Overload slateType create function for easier random op generation
 */
slateType.create = function (init: Element) {
  console.log('called create in SlateType');
  init = _.cloneDeep(testDoc);
  const e = createEditor();
  e.children = init.children;
  return <Editor>init;
};
Example #3
Source File: image-editable.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withImage(withAngular(createEditor()));
Example #4
Source File: basic-editable.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #5
Source File: advanced-editable.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #6
Source File: tables.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withBlockCard(withTable(withAngular(createEditor())));
Example #7
Source File: search-highlighting.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #8
Source File: richtext.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withHistory(withAngular(createEditor()));
Example #9
Source File: readonly.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #10
Source File: placeholder.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editorWithCustomDecoration = withAngular(createEditor());
Example #11
Source File: placeholder.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #12
Source File: mentions.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withMentions(withHistory(withAngular(createEditor())));
Example #13
Source File: markdown-shortcuts.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withShortcuts(withHistory(withAngular(createEditor())));
Example #14
Source File: inlines.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withInlines(withHistory(withAngular(createEditor())));
Example #15
Source File: images.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withImage(withAngular(createEditor()));
Example #16
Source File: huge-document.component.ts    From slate-angular with MIT License 5 votes vote down vote up
editor = withAngular(createEditor());
Example #17
Source File: client.ts    From slate-ot with MIT License 5 votes vote down vote up
e: Editor = createEditor()
Example #18
Source File: rich-text.tsx    From platyplus with MIT License 5 votes vote down vote up
RichText: React.FC<
  FormControlBaseProps<Descendant[]> & { readOnly?: boolean }
> = ({
  value: valueProp,
  defaultValue = [
    {
      type: 'paragraph',
      children: [{ text: '' }]
    }
  ],
  // eslint-disable-next-line @typescript-eslint/no-empty-function
  onChange = () => {},
  readOnly = false
}) => {
  const fallbackValue =
    valueProp !== undefined && valueProp.length ? valueProp : defaultValue
  const [state, setState] = useState(fallbackValue)
  const renderElement = useCallback((props) => <Element {...props} />, [])
  const renderLeaf = useCallback((props) => <Leaf {...props} />, [])
  const editor = useMemo(() => withHistory(withReact(createEditor())), [])
  useEffect(() => {
    // TODO doesn't work
    setState(valueProp)
  }, [valueProp, editor])

  useEffect(() => {
    if (!readOnly) {
      ReactEditor.focus(editor)
    }
  }, [readOnly, editor])
  return (
    <Slate
      editor={editor}
      value={state}
      onChange={(v) => {
        if (!readOnly) {
          setState(v)
          const isAstChange = editor.operations.some(
            (op) => 'set_selection' !== op.type
          )
          if (isAstChange) {
            onChange(v, null)
          }
        }
      }}
    >
      {!readOnly && (
        <ButtonToolbar>
          <MarkButton format="bold" icon="bold" />
          <MarkButton format="italic" icon="italic" />
          <MarkButton format="underline" icon="underline" />
          <MarkButton format="code" icon="code" />
          <BlockButton format="heading-one" icon="header" />
          <BlockButton format="heading-two" icon="header" />
          <BlockButton format="block-quote" icon="quote-left" />
          <BlockButton format="numbered-list" icon="list-ol" />
          <BlockButton format="bulleted-list" icon="list-ul" />
        </ButtonToolbar>
      )}
      <Editable
        renderElement={renderElement}
        renderLeaf={renderLeaf}
        placeholder="Enter some rich text…"
        spellCheck
        autoFocus
        readOnly={readOnly}
        onKeyDown={(event) => {
          for (const hotkey in HOTKEYS) {
            if (isHotkey(hotkey, event)) {
              event.preventDefault()
              const mark = HOTKEYS[hotkey]
              toggleMark(editor, mark)
            }
          }
        }}
      />
    </Slate>
  )
}
Example #19
Source File: RichEditor.tsx    From Full-Stack-React-TypeScript-and-Node with MIT License 5 votes vote down vote up
RichEditor: FC<RichEditorProps> = ({ existingBody }) => {
  const [value, setValue] = useState<Node[]>(initialValue);
  const renderElement = useCallback((props) => <Element {...props} />, []);
  const renderLeaf = useCallback((props) => <Leaf {...props} />, []);
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);

  useEffect(() => {
    if (existingBody) {
      setValue([
        {
          type: "paragraph",
          text: existingBody,
        },
      ]);
    }
  }, []);

  const onChangeEditorValue = (val: Node[]) => {
    setValue(val);
  };

  return (
    <Slate editor={editor} value={value} onChange={onChangeEditorValue}>
      <Toolbar>
        <MarkButton format="bold" icon="bold" />
        <MarkButton format="italic" icon="italic" />
        <MarkButton format="underline" icon="underlined" />
        <MarkButton format="code" icon="code" />
        <BlockButton format="heading-one" icon="header1" />
        <BlockButton format="block-quote" icon="in_quotes" />
        <BlockButton format="numbered-list" icon="list_numbered" />
        <BlockButton format="bulleted-list" icon="list_bulleted" />
      </Toolbar>
      <Editable
        className="editor"
        renderElement={renderElement}
        renderLeaf={renderLeaf}
        placeholder="Enter some rich text…"
        spellCheck
        autoFocus
        onKeyDown={(event) => {
          for (const hotkey in HOTKEYS) {
            if (isHotkey(hotkey, event as any)) {
              event.preventDefault();
              const mark = HOTKEYS[hotkey];
              toggleMark(editor, mark);
            }
          }
        }}
      />
    </Slate>
  );
}
Example #20
Source File: slate-plugin.ts    From slate-vue with MIT License 5 votes vote down vote up
createEditorInstance = () => {
  const editor = withVue(createEditor())
  const gvm = createGvm()
  EDITOR_TO_GVM.set(editor, gvm)
  GVM_TO_EDITOR.set(gvm, editor)
  return editor
}
Example #21
Source File: RichEditor.tsx    From Full-Stack-React-TypeScript-and-Node with MIT License 5 votes vote down vote up
RichEditor: FC<RichEditorProps> = ({
  existingBody,
  readOnly,
  sendOutBody,
}) => {
  const [value, setValue] = useState<Node[]>(initialValue);
  const renderElement = useCallback((props) => <Element {...props} />, []);
  const renderLeaf = useCallback((props) => <Leaf {...props} />, []);
  const editor = useMemo(() => withHistory(withReact(createEditor())), []);

  useEffect(() => {
    console.log("existingBody", existingBody);
    if (existingBody) {
      setValue(JSON.parse(existingBody));
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [existingBody]);

  const onChangeEditorValue = (val: Node[]) => {
    setValue(val);
    sendOutBody && sendOutBody(val);
  };

  return (
    <Slate editor={editor} value={value} onChange={onChangeEditorValue}>
      {readOnly ? null : (
        <Toolbar>
          <MarkButton format="bold" icon="bold" />
          <MarkButton format="italic" icon="italic" />
          <MarkButton format="underline" icon="underlined" />
          <MarkButton format="code" icon="code" />
          <BlockButton format="heading-one" icon="header1" />
          <BlockButton format="block-quote" icon="in_quotes" />
          <BlockButton format="numbered-list" icon="list_numbered" />
          <BlockButton format="bulleted-list" icon="list_bulleted" />
        </Toolbar>
      )}
      <Editable
        className="editor"
        renderElement={renderElement}
        renderLeaf={renderLeaf}
        placeholder="Enter your post here."
        spellCheck
        autoFocus
        onKeyDown={(event) => {
          for (const hotkey in HOTKEYS) {
            if (isHotkey(hotkey, event as any)) {
              event.preventDefault();
              const mark = HOTKEYS[hotkey];
              toggleMark(editor, mark);
            }
          }
        }}
        readOnly={readOnly}
      />
    </Slate>
  );
}
Example #22
Source File: SlateType.ts    From slate-ot with MIT License 5 votes vote down vote up
slateType = {
  name: 'slate-ot-type',

  uri: 'http://sharejs.org/types/slate-ot-type',

  create(init: Element): Editor {
    const e = createEditor();
    e.children = init.children;
    return <Editor>init;
  },

  apply(snapshot: Editor, op: Operation[] | Operation) {
    slateType.normalize(op).forEach((o) => {
      if (o.type === 'set_node' && o.path.length === 0) {
        for (const key in o.newProperties) {
          if (key === 'id' || key === 'type' || key === 'children') {
            throw new Error(`Cannot set the "${key}" property of nodes!`);
          }

          const value = o.newProperties[key];

          if (value == null) {
            delete snapshot[key];
          } else {
            snapshot[key] = value;
          }
        }
      } else {
        Transforms.transform(snapshot, o);
      }
    });
    return snapshot;
  },

  transform(
    leftOps: Operation[],
    rightOps: Operation[],
    side: 'left' | 'right'
  ): Operation[] {
    let [leftRes] = xTransformMxN(leftOps, rightOps, side);
    return leftRes;
  },

  // serialize(snapshot) {
  //   return JSON.stringify(snapshot);
  // },

  // deserialize(data) {
  //   // return Value.fromJSON(data);
  // },

  normalize(op: Operation | Operation[]): Operation[] {
    return Array.isArray(op) ? op : [op];
  },
}
Example #23
Source File: md.tsx    From fantasy-editor with MIT License 4 votes vote down vote up
FullDemo: FunctionComponent = () => {

  const [value, setValue] = useState<Node[]>(initValue as any);
  const [md, setMd] = useState('');

  const plugins: SlatePlugin[] = useMemo(() => {
    const list: SlatePlugin[] = [];
    list.push(SoftBreakPlugin());
    list.push(HeadingPlugin());
    list.push(FontSizePlugin());
    list.push(BoldPlugin());
    list.push(ItalicPlugin());
    list.push(UnderlinePlugin());
    list.push(StrikeThroughPlugin());
    list.push(BlockQuotePlugin());
    list.push(SubscriptPlugin());
    list.push(SuperscriptPlugin());
    list.push(FontColorPlugin());
    list.push(BgColorPlugin());
    list.push(AlignPlugin());
    list.push(CodePlugin());
    list.push(CodeBlockPlugin());
    list.push(ListPlugin());
    list.push(IdentPlugin());
    list.push(LinkPlugin());
    list.push(ImagePlugin());
    list.push(HrPlugin());
    list.push(FilePlugin());
    list.push(LineHeightPlugin());
    list.push(TaskListPlugin())

    return list;
  }, []);


  const editor = useMemo(() => pipe(createEditor(), ...withPlugins), []);
  const [fullPage, setFullPage] = useState(false);

  const onChange = useCallback(
    (value: Node[]) => {
      setValue(value);
    },
    [editor, setValue],
  );

  const serialize = () => {
    setMd(serializeMarkdown(value));
  };

  return (
    <div>
      <div className={classNames('fc-editor', {'full-page': fullPage})}>
        <LocaleProvider locale={enUS}>
          <FullPageProvider full={fullPage} setFull={setFullPage}>
            <Slate
              editor={editor}
              value={value}
              onChange={onChange}
            >
              <Toolbar>
                <ButtonUndo/>
                <ButtonRedo/>
                <ButtonHeading/>
                <ButtonFontSize/>
                <ButtonBold/>
                <ButtonItalic/>
                <ButtonUnderline/>
                <ButtonStrikeThrough/>
                <ButtonBlockQuote/>
                <ButtonSubscript/>
                <ButtonSuperscript/>
                <ButtonFontColor/>
                <ButtonBgColor/>
                <ButtonAlign/>
                <ButtonCode/>
                <ButtonCodeBlock/>
                <ButtonNumberedList/>
                <ButtonBulletedList/>
                <ButtonTaskList/>
                <ButtonIdentInc/>
                <ButtonIdentDec/>
                <ButtonLineHeight/>
                <ButtonLink/>
                <ButtonImage/>
                <ButtonFile/>
                <ButtonHr/>
                <ButtonFull/>
              </Toolbar>
              <div className="fc-content" style={{height: 500}}>
                <PluginEditor plugins={plugins}/>
              </div>
            </Slate>
          </FullPageProvider>
        </LocaleProvider>
      </div>
      <div style={{padding: 16}}>
        <Button onClick={serialize} type="primary">Serialize Markdown</Button>
      </div>
      {md&&(
        <div className="content-display">
          {md}
        </div>
      )}
    </div>
  );
}
Example #24
Source File: Client.tsx    From slate-yjs-example with MIT License 4 votes vote down vote up
Client: React.FC<ClientProps> = ({ id, name, slug, removeUser }) => {
  const [value, setValue] = useState<Node[]>([]);
  const [isOnline, setOnlineState] = useState<boolean>(false);

  const color = useMemo(
    () =>
      randomColor({
        luminosity: "dark",
        format: "rgba",
        alpha: 1,
      }),
    []
  );

  const [sharedType, provider] = useMemo(() => {
    const doc = new Y.Doc();
    const sharedType = doc.getArray<SyncElement>("content");
    const provider = new WebsocketProvider(WEBSOCKET_ENDPOINT, slug, doc, {
      connect: false,
    });

    return [sharedType, provider];
  }, [id]);

  const editor = useMemo(() => {
    const editor = withCursor(
      withYjs(withLinks(withReact(withHistory(createEditor()))), sharedType),
      provider.awareness
    );

    return editor;
  }, [sharedType, provider]);

  useEffect(() => {
    provider.on("status", ({ status }: { status: string }) => {
      setOnlineState(status === "connected");
    });

    provider.awareness.setLocalState({
      alphaColor: color.slice(0, -2) + "0.2)",
      color,
      name,
    });

    // Super hacky way to provide a initial value from the client, if
    // you plan to use y-websocket in prod you probably should provide the
    // initial state from the server.
    provider.on("sync", (isSynced: boolean) => {
      if (isSynced && sharedType.length === 0) {
        toSharedType(sharedType, [
          { type: "paragraph", children: [{ text: "Hello world!" }] },
        ]);
      }
    });

    provider.connect();

    return () => {
      provider.disconnect();
    };
  }, [provider]);

  const { decorate } = useCursors(editor);

  const toggleOnline = () => {
    isOnline ? provider.disconnect() : provider.connect();
  };

  return (
    <Instance online={isOnline}>
      <Title>
        <Head>Editor: {name}</Head>
        <div style={{ display: "flex", marginTop: 10, marginBottom: 10 }}>
          <Button type="button" onClick={toggleOnline}>
            Go {isOnline ? "offline" : "online"}
          </Button>
          <Button type="button" onClick={() => removeUser(id)}>
            Remove
          </Button>
        </div>
      </Title>

      <EditorFrame
        editor={editor}
        value={value}
        decorate={decorate}
        onChange={(value: Node[]) => setValue(value)}
      />
    </Instance>
  );
}
Example #25
Source File: with-angular.spec.ts    From slate-angular with MIT License 4 votes vote down vote up
describe("with-angular", () => {
  let angularEditor: AngularEditor;
  function configEditor() {
    angularEditor = withAngular(createEditor());
    angularEditor.children = [
      {
        type: "paragraph",
        children: [
          { text: "This is editable " },
          { text: "rich" },
          { text: " text, " },
          { text: "much" },
          { text: " better than a " },
          { text: "<textarea>" },
          { text: "!" },
        ],
      },
    ];
  }
  beforeEach(() => {
    configEditor();
  });
  describe("onChange", () => {
    it("default onChange was called", fakeAsync(() => {
      spyOn(angularEditor, "onChange").and.callThrough();
      Transforms.select(angularEditor, {
        anchor: {
          path: [0, 0],
          offset: 0,
        },
        focus: {
          path: [0, 0],
          offset: 3,
        },
      });
      flush();
      expect(angularEditor.onChange).toHaveBeenCalled();
    }));
    it("custom onChange was called", fakeAsync(() => {
      let isOnChanged = false;
      EDITOR_TO_ON_CHANGE.set(angularEditor, () => {
        isOnChanged = true;
      });
      Transforms.select(angularEditor, {
        anchor: {
          path: [0, 0],
          offset: 0,
        },
        focus: {
          path: [0, 0],
          offset: 3,
        },
      });
      flush();
      expect(isOnChanged).toBeTruthy();
    }));
  });

  describe('apply', () => {
    let component: BasicEditableComponent;
    let fixture: ComponentFixture<BasicEditableComponent>;

    beforeEach(fakeAsync(() => {
      configureBasicEditableTestingModule([BasicEditableComponent]);
      fixture = TestBed.createComponent(BasicEditableComponent);
      component = fixture.componentInstance;
      component.value = [
        { type: 'paragraph', children: [{ text: 'first text!' }] },
        {
          type: "table",
          children: [
            {
              type: "table-row",
              children: [
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '1!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '2!' }]
                    }
                  ]
                },
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '3!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '4!' }]
                    }
                  ]
                },
              ],
            },
            {
              type: "table-row",
              children: [
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '5!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '6!' }]
                    }
                  ]
                },
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '7!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '8!' }]
                    }
                  ]
                },
              ],
            },
          ],
        },
        {
          type: "table",
          children: [
            {
              type: "table-row",
              children: [
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '1!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '2!' }]
                    }
                  ]
                },
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '3!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '4!' }]
                    }
                  ]
                },
              ],
            },
            {
              type: "table-row",
              children: [
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '5!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '6!' }]
                    }
                  ]
                },
                {
                  type: "table-cell",
                  children: [
                    {
                      type: 'paragraph',
                      children: [{ text: '7!' }]
                    },
                    {
                      type: 'paragraph',
                      children: [{ text: '8!' }]
                    }
                  ]
                },
              ],
            },
          ],
        },
        { type: 'paragraph', children: [{ text: 'last text!' }] }
      ];
      fixture.detectChanges();
      flush();
      fixture.detectChanges();
    }));

    afterEach(() => {
      fixture.destroy();
    });

    it('move node to sibling when there have a common parent', fakeAsync(() => {
      const oldPath = [1,0,0,0];
      const newPath = [1,0,0,1];
      const tablePath = [1];
      const tableRowPath = [1, 0];
      const tableCellPath = [1, 0, 0];
      const tableNode = Node.get(component.editor, tablePath);
      const tableRowNode = Node.get(component.editor, tableRowPath);
      const tableCellNode = Node.get(component.editor, tableCellPath);
      Transforms.moveNodes(component.editor, {
        at: oldPath,
        to: newPath,
      });
      tick(100);
      const newTableNode = Node.get(component.editor, tablePath);
      const newTableRowNode = Node.get(component.editor, tableRowPath);
      const newTableCellNode = Node.get(component.editor, tableCellPath);
      expect(tableNode).not.toEqual(newTableNode);
      validKey(tableNode, newTableNode);
      expect(tableRowNode).not.toEqual(newTableRowNode);
      validKey(tableRowNode, newTableRowNode);
      expect(tableCellNode).not.toEqual(newTableCellNode);
      validKey(tableCellNode, newTableCellNode);
    }));

    it('move node to sibling when there is no common parent', fakeAsync(() => {
      const oldPath = [1,0,0,0];
      const newPath = [2,0,0,1];

      const tablePath = [1];
      const tableRowPath = [1, 0];
      const tableCellPath = [1, 0, 0];
      const tableNode = Node.get(component.editor, tablePath);
      const tableRowNode = Node.get(component.editor, tableRowPath);
      const tableCellNode = Node.get(component.editor, tableCellPath);

      const tablePath2 = [2];
      const tableRowPath2 = [2, 0];
      const tableCellPath2 = [2, 0, 0];
      const tableNode2 = Node.get(component.editor, tablePath2);
      const tableRowNode2 = Node.get(component.editor, tableRowPath2);
      const tableCellNode2 = Node.get(component.editor, tableCellPath2);

      Transforms.moveNodes(component.editor, {
        at: oldPath,
        to: newPath,
      });
      tick(100);

      // valid move origin
      const newTableNode = Node.get(component.editor, tablePath);
      const newTableRowNode = Node.get(component.editor, tableRowPath);
      const newTableCellNode = Node.get(component.editor, tableCellPath);
      expect(tableNode).not.toEqual(newTableNode);
      validKey(tableNode, newTableNode);
      expect(tableRowNode).not.toEqual(newTableRowNode);
      validKey(tableRowNode, newTableRowNode);
      expect(tableCellNode).not.toEqual(newTableCellNode);
      validKey(tableCellNode, newTableCellNode);

      // valid move targit
      const newTableNode2 = Node.get(component.editor, tablePath2);
      const newTableRowNode2 = Node.get(component.editor, tableRowPath2);
      const newTableCellNode2 = Node.get(component.editor, tableCellPath2);
      expect(tableNode2).not.toEqual(newTableNode2);
      validKey(tableNode2, newTableNode2);
      expect(tableRowNode2).not.toEqual(newTableRowNode2);
      validKey(tableRowNode2, newTableRowNode2);
      expect(tableCellNode2).not.toEqual(newTableCellNode2);
      validKey(tableCellNode2, newTableCellNode2);
    }));

    it('can correctly insert the list in the last row', fakeAsync(() => {
      Transforms.select(component.editor, Editor.end(component.editor, [3]));
      component.editor.insertBreak();
      Transforms.wrapNodes(
        component.editor,
        { type: 'list-item', children: [] },
        {
            at: [4],
            split: true
        }
      );
      Transforms.wrapNodes(component.editor, { type: 'numbered-list', children: [] } as any, {
        at: [4, 0, 0],
        match: node => Element.isElement(node) && node.type === 'list-item'
      });

      expect(component.editor.children.length).toBe(5);
      expect((component.editor.children[4] as any).type).toBe('numbered-list');
    }));
  })
});
Example #26
Source File: index.tsx    From fantasy-editor with MIT License 4 votes vote down vote up
FullDemo: FunctionComponent = () => {

  const [value, setValue] = useState<Node[]>(initValue as any);

  const plugins: SlatePlugin[] = useMemo(() => {
    const list: SlatePlugin[] = [];
    list.push(SoftBreakPlugin());
    list.push(HeadingPlugin());
    list.push(FontSizePlugin());
    list.push(BoldPlugin());
    list.push(ItalicPlugin());
    list.push(UnderlinePlugin());
    list.push(StrikeThroughPlugin());
    list.push(BlockQuotePlugin());
    list.push(SubscriptPlugin());
    list.push(SuperscriptPlugin());
    list.push(FontColorPlugin());
    list.push(BgColorPlugin());
    list.push(AlignPlugin());
    list.push(CodePlugin());
    list.push(CodeBlockPlugin());
    list.push(ListPlugin());
    list.push(IdentPlugin());
    list.push(LinkPlugin());
    list.push(ImagePlugin());
    list.push(HrPlugin());
    list.push(FilePlugin());
    list.push(TablePlugin());
    list.push(LineHeightPlugin());
    list.push(
      MentionPlugin({
        onClick: value => console.log(`Hello ${value}!`),
      }),
    );
    list.push(TaskListPlugin())

    return list;
  }, []);

  const {onChangeMention, onKeyDownMention, search, index, target, values} = useMention(MENTIONS, {
    maxSuggestions: 10,
    trigger: '@',
  });

  const editor = useMemo(() => pipe(createEditor(), ...withPlugins), []);
  const [fullPage, setFullPage] = useState(false);

  const onChange = useCallback(
    (value: Node[]) => {
      onChangeMention(editor);
      console.log(value);
      setValue(value);
    },
    [editor, onChangeMention, setValue],
  );

  return (
    <div className={classNames('fc-editor', {'full-page': fullPage})}>
      <LocaleProvider locale={enUS}>
        <FullPageProvider full={fullPage} setFull={setFullPage}>
          <Slate
            editor={editor}
            value={value}
            onChange={onChange}
          >
            <Toolbar>
              <ButtonUndo/>
              <ButtonRedo/>
              <ButtonHeading/>
              <ButtonFontSize/>
              <ButtonBold/>
              <ButtonItalic/>
              <ButtonUnderline/>
              <ButtonStrikeThrough/>
              <ButtonBlockQuote/>
              <ButtonSubscript/>
              <ButtonSuperscript/>
              <ButtonFontColor/>
              <ButtonBgColor/>
              <ButtonAlign/>
              <ButtonCode/>
              <ButtonCodeBlock/>
              <ButtonNumberedList/>
              <ButtonBulletedList/>
              <ButtonTaskList/>
              <ButtonIdentInc/>
              <ButtonIdentDec/>
              <ButtonLineHeight/>
              <ButtonLink/>
              <ButtonImage/>
              <ButtonFile/>
              <ButtonTable/>
              <ButtonHr/>
              <ButtonFull/>
            </Toolbar>
            <div className="fc-content" style={{height: 500}}>
              <PluginEditor plugins={plugins} onKeyDown={[onKeyDownMention]} onKeyDownDeps={[index, search, target]}/>
            </div>
            <MentionSelect at={target} valueIndex={index} options={values}/>
          </Slate>
        </FullPageProvider>
      </LocaleProvider>
    </div>
  );
}
Example #27
Source File: html-zh.tsx    From fantasy-editor with MIT License 4 votes vote down vote up
FullDemo: FunctionComponent = () => {

  const [value, setValue] = useState<Node[]>(initValue as any);
  const [html, setHtml] = useState('');
  const [format, setFormat] = useState(false);

  const plugins: SlatePlugin[] = useMemo(() => {
    const list: SlatePlugin[] = [];
    list.push(SoftBreakPlugin());
    list.push(HeadingPlugin());
    list.push(FontSizePlugin());
    list.push(BoldPlugin());
    list.push(ItalicPlugin());
    list.push(UnderlinePlugin());
    list.push(StrikeThroughPlugin());
    list.push(BlockQuotePlugin());
    list.push(SubscriptPlugin());
    list.push(SuperscriptPlugin());
    list.push(FontColorPlugin());
    list.push(BgColorPlugin());
    list.push(AlignPlugin());
    list.push(CodePlugin());
    list.push(CodeBlockPlugin());
    list.push(ListPlugin());
    list.push(IdentPlugin());
    list.push(LinkPlugin());
    list.push(ImagePlugin());
    list.push(HrPlugin());
    list.push(FilePlugin());
    list.push(LineHeightPlugin());
    list.push(TaskListPlugin())

    return list;
  }, []);


  const editor = useMemo(() => pipe(createEditor(), ...withPlugins), []);
  const [fullPage, setFullPage] = useState(false);

  const onChange = useCallback(
    (value: Node[]) => {
      setValue(value);
    },
    [editor, setValue],
  );

  const serialize = () => {
    setHtml(serializeHtml(value, format));
  };

  return (
    <div>
      <div className={classNames('fc-editor', {'full-page': fullPage})}>
        <LocaleProvider locale={enUS}>
          <FullPageProvider full={fullPage} setFull={setFullPage}>
            <Slate
              editor={editor}
              value={value}
              onChange={onChange}
            >
              <Toolbar>
                <ButtonUndo/>
                <ButtonRedo/>
                <ButtonHeading/>
                <ButtonFontSize/>
                <ButtonBold/>
                <ButtonItalic/>
                <ButtonUnderline/>
                <ButtonStrikeThrough/>
                <ButtonBlockQuote/>
                <ButtonSubscript/>
                <ButtonSuperscript/>
                <ButtonFontColor/>
                <ButtonBgColor/>
                <ButtonAlign/>
                <ButtonCode/>
                <ButtonCodeBlock/>
                <ButtonNumberedList/>
                <ButtonBulletedList/>
                <ButtonTaskList/>
                <ButtonIdentInc/>
                <ButtonIdentDec/>
                <ButtonLineHeight/>
                <ButtonLink/>
                <ButtonImage/>
                <ButtonFile/>
                <ButtonHr/>
                <ButtonFull/>
              </Toolbar>
              <div className="fc-content" style={{height: 500}}>
                <PluginEditor plugins={plugins}/>
              </div>
            </Slate>
          </FullPageProvider>
        </LocaleProvider>
      </div>
      <div style={{padding: 16}}>
        <Switch checked={format} onChange={e=>setFormat(e)}/>转换代码块
        &nbsp;&nbsp;
        <Button onClick={serialize} type="primary">生成HTML</Button>
      </div>
      {html&&(
        <div className="content-display">
          {html}
        </div>
      )}
    </div>
  );
}
Example #28
Source File: html.tsx    From fantasy-editor with MIT License 4 votes vote down vote up
FullDemo: FunctionComponent = () => {

  const [value, setValue] = useState<Node[]>(initValue as any);
  const [html, setHtml] = useState('');
  const [format, setFormat] = useState(false);

  const plugins: SlatePlugin[] = useMemo(() => {
    const list: SlatePlugin[] = [];
    list.push(SoftBreakPlugin());
    list.push(HeadingPlugin());
    list.push(FontSizePlugin());
    list.push(BoldPlugin());
    list.push(ItalicPlugin());
    list.push(UnderlinePlugin());
    list.push(StrikeThroughPlugin());
    list.push(BlockQuotePlugin());
    list.push(SubscriptPlugin());
    list.push(SuperscriptPlugin());
    list.push(FontColorPlugin());
    list.push(BgColorPlugin());
    list.push(AlignPlugin());
    list.push(CodePlugin());
    list.push(CodeBlockPlugin());
    list.push(ListPlugin());
    list.push(IdentPlugin());
    list.push(LinkPlugin());
    list.push(ImagePlugin());
    list.push(HrPlugin());
    list.push(FilePlugin());
    list.push(LineHeightPlugin());
    list.push(TaskListPlugin())

    return list;
  }, []);


  const editor = useMemo(() => pipe(createEditor(), ...withPlugins), []);
  const [fullPage, setFullPage] = useState(false);

  const onChange = useCallback(
    (value: Node[]) => {
      setValue(value);
    },
    [editor, setValue],
  );

  const serialize = () => {
    setHtml(serializeHtml(value, format));
  };

  return (
    <div>
      <div className={classNames('fc-editor', {'full-page': fullPage})}>
        <LocaleProvider locale={enUS}>
          <FullPageProvider full={fullPage} setFull={setFullPage}>
            <Slate
              editor={editor}
              value={value}
              onChange={onChange}
            >
              <Toolbar>
                <ButtonUndo/>
                <ButtonRedo/>
                <ButtonHeading/>
                <ButtonFontSize/>
                <ButtonBold/>
                <ButtonItalic/>
                <ButtonUnderline/>
                <ButtonStrikeThrough/>
                <ButtonBlockQuote/>
                <ButtonSubscript/>
                <ButtonSuperscript/>
                <ButtonFontColor/>
                <ButtonBgColor/>
                <ButtonAlign/>
                <ButtonCode/>
                <ButtonCodeBlock/>
                <ButtonNumberedList/>
                <ButtonBulletedList/>
                <ButtonTaskList/>
                <ButtonIdentInc/>
                <ButtonIdentDec/>
                <ButtonLineHeight/>
                <ButtonLink/>
                <ButtonImage/>
                <ButtonFile/>
                <ButtonHr/>
                <ButtonFull/>
              </Toolbar>
              <div className="fc-content" style={{height: 500}}>
                <PluginEditor plugins={plugins}/>
              </div>
            </Slate>
          </FullPageProvider>
        </LocaleProvider>
      </div>
      <div style={{padding: 16}}>
        <Switch checked={format} onChange={e=>setFormat(e)}/>Format Code Block
        &nbsp;&nbsp;
        <Button onClick={serialize} type="primary">Serialize Html</Button>
      </div>
      {html&&(
        <div className="content-display">
          {html}
        </div>
      )}
    </div>
  );
}
Example #29
Source File: md-zh.tsx    From fantasy-editor with MIT License 4 votes vote down vote up
FullDemo: FunctionComponent = () => {

  const [value, setValue] = useState<Node[]>(initValue as any);
  const [md, setMd] = useState('');

  const plugins: SlatePlugin[] = useMemo(() => {
    const list: SlatePlugin[] = [];
    list.push(SoftBreakPlugin());
    list.push(HeadingPlugin());
    list.push(FontSizePlugin());
    list.push(BoldPlugin());
    list.push(ItalicPlugin());
    list.push(UnderlinePlugin());
    list.push(StrikeThroughPlugin());
    list.push(BlockQuotePlugin());
    list.push(SubscriptPlugin());
    list.push(SuperscriptPlugin());
    list.push(FontColorPlugin());
    list.push(BgColorPlugin());
    list.push(AlignPlugin());
    list.push(CodePlugin());
    list.push(CodeBlockPlugin());
    list.push(ListPlugin());
    list.push(IdentPlugin());
    list.push(LinkPlugin());
    list.push(ImagePlugin());
    list.push(HrPlugin());
    list.push(FilePlugin());
    list.push(LineHeightPlugin());
    list.push(TaskListPlugin())

    return list;
  }, []);


  const editor = useMemo(() => pipe(createEditor(), ...withPlugins), []);
  const [fullPage, setFullPage] = useState(false);

  const onChange = useCallback(
    (value: Node[]) => {
      setValue(value);
    },
    [editor, setValue],
  );

  const serialize = () => {
    setMd(serializeMarkdown(value));
  };

  return (
    <div>
      <div className={classNames('fc-editor', {'full-page': fullPage})}>
        <LocaleProvider locale={enUS}>
          <FullPageProvider full={fullPage} setFull={setFullPage}>
            <Slate
              editor={editor}
              value={value}
              onChange={onChange}
            >
              <Toolbar>
                <ButtonUndo/>
                <ButtonRedo/>
                <ButtonHeading/>
                <ButtonFontSize/>
                <ButtonBold/>
                <ButtonItalic/>
                <ButtonUnderline/>
                <ButtonStrikeThrough/>
                <ButtonBlockQuote/>
                <ButtonSubscript/>
                <ButtonSuperscript/>
                <ButtonFontColor/>
                <ButtonBgColor/>
                <ButtonAlign/>
                <ButtonCode/>
                <ButtonCodeBlock/>
                <ButtonNumberedList/>
                <ButtonBulletedList/>
                <ButtonTaskList/>
                <ButtonIdentInc/>
                <ButtonIdentDec/>
                <ButtonLineHeight/>
                <ButtonLink/>
                <ButtonImage/>
                <ButtonFile/>
                <ButtonHr/>
                <ButtonFull/>
              </Toolbar>
              <div className="fc-content" style={{height: 500}}>
                <PluginEditor plugins={plugins}/>
              </div>
            </Slate>
          </FullPageProvider>
        </LocaleProvider>
      </div>
      <div style={{padding: 16}}>
        <Button onClick={serialize} type="primary">生成Markdown</Button>
      </div>
      {md&&(
        <div className="content-display">
          {md}
        </div>
      )}
    </div>
  );
}