Skip to content

Commit

Permalink
feat(contexts): implemement artboards and sprites contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
albizures committed Jul 3, 2019
1 parent 3743eb5 commit 49983e7
Show file tree
Hide file tree
Showing 14 changed files with 110 additions and 218 deletions.
66 changes: 58 additions & 8 deletions src/components/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@ import React from 'react';
import { css, jsx } from '@emotion/core';

import { getTransparentPattern, clean } from '../utils';
import { Sprite, useSprite } from '../contexts/SpritesContext';
import { Sprite, useSprite } from '../contexts/Sprite';
import { useSpritesActions, useSprites } from '../contexts/Sprites';
import { useArtboards, useArtboardsActions } from '../contexts/Artboards';
import {
useArtboard,
useArtboardActions,
Artboard,
useArtboardsActions,
} from '../contexts/Artboards';
} from '../contexts/Artboard';

const base = css`
cursor: crosshair;
Expand Down Expand Up @@ -61,16 +63,15 @@ let out;
const Canvas: React.FC = () => {
const sprite = useSprite();
const [stats, setStats] = React.useState<ClientRect>();
const artboard = useArtboard(sprite.id);
const { center, changeScale } = useArtboardsActions();
const artboard = useArtboard();
const { center, changePosition } = useArtboardActions();
const elementRef = React.useRef<HTMLDivElement>();
const { onRef: backgroundRef, context: background } = useCanvas2DContext();
const { onRef: mainRef } = useCanvas2DContext();
const { onRef: previewRef } = useCanvas2DContext();
const { onRef: maskRef } = useCanvas2DContext();
const { current: element } = elementRef;
const { innerWidth: width, innerHeight: height } = window;
const { id } = sprite;

React.useEffect(() => {
if (background && sprite && artboard) {
Expand Down Expand Up @@ -104,6 +105,7 @@ const Canvas: React.FC = () => {
ref={elementRef}
style={style}
onWheel={(event) => {
const { y, x } = artboard;
const deltaY = event.deltaY;
if (out) {
return;
Expand All @@ -119,7 +121,12 @@ const Canvas: React.FC = () => {
diff = 1.1;
method = 'ceil';
}
changeScale(id, Math[method](artboard.scale * diff));
const scale = Math[method](artboard.scale * diff);
changePosition({
scale,
y,
x,
});
}, 40);
}}
>
Expand Down Expand Up @@ -155,4 +162,47 @@ const Canvas: React.FC = () => {
);
};

export default Canvas;
const CanvasLoader = () => {
const { addSprite } = useSpritesActions();
const { addArtboard } = useArtboardsActions();

const sprite = useSprite();
const sprites = useSprites();
const artboards = useArtboards();
const artboard = useArtboard();

if (!sprite) {
const spriteIds = Object.keys(sprites);
if (spriteIds.length === 0) {
addSprite({
id: '1',
name: 'New Sprite',
width: 50,
height: 50,
layers: [],
frames: [],
});
}

return 'Loading...';
}

if (!artboard) {
const { id } = sprite;
const artboardIds = Object.keys(artboards);
if (artboardIds.length === 0) {
addArtboard({
id,
scale: 1,
y: 0,
x: 0,
});
}

return 'Loading...';
}

return <Canvas />;
};

export default CanvasLoader;
29 changes: 10 additions & 19 deletions src/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
import React from 'react';

import * as Sprites from '../contexts/Sprites';
import * as Sprite from '../contexts/Sprite';
import * as Artboards from '../contexts/Artboards';
import {
defaultState as editorDefaultState,
Provider as EditorContextProvider,
} from '../contexts/EditorContext';
import {
defaultState as spritesDefaultState,
Provider as SpritesContextProvider,
} from '../contexts/SpritesContext';
import { reducer as editorReducer } from '../reducers/editorReducer';
import { reducer as spritesReducer } from '../reducers/spritesReducer';
import * as Artboard from '../contexts/Artboard';

interface EditorProps {
children: React.ReactNode;
}

const Editor: React.FC<EditorProps> = (props) => {
const { children } = props;
const [spritesState] = React.useReducer(spritesReducer, spritesDefaultState);
const [editorState] = React.useReducer(editorReducer, editorDefaultState);

return (
<Artboards.Provider>
<SpritesContextProvider value={spritesState}>
<EditorContextProvider value={editorState}>
{children}
</EditorContextProvider>
</SpritesContextProvider>
</Artboards.Provider>
<Sprites.Provider>
<Sprite.Provider>
<Artboards.Provider>
<Artboard.Provider>{children}</Artboard.Provider>
</Artboards.Provider>
</Sprite.Provider>
</Sprites.Provider>
);
};

Expand Down
28 changes: 16 additions & 12 deletions src/contexts/Artboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import invariant from 'invariant';
import { Artboard, ArtboardsActions, Artboards } from './types';
import { Artboard, ArtboardsActions } from './types';
import { reducer, createActions } from './reducer';
import { useArtboards } from '../Artboards';

const defaultValueState = undefined;

Expand All @@ -12,7 +13,7 @@ const defaultValueActions = {
changePosition(payload) {
invariant(false, 'Context not implemented');
},
changeArtboard(id: string) {
changeArtboard(artboard) {
invariant(false, 'Context not implemented');
},
};
Expand All @@ -22,22 +23,25 @@ const ArtboardActionsContext = React.createContext<ArtboardsActions>(
defaultValueActions,
);

const useArtboardsActions = () => React.useContext(ArtboardActionsContext);
const useArtboard = (id: string) => {
const artboards = React.useContext(ArtboardStateContext);
return artboards[id];
};
const useArtboardActions = () => React.useContext(ArtboardActionsContext);
const useArtboard = () => React.useContext(ArtboardStateContext);

interface ProviderProps {
children: React.ReactNode;
}

const Provider: React.FC<ProviderProps> = (props) => {
const artboardsRef = React.useRef<Artboards>({});
const artboards = useArtboards();
const [state, dispatch] = React.useReducer(reducer, defaultValueState);
const actions = React.useMemo(() => createActions(dispatch, artboardsRef), [
dispatch,
]);
const actions = React.useMemo(() => createActions(dispatch), [dispatch]);
const { changeArtboard } = actions;

const artboardIds = React.useMemo(() => Object.keys(artboards), [artboards]);
if (!state && artboardIds.length !== 0) {
const artboard = artboards[artboardIds[0]];
changeArtboard(artboard);
}

const { children } = props;
return (
<ArtboardActionsContext.Provider value={actions}>
Expand All @@ -49,4 +53,4 @@ const Provider: React.FC<ProviderProps> = (props) => {
};

export * from './types';
export { Provider, useArtboard, useArtboardsActions };
export { Provider, useArtboard, useArtboardActions };
26 changes: 4 additions & 22 deletions src/contexts/Artboard/reducer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import invariant from 'invariant';
import { Sprite } from '../SpritesContext';
import {
Artboard,
Artboards,
ArtboardsActions,
actionType,
Action,
Stats,
} from './types';
import { Sprite } from '../Sprite';
import { Artboard, ArtboardsActions, actionType, Action, Stats } from './types';

const { floor } = Math;

Expand Down Expand Up @@ -47,15 +39,13 @@ export function getPreviewSize(maxSize: Size, size: Size) {

const reducer = (state: Artboard, action: Action): Artboard => {
const { type, payload } = action;
const { id } = state;

switch (type) {
case actionType.CHANGE_POSITION:
case actionType.CENTER:
return {
...state,
...payload,
id,
};
case actionType.CHANGE_ARTBOARD:
return payload as Artboard;
Expand All @@ -66,17 +56,9 @@ const reducer = (state: Artboard, action: Action): Artboard => {

type Dispatch = (action: Action) => void;

const createActions = (
dispatch: Dispatch,
artboardsRef: React.MutableRefObject<Artboards>,
): ArtboardsActions => {
const createActions = (dispatch: Dispatch): ArtboardsActions => {
return {
changeArtboard(id: string) {
const { current: artboards } = artboardsRef;
const artboard = artboards[id];

invariant(!artboard, `Unknown '${id}' artboard `);

changeArtboard(artboard: Artboard) {
dispatch({
type: actionType.CHANGE_ARTBOARD,
payload: artboard,
Expand Down
9 changes: 2 additions & 7 deletions src/contexts/Artboard/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,6 @@ enum actionType {
CHANGE_POSITION,
CHANGE_ARTBOARD,
}

interface Artboards {
[key: string]: Artboard;
}

type Stats = {
width: number;
height: number;
Expand All @@ -26,7 +21,7 @@ type ChangePositionPayload = {
interface ArtboardsActions {
center: (stats: Stats, sprite: Sprite) => void;
changePosition: (payload: ChangePositionPayload) => void;
changeArtboard: (id: string) => void;
changeArtboard: (artboard: Artboard) => void;
}

interface Artboard {
Expand All @@ -44,4 +39,4 @@ interface Action {
payload: Payload;
}

export { Stats, Artboard, Artboards, ArtboardsActions, Action, actionType };
export { Stats, Artboard, ArtboardsActions, Action, actionType };
7 changes: 5 additions & 2 deletions src/contexts/Artboards/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ const ArtboardsActionsContext = React.createContext<ArtboardsActions>(
defaultActions,
);

const useArtboardsActions = () => React.useContext(ArtboardsActionsContext);
const useArtboards = () => React.useContext(ArtboardsContext);

interface ProviderProps {
children: React.ReactNode;
}

const Provider: React.FC<ProviderProps> = (props) => {
const [artboards, dispatch] = React.useReducer(reducer, undefined);
const [artboards, dispatch] = React.useReducer(reducer, defaultState);
const { children } = props;
const actions = React.useMemo(() => createActions(dispatch), [dispatch]);

Expand All @@ -32,4 +35,4 @@ const Provider: React.FC<ProviderProps> = (props) => {
);
};

export { Provider };
export { Provider, useArtboards, useArtboardsActions };
15 changes: 0 additions & 15 deletions src/contexts/EditorContext.ts

This file was deleted.

9 changes: 9 additions & 0 deletions src/contexts/Sprite/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import invariant from 'invariant';
import { Sprite, SpriteActions } from './types';
import { reducer, createActions } from './reducer';
import { useSprites } from '../Sprites';

const defaultValueState = undefined;

Expand All @@ -27,9 +28,17 @@ interface ProviderProps {
}

const Provider: React.FC<ProviderProps> = (props) => {
const sprites = useSprites();
const [state, dispatch] = React.useReducer(reducer, defaultValueState);
const actions = React.useMemo(() => createActions(dispatch), [dispatch]);
const { children } = props;
const { changeSprite } = actions;

const spriteIds = React.useMemo(() => Object.keys(sprites), [sprites]);
if (!state && spriteIds.length !== 0) {
const sprite = sprites[spriteIds[0]];
changeSprite(sprite);
}
return (
<SpriteActionsContext.Provider value={actions}>
<SpriteStateContext.Provider value={state}>
Expand Down
2 changes: 1 addition & 1 deletion src/contexts/Sprite/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { SpriteActions, Sprite, Action, actionType } from './types';

const reducer = (state: Sprite, action: Action): Sprite => {
const { type, payload } = action;
const { id } = state;
switch (type) {
case actionType.CHANGE_SPRITE:
return payload as Sprite;
case actionType.CHANGE_NAME:
const { id } = state;
return {
...state,
name: payload as string,
Expand Down
1 change: 0 additions & 1 deletion src/contexts/Sprite/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ interface Sprite {
layers: Layer[];
frames: Frame[];
palette?: Palette;
color: string;
}

interface SpriteActions {
Expand Down
Loading

0 comments on commit 49983e7

Please sign in to comment.