Skip to content

Commit

Permalink
#14: refine architecture with singleton pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
Leo Y. Li committed Apr 18, 2019
1 parent 237f5a5 commit d2ec64d
Show file tree
Hide file tree
Showing 25 changed files with 361 additions and 347 deletions.
107 changes: 21 additions & 86 deletions addons/addon-contexts/src/@types/index.ts
Original file line number Diff line number Diff line change
@@ -1,110 +1,45 @@
declare type Channel = import('@storybook/channels').Channel;
declare type ComponentType = import('react').ComponentType;
declare type ComponentProps<C> = import('react').ComponentProps<C>;
declare type ReactNode = import('react').ReactNode;
declare type FC<P> = import('react').FunctionComponent<P>;
export * from './manager';
export * from './preview';

// auxiliary types
declare type FCNoChildren<P> = FC<{ children?: never } & P>;
declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
declare type AnyFunctionReturns<T> = (...args: any[]) => T;
declare type GenericProps = { [key: string]: GenericProps } | null;
export declare type StringObject = { [key: string]: string };
// helpers
export declare type AnyFunctionReturns<T> = (...args: any[]) => T;
export declare type GenericObject = { [key: string]: GenericObject };
export declare type GenericProp = GenericObject | null;
export declare type StringTuple = [string, string];
export declare type StringObject = { [key: string]: string };
export declare type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;

// config types
// shapes
export declare type AddonOptions = {
deep?: boolean;
disable?: boolean;
cancelable?: boolean;
};

export declare type AddonSetting = {
icon?: string;
title: string;
components?: ComponentType[];
components?: unknown[];
params?: {
name: string;
props: GenericProps;
props: GenericProp;
default?: boolean;
}[];
options?: AddonOptions;
};
export declare type WrapperSettings = {
options?: AddonSetting[];
parameters?: AddonSetting[];
};

export declare type ContextNode = Required<AddonSetting> & {
nodeId: string;
};

// duck types
export declare type UPDATE_PROPS_MAP = {
type: 'UPDATE_PROPS_MAP';
payload: {
nodeId: string;
props: GenericProps | null;
};
// wrappers
export declare type WrapperSettings = {
options: AddonSetting[] | undefined;
parameters?: AddonSetting[] | undefined;
};
export declare type PropsMapUpdaterType = (
nodes: ContextNode[]
) => ([nodeId, name]: StringTuple) => UPDATE_PROPS_MAP;

// helper types
export declare type AggregateComponents = <T>(
h: AnyFunctionReturns<T>
) => (...args: [ComponentType[], GenericProps, AddonOptions, number]) => AnyFunctionReturns<T>;
export declare type AggregateContexts = <T>(
h: AnyFunctionReturns<T>
) => (...args: [ContextNode[], Exclude<GenericProps, null>]) => AnyFunctionReturns<T>;
export declare type MergeSettings = (
...args: [Partial<AddonSetting>, Partial<AddonSetting>]
) => ContextNode;
export declare type GetContextNodes = (settings: WrapperSettings) => ContextNode[];
export declare type Memorize = <T, U extends any[]>(
fn: (...args: U) => T,
resolver: (...args: U) => unknown
) => (...args: U) => T;
export declare type UseChannel = (
event: string,
eventHandler: AnyFunctionReturns<void>,
input?: unknown[]
) => void;

// Component types
export declare type Wrapper = (...args: [Function, unknown, WrapperSettings]) => unknown;
export declare type TAddonManager = FCNoChildren<{
channel: Channel;
}>;
export declare type TAddonWrapper = FC<{
channel: Channel;
nodes: ContextNode[];
children: (ready: boolean) => ReactNode;
}>;
export declare type TMenuController = FCNoChildren<
Omit<
ContextNode & {
setSelect: (...args: StringTuple) => void;
},
'components'
>
>;
export declare type TToolBar = FCNoChildren<{
setSelect: ComponentProps<TMenuController>['setSelect'];
nodes: ContextNode[];
}>;
export declare type TToolBarMenu = FCNoChildren<{
icon: string;
title: string;
active: boolean;
expanded: boolean;
setExpanded: (state: boolean) => void;
optionsProps: ComponentProps<TToolBarMenuOptions>;
}>;
export declare type TToolBarMenuOptions = FCNoChildren<{
activeName: string;
list: string[];
onSelectOption: (name: string) => () => void;
}>;
export declare type Wrapper = (
...args: [AnyFunctionReturns<unknown>, unknown, WrapperSettings]
) => unknown;

// core types
export declare type WithContexts = (contexts: AddonSetting[]) => any;
export declare type WithContexts = (contexts: AddonSetting[]) => unknown;
49 changes: 49 additions & 0 deletions addons/addon-contexts/src/@types/manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Channel } from '@storybook/channels';
import { FunctionComponent, ComponentProps } from 'react';
import { AnyFunctionReturns, StringTuple, StringObject, Omit, ContextNode } from './index';

// helper
declare type FCNoChildren<P> = FunctionComponent<{ children?: never } & P>;

// hooks
export declare type UseChannel = (
event: string,
eventHandler: AnyFunctionReturns<void>,
input?: unknown[]
) => void;

// components
export type TAddonManager = FCNoChildren<{
channel: Channel;
}>;

export type TToolbarControl = FCNoChildren<
Omit<
ContextNode & {
selected: string;
setSelected: (...args: StringTuple) => void;
},
'components'
>
>;

export type TToolBar = FCNoChildren<{
nodes: ContextNode[];
state: StringObject;
setSelected: ComponentProps<TToolbarControl>['setSelected'];
}>;

export type TToolBarMenu = FCNoChildren<{
icon: string;
title: string;
active: boolean;
expanded: boolean;
setExpanded: (state: boolean) => void;
optionsProps: ComponentProps<TToolBarMenuOptions>;
}>;

export type TToolBarMenuOptions = FCNoChildren<{
activeName: string;
list: string[];
onSelectOption: (name: string) => () => void;
}>;
39 changes: 39 additions & 0 deletions addons/addon-contexts/src/@types/preview.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import {
AddonOptions,
AddonSetting,
AnyFunctionReturns,
ContextNode,
GenericObject,
GenericProp,
StringObject,
WrapperSettings,
} from './index';

export declare type Memorize = <T, U extends any[]>(
fn: (...args: U) => T,
resolver?: (...args: U) => unknown
) => (...args: U) => T;

export declare type Singleton = <T, U extends any[]>(fn: (...args: U) => T) => (...args: U) => T;

export declare type AggregateComponents = <T>(
h: AnyFunctionReturns<T>
) => (
...args: [ContextNode['components'], GenericProp, AddonOptions, number]
) => AnyFunctionReturns<T>;

export declare type AggregateContexts = <T>(
h: AnyFunctionReturns<T>
) => (...args: [ContextNode[], GenericObject, AnyFunctionReturns<any>]) => T;

export declare type GetMergedSettings = (
...args: [Partial<AddonSetting>, Partial<AddonSetting>]
) => ContextNode;

export declare type GetContextNodes = (settings: WrapperSettings) => ContextNode[];

export declare type GetPropsByParamName = (
params: ContextNode['params'],
name?: string
) => GenericProp;
export declare type GetPropsMap = (nodes: ContextNode[], state: StringObject) => GenericObject;
17 changes: 0 additions & 17 deletions addons/addon-contexts/src/components/ToolBar.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,5 @@ export const PARAM = 'contexts';
export const OPT_OUT = '__OPT_OUT__';

// events
export const INIT_WRAPPER = `${ID}/INIT_WRAPPER`;
export const UPDATE_MANAGER = `${ID}/UPDATE_MANAGER`;
export const UPDATE_WRAPPER = `${ID}/UPDATE_WRAPPER`;
export const UPDATE_PREVIEW = `${ID}/UPDATE_PREVIEW`;
35 changes: 0 additions & 35 deletions addons/addon-contexts/src/containers/AddonManager.tsx

This file was deleted.

30 changes: 0 additions & 30 deletions addons/addon-contexts/src/containers/ReactWrapper.tsx

This file was deleted.

19 changes: 4 additions & 15 deletions addons/addon-contexts/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
import { createElement as h } from 'react';
import addons, { makeDecorator } from '@storybook/addons';
import { ReactWrapper } from './containers/ReactWrapper';
import { ID, PARAM } from './libs/constants';
import { getContextNodes } from './libs/helpers';
import { WithContexts, Wrapper } from './@types';

const wrapper: Wrapper = (getStory, context, settings) => {
const nodes = getContextNodes(settings);
return h(ReactWrapper, {
nodes,
channel: addons.getChannel(),
children: (ready: boolean) => () => (ready ? getStory(context) : h('div')),
});
};
import { makeDecorator } from '@storybook/addons';
import { ID, PARAM } from './constants';
import { wrapper } from './preview';
import { WithContexts } from './@types';

export const withContexts: WithContexts = makeDecorator({
name: ID,
Expand Down
41 changes: 0 additions & 41 deletions addons/addon-contexts/src/libs/ducks.ts

This file was deleted.

Loading

0 comments on commit d2ec64d

Please sign in to comment.