3.4.1 • Published 10 months ago

@appello/common v3.4.1

Weekly downloads
-
License
ISC
Repository
bitbucket
Last release
10 months ago

Common frontend library of components for web and mobile environmental

How to use it

Install package from npm:

npm i @appello/common

Import modules you need in your code:

import { useInterval, isNill } from '@appello/common';

Development guide

For developers

Each new functionality must be added to the folder and exported from the root! This is necessary to simplify the import of the necessary functionality:

import { useInterval, isFunction, ... } from '@appello/common';

If you need to create a new module, remember to add index.ts with exports.

Hooks

useCodeTimer

import { useCodeTimer } from '@appello/common';

Ready-made hook for setting a timer when sending SMS again.

API:

import { useCodeTimer } from "@appello/common";

const Component = () => {
  const { seconds, inProgress, sendCode } = useCodeTimer();
  
  return (
    <div>
      ...
      {
        inProgress && (
          <span>{seconds}</span>
        )
      }
      <button type="button" onClick={sendCode} />
      ...
    </div>
  );
};

Params:

PropertyDescriptionTypeDefault
defaultSecondsCountdown time in seconds. Optional.number59

Return:

PropertyDescriptionType
secondsAmount of time in seconds.number
inProgressSyntactic sugar. Is the timer running?boolean
sendCodeMethod that starts the timer.void

useCombinedRef

import { useCombinedRef } from '@appello/common';

Hook for combining refs.

API:

import { useCombinedRef } from '@appello/common';

const Component = () => {
  const firstRef = useRef<number>(0);
  const secondRef = useRef<number>(0);
  const combinedRef = useCombinedRef(firstRef, secondRef);

  combinedRef(5);
}

Params:

PropertyDescriptionTypeDefault
listOfRefsList of refs.RefOne of required

Return:

PropertyDescriptionType
combinedRefCombined ref.Ref

useStep

import { useStep } from '@appello/common';

React state hook that tracks a numeric value.

API:

import { useStep } from '@appello/common';

const Component = () => {
  const { count, setCount, increment, decrement, reset } = useStep(0)

  return (
    <div>
      <p>Count is {count}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
      <button onClick={reset}>Reset</button>
      <button onClick={() => setCount((x) => x * 2)}>Multiply by 2</button>
    </div>
  )
}

Params:

PropertyDescriptionTypeDefault
initialValueThe initial value for the counter.number0

Return:

PropertyDescriptionType
countCurrent count.number
incrementIncrement count.() => void
decrementDecrement count.() => void
resetReset count.() => void
setCountSet count.(count: number) => void

useDebounceCallback

import { useDebounceCallback } from '@appello/common';

A hook that deal with the debounced function.

API:

import { useDebounceCallback } from '@appello/common';

const Component = () => {
  const [value, setValue] = useState(0);
  const { debounce } = useDebounceCallback(
    () => {
      setValue(value + 1);
    },
  );

  return (
    <button type="button" onClick={debounce}>
      Click
    </button>
  );
};

Params:

PropertyDescriptionTypeDefault
fnCallback for the debounce.AnyFuctionRequired
optionsLodash optionsDebounceOptionsOptional

DebounceOptions:

export interface DebounceOptions {
  wait?: number;
  leading?: boolean;
  trailing?: boolean;
  maxWait?: number;
}

Return:

PropertyDescriptionType
debounceInvoke and pass parameters to fn.AnyFuction
cancelCancel the invocation of currently debounced function.() => void
flushImmediately invoke currently debounced function.() => void

useDebounceEffect

import { useDebounceEffect } from '@appello/common';

An effect with debouncing

API:

import { useDebounceEffect } from '@appello/common';

const Component = () => {
  const [value, setValue] = useState('hello');
  const [records, setRecords] = useState<string[]>([]);

  useDebounceEffect(
    () => {
      setRecords((val) => [...val, value]);
    },
    [value],
  );

  return (
    <>
      <input
        value={value}
        onChange={(e) => setValue(e.target.value)}
        placeholder="Write text"
      />
      <ul>
        {records.map((record, index) => (
          <li key={index}>{record}</li>
        ))}
      </ul>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
effectThe effect callback.EffectCallbackRequired
depsThe dependencies list.DependencyListundefined
optionsConfig for the debounce behaviors. See the Options section below for details.DebounceOptionsundefined

DebounceOptions:

export interface DebounceOptions {
  wait?: number;
  leading?: boolean;
  trailing?: boolean;
  maxWait?: number;
}

useDefault

import { useDefault } from '@appello/common';

React state hook that returns the default value when state is null or undefined.

API:

import { useDefault } from '@appello/common';

const Component = () => {
  const [user, setUser] = useDefault({ name: 'Mathers' }, { name: 'Marshall' });
  
  return (
    <div>
      <div>User: {user.name}</div>
      <input onChange={e => setUser({ name: e.target.value })} />
      <button onClick={() => setUser(null)}>Set to null</button>
    </div>
  )
};

Params:

PropertyDescriptionTypeDefault
defaultValueDefault value.anyRequired
initialValueInitial value.anyRequired

Return:

PropertyDescriptionType
stateState and set state.[any, Dispatch<SetStateAction<any>>]

useFirstMountState

import { useFirstMountState } from '@appello/common';

A hook that returns the first rendering

API:

import { useFirstMountState } from '@appello/common';

const Component = () => {
  const isFirstMount = useFirstMountState();
  return (
    <div>
      {isFirstMount}
    </div>
  )
};

Return:

PropertyDescriptionType
isFirstMountReturn first renderbollean

useHookFormPersist

import { useHookFormPersist } from '@appello/common';

A hook for save temporary data from React hook form inside storage (LocalStorage / SessionStorage / AsyncStorage).

API:

import { useHookFormPersist } from "@appello/common";
import { Controller } from 'react-hook-form';
import AsyncStorage from '@react-native-async-storage/async-storage';

type FormType = {
  name: string;
  email: string;
}

const Component = () => {
  const { syncFromStorage, syncToStorage } = useHookFormPersist<FormType>({
    key: 'StorageKey',
    storage: AsyncStorage,
  });

  const {
    control,
    submit,
    watch,
    formState: { defaultValues },
  } = useForm<FormType>({
    defaultValues: () => {
      // Sync data form storage (you can select sync-policy)
      return syncFromStorage({
        defaultValues: {
          name: '',
          email: ''
        },
      });
    },
  })

  // Sync to storage
  syncToStorage(watch());

  return (
    <div>
      <Controller
        control={control}
        name="name"
        render={({ field: { value, onChange } }) => (
          <input
            type="text"
            value={value}
            onChange={onChange}
          />
        )}
      />
    </div>
  );
};

Params:

PropertyDescriptionTypeDefault
keyKey for storagestringRequired
storageObject StorageStorageRequired
excludeFieldsFields that should not be saved and synchronizedstring[]Optional
includeFieldsfields that should be saved and synchronizedstring[]Optional

Return:

PropertyDescriptionType
syncFromStorageSync values from storage.({ defaultValues?: UseFormProps<FieldValues>['defaultValues']; syncPolicy?: CachePolicyLiteral; }) => Promise
syncToStorageSync values to storage.(watchedValues: FieldValues) => void
clearClear storage by key.() => void

useInterval

import { useInterval } from '@appello/common';

A hook that allows you to call a callback function in a time interval

API:

import { useInterval } from '@appello/common';

const Component = () => {
  const { start } = useInterval({
    fn: () => {
      console.log('Hello')
    },
  });

  return (
    <button type="button" onClick={start}>
      Start timer
    </button>
  )
};

Params:

PropertyDescriptionTypeDefault
fnCallback function, a function that will be called with a certain delay.EffectCallbackRequired
delayDelay time.number1000 ms
immediateStartStarts immediately.bolleanundefined
immediateCallFnIs it necessary to call a callback immediately before the timer starts.bolleanundefined
onStopA callback that will be called after the timer stops.() => voidundefined

Return:

PropertyDescriptionType
startFunction for starting timer.() => void
stopFunction for stopping timer.() => void
setStateMethod for change state of an interval manually.(v: bollean) => void

useIsClient

import { useIsClient } from '@appello/common';

This hook can be useful in an SSR environment to wait until be in a browser to execution some functions.

API:

import { useIsClient } from '@appello/common';

const Component = () => {
  const isClient = useIsClient()

  return <div>{isClient ? 'Client' : 'server'}</div>
};

Return:

PropertyDescriptionType
valueValue is booleanboolean

useIsMounted

import { useIsMounted } from '@appello/common';

This hook can be useful for checking is mount component.

API:

import { useIsMounted } from '@appello/common';

const Component = () => {
  const isMounted = useIsMounted()

  return <div>{isMounted() && 'Component is mount'}</div>
};

Return:

PropertyDescriptionType
valueValue is booleanboolean

useLatest

import { useLatest } from '@appello/common';

A Hook that returns the latest value, effectively avoiding the closure problem.

API:

import { useLatest } from "@appello/common";

const Component = () => {
  const [count, setCount] = useState(0);
  const latestCountRef = useLatest(count);

  useEffect(() => {
    const interval = setInterval(() => {
      setCount(latestCountRef.current + 1);
    }, 1000);
    return () => clearInterval(interval);
  }, []);

  return (
    <>
      <p>count: {count}</p>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
valueFunction, ref or any type value for get last active value.anyRequired

Return:

PropertyDescriptionType
resultValueLatest value.any

useManualUpdate

import { useManualUpdate } from '@appello/common';

A hook that can be used to manually update a component.

API:

import { useManualUpdate } from '@appello/common';

const Component = () => {
  const update = useManualUpdate();

  return (
    <>
      <div>Time: {Date.now()}</div>
      <button type="button" onClick={update}>
        Update
      </button>
    </>
  );
};

Return:

PropertyDescriptionType
updateCallback for update component.() => void

useMemoCallback

import { useMemoCallback } from '@appello/common';

Hooks for persistent functions. In theory, useMemoizedFn can be used instead of useCallback.

In some scenarios, we need to use useCallback to cache a function, but when the second parameter deps changes, the function will be regenerated, causing the function reference to change.

API:

import { useMemoCallback } from '@appello/common';

const Component = () => {
  const [count, setCount] = useState(0);

  const memoCallback = useMemoCallback(() => {
    message.info(`Current count is ${count}`);
  });

  return (
    <>
      <p>count: {count}</p>
      <button
        type="button"
        onClick={() => setCount((v) => v + 1)}
      >
        Add Count
      </button>
      <button type="button" onClick={memoCallback}>
        Call
      </button>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
callbackCallback for memorize.AnyFunctionRequired

Return:

PropertyDescriptionType
callbackFunction that require persistence.AnyFunction

useMountEffect

import { useMountEffect } from '@appello/common';

A hook that executes a function after the component is mounted.

API:

import { useMountEffect } from '@appello/common';

const Component = () => {
  useMountEffect(() => {
    console.log("Mount")
  })

  return (
    <span>component</span>
  );
};

Params:

PropertyDescriptionTypeDefault
callbackCallback that is called when the component is mounted.AnyFunctionRequired

usePrevious

import { usePrevious } from '@appello/common';

A Hook to return to the previous state.

API:

import { usePrevious } from '@appello/common';

const Component = () => {
  const [count, setCount] = useState(0);
  const previous = usePrevious(count);
  
  return (
    <>
      <div>counter current value: {count}</div>
      <div>counter previous value: {previous}</div>
      <button type="button" onClick={() => setCount((c) => c + 1)}>
        increase
      </button>
      <button type="button" onClick={() => setCount((c) => c - 1)}>
        decrease
      </button>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
valueAny value that will be saved.anyRequired

Return:

PropertyDescriptionType
valueAny value that saved.any

useQueryParamsBuilder

import { useQueryParamsBuilder } from '@appello/common';

A Hook for manager query params with debounced time.

API:

import { useQueryParamsBuilder } from '@appello/common';

const Component = () => {
  const [getService, { data }] = useAnyRequest();

  const { updateQueryParams } = useQueryParamsBuilder({
    requestCb: params => getService(params),
    defaultParams: {
      categoryId,
      search: '',
    },
  });
  
  return (
    <></>
  );
};

Params:

PropertyDescriptionTypeDefault
requestCbAny request function() => Promise<any>Required
defaultParamsAny object.AnyObjectRequired
optionsLodash optionsDebounceOptionsOptional

Return:

PropertyDescriptionType
loadingLoading promise.boolean
queryParamsObject with query params.AnyObject
updateQueryParamsUpdate query params with.(params: Partial<T>, withDebounce = false) => void
resetReset query params object.() => void

useSelectOptions

import { useSelectOptions } from '@appello/common';

Converts dictionaries for picker to structure:

[
  {
    value: 1,
    label: 'Select 1'
  }, {
    value: 2,
    label: 'Select 2'
  }
]

API:

import { useSelectOptions } from '@appello/common';

const Component = () => {
  const convertedOptions = useSelectOptions([
    {
      val: 1,
      text: 'Select 1',
    },
    {
      val: 2,
      text: 'Select 2',
    },
  ], {
    label: 'text',
    value: 'val',
  })

  return (
    <span>{JSON.stringify(convertedOptions)}</span>
  );
};

Params:

PropertyDescriptionTypeDefault
collectionCollection of objects to be converted.AnyObject[]Required
objectKey Matching Object.{label: string, value: string}Required

Return:

PropertyDescriptionType
newCollectionConverted collection.{label: string, value: string}[]

useStateObject

import { useStateObject } from '@appello/common';

Hook with state for working with objects.

API:

import { useStateObject } from "@appello/common";
import { setState } from "jest-circus";

const Component = () => {
  const [state, setState] = useStateObject({
    name: "Test",
    lastName: "Jest",
    age: 21
  });

  return (
    <>
      <span>{JSON.stringify(state)}</span>
      <button
        type="button"
        onClick={() => {
          setState(prev => ({
            age: prev.age + 25
          }));
        }}
      >
        Update using callback
      </button>
      <button
        type="button"
        onClick={() => {
          setState({
            name: "New",
            lastName: "Test"
          });
        }}
      >
        Update using object
      </button>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
objectDefault object.AnyObjectRequired

Return:

PropertyDescriptionType
stateReturns a stateful value, and a function to update it.[AnyObject, Dispatch<SetStateAction<AnyObject>>]

useStep

import { useStep } from '@appello/common';

Custom hook that manages steps in a multistep process.

API:

import { useStep } from "@appello/common";

const Component = () => {
  const { step, increment, decrement } = useStep(0);

  return (
    <>
      <p>Current step: {step}</p>
      <p>
        <button type="button" onClick={increment}>
          Increment
        </button>
        <button type="button" onClick={decrement} style={{ margin: "0 8px" }}>
          Decrement
        </button>
      </p>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
initialValueInitial value.boolean0

Return:

PropertyDescriptionType
stepCurrent step.number
incrementIncrease the step by one.() => void
decrementReduce the pitch by one.() => void
resetReset steps to default value.() => void
setStepSet step manually.Dispatch<SetStateAction<number>>

useSwitchValue

import { useSwitchValue } from '@appello/common';

A hook that toggle states.

API:

import { useSwitchValue } from "@appello/common";

const Component = () => {
  const { value, on, off, toggle } = useSwitchValue(false);

  return (
    <>
      <p>{`${value}`}</p>
      <p>
        <button type="button" onClick={on}>
          On
        </button>
        <button type="button" onClick={off} style={{ margin: "0 8px" }}>
          Off
        </button>
        <button type="button" onClick={toggle}>
          Toggle
        </button>
      </p>
    </>
  );
};

Params:

PropertyDescriptionTypeDefault
defaultValueDefault value.booleanRequired

Return:

PropertyDescriptionType
valueSwitching value.boolean
onSet value true.() => void
offSet value false.() => void
toggleToggle value.() => void
setSet value manually.Dispatch<SetStateAction<boolean>>

useUnmountEffect

import { useUnmountEffect } from '@appello/common';

A hook that executes the function right before the component is unmounted.

API:

import { useUnmountEffect } from "@appello/common";

const Component = () => {
  useUnmountEffect(() => {
    console.log('Unmount');
  });

  return <p>Hello World!</p>;
};

Params:

PropertyDescriptionTypeDefault
callbackCallback that is called when the component is unmounted.() => voidRequired

useUpdateEffect

import { useUpdateEffect } from '@appello/common';

A hook alike useEffect but skips running the effect for the first time.

API:

import { useUpdateEffect } from "@appello/common";

const Component = () => {
  const [count, setCount] = useState(0);
  const [updateEffectCount, setUpdateEffectCount] = useState(0);

  useUpdateEffect(() => {
    setUpdateEffectCount((c) => c + 1);
  }, [count]);

  return (
    <div>
      <p>updateEffectCount: {updateEffectCount}</p>
      <button type="button" onClick={() => setCount((c) => c + 1)}>
        reRender
      </button>
    </div>
  );
};

Params:

PropertyDescriptionTypeDefault
effectCallback that is called when the component is updated.() => voidRequired
depsThe dependencies list.DependencyListundefined

Types:

ElementType

import { ElementType } from '@appello/common';

The type returns any HTML element.

Usage:

import { ElementType } from '@appello/common';


const target: ElementType = document.getElementById('#user');

Nullable

import { Nullable } from '@appello/common';

The type returns either null or generic.

Usage:

import { Nullable } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: Nullable<User> = null;

Nillable

import { Nillable } from '@appello/common';

The type returns either null or undefined or generic.

Usage:

import { Nillable } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: Nillable<User> = null;
const user2: Nillable<User> = undefined;

NotNullable

import { NotNullable } from '@appello/common';

Prohibits the type from being null, only generic.

Usage:

import { NotNullable } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: NotNullable<User> = {
  name: string,
  lastName: string,
};

NotNillable

import { NotNillable } from '@appello/common';

Prohibits the type from being null or undefined, only generic.

Usage:

import { NotNillable } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: NotNillable<User> = {
  name: string,
  lastName: string,
};

Unidentifiable

import { Unidentifiable } from '@appello/common';

The type returns either undefined or generic.

Usage:

import { Unidentifiable } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: Unidentifiable<User> = undefined;

Negative

import { Negative } from '@appello/common';

Entity can match undefined, null, false or generic.

Usage:

import { Negative } from '@appello/common';

type User = {
  name: string;
  lastName: string; 
}

const user: Negative<User> = undefined;
const user1: Negative<User> = null;
const user2: Negative<User> = false;
const user3: Negative<User> = {
  name: string,
  lastName: string,
};

ValueOf

import { ValueOf } from '@appello/common';

Get values from any type.

Usage:

import { ValueOf } from '@appello/common';

type User = {
  name: string;
  age: number; 
}

const userName: ValueOf<User> = 'User';
const userAge: ValueOf<User> = 22;

AnyObject

import { AnyObject } from '@appello/common';

Common type for objects if we don't know an object type.

Usage:

import { AnyObject } from '@appello/common';

const user: AnyObject = {
  name: 'User',
  age: 123,
  lastName: 'User 2',
}

AnyPromise

import { AnyPromise } from '@appello/common';

Can be used for any promises.

Usage:

import { AnyPromise } from '@appello/common';

const getUser: AnyPromise = Promise.resolve('User'); 

PartialRecord

import { PartialRecord } from '@appello/common';

It can be used to create a type that represents a partial object.

Usage:

import { PartialRecord } from '@appello/common';

type Keys = 'name' | 'age' | 'address';
type Value = string;

type PartialPerson = PartialRecord<Keys, Value>;

const person1: PartialPerson = {};
const person2: PartialPerson = { name: 'John' };
const person3: PartialPerson = { age: '30', address: '123 Main St' };

PartialDeep

import { PartialDeep } from '@appello/common';

This type allows you to create partial versions of nested objects.

Usage:

import { PartialDeep } from '@appello/common';

interface User {
  name: string;
  address: {
    city: string;
    country: string;
  };
}

const user: PartialDeep<User> = {
  address: {
    city: 'New York'
  }
};

ResponseErrors

import { ResponseErrors } from '@appello/common';

Type for object where the key is a string, and the value is also a string.

Usage:

import { ResponseErrors } from '@appello/common';

const error: ResponseErrors = {
  text: 'Something was wrong',
};

UnknownFunction

import { UnknownFunction } from '@appello/common';

Type for an unknown function with unknown parameters.

Usage:

import { UnknownFunction } from '@appello/common';

const unknownFunction: UnknownFunction = props => {
  console.log(props);
};

AnyFunction

import { AnyFunction } from '@appello/common';

Type for any function (best to avoid this).

Usage:

import { AnyFunction } from '@appello/common';

const anyFunction: AnyFunction = props => {
  console.log(props);
};

PromiseType

import { PromiseType } from '@appello/common';

This type extracts the value type from the Promise.

Usage:

import { PromiseType } from '@appello/common';

type User = { 
  id: number; 
  name: string 
}

async function fetchUser(): Promise<> {
  return { id: 1, name: 'John' };
}

type UserType = PromiseType<ReturnType<typeof fetchUser>>;

RequiredKeys / OptionalKeys

import { RequiredKeys, OptionalKeys } from '@appello/common';

This type separates mandatory and optional object keys.

Usage:

import { RequiredKeys, OptionalKeys } from '@appello/common';

type User = {
  id: number;
  name?: string;
  email?: string;
}

type UserRequiredKeys = RequiredKeys<User>; // "id"
type UserOptionalKeys = OptionalKeys<User>; // "name" | "email"

Merge

import { Merge } from '@appello/common';

This type combines two types, where properties of first type override properties of a second type.

Usage:

import { Merge } from '@appello/common';

type User = {
  name: string;
  age: number;
}

type Admin = {
  isAdmin: boolean;
}

type UserAdmin = Merge<A, B>;

const user1: UserAdmin = {
  name: 'hello',
  age: 12,
  isAdmin: true,
};

AsyncReturnType

import { AsyncReturnType } from '@appello/common';

This type retrieves the return type of asynchronous function.

Usage:

import { AsyncReturnType } from '@appello/common';

async function getUser() {
  return { id: 1, name: 'John' };
}

type UserType = AsyncReturnType<typeof getUser>;

FirstArgument

import { FirstArgument } from '@appello/common';

This type retrieves the type of the function's first argument.

Usage:

import { FirstArgument } from '@appello/common';

function logUser(user: { id: number; name: string }) {
  console.log(user);
}

type UserArg = FirstArgument<typeof logUser>;

3.4.1

10 months ago

3.2.0

10 months ago

3.1.0

10 months ago

3.4.0

10 months ago

3.3.0

10 months ago

3.0.7

10 months ago

3.0.6

10 months ago

3.0.4

11 months ago

3.0.3

11 months ago

3.0.2

12 months ago

3.0.5

11 months ago

2.0.17-alpha.0

1 year ago

2.0.17-alpha.3

1 year ago

2.0.17-alpha.4

1 year ago

2.0.17-alpha.1

1 year ago

2.0.17-alpha.2

1 year ago

2.0.17-alpha.7

1 year ago

2.0.17-alpha.8

1 year ago

2.0.17-alpha.5

1 year ago

2.0.17-alpha.6

1 year ago

3.0.1

1 year ago

3.0.0

1 year ago

2.0.16

1 year ago

2.0.15

2 years ago

2.0.13

2 years ago

2.0.14

2 years ago

2.0.11

2 years ago

2.0.12

2 years ago

2.0.10

2 years ago

2.0.3

2 years ago

2.0.2

2 years ago

2.0.5

2 years ago

2.0.4

2 years ago

2.0.7

2 years ago

2.0.6

2 years ago

2.0.9

2 years ago

2.0.8

2 years ago

2.0.1

2 years ago

2.0.0

2 years ago

1.0.39

2 years ago

1.0.40

2 years ago

1.0.29

2 years ago

1.0.33

2 years ago

1.0.32

2 years ago

1.0.31

2 years ago

1.0.30

2 years ago

1.0.37

2 years ago

1.0.36

2 years ago

1.0.35

2 years ago

1.0.34

2 years ago

1.0.38

2 years ago

1.0.28

2 years ago

1.0.26

2 years ago

1.0.25

2 years ago

1.0.27

2 years ago

1.0.24

2 years ago

1.0.23

2 years ago

1.0.22

3 years ago

1.0.21

3 years ago

1.0.20

3 years ago

1.0.19

3 years ago

1.0.18

3 years ago

1.0.17

3 years ago

1.0.16

3 years ago

1.0.11

3 years ago

1.0.15

3 years ago

1.0.14

3 years ago

1.0.13

3 years ago

1.0.12

3 years ago

1.0.10

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

1.0.0

3 years ago

1.0.9

3 years ago

1.0.8

3 years ago

1.0.7

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

0.1.20

3 years ago

0.1.21-alpha.0

3 years ago

0.1.19

3 years ago

0.2.1

3 years ago

0.2.0

3 years ago

0.1.17

3 years ago

0.1.18

3 years ago

0.2.3

3 years ago

0.2.2

3 years ago

0.2.4

3 years ago

0.1.12

3 years ago

0.1.13

3 years ago

0.1.14

3 years ago

0.1.15

3 years ago

0.1.16

3 years ago

0.1.11

4 years ago

0.1.10

4 years ago

0.1.8

4 years ago

0.1.9

4 years ago

0.1.7

4 years ago

0.1.4

4 years ago

0.1.6

4 years ago

0.1.5

4 years ago

0.1.2

4 years ago

0.1.3

4 years ago

0.1.1

4 years ago

0.1.0

4 years ago

0.0.16

4 years ago

0.0.13

4 years ago

0.0.14

4 years ago

0.0.15

4 years ago

0.0.11

4 years ago

0.0.12

4 years ago

0.0.10

4 years ago

0.0.8

4 years ago

0.0.7

4 years ago

0.0.6

4 years ago

0.0.5

4 years ago

0.0.4

4 years ago

0.0.3

4 years ago

0.0.2

4 years ago

0.0.1

4 years ago