Typescript

This commit is contained in:
Mitchell McCaffrey 2021-07-17 18:39:49 +10:00
parent a4363e542c
commit 029a992381
20 changed files with 61 additions and 47 deletions

View File

@ -43,7 +43,6 @@ function SortableTilesDragOverlay({
const dragBounce = useSpring({ const dragBounce = useSpring({
transform: !!dragId ? "scale(0.9)" : "scale(1)", transform: !!dragId ? "scale(0.9)" : "scale(1)",
config: config.wobbly, config: config.wobbly,
position: "relative",
}); });
function renderDragOverlays() { function renderDragOverlays() {
@ -75,7 +74,7 @@ function SortableTilesDragOverlay({
transform: `translate(${coords[index].x}%, ${coords[index].y}%)`, transform: `translate(${coords[index].x}%, ${coords[index].y}%)`,
}} }}
> >
<animated.div style={dragBounce}> <animated.div style={{ ...dragBounce, position: "relative" }}>
{renderTile(group)} {renderTile(group)}
{index === selectedIndices.length - 1 && {index === selectedIndices.length - 1 &&
selectedGroupIds.length > 1 && ( selectedGroupIds.length > 1 && (

View File

@ -18,7 +18,7 @@ function TileActionBar({ onAdd, addTitle }: TileActionBarProps) {
const { const {
selectMode, selectMode,
onSelectModeChange, onSelectModeChange,
onGroupSelect, onClearSelection,
filter, filter,
onFilterChange, onFilterChange,
} = useGroup(); } = useGroup();
@ -37,7 +37,7 @@ function TileActionBar({ onAdd, addTitle }: TileActionBarProps) {
outlineOffset: "0px", outlineOffset: "0px",
}, },
}} }}
onFocus={() => onGroupSelect(undefined)} onFocus={() => onClearSelection()}
> >
<Search value={filter} onChange={(e) => onFilterChange(e.target.value)} /> <Search value={filter} onChange={(e) => onFilterChange(e.target.value)} />
<Flex <Flex

View File

@ -10,7 +10,7 @@ import useResponsiveLayout from "../../hooks/useResponsiveLayout";
import Droppable from "../drag/Droppable"; import Droppable from "../drag/Droppable";
function TilesContainer({ children }: { children: React.ReactNode }) { function TilesContainer({ children }: { children: React.ReactNode }) {
const { onGroupSelect } = useGroup(); const { onClearSelection } = useGroup();
const { theme } = useThemeUI(); const { theme } = useThemeUI();
@ -23,7 +23,7 @@ function TilesContainer({ children }: { children: React.ReactNode }) {
height: layout.tileContainerHeight, height: layout.tileContainerHeight,
backgroundColor: theme.colors?.muted as string, backgroundColor: theme.colors?.muted as string,
}} }}
onClick={() => onGroupSelect(undefined)} onClick={() => onClearSelection()}
> >
<Grid <Grid
p={3} p={3}

View File

@ -24,8 +24,13 @@ type TilesOverlayProps = {
}; };
function TilesOverlay({ modalSize, children }: TilesOverlayProps) { function TilesOverlay({ modalSize, children }: TilesOverlayProps) {
const { groups, openGroupId, onGroupClose, onGroupSelect, onGroupsChange } = const {
useGroup(); groups,
openGroupId,
onGroupClose,
onClearSelection,
onGroupsChange,
} = useGroup();
const { theme } = useThemeUI(); const { theme } = useThemeUI();
@ -48,7 +53,7 @@ function TilesOverlay({ modalSize, children }: TilesOverlayProps) {
const [isGroupNameModalOpen, setIsGroupNameModalOpen] = useState(false); const [isGroupNameModalOpen, setIsGroupNameModalOpen] = useState(false);
function handleGroupNameChange(name: string) { function handleGroupNameChange(name: string) {
if (openGroupId) { if (openGroupId) {
onGroupsChange(renameGroup(groups, openGroupId, name), undefined); onGroupsChange(renameGroup(groups, openGroupId, name));
setIsGroupNameModalOpen(false); setIsGroupNameModalOpen(false);
} }
} }
@ -134,7 +139,7 @@ function TilesOverlay({ modalSize, children }: TilesOverlayProps) {
marginBottom: "8px", marginBottom: "8px",
backgroundColor: theme.colors?.muted as string, backgroundColor: theme.colors?.muted as string,
}} }}
onClick={() => onGroupSelect(undefined)} onClick={() => onClearSelection()}
> >
<Grid <Grid
sx={{ sx={{

View File

@ -116,6 +116,7 @@ function TokenPreview({ token }: TokenPreviewProps) {
bottomRight: { x: 1, y: 1 }, bottomRight: { x: 1, y: 1 },
}, },
type: "square", type: "square",
measurement: { type: "chebyshev", scale: "5ft" },
}} }}
width={gridWidth} width={gridWidth}
height={gridHeight} height={gridHeight}

View File

@ -16,13 +16,14 @@ export type GetAssetEventHanlder = (
export type AddAssetsEventHandler = (assets: Asset[]) => Promise<void>; export type AddAssetsEventHandler = (assets: Asset[]) => Promise<void>;
export type PutAssetEventsHandler = (asset: Asset) => Promise<void>; export type PutAssetEventsHandler = (asset: Asset) => Promise<void>;
type AssetsContext = { type AssetsContextValue = {
getAsset: GetAssetEventHanlder; getAsset: GetAssetEventHanlder;
addAssets: AddAssetsEventHandler; addAssets: AddAssetsEventHandler;
putAsset: PutAssetEventsHandler; putAsset: PutAssetEventsHandler;
}; };
const AssetsContext = React.createContext<AssetsContext | undefined>(undefined); const AssetsContext =
React.createContext<AssetsContextValue | undefined>(undefined);
// 100 MB max cache size // 100 MB max cache size
const maxCacheSize = 1e8; const maxCacheSize = 1e8;

View File

@ -2,12 +2,13 @@ import React, { useState, useEffect, useContext } from "react";
import FakeStorage from "../helpers/FakeStorage"; import FakeStorage from "../helpers/FakeStorage";
type AuthContext = { type AuthContextValue = {
password: string; password: string;
setPassword: React.Dispatch<React.SetStateAction<string>>; setPassword: React.Dispatch<React.SetStateAction<string>>;
}; };
const AuthContext = React.createContext<AuthContext | undefined>(undefined); const AuthContext =
React.createContext<AuthContextValue | undefined>(undefined);
let storage: Storage | FakeStorage; let storage: Storage | FakeStorage;
try { try {

View File

@ -12,7 +12,7 @@ import { DatabaseWorkerService } from "../workers/DatabaseWorker";
export type DatabaseStatus = "loading" | "disabled" | "upgrading" | "loaded"; export type DatabaseStatus = "loading" | "disabled" | "upgrading" | "loaded";
type DatabaseContext = { type DatabaseContextValue = {
database: Dexie | undefined; database: Dexie | undefined;
databaseStatus: DatabaseStatus; databaseStatus: DatabaseStatus;
databaseError: Error | undefined; databaseError: Error | undefined;
@ -20,7 +20,7 @@ type DatabaseContext = {
}; };
const DatabaseContext = const DatabaseContext =
React.createContext<DatabaseContext | undefined>(undefined); React.createContext<DatabaseContextValue | undefined>(undefined);
const worker: Comlink.Remote<DatabaseWorkerService> = Comlink.wrap( const worker: Comlink.Remote<DatabaseWorkerService> = Comlink.wrap(
new DatabaseWorker() new DatabaseWorker()
@ -127,7 +127,7 @@ export function DatabaseProvider({ children }: { children: React.ReactNode }) {
); );
} }
export function useDatabase(): DatabaseContext { export function useDatabase() {
const context = useContext(DatabaseContext); const context = useContext(DatabaseContext);
if (context === undefined) { if (context === undefined) {
throw new Error("useDatabase must be used within a DatabaseProvider"); throw new Error("useDatabase must be used within a DatabaseProvider");

View File

@ -3,14 +3,14 @@ import React, { useState, useContext, ReactChild } from "react";
export type AssetLoadStartEventHandler = () => void; export type AssetLoadStartEventHandler = () => void;
export type AssetLoadFinishEventHandler = () => void; export type AssetLoadFinishEventHandler = () => void;
type DiceLoadingContext = { type DiceLoadingContextValue = {
assetLoadStart: AssetLoadStartEventHandler; assetLoadStart: AssetLoadStartEventHandler;
assetLoadFinish: AssetLoadFinishEventHandler; assetLoadFinish: AssetLoadFinishEventHandler;
isLoading: boolean; isLoading: boolean;
}; };
const DiceLoadingContext = const DiceLoadingContext =
React.createContext<DiceLoadingContext | undefined>(undefined); React.createContext<DiceLoadingContextValue | undefined>(undefined);
export function DiceLoadingProvider({ children }: { children: ReactChild }) { export function DiceLoadingProvider({ children }: { children: ReactChild }) {
const [loadingAssetCount, setLoadingAssetCount] = useState(0); const [loadingAssetCount, setLoadingAssetCount] = useState(0);
@ -38,7 +38,7 @@ export function DiceLoadingProvider({ children }: { children: ReactChild }) {
); );
} }
export function useDiceLoading(): DiceLoadingContext { export function useDiceLoading() {
const context = useContext(DiceLoadingContext); const context = useContext(DiceLoadingContext);
if (context === undefined) { if (context === undefined) {
throw new Error("useDiceLoading must be used within a DiceLoadingProvider"); throw new Error("useDiceLoading must be used within a DiceLoadingProvider");

View File

@ -26,7 +26,7 @@ export type GroupClearSelectionEventHandler = () => void;
export type GroupFilterChangeEventHandler = (filter: string) => void; export type GroupFilterChangeEventHandler = (filter: string) => void;
export type GroupClearFilterEventHandler = () => void; export type GroupClearFilterEventHandler = () => void;
type GroupContext = { type GroupContextValue = {
groups: Group[]; groups: Group[];
activeGroups: Group[] | GroupItem[]; activeGroups: Group[] | GroupItem[];
openGroupId: string | undefined; openGroupId: string | undefined;
@ -46,7 +46,8 @@ type GroupContext = {
onFilterClear: GroupClearFilterEventHandler; onFilterClear: GroupClearFilterEventHandler;
}; };
const GroupContext = React.createContext<GroupContext | undefined>(undefined); const GroupContext =
React.createContext<GroupContextValue | undefined>(undefined);
type GroupProviderProps = { type GroupProviderProps = {
groups: Group[]; groups: Group[];
@ -249,7 +250,7 @@ export function GroupProvider({
useBlur(handleBlur); useBlur(handleBlur);
const value: GroupContext = { const value = {
groups, groups,
activeGroups, activeGroups,
openGroupId, openGroupId,

View File

@ -33,7 +33,7 @@ export type GetMapStateEventHandler = (
export type GetMapEventHandler = (id: string) => Promise<Map | undefined>; export type GetMapEventHandler = (id: string) => Promise<Map | undefined>;
export type UpdateMapGroupsEventHandler = (groups: Group[]) => Promise<void>; export type UpdateMapGroupsEventHandler = (groups: Group[]) => Promise<void>;
type MapDataContext = { type MapDataContextValue = {
maps: Array<Map>; maps: Array<Map>;
mapStates: MapState[]; mapStates: MapState[];
/** Adds a map to the database, also adds an assosiated state and group for that map */ /** Adds a map to the database, also adds an assosiated state and group for that map */
@ -51,7 +51,7 @@ type MapDataContext = {
}; };
const MapDataContext = const MapDataContext =
React.createContext<MapDataContext | undefined>(undefined); React.createContext<MapDataContextValue | undefined>(undefined);
const defaultMapState: Omit<MapState, "mapId"> = { const defaultMapState: Omit<MapState, "mapId"> = {
tokens: {}, tokens: {},

View File

@ -9,7 +9,7 @@ type MapLoadingProgressUpdate = MapLoadingProgress & {
id: string; id: string;
}; };
type MapLoadingContext = { type MapLoadingContextValue = {
isLoading: boolean; isLoading: boolean;
assetLoadStart: (id: string) => void; assetLoadStart: (id: string) => void;
assetProgressUpdate: (update: MapLoadingProgressUpdate) => void; assetProgressUpdate: (update: MapLoadingProgressUpdate) => void;
@ -17,7 +17,7 @@ type MapLoadingContext = {
}; };
const MapLoadingContext = const MapLoadingContext =
React.createContext<MapLoadingContext | undefined>(undefined); React.createContext<MapLoadingContextValue | undefined>(undefined);
export function MapLoadingProvider({ export function MapLoadingProvider({
children, children,

View File

@ -4,13 +4,13 @@ import { getSettings } from "../settings";
import { Settings } from "../types/Settings"; import { Settings } from "../types/Settings";
type SettingsContext = { type SettingsContextValue = {
settings: Settings; settings: Settings;
setSettings: React.Dispatch<React.SetStateAction<Settings>>; setSettings: React.Dispatch<React.SetStateAction<Settings>>;
}; };
const SettingsContext = const SettingsContext =
React.createContext<SettingsContext | undefined>(undefined); React.createContext<SettingsContextValue | undefined>(undefined);
const settingsProvider = getSettings(); const settingsProvider = getSettings();

View File

@ -29,7 +29,7 @@ export type UpdateTokensHiddenEventHandler = (
hideInSidebar: boolean hideInSidebar: boolean
) => Promise<void>; ) => Promise<void>;
type TokenDataContext = { type TokenDataContextValue = {
tokens: Token[]; tokens: Token[];
addToken: AddTokenEventHandler; addToken: AddTokenEventHandler;
tokenGroups: Group[]; tokenGroups: Group[];
@ -43,7 +43,7 @@ type TokenDataContext = {
}; };
const TokenDataContext = const TokenDataContext =
React.createContext<TokenDataContext | undefined>(undefined); React.createContext<TokenDataContextValue | undefined>(undefined);
export function TokenDataProvider({ children }: { children: React.ReactNode }) { export function TokenDataProvider({ children }: { children: React.ReactNode }) {
const { database } = useDatabase(); const { database } = useDatabase();
@ -152,7 +152,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
); );
}, [tokens]); }, [tokens]);
const value: TokenDataContext = { const value = {
tokens, tokens,
addToken, addToken,
tokenGroups, tokenGroups,
@ -172,7 +172,7 @@ export function TokenDataProvider({ children }: { children: React.ReactNode }) {
); );
} }
export function useTokenData(): TokenDataContext { export function useTokenData() {
const context = useContext(TokenDataContext); const context = useContext(TokenDataContext);
if (context === undefined) { if (context === undefined) {
throw new Error("useTokenData must be used within a TokenDataProvider"); throw new Error("useTokenData must be used within a TokenDataProvider");

1
src/global.d.ts vendored
View File

@ -19,3 +19,4 @@ declare module "*.bin" {
export default source; export default source;
} }
declare module "react-router-hash-link"; declare module "react-router-hash-link";
declare module "intersection-observer";

View File

@ -1,4 +1,4 @@
import React, { useState, useEffect, useRef } from "react"; import { useState, useEffect, useRef } from "react";
import Konva from "konva"; import Konva from "konva";
import { Line, Group, Path, Circle } from "react-konva"; import { Line, Group, Path, Circle } from "react-konva";
import Color from "color"; import Color from "color";

View File

@ -1,5 +1,7 @@
import Case from "case"; import Case from "case";
import { Map, MapState } from "../components/map/Map";
import { DefaultMap } from "../types/Map";
import { MapState } from "../types/MapState";
import blankImage from "./Blank.jpg"; import blankImage from "./Blank.jpg";
import grassImage from "./Grass.jpg"; import grassImage from "./Grass.jpg";
@ -19,15 +21,18 @@ export const mapSources = {
wood: woodImage, wood: woodImage,
}; };
export function getDefaultMaps(userId: string) : {maps: Map[], mapStates: MapState[]} { export function getDefaultMaps(userId: string): {
maps: DefaultMap[];
mapStates: MapState[];
} {
const mapKeys = Object.keys(mapSources); const mapKeys = Object.keys(mapSources);
let maps = []; let maps: DefaultMap[] = [];
let mapStates = []; let mapStates: MapState[] = [];
for (let i = 0; i < mapKeys.length; i++) { for (let i = 0; i < mapKeys.length; i++) {
const key = mapKeys[i]; const key = mapKeys[i];
const name = Case.capital(key); const name = Case.capital(key);
const id = `__default-${name}`; const id = `__default-${name}`;
const map = { const map: DefaultMap = {
id, id,
key, key,
name, name,
@ -45,10 +50,9 @@ export function getDefaultMaps(userId: string) : {maps: Map[], mapStates: MapSta
lastModified: Date.now(), lastModified: Date.now(),
showGrid: key !== "stone", showGrid: key !== "stone",
snapToGrid: true, snapToGrid: true,
group: "",
}; };
maps.push(map); maps.push(map);
const state = { const state: MapState = {
mapId: id, mapId: id,
tokens: {}, tokens: {},
drawShapes: {}, drawShapes: {},

View File

@ -94,7 +94,7 @@ function ImportExportModal({
await worker.importData( await worker.importData(
file, file,
importDBName, importDBName,
Comlink.proxy(handleDBProgress) Comlink.proxy(handleDBProgress) as any
); );
setIsLoading(false); setIsLoading(false);
@ -387,7 +387,7 @@ function ImportExportModal({
try { try {
const buffer = await worker.exportData( const buffer = await worker.exportData(
Comlink.proxy(handleDBProgress), Comlink.proxy(handleDBProgress) as any,
mapIds, mapIds,
tokenIds tokenIds
); );

View File

@ -1,4 +1,5 @@
import Case from "case"; import Case from "case";
import { DefaultToken } from "../types/Token";
import aberration from "./Aberration.png"; import aberration from "./Aberration.png";
import artificer from "./Artificer.png"; import artificer from "./Artificer.png";
@ -80,13 +81,13 @@ function getDefaultTokenSize(key: string) {
} }
} }
export function getDefaultTokens(userId: string) { export function getDefaultTokens(userId: string): DefaultToken[] {
const tokenKeys = Object.keys(tokenSources); const tokenKeys = Object.keys(tokenSources);
let tokens = []; let tokens: DefaultToken[] = [];
for (let i = 0; i < tokenKeys.length; i++) { for (let i = 0; i < tokenKeys.length; i++) {
const key = tokenKeys[i]; const key = tokenKeys[i];
const name = Case.capital(key); const name = Case.capital(key);
const token = { const token: DefaultToken = {
key, key,
name, name,
id: `__default-${name}`, id: `__default-${name}`,

View File

@ -93,7 +93,7 @@ let service = {
assetIds.push(map.file); assetIds.push(map.file);
assetIds.push(map.thumbnail); assetIds.push(map.thumbnail);
for (let res of Object.values(map.resolutions)) { for (let res of Object.values(map.resolutions)) {
assetIds.push(res); res && assetIds.push(res);
} }
} }
} }