3.4.1 • Published 8 months ago

@appello/common v3.4.1

Weekly downloads
-
License
ISC
Repository
bitbucket
Last release
8 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

8 months ago

3.2.0

8 months ago

3.1.0

8 months ago

3.4.0

8 months ago

3.3.0

8 months ago

3.0.7

8 months ago

3.0.6

8 months ago

3.0.4

9 months ago

3.0.3

9 months ago

3.0.2

10 months ago

3.0.5

9 months ago

2.0.17-alpha.0

12 months ago

2.0.17-alpha.3

12 months ago

2.0.17-alpha.4

12 months ago

2.0.17-alpha.1

12 months ago

2.0.17-alpha.2

12 months ago

2.0.17-alpha.7

11 months ago

2.0.17-alpha.8

11 months ago

2.0.17-alpha.5

11 months ago

2.0.17-alpha.6

11 months ago

3.0.1

11 months ago

3.0.0

11 months 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

2 years ago

1.0.21

2 years ago

1.0.20

2 years ago

1.0.19

2 years ago

1.0.18

2 years ago

1.0.17

2 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

3 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