Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ module.exports = {
"plugin:react/recommended",
"plugin:react-hooks/recommended",
],
overrides: [],
parserOptions: {
ecmaVersion: "latest",
sourceType: "module",
Expand All @@ -29,4 +28,29 @@ module.exports = {
version: "detect",
},
},
overrides: [
{
files: ["*.ts", "*.tsx"],
extends: [
"eslint:recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"plugin:@typescript-eslint/recommended",
],
plugins: ["@typescript-eslint"],
parser: "@typescript-eslint/parser",
parserOptions: {
project: "./tsconfig.json",
tsconfigRootDir: __dirname,
},
rules: {
"@typescript-eslint/no-explicit-any": "warn",
"@typescript-eslint/explicit-module-boundary-types": "warn",
"@typescript-eslint/consistent-type-imports": "warn",
"@typescript-eslint/prefer-readonly": "warn",
"@typescript-eslint/explicit-function-return-type": "warn",
"@typescript-eslint/prefer-optional-chain": "warn",
},
},
],
};
3 changes: 2 additions & 1 deletion babel.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
}
}
],
"@babel/preset-react"
"@babel/preset-react",
"@babel/preset-typescript"
],
"plugins": [
// required since @skedwards88/word_lists uses
Expand Down
5,738 changes: 1,989 additions & 3,749 deletions package-lock.json

Large diffs are not rendered by default.

14 changes: 11 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
"dev": "webpack-dev-server --mode development",
"start": "webpack-dev-server",
"eslint": "npx eslint --ignore-path .gitignore . --fix",
"tslint": "npx tsc --noEmit",
"prettier": "npx prettier --write .",
"style": "npx stylelint '**/*.css' --fix",
"lint": "npm run eslint && npm run prettier && npm run style"
"lint": "npm run eslint && npm run tslint && npm run prettier && npm run style"
},
"repository": {
"type": "git",
Expand All @@ -28,8 +29,7 @@
"dependencies": {
"@skedwards88/shared-components": "latest",
"@skedwards88/word_lists": "latest",
"@skedwards88/word_logic": "4.0.2",
"lodash.clonedeep": "^4.5.0",
"@skedwards88/word_logic": "4.0.8",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"seedrandom": "3.0.5"
Expand All @@ -39,6 +39,13 @@
"@babel/plugin-syntax-import-assertions": "^7.22.5",
"@babel/preset-env": "^7.23.2",
"@babel/preset-react": "^7.16.7",
"@babel/preset-typescript": "^7.29.7",
"@types/jest": "^30.0.0",
"@types/react": "^19.2.17",
"@types/react-dom": "^19.2.3",
"@types/seedrandom": "^3.0.8",
"@typescript-eslint/eslint-plugin": "^8.62.0",
"@typescript-eslint/parser": "^8.62.0",
"babel-jest": "^29.7.0",
"babel-loader": "^8.2.3",
"copy-webpack-plugin": "^10.2.4",
Expand All @@ -53,6 +60,7 @@
"style-loader": "^3.3.1",
"stylelint": "^14.6.0",
"stylelint-config-standard": "^25.0.0",
"typescript": "^6.0.3",
"webpack": "^5.68.0",
"webpack-cli": "^4.9.2",
"webpack-dev-server": "^4.7.4",
Expand Down
207 changes: 207 additions & 0 deletions src/Types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
export type PieceWithoutLocation = {
letters: LetterOrEmpty[][];
id: number;
solutionTop: number; // the vertical location of the top of the piece in the "official" solved puzzle
solutionLeft: number; // the horizontal location of the left side of the piece in the "official" solved puzzle
};
export type PieceInPool = PieceWithoutLocation & {
poolIndex: number; // The position of the piece in the pool. Undefined if the piece is on the board or being dragged.
boardTop: undefined;
boardLeft: undefined;
dragGroupTop: undefined;
dragGroupLeft: undefined;
};

export type PieceInBoard = PieceWithoutLocation & {
poolIndex: undefined;
boardTop: number; // The current vertical location of the top of the piece in the board. Undefined if the piece is in the pool or being dragged.
boardLeft: number; // The current horizontal location of the left of the piece in the board. Undefined if the piece is in the pool or being dragged
dragGroupTop: undefined;
dragGroupLeft: undefined;
};

export type PieceInDrag = PieceWithoutLocation & {
poolIndex: undefined;
boardTop: undefined;
boardLeft: undefined;
dragGroupTop: number; // The vertical distance from the top of the piece to the top of the collection of pieces being dragged. Undefined if the piece is not being dragged.
dragGroupLeft: number; // The horizontal distance from the left of the piece to the left of the collection of pieces being dragged. Undefined if the piece is not being dragged.
};

export type PieceInGame = PieceInPool | PieceInBoard | PieceInDrag;

export type Puzzle = {
gridSize: number;
pieces: PieceInGame[];
maxShiftLeft: number;
maxShiftRight: number;
maxShiftUp: number;
maxShiftDown: number;
};

export type Position = {
x: number;
y: number;
};

export type DragOrigin =
| {
where: "pool";
index: number; // The starting index of the drag group in the pool
}
| {
where: "board";
};

export type DragDestinationPool = {
where: "pool";
index: number; // The starting index of the drag group in the pool
};

export type DragDestinationBoard = {
where: "board";
top: number; // The starting vertical location of the top of the drag group in the board.
left: number; // The starting horizontal location of the left of the drag group in the board.
};

export type DragDestination = DragDestinationBoard | DragDestinationPool;

export type DragState = {
pieceIDs: number[]; // The IDs of the pieces being dragged.
boardIsShifting: boolean; // Whether the whole board is being dragged.
dragHasMoved: boolean; // Whether the pointer has moved (ignoring some wiggle) since the drag started.
pointerID: number; // The ID of the pointer, as captured by the pointer down event.
// The x and y position of the pointer, as captured by the pointer down event.
pointerStartPosition: Position;
pointer: Position;
// The distance between the pointer and the top left corner of the drag group:
pointerOffset: Position;
// Info about where the piece originated:
origin: DragOrigin;
// Info about where the pieces would be dropped, based on the position of the pointer:
destination: DragDestination;
};

export type BaseGameState = {
pieces: PieceInGame[];
gridSize: number;
dragCount: number;
dragState?: DragState | undefined;
seed: string;
maxShiftLeft: number;
maxShiftRight: number;
maxShiftUp: number;
maxShiftDown: number;
numLetters: number;
allPiecesAreUsed: boolean;
gameIsSolved: boolean;
gameIsSolvedReason: string;
hintTally: number;
isResumedFromSave: boolean;
isCustomCreating?: false;
};

export type GameStateRandom = BaseGameState & {
isCustom: false;
isDaily: false;
isAdventure: false;
};

export type GameStateDaily = BaseGameState & {
stats: Stats;
isCustom: false;
isDaily: true;
isAdventure: false;
};

export type GameStateCustom = BaseGameState & {
isCustom: true;
isDaily: false;
isAdventure: false;
};

export type GameStateAdventure = BaseGameState & {
isCustom: false;
isDaily: false;
isAdventure: true;
currentLevel: number;
totalHints: number;
adventureComplete: boolean;
};

export type GameState =
| GameStateRandom
| GameStateDaily
| GameStateCustom
| GameStateAdventure;

export type Stats = {
lastDateWon?: string | undefined;
streak: number;
maxStreak: number;
numHintlessInStreak: number;
numHintsInStreak: number;
days: {
0: {won: number; noHints: number};
1: {won: number; noHints: number};
2: {won: number; noHints: number};
3: {won: number; noHints: number};
4: {won: number; noHints: number};
5: {won: number; noHints: number};
6: {won: number; noHints: number};
};
};

export type Letter =
| "A"
| "B"
| "C"
| "D"
| "E"
| "F"
| "G"
| "H"
| "I"
| "J"
| "K"
| "L"
| "M"
| "N"
| "O"
| "P"
| "Q"
| "R"
| "S"
| "T"
| "U"
| "V"
| "W"
| "X"
| "Y"
| "Z";

export type LetterOrEmpty = Letter | "";

export type DayNumber = 0 | 1 | 2 | 3 | 4 | 5 | 6;

export type DisplayState =
| "game"
| "rules"
| "heart"
| "settings"
| "daily"
| "dailyStats"
| "custom"
| "customError"
| "customShare"
| "customLookup"
| "moreGames"
| "installOverview"
| "pwaInstall"
| "extendedMenu"
| "adventure"
| "whatsNew";

export type CSSPropertiesWithVars = React.CSSProperties & {
[key: `--${string}`]: string | number;
};
Loading
Loading