Skip to content

Commit

Permalink
chore(jsdoc): toast jsdoc and improvements (#104)
Browse files Browse the repository at this point in the history
* chore(jsdoc): added toast jsdocs

* chore: jsdoc updates

* chore: toast jsdoc and improvements

* chore: use strict parameters

* chore: extract createContext
  • Loading branch information
anuraghazra authored Oct 21, 2020
1 parent fb0a82b commit 7ed738e
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 14 deletions.
17 changes: 15 additions & 2 deletions src/segment/SegmentState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ const TYPE_MAPPING = {
export interface SegmentStateProps {
value?: Date;
defaultValue?: Date;
/**
* Sets formmating of date based on Intl.DateFormatOptions
*
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat
*
* @example
* {
* year: "numeric",
* month: "2-digit",
* day: "2-digit",
* weekday: "long",
* }
*
*/
formatOptions?: DateTimeFormatOpts;
placeholderDate?: Date;
onChange?: (value: Date, ...args: any[]) => void;
Expand Down Expand Up @@ -124,8 +138,7 @@ export function useSegmentState(props: SegmentStateProps) {
) => {
validSegments[type] = true;
setValidSegments({ ...validSegments });
// @ts-ignore
setValue(add(value, type, amount, resolvedOptions));
setValue(add(value, type, amount, resolvedOptions) as Date);
};

return {
Expand Down
19 changes: 19 additions & 0 deletions src/toast/ToastController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,29 @@ import React from "react";
import { useTimeout } from "@chakra-ui/hooks";

interface ToastControllerProps {
/**
* unique id of the toast
*/
id: string;
/**
* Duration after the toast will be removed automatically if autoDismiss is true
*
* @default 0
*/
duration?: number;
/**
* If True the toast will automatically dismiss after the specified duration
*/
autoDismiss?: boolean;
/**
* Dragging threshold at which point the toast will be swiped out
*
* @default 100
*/
dragThreshold?: number;
/**
* Callback to fire when toast is flagged as removed
*/
onRequestRemove: (id: string) => void;
}

Expand Down
35 changes: 29 additions & 6 deletions src/toast/ToastProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from "react";
import ReactDOM from "react-dom";
import { canUseDOM } from "reakit-utils";
import { createContext } from "@chakra-ui/utils";

import { ToastStateReturn } from "./ToastState";
import { ToastController } from "./ToastController";
import { useToastState, IToast } from "./ToastState";
import { isFunction, createContext } from "../utils";

const DEFAULT_TIMEOUT = 5000;
const PLACEMENTS = {
Expand Down Expand Up @@ -41,12 +41,35 @@ export type ToastTypes = Record<
>;

export type TToastWrapper = (props: any) => React.ReactElement<any>;

type IToastProvider = {
/**
* Specify types of toast in an object
*/
toastTypes: ToastTypes;
/**
* If True the toast will automatically dismiss after the specified duration
*/
autoDismiss?: boolean;
/**
* Timeout after the toast will be removed automatically if autoDismiss is true
*
* @default 5000
*/
timeout?: number;
/**
* Duration of delay after the toast will be unmounted, so that animations can run
*
* @default 0
*/
animationTimeout?: number;
/**
* Wrapper function to enhance the behaviour of ToastController
*/
toastWrapper?: TToastWrapper;
/**
* Placement of the toast on the screen
*/
placement?: Placements;
};

Expand Down Expand Up @@ -75,7 +98,7 @@ export const ToastProvider: React.FC<IToastProvider> = ({
}}
>
{toastList.map(
({ id, type, content, timeout, autoDismiss, isVisible }) => {
({ id, type = "", content, timeout, autoDismiss, isVisible }) => {
return (
<ToastWrapperComponent
key={id}
Expand All @@ -89,13 +112,13 @@ export const ToastProvider: React.FC<IToastProvider> = ({
duration={timeout ?? providerTimeout}
autoDismiss={autoDismiss ?? providerAutoDismiss}
>
{typeof content === "function"
{isFunction(content)
? content({ id, isVisible, remove: state.hide })
: toastTypes[type || ""]?.({
content,
: toastTypes[type]?.({
id,
remove: state.hide,
content,
isVisible,
remove: state.hide,
}) || content}
</ToastController>
</ToastWrapperComponent>
Expand Down
24 changes: 22 additions & 2 deletions src/toast/ToastState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,36 @@ import { v4 as uuidv4 } from "uuid";

import { Placements } from "./ToastProvider";

type JSXFunction = (props: any) => JSX.Element;
type StringOrElement = string | JSXFunction;
type StringOrElement = string | React.ReactNode;

export interface IToast {
/**
* uniue id of toast
*/
id: string;
/**
* type of toast
*/
type?: string;
/**
* content inside the toast
*/
content: StringOrElement;
/**
* Timeout after the toast will be removed automatically if autoDismiss is true
*/
timeout?: number;
/**
* sets the placement of the toast
*/
placement?: Placements;
/**
* If True the toast will automatically dismiss after the specified duration
*/
autoDismiss?: boolean;
/**
* Sets toast initial visibility
*/
isVisible?: boolean;
}

Expand Down
2 changes: 1 addition & 1 deletion src/toast/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "./ToastController";
export * from "./ToastState";
export * from "./ToastProvider";
export * from "./ToastController";
4 changes: 2 additions & 2 deletions src/toast/stories/AnimatedToast.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import "./style.css";
import React from "react";
import { Meta } from "@storybook/react";
import { useTransition, animated } from "react-spring";
import { CSSTransition } from "react-transition-group";
import { useTransition, animated } from "react-spring";

import "./style.css";
import Demo, { getTransform } from "./Demo";
import { ToastProvider, TToastWrapper } from "../index";

Expand Down
2 changes: 1 addition & 1 deletion src/toast/stories/BasicToast.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import "./style.css";
import React from "react";
import { Meta } from "@storybook/react";

import "./style.css";
import Demo from "./Demo";
import { ToastProvider } from "../index";

Expand Down
50 changes: 50 additions & 0 deletions src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import React from "react";
import { Booleanish } from "./types";
import { warn } from "@chakra-ui/utils";

Expand Down Expand Up @@ -51,6 +52,55 @@ export const dataAttr = (condition: boolean | undefined) =>
export const ariaAttr = (condition: boolean | undefined) =>
condition ? true : undefined;

export interface CreateContextOptions {
/**
* If `true`, React will throw if context is `null` or `undefined`
* In some cases, you might want to support nested context, so you can set it to `false`
*/
strict?: boolean;
/**
* Error message to throw if the context is `undefined`
*/
errorMessage?: string;
/**
* The display name of the context
*/
name?: string;
}

type CreateContextReturn<T> = [React.Provider<T>, () => T, React.Context<T>];

/**
* Creates a named context, provider, and hook.
*
* @param options create context options
*/
export function createContext<ContextType>(options: CreateContextOptions = {}) {
const {
strict = true,
errorMessage = "useContext: `context` is undefined. Seems you forgot to wrap component within the Provider",
name,
} = options;

const Context = React.createContext<ContextType | undefined>(undefined);

Context.displayName = name;

function useContext() {
const context = React.useContext(Context);

if (!context && strict) {
throw new Error(errorMessage);
}

return context;
}

return [Context.Provider, useContext, Context] as CreateContextReturn<
ContextType
>;
}

export const cx = (...classNames: any[]) =>
classNames.filter(Boolean).join(" ");

Expand Down

0 comments on commit 7ed738e

Please sign in to comment.