0.9.3 • Published 3 years ago

@anovel/tachyon v0.9.3

Weekly downloads
123
License
MIT
Repository
github
Last release
3 years ago

Tachyon

Helpers to be used within a frontend framework.

yarn add @anovel/tachyon

A light framework for easier and advanced DOM manipulations.

OS

Get the current running OS.

import {getOS, literals} from '@anovel/tachyon';

const myOS = getOS();

if (myOS === literals.OS.MACOS) {
  // Do something.
}

getOS may return any of the following strings (all can be found in literals.OS):

KeyValue
WINDOWS'Windows'
LINUX'Linux'
MACOS'macOS'
IOS'iOS'
ANDROID'Android'
OTHER'unknown'

Url

goTo

Extra implementation of url navigator with options.

import {goTo} from '@anovel/tachyon';

// Basic example
goTo('/foo/bar', history); // opens '/foo/bar' in current tab

// With flags
goTo('/foo/bar', history, {openOutside: true}); // opens '/foo/bar' in a new browser tab
goTo('/foo/bar', history, {skip: true}); // opens '/foo/bar' in current tab, and remove previous location from history

// Using url build options
goTo('/foo/:param', history, {params: {param: 'bar'}}); // opens '/foo/bar'
goTo('/foo/bar', history, {query: {uid: 'user_id'}}); // opens '/foo/bar?uid=user_id'
goTo('/foo/bar', history, {anchor: 'section2'}); // opens '/foo/bar#section2'

Arguments

ArgumentTypeRequiredDescription
destinationstringtrueThe url to open.
historyHistorytrueThe history manager. 1
optionsObject-Options (see below table).

(1) You can read more about routers at this link.

Options

Additional parameters are available to perform your navigation.

KeyTypeDescription
paramsObject.<string, string>A map of <string, string>. Each key/value pair corresponds to an url parameter and the value to interpolate it with.
queryObject.<string, any>A map that represents query parameters. Query parameters are appended to the url after the ? character.
anchorstringLoad url to a specific anchor.
openOutsidebooleanIf true, open the url in a new browser tab.
skipbooleanIf true, replace the current entry in history with the new url. Hitting return from there will go back to previous page instead of the current one.

isActive

Check if the current route is active.

import {isActive} from '@anovel/tachyon';

// Retrieve your current location from the most convenient way
// (window.location or the react-router location property).
let location;

// The following examples will assume that current location 
// pathname is '/foo/bar/qux'.

console.log(isActive('/foo/bar', location)); // true
console.log(isActive('/foo/qux', location)); // false
console.log(isActive('/foo/bar', location, true)); // false

// You can also check multiple routes at once by passing an array as first argument.
console.log(isActive(['/foo/qux', '/foo/bar'], location)); // true

Trailing slashes are ignored, so /foo/bar and /foo/bar/ will be treated the same, weather in target or currentLocation. Also, if leading slash is missing, it will be added automatically.

Arguments

ArgumentTypeRequiredDescription
targetstring[]stringtrueThe target route(s) to verify. Returns true if the current location matches any of them.
currentLocationstringtrueThe current location. A valid location is any Object with a non empty pathname string key.
exactboolean-Only match if current location correspond exactly to a target.

buildUrl

Build an url from a template string and parameters.

import {buildUrl} from '@anovel/tachyon';

buildUrl('/foo'); // '/foo'
buildUrl('/foo/:param1', {param1: 'bar'}); // '/foo/bar'
buildUrl('/foo/:param1', {param1: 'bar'}, {uid: 'user_uid'}); // '/foo/bar?uid=user_id'
buildUrl('/search', null, {genre: 'books', priceMax: 10}); // '/search?genre=books&priceMax=10'

Arguments

ArgumentTypeRequiredDescription
urlstringtrueThe url template string.
paramsObject.<string, string>trueA map of <string, string>. Each key/value pair corresponds to an url parameter and the value to interpolate it with.
queryObject.<string, any>trueA map that represents query parameters. Query parameters are appended to the url after the ? character.
anchorstringtrueLoad url to a specific anchor.

Keys

A sequencer allows you to listen for keypress on any html element and trigger actions whenever a combo is hit.

import React from 'react';
import {Sequencer, literals} from '@anovel/tachyon';
import css from 'myStyle.module.css';

// Example with a copy/paste mock implementation.
const MyComponent = () => {
  const sequencer = new Sequencer();
  
  const combos = [
    {trigger: literals.COMBOS.COPY, action: () => console.log('I am copied!')},
    {trigger: literals.COMBOS.PASTE, action: () => console.log('I am paste!')}
  ];
  
  return (
    <div className={css.container}>
      <div
        onKeyDown={sequencer.update({combos})}
        onKeyUp={sequencer.remove}
      >Copy me (CTRL + C) or Paste me (CTRL + V)</div>
    </div>
  );
};

The Sequencer constructor does not take any arguments. Instead, every parameters are passed on the go through its methods, which allows for highly dynamic behavior.

Sequencer ships with 4 public methods.

Sequencer.update

Update sequence and return the updated list of pressed keys in the sequence. Return the current pressed keys array.

function handler(e) {
  const keys = sequencer.update(options)(e);
}

Arguments

ArgumentTypeRequiredDescription
optionsObject-Arguments to control key sequence behavior.

Options

KeyTypeDescription
lifespannumberAutomatically removes the key from the chain passed a certain amount of time (in milliseconds). If not set, key should be removed manually with the remove method.
sustainbooleanIf set to true, a new entry will automatically reset all timers for each key in the sequence. If a key was not timed, it will initialize a new timer on it.
combos[]ObjectList of actions to take if a valid sequence of keys is matched.

Combo

KeyRequiredTypeDescription
triggertrue[]stringThe sequence of keys to trigger an action. Each element must correspond to a valid key attribute (of a KeyboardEvent).
actiontruefunctionRun this action (with no arguments) when the current sequences array ends with the keys in trigger.
intermediateAction-functionRun this function when the current sequence partially matches trigger. Takes the number of triggered keys as an argument.
alwaysTrigger-booleanIf true and intermediateAction is set, runs intermediateAction on any keypress when action is not triggered, even if trigger has 0 matches.

Sequencer.remove

Remove all occurences of a keycode from the sequence. Takes a KeyboardEvent as argument. Return the current pressed keys array.

function handler(e) {
  const keys = sequencer.remove(e);
}

Sequencer.clear

Empty (reset) the current key chain.

sequencer.clear();

Sequencer.keys

Return the current pressed keys array.

const keys = sequencer.keys();

RecordsManager

Manage a record history for textual inputs from pure javascript.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

Constructor Arguments

ArgumentTypeRequiredDescription
baseStringstringtrueThe base value for the string, prior to any alteration.
optionsObject-See below section for more information.

Constructor Options

import {RecordsManager} from '@anovel/tachyon';

// Do not keep more than 100 records in history.
const manager1 = new RecordsManager('', {maxLength: 100});

const baseHistory = [{
  newContent: 'hello',
  caret: {start: 0, end: 0}, 
  oldContent: '', 
  timestamp: 1613609752021
}];

// Will start with value 'hello'.
const manager2 = new RecordsManager('', {history: baseHistory});

// Will start with value ''. This is a bad utilization since history record do not match the actual state.
const manager3 = new RecordsManager('', {history: baseHistory, trustStartValue: true});

// Good utilization of above case : the history records match the current state.
const manager4 = new RecordsManager('hello world', {history: baseHistory, trustStartValue: true});
KeyTypeDescription
historyArray.<StaticRecord>An array of previous history records to preload.
maxLengthnumberThe maximum number of records to keep in history.
packPackOptionPack options allow to merge separate entries within history, based on some rules.
trustStartValuebooleanIf set to true, do not rebuild history from base value on loading.

StaticRecord

import {RecordsManager} from '@anovel/tachyon';

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0}, 
  oldContent: '', 
  timestamp: 1613609752021
}, {
  newContent: 'world',
  caret: {start: 6, end: 6},
  oldContent: '',
  timestamp: 1613609754927,
  canceled: true
}];

// Will start with value 'hello '.
const manager = new RecordsManager('', {history: baseHistory});

console.log(manager.redo()); // hello world
KeyTypeRequiredDescription
caretCarettrueThe caret position before the alteration occured.
oldContentstringtrueThe old string slice that was lost in the process.
newContentstringtrueThe new string slice that was created in the process.
timestampnumbertrueThe time when the record was added to history (milliseconds).
canceledboolean-Indicate the record is not active yet in the current history (likely canceled with undo).

PackOption

Define rules for merging records together when they are 'close enough'.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('', {pack: {maxSize: 2}});

// Type 'hello world'
manager.push({newContent: 'h', caret: {start: 0, end: 0}});
manager.push({newContent: 'e', caret: {start: 1, end: 1}});
manager.push({newContent: 'l', caret: {start: 2, end: 2}});
manager.push({newContent: 'l', caret: {start: 3, end: 3}});
manager.push({newContent: 'o', caret: {start: 4, end: 4}});
manager.push({newContent: ' ', caret: {start: 5, end: 5}});
manager.push({newContent: 'w', caret: {start: 6, end: 6}});
manager.push({newContent: 'o', caret: {start: 7, end: 7}});
manager.push({newContent: 'r', caret: {start: 8, end: 8}});
manager.push({newContent: 'l', caret: {start: 9, end: 9}});
manager.push({newContent: 'd', caret: {start: 10, end: 10}});

console.log(manager.content()); // 'hello world'
console.log(manager.undo()); // 'hello worl'
console.log(manager.undo()); // 'hello wo'
console.log(manager.undo()); // 'hello '
console.log(manager.undo()); // 'hell'
import {RecordsManager} from '@anovel/tachyon';

// Break on spaces (words).
const manager = new RecordsManager('', {pack: {separators: [' ']}});

// Type 'hello world'
manager.push({newContent: 'h', caret: {start: 0, end: 0}});
manager.push({newContent: 'e', caret: {start: 1, end: 1}});
manager.push({newContent: 'l', caret: {start: 2, end: 2}});
manager.push({newContent: 'l', caret: {start: 3, end: 3}});
manager.push({newContent: 'o', caret: {start: 4, end: 4}});
manager.push({newContent: ' ', caret: {start: 5, end: 5}});
manager.push({newContent: 'w', caret: {start: 6, end: 6}});
manager.push({newContent: 'o', caret: {start: 7, end: 7}});
manager.push({newContent: 'r', caret: {start: 8, end: 8}});
manager.push({newContent: 'l', caret: {start: 9, end: 9}});
manager.push({newContent: 'd', caret: {start: 10, end: 10}});

console.log(manager.content()); // 'hello world'
console.log(manager.undo()); // 'hello '
console.log(manager.undo()); // ''
import {RecordsManager} from '@anovel/tachyon';

// Break after 600ms.
const manager = new RecordsManager('', {pack: {timeout: 600}});

// Type 'hello world'
manager.push({newContent: 'h', caret: {start: 0, end: 0}});
manager.push({newContent: 'e', caret: {start: 1, end: 1}});
manager.push({newContent: 'l', caret: {start: 2, end: 2}});
manager.push({newContent: 'l', caret: {start: 3, end: 3}});
manager.push({newContent: 'o', caret: {start: 4, end: 4}});

// wait 1s.
await new Promise(resolve => setTimeout(resolve, 1000));

manager.push({newContent: ' ', caret: {start: 5, end: 5}});
manager.push({newContent: 'w', caret: {start: 6, end: 6}});
manager.push({newContent: 'o', caret: {start: 7, end: 7}});
manager.push({newContent: 'r', caret: {start: 8, end: 8}});
manager.push({newContent: 'l', caret: {start: 9, end: 9}});
manager.push({newContent: 'd', caret: {start: 10, end: 10}});

console.log(manager.content()); // 'hello world'
console.log(manager.undo()); // 'hello'
KeyTypeDescription
maxSizenumberThe maximum size a record newContent can aggregate.
separatorsArray.String values that will split a record in 2 when occurring.
timeoutnumberA maximal time interval in milliseconds between the 2 records to merge.

Caret

KeyTypeRequiredDescription
startnumbertrueCaret start position (in 0 index basis).
endnumbertrueCaret end position (in 0 index basis).

RecordsManager.undo

Undo the last active entry. Returns the altered content.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0},
  oldContent: '',
  timestamp: 1613609752021
}, {
  newContent: 'world',
  caret: {start: 6, end: 6},
  oldContent: '',
  timestamp: 1613609754927
}];

// Will start with value 'hello world'.
const manager = new RecordsManager('', {history: baseHistory});

console.log(manager.undo()); // 'hello '

RecordsManager.redo

Undo the first inactive entry. Returns the altered content.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0},
  oldContent: '',
  timestamp: 1613609752021
}, {
  newContent: 'world',
  caret: {start: 6, end: 6},
  oldContent: '',
  timestamp: 1613609754927,
  canceled: true
}];

// Will start with value 'hello '.
const manager = new RecordsManager('', {history: baseHistory});

console.log(manager.redo()); // 'hello world'

RecordsManager.push

Add a record to history. Returns the altered content.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0},
  oldContent: '',
  timestamp: 1613609752021
}];

// Will start with value 'hello '.
const manager = new RecordsManager('', {history: baseHistory});

console.log(manager.push({newContent: 'world', caret: {start: 6, end: 6}})); // 'hello world'

RecordsManager.clearAll

Clear history. Cannot be recovered.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0},
  oldContent: '',
  timestamp: 1613609752021
}];

// Will start with value 'hello '.
const manager = new RecordsManager('', {history: baseHistory});

manager.cleanAll();

console.log(manager.undo()); // 'hello ' since last entry was lost and cannot be undone.

RecordsManager.content

Returns the current string content.

import {RecordsManager} from '@anovel/tachyon';

const manager = new RecordsManager('');

const baseHistory = [{
  newContent: 'hello ',
  caret: {start: 0, end: 0},
  oldContent: '',
  timestamp: 1613609752021
}];

// Will start with value 'hello '.
const manager = new RecordsManager('', {history: baseHistory});

console.log(manager.content()); // 'hello '

License

Licensed under MIT for A-Novel.

0.9.3

3 years ago

0.9.0

3 years ago

0.9.2

3 years ago

0.9.1

3 years ago

0.8.8

3 years ago

0.8.7

3 years ago

0.8.6

3 years ago

0.8.5

3 years ago

0.8.4

3 years ago

0.8.3-beta

3 years ago

0.8.2

3 years ago

0.8.1

3 years ago

0.8.0

3 years ago

0.7.4

3 years ago

0.7.3

3 years ago

0.7.2

4 years ago

0.7.1

4 years ago

0.7.0

4 years ago

0.6.2

4 years ago

0.6.1

4 years ago

0.6.0

4 years ago

0.5.4

4 years ago

0.5.3

4 years ago

0.5.2

4 years ago

0.5.0

4 years ago

0.5.1

4 years ago

0.4.5

4 years ago

0.4.4

4 years ago

0.4.6

4 years ago

0.4.2

4 years ago

0.4.1

4 years ago

0.4.0

4 years ago

0.3.1

4 years ago

0.3.0

4 years ago

0.2.0

4 years ago

0.1.2

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago