Home

Awesome

<h1 align="center"> <code> @typeskill/typer </code> </h1> <p align="center"> <em> Typeskill, the Operational-Transform Based (React) Native Rich Text Library. </em> </p> <p align="center"> <a href="https://www.npmjs.com/package/@typeskill/typer" alt="Npm Version"> <img src="https://img.shields.io/npm/v/@typeskill/typer.svg" /></a> <img src="https://img.shields.io/badge/platforms-android%20|%20ios%20|%20windows-lightgrey.svg" /> <img src="https://img.shields.io/npm/l/@typeskill/typer.svg"/> <a href="https://github.com/typeskill/typer/issues?q=is%3Aissue+is%3Aopen+label%3A%22scheduled+feature%22" > <img src="https://img.shields.io/github/issues-raw/typeskill/typer/scheduled%20feature.svg?label=scheduled%20feature&colorB=125bba" alt="scheduled features" /> </a> </p> <p align="center"> <a href="https://circleci.com/gh/typeskill/typer"> <img src="https://circleci.com/gh/typeskill/typer.svg?style=shield" alt="Circle CI" /> </a> <a href="https://codecov.io/gh/typeskill/typer"> <img src="https://codecov.io/gh/typeskill/typer/branch/master/graph/badge.svg" alt="Code coverage"> </a> <a href="https://github.com/typeskill/typer/issues?q=is%3Aissue+is%3Aopen+label%3Abug"> <img src="https://img.shields.io/github/issues-raw/typeskill/typer/bug.svg?label=open%20bugs" alt="open bugs"> </a> <img alt="Greenkeeper badge" src="https://badges.greenkeeper.io/typeskill/typer.svg"> <a href="https://snyk.io/test/github/typeskill/typer"> <img alt="vulnerabilities" src="https://snyk.io/test/github/typeskill/typer/badge.svg"> </a> </p> <p align="center"> <code> npm install --save @typeskill/typer </code> </p> <p align="center"> <img width="400" src="https://raw.githubusercontent.com/typeskill/typeskill/HEAD/images/screenshot.png" alt="Typeskill screenshot"> </p> <p align="center"> <a href="https://expo.io/@jsamr/typeskill-showcase"> <strong>Give it a try on Expo</strong> </a> <br/><br/> <a href="https://expo.io/@jsamr/typeskill-showcase"> <img src="https://raw.githubusercontent.com/typeskill/typeskill/HEAD/images/qr-showcase.png" alt="Expo QR code"> </a> <br/> <a href="#trying-locally">You can also run it locally in seconds</a> </p>

Features & design principles

Design

Features

<a name="trying-locally" />

Trying locally

Prerequisite: you must have npm and expo-cli globally installed

git clone https://github.com/typeskill/examples/tree/master
cd examples/expo-showcase
npm install
expo start

Architecture & example

Introduction

The library exposes two components to render documents:

Definitions

The shape of a Document

A document is an object describing rich content and the current selection. Its op field is an array of operational transforms implemented with delta library. Its schemaVersion guarantees retro-compatibility in the future and, if needed, utilities to convert from one version to the other.

To explore the structure in seconds, the easiest way is with the debugger: @typeskill/debugger.

Controlled components

Document renderers and controls are controlled components, which means you need to define how to store the state from a master component, or through a store architecture such as a Redux. You can study Editor.tsx, a minimal example master component.

A domain of shared events

Document renderers need an invariant Bridge instance prop. The bridge has two responsibilities:

A Bridge instance must be hold by the master component, and can be shared with any external control such as Toolbar to operate on the document.

Remarks

Robustness

This decoupled design has the following advantages:

Minimal example

Bellow is a simplified snippet from the minimal expo example to show you how the Toolbar can be interfaced with the Typer component. You need a linked react-native-vector-icons or @expo/vector-icons if you are on expo to make this example work.

import React from 'react';
import { View } from 'react-native';
import {
  Typer,
  Toolbar,
  DocumentControlAction,
  buildVectorIconControlSpec,
  useBridge,
  useDocument,
} from '@typeskill/typer';
/** NON EXPO **/
import { MaterialCommunityIcons } from 'react-native-vector-icons/MaterialCommunityIcons';
/** EXPO **/
// import { MaterialCommunityIcons } from '@expo/vector-icons'

function buildMaterialControlSpec(actionType, name) {
  return buildVectorIconControlSpec(MaterialCommunityIcons, actionType, name);
}

const toolbarLayout = [
  buildMaterialControlSpec(
    DocumentControlAction.SELECT_TEXT_BOLD,
    'format-bold',
  ),
  buildMaterialControlSpec(
    DocumentControlAction.SELECT_TEXT_ITALIC,
    'format-italic',
  ),
  buildMaterialControlSpec(
    DocumentControlAction.SELECT_TEXT_UNDERLINE,
    'format-underline',
  ),
  buildMaterialControlSpec(
    DocumentControlAction.SELECT_TEXT_STRIKETHROUGH,
    'format-strikethrough-variant',
  ),
];

export function Editor() {
  const [document, setDocument] = useDocument();
  const bridge = useBridge();
  return (
    <View style={{ flex: 1 }}>
      <Typer
        document={document}
        onDocumentUpdate={setDocument}
        bridge={bridge}
        maxMediaBlockHeight={300}
      />
      <Toolbar document={document} layout={toolbarLayout} bridge={bridge} />
    </View>
  );
}

API Contract

You need to comply with this contract to avoid bugs:

API Reference

Typescript definitions provide an exhaustive and curated documentation reference. The comments are 100% compliant with tsdoc and generated with Microsoft famous API Extractor utility. These definitions follow semantic versioning.

Please note that props definitions are namespaced. For example, if you are looking at Toolbar component definitions, you should look for Props definition inside Toolbar namespace.

Inspecting and reporting bugs

@typeskill/debugger is a tool to inspect and reproduce bugs. If you witness a bug, please try a reproduction on the debugger prior to reporting it.

Customizing

Integrating your image picker

Typeskill won't chose a picker on your behalf, as it would break its commitment to modular design. You can check Editor.tsx component from the showcase expo example to see how to integrate your image picker.