diff --git a/playground/index.html b/playground/index.html
index 454cef5..8b4a22c 100644
--- a/playground/index.html
+++ b/playground/index.html
@@ -1,6 +1,19 @@
+
+
+
-
+
diff --git a/playground/src/actions/index.ts b/playground/src/actions/index.ts
deleted file mode 100644
index b99f899..0000000
--- a/playground/src/actions/index.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import { action, GenericActionTypes, GenericAction, GenericActionLookup } from '../redux-utils/action';
-import { Dispatch } from 'redux';
-import { Store } from '../store';
-import uuid from 'uuid/v4';
-import * as todosService from '../service/todosService';
-
-export const actions = {
- add: (label: string) => action('add', { id: uuid(), label }),
- remove: (id: string) => action('remove', { id }),
- edit: (id: string, label: string) => action('edit', { id, label }),
- complete: (id: string) => action('complete', { id }),
- clear: () => action('clear'),
- setFilter: (filter: string) => action('setFilter', { filter })
-};
-
-export const actionsWithService = {
- add: (label: string) => {
- return async (dispatch: Dispatch, getState: () => Store) => {
- const addAction = actions.add(label);
- const id = addAction.id;
- dispatch(addAction);
- await todosService.add(id, getState().todos[id]);
- };
- },
-
- edit: (id: string, label: string) => {
- return async (dispatch: Dispatch, getState: () => Store) => {
- dispatch(actions.edit(id, label));
- await todosService.edit(id, getState().todos[id]);
- };
- },
-
- remove: (id: string) => {
- return async (dispatch: Dispatch, getState: () => Store) => {
- dispatch(actions.remove(id));
- await todosService.remove(id);
- };
- },
-
- complete: (id: string) => {
- return async (dispatch: Dispatch, getState: () => Store) => {
- dispatch(actions.complete(id));
- await todosService.edit(id, getState().todos[id]);
- };
- },
-
- clear: () => {
- return async (dispatch: Dispatch, getState: () => Store) => {
- dispatch(actions.clear());
- await todosService.editBulk(getState().todos);
- };
- }
-};
-
-export type ActionTypes = GenericActionTypes;
-export type TodoAction = GenericAction;
-export type TodoActionWithService = GenericAction;
-export type TodoActionLookup = GenericActionLookup;
diff --git a/playground/src/components/TodoApp.tsx b/playground/src/components/TodoApp.tsx
deleted file mode 100644
index 13fb83f..0000000
--- a/playground/src/components/TodoApp.tsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from 'react';
-import { Stack } from 'office-ui-fabric-react';
-import { TodoFooter } from './TodoFooter';
-import { TodoHeader } from './TodoHeader';
-import { TodoList } from './TodoList';
-
-export const TodoApp = (props: {}) => (
-
-
-
-
-
-
-
-);
diff --git a/playground/src/components/TodoFooter.tsx b/playground/src/components/TodoFooter.tsx
deleted file mode 100644
index 66f0c47..0000000
--- a/playground/src/components/TodoFooter.tsx
+++ /dev/null
@@ -1,38 +0,0 @@
-import React from 'react';
-
-import { Store } from '../store';
-import { DefaultButton, Stack, Text } from 'office-ui-fabric-react';
-import { actionsWithService } from '../actions';
-import { connect } from 'react-redux';
-
-// Redux Container
-export function mapStateToProps({ todos, filter }: Store) {
- return {
- todos,
- filter
- };
-}
-
-export function mapDispatchToProps(dispatch: any) {
- return {
- clear: () => dispatch(actionsWithService.clear())
- };
-}
-
-type TodoFooterProps = ReturnType & ReturnType;
-
-export const TodoFooter = connect(
- mapStateToProps,
- mapDispatchToProps
-)((props: TodoFooterProps) => {
- const itemCount = Object.keys(props.todos).filter(id => !props.todos[id].completed).length;
-
- return (
-
-
- {itemCount} item{itemCount === 1 ? '' : 's'} left
-
- props.clear()}>Clear Completed
-
- );
-});
diff --git a/playground/src/components/TodoHeader.tsx b/playground/src/components/TodoHeader.tsx
deleted file mode 100644
index 8fe1c8c..0000000
--- a/playground/src/components/TodoHeader.tsx
+++ /dev/null
@@ -1,79 +0,0 @@
-import React from 'react';
-import { Pivot, PivotItem, TextField, Stack, Text } from 'office-ui-fabric-react';
-import { FilterTypes, Store } from '../store';
-import { actionsWithService, actions } from '../actions';
-import { connect } from 'react-redux';
-
-function mapStateToProps({ todos, filter }: Store) {
- return {
- todos,
- filter
- };
-}
-
-function mapDispatchToProps(dispatch: any) {
- return {
- add: (label: string) => dispatch(actionsWithService.add(label)),
- remove: (id: string) => dispatch(actionsWithService.remove(id)),
- setFilter: (filter: FilterTypes) => dispatch(actions.setFilter(filter))
- };
-}
-
-type TodoHeaderProps = ReturnType & ReturnType;
-
-interface TodoHeaderState {
- labelInput: string;
-}
-
-class TodoHeader extends React.Component {
- constructor(props: TodoHeaderProps) {
- super(props);
- this.state = { labelInput: undefined };
- }
-
- onKeyPress = (evt: React.KeyboardEvent) => {
- if (evt.charCode === 13) {
- this.props.add(this.state.labelInput);
- this.setState({ labelInput: undefined });
- }
- };
-
- onChange = (evt: React.FormEvent, newValue: string) => {
- this.setState({ labelInput: newValue });
- };
-
- onFilter = (item: PivotItem) => {
- this.props.setFilter(item.props.headerText as FilterTypes);
- };
-
- render() {
- return (
-
-
- todos
-
-
-
-
-
-
-
-
-
-
- );
- }
-}
-
-// Hook up the Redux state and dispatches
-const component = connect(
- mapStateToProps,
- mapDispatchToProps
-)(TodoHeader);
-
-export { component as TodoHeader };
diff --git a/playground/src/components/TodoList.tsx b/playground/src/components/TodoList.tsx
deleted file mode 100644
index 3e4b05c..0000000
--- a/playground/src/components/TodoList.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import React from 'react';
-import { Stack } from 'office-ui-fabric-react';
-import { TodoListItem } from './TodoListItem';
-import { Store } from '../store';
-import { connect } from 'react-redux';
-
-function mapStateToProps({ todos, filter }: Store) {
- return {
- todos,
- filter
- };
-}
-
-function mapDispatchToProps(dispatch: any) {}
-
-type TodoListProps = ReturnType & ReturnType;
-
-class TodoList extends React.Component {
- render() {
- const { filter, todos } = this.props;
- const filteredTodos = Object.keys(todos).filter(id => {
- return filter === 'all' || (filter === 'completed' && todos[id].completed) || (filter === 'active' && !todos[id].completed);
- });
-
- return (
-
- {filteredTodos.map(id => (
-
- ))}
-
- );
- }
-}
-
-const component = connect(
- mapStateToProps,
- mapDispatchToProps
-)(TodoList);
-
-export { component as TodoList };
diff --git a/playground/src/components/TodoListItem.tsx b/playground/src/components/TodoListItem.tsx
deleted file mode 100644
index c8132cf..0000000
--- a/playground/src/components/TodoListItem.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import React from 'react';
-import { Stack, Checkbox, IconButton, TextField } from 'office-ui-fabric-react';
-import { mergeStyles } from '@uifabric/styling';
-import { Store } from '../store';
-import { actionsWithService } from '../actions';
-import { connect } from 'react-redux';
-
-function mapStateToProps({ todos }: Store) {
- return {
- todos
- };
-}
-
-function mapDispatchToProps(dispatch: any) {
- return {
- remove: (id: string) => dispatch(actionsWithService.remove(id)),
- complete: (id: string) => dispatch(actionsWithService.complete(id)),
- edit: (id: string, label: string) => dispatch(actionsWithService.edit(id, label))
- };
-}
-
-type TodoListItemProps = { id: string } & ReturnType & ReturnType;
-
-interface TodoListItemState {
- editing: boolean;
- editLabel: string;
-}
-
-const className = mergeStyles({
- selectors: {
- '.clearButton': {
- visibility: 'hidden'
- },
- '&:hover .clearButton': {
- visibility: 'visible'
- }
- }
-});
-
-class TodoListItem extends React.Component {
- /**
- *
- */
- constructor(props: TodoListItemProps) {
- super(props);
- this.state = { editing: false, editLabel: undefined };
- }
-
- onEdit = () => {
- const { todos, id } = this.props;
- const { label } = todos[id];
-
- this.setState(prevState => ({
- editing: true,
- editLabel: prevState.editLabel || label
- }));
- };
-
- onDoneEdit = () => {
- this.props.edit(this.props.id, this.state.editLabel);
- this.setState(prevState => ({
- editing: false,
- editLabel: undefined
- }));
- };
-
- onKeyDown = (evt: React.KeyboardEvent) => {
- if (evt.which === 13) {
- this.onDoneEdit();
- }
- };
-
- onChange = (evt: React.FormEvent, newValue: string) => {
- this.setState({ editLabel: newValue });
- };
-
- render() {
- const { todos, id, complete, remove } = this.props;
- const item = todos[id];
-
- return (
-
- {!this.state.editing && (
- <>
- complete(id)} />
-
-
- remove(id)} />
-
- >
- )}
-
- {this.state.editing && }
-
- );
- }
-}
-
-const component = connect(
- mapStateToProps,
- mapDispatchToProps
-)(TodoListItem);
-
-export { component as TodoListItem };
diff --git a/playground/src/index.tsx b/playground/src/index.tsx
deleted file mode 100644
index 72bfb40..0000000
--- a/playground/src/index.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import { createStore, applyMiddleware, compose } from 'redux';
-import { Provider } from 'react-redux';
-import { reducer } from './reducers';
-import { TodoApp } from './components/TodoApp';
-import { initializeIcons } from '@uifabric/icons';
-import thunk from 'redux-thunk';
-import * as todosService from './service/todosService';
-import { FilterTypes } from './store';
-
-declare var window: any;
-
-const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
-
-// For preloading store
-initializeIcons();
-
-(async () => {
- const preloadStore = {
- todos: await todosService.getAll(),
- filter: 'all' as FilterTypes
- };
-
- const store = createStore(reducer, preloadStore, composeEnhancers(applyMiddleware(thunk)));
-
- ReactDOM.render(
-
-
- ,
- document.getElementById('app')
- );
-})();
-
-// For Synchronous Case
-// const store = createStore(reducer, { todos: {}, filter: 'all' }, composeEnhancers(applyMiddleware(thunk)));
diff --git a/playground/src/reducers/__tests__/reducers.spec.ts b/playground/src/reducers/__tests__/reducers.spec.ts
deleted file mode 100644
index b666d8a..0000000
--- a/playground/src/reducers/__tests__/reducers.spec.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { reducer } from '../index';
-
-describe('reducers', () => {
- it('should add item to the list', () => {
- const newStore = reducer({ todos: {}, filter: 'all' }, { type: 'add', label: 'hello' });
- const keys = Object.keys(newStore.todos);
- expect(keys.length).toBe(1);
- expect(newStore.todos[keys[0]].label).toBe('hello');
- });
-});
diff --git a/playground/src/reducers/createReducer.ts b/playground/src/reducers/createReducer.ts
deleted file mode 100644
index eb195ab..0000000
--- a/playground/src/reducers/createReducer.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { ActionTypes, TodoActionLookup, actions } from '../actions';
-import { createGenericReducer, HandlerMap, ImmerReducer } from '../redux-utils/reducer';
-import { Reducer } from 'redux';
-
-export function createReducer(
- initialState: T,
- handlerOrMap: HandlerMap | ImmerReducer
-): Reducer {
- return createGenericReducer(initialState, handlerOrMap);
-}
diff --git a/playground/src/reducers/index.ts b/playground/src/reducers/index.ts
deleted file mode 100644
index df6ccf7..0000000
--- a/playground/src/reducers/index.ts
+++ /dev/null
@@ -1,42 +0,0 @@
-import { createReducer } from './createReducer';
-import { Store, FilterTypes } from '../store';
-import { combineReducers } from 'redux';
-
-export const reducer = combineReducers({
- todos: createReducer(
- {},
- {
- add(draft, action) {
- draft[action.id] = { label: action.label, completed: false };
- return draft;
- },
-
- remove(draft, action) {
- delete draft[action.id];
- return draft;
- },
-
- complete(draft, action) {
- draft[action.id].completed = !draft[action.id].completed;
- return draft;
- },
-
- clear(draft) {
- Object.keys(draft).forEach(id => {
- if (draft[id].completed) {
- delete draft[id];
- }
- });
- return draft;
- },
-
- edit(draft, action) {
- draft[action.id].label = action.label;
- return draft;
- }
- }
- ),
- filter: createReducer('all', (draft, action) => {
- return action.filter as FilterTypes;
- })
-});
diff --git a/playground/src/redux-utils/action.ts b/playground/src/redux-utils/action.ts
deleted file mode 100644
index 32c96dc..0000000
--- a/playground/src/redux-utils/action.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { Action } from 'redux';
-
-type ActionWithPayload = Action & P;
-
-export function action(type: T): Action;
-export function action(type: T, payload: P): ActionWithPayload;
-export function action(type: T, payload?: P) {
- return { type, ...payload };
-}
-
-export type GenericActionMapping = { [somekey in keyof A]: (...args: any) => Action | ActionWithPayload };
-export type GenericActionTypes> = ReturnType['type'];
-export type GenericAction> = ReturnType]>;
-export type GenericActionLookup> = { [a in GenericActionTypes]: ReturnType };
diff --git a/playground/src/redux-utils/reducer.ts b/playground/src/redux-utils/reducer.ts
deleted file mode 100644
index fa6c4a3..0000000
--- a/playground/src/redux-utils/reducer.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import { Reducer } from 'redux';
-import { Draft, produce } from 'immer';
-import { GenericActionLookup, GenericActionMapping } from './action';
-
-export type ImmerReducer = (state: Draft, action?: A) => T;
-export type HandlerMap> = {
- [actionType in keyof A]?: ImmerReducer[actionType]>
-};
-
-function isHandlerFunction>(
- handlerOrMap: HandlerMap | ImmerReducer
-): handlerOrMap is ImmerReducer {
- if (typeof handlerOrMap === 'function') {
- return true;
- }
-
- return false;
-}
-
-export function createGenericReducer, AM = keyof GenericActionMapping>(
- initialState: T,
- handlerOrMap: HandlerMap | ImmerReducer[AM]>
-): Reducer {
- return function reducer(state = initialState, action: GenericActionLookup[AM]): T {
- if (isHandlerFunction(handlerOrMap)) {
- return produce(state, draft => handlerOrMap(draft, action as GenericActionLookup[AM]));
- } else if (handlerOrMap.hasOwnProperty(action.type)) {
- const handler = (handlerOrMap as any)[action.type] as ImmerReducer[AM]>;
- return produce(state, draft => handler(draft, action));
- } else {
- return state;
- }
- };
-}
diff --git a/playground/src/service/todosService.ts b/playground/src/service/todosService.ts
deleted file mode 100644
index b2c2481..0000000
--- a/playground/src/service/todosService.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { TodoItem, Store } from '../store';
-const HOST = 'http://localhost:3000';
-
-export async function add(id: string, todo: TodoItem) {
- const response = await fetch(`${HOST}/todos/${id}`, {
- method: 'post',
- headers: { 'content-type': 'application/json' },
- body: JSON.stringify(todo)
- });
-
- return await response.json();
-}
-
-export async function edit(id: string, todo: TodoItem) {
- const response = await fetch(`${HOST}/todos/${id}`, {
- method: 'put',
- headers: { 'content-type': 'application/json' },
- body: JSON.stringify(todo)
- });
-
- return await response.json();
-}
-
-export async function remove(id: string) {
- const response = await fetch(`${HOST}/todos/${id}`, {
- method: 'delete'
- });
-
- return await response.json();
-}
-
-export async function getAll() {
- const response = await fetch(`${HOST}/todos`, {
- method: 'get'
- });
-
- return await response.json();
-}
-
-export async function editBulk(todos: Store['todos']) {
- const response = await fetch(`${HOST}/todos`, {
- method: 'post',
- headers: { 'content-type': 'application/json' },
- body: JSON.stringify(todos)
- });
-
- return await response.json();
-}
diff --git a/playground/src/store/index.ts b/playground/src/store/index.ts
deleted file mode 100644
index 221b5f4..0000000
--- a/playground/src/store/index.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-export type FilterTypes = 'all' | 'active' | 'completed';
-
-export interface TodoItem {
- label: string;
- completed: boolean;
-}
-
-export interface Store {
- todos: {
- [id: string]: TodoItem;
- };
-
- filter: FilterTypes;
-}
diff --git a/webpack.config.js b/webpack.config.js
index ac13d60..b8e1733 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -34,7 +34,7 @@ fs.readdirSync('./').filter(step => {
}
}
- if (!isEntryPoint && step.includes('step')) {
+ if (!isEntryPoint && (step.includes('step') || step.includes('playground'))) {
nonWebpackedEntries.push(step);
}
});