Some fiddling, but also version upgrades and a new button for downloading a pdf version of the current maze.
Some checks reported errors
continuous-integration/drone/push Build encountered an error
Some checks reported errors
continuous-integration/drone/push Build encountered an error
This commit is contained in:
parent
79467e29f2
commit
b6359bcb5d
21 changed files with 2002 additions and 927 deletions
1
next-env.d.ts
vendored
1
next-env.d.ts
vendored
|
|
@ -1,5 +1,6 @@
|
||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
import "./.next/dev/types/routes.d.ts";
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
|
||||||
|
|
|
||||||
1963
package-lock.json
generated
1963
package-lock.json
generated
File diff suppressed because it is too large
Load diff
13
package.json
13
package.json
|
|
@ -9,17 +9,18 @@
|
||||||
"lint": "next lint"
|
"lint": "next lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react": "^19.0.0",
|
"next": "^16.1.4",
|
||||||
"react-dom": "^19.0.0",
|
"react": "^19.2.3",
|
||||||
"next": "15.1.2"
|
"react-dom": "^19.2.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"typescript": "^5",
|
"@eslint/eslintrc": "^3",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "15.1.2",
|
"eslint-config-next": "^16.1.4",
|
||||||
"@eslint/eslintrc": "^3"
|
"sass": "^1.85.1",
|
||||||
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
109
src/app/cell.css
109
src/app/cell.css
|
|
@ -1,109 +0,0 @@
|
||||||
.solution {
|
|
||||||
background-color: var(--color-maze-cell-solution);
|
|
||||||
}
|
|
||||||
|
|
||||||
.solution:hover {
|
|
||||||
background-color: var(--color-maze-cell-solution-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
.top {
|
|
||||||
border-top-color: var(--color-maze-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
border-right-color: var(--color-maze-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom {
|
|
||||||
border-bottom-color: var(--color-maze-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
border-left-color: var(--color-maze-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userSELF {
|
|
||||||
background: radial-gradient(
|
|
||||||
ellipse 16% 16% at center,
|
|
||||||
var(--color-maze-cell-user) 0,
|
|
||||||
var(--color-maze-cell-user) 100%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userSELF:hover {
|
|
||||||
background: radial-gradient(
|
|
||||||
ellipse 33% 33% at center,
|
|
||||||
var(--color-maze-cell-user) 0,
|
|
||||||
var(--color-maze-cell-user) 80%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.marker {
|
|
||||||
display: inline-block;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
.marker:hover {
|
|
||||||
background: #fc08;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userUP .marker.UP {
|
|
||||||
height: 50%;
|
|
||||||
width: 100%;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
#0000 0,
|
|
||||||
#0000 33%,
|
|
||||||
var(--color-maze-cell-user) 33%,
|
|
||||||
var(--color-maze-cell-user) 66%,
|
|
||||||
#0000 66%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userRIGHT .marker.RIGHT {
|
|
||||||
height: 100%;
|
|
||||||
width: 50%;
|
|
||||||
left: 50%;
|
|
||||||
background: linear-gradient(
|
|
||||||
0deg,
|
|
||||||
#0000 0,
|
|
||||||
#0000 33%,
|
|
||||||
var(--color-maze-cell-user) 33%,
|
|
||||||
var(--color-maze-cell-user) 66%,
|
|
||||||
#0000 66%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userDOWN .marker.DOWN {
|
|
||||||
height: 50%;
|
|
||||||
width: 100%;
|
|
||||||
top: 50%;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
#0000 0,
|
|
||||||
#0000 33%,
|
|
||||||
var(--color-maze-cell-user) 33%,
|
|
||||||
var(--color-maze-cell-user) 66%,
|
|
||||||
#0000 66%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.userLEFT .marker.LEFT {
|
|
||||||
height: 100%;
|
|
||||||
width: 50%;
|
|
||||||
background: linear-gradient(
|
|
||||||
0deg,
|
|
||||||
#0000 0,
|
|
||||||
#0000 33%,
|
|
||||||
var(--color-maze-cell-user) 33%,
|
|
||||||
var(--color-maze-cell-user) 66%,
|
|
||||||
#0000 66%,
|
|
||||||
#0000 100%
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
.cell {
|
|
||||||
display: table-cell;
|
|
||||||
border: 1px solid transparent;
|
|
||||||
height: 2em;
|
|
||||||
width: 2em;
|
|
||||||
padding: 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.cell:hover {
|
|
||||||
background-color: var(--color-background-highlight);
|
|
||||||
}
|
|
||||||
12
src/app/cell.module.scss
Normal file
12
src/app/cell.module.scss
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
.cell {
|
||||||
|
display: table-cell;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
height: 2em;
|
||||||
|
width: 2em;
|
||||||
|
padding: 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-background-highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
186
src/app/cell.scss
Normal file
186
src/app/cell.scss
Normal file
|
|
@ -0,0 +1,186 @@
|
||||||
|
.solution {
|
||||||
|
background-color: var(--color-maze-cell-solution);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: var(--color-maze-cell-solution-highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top {
|
||||||
|
border-top-color: var(--color-maze-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
border-right-color: var(--color-maze-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom {
|
||||||
|
border-bottom-color: var(--color-maze-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
border-left-color: var(--color-maze-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userSELF {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse 16% 16% at center,
|
||||||
|
var(--color-maze-cell-user) 0,
|
||||||
|
var(--color-maze-cell-user) 100%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
&.solution {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse 16% 16% at center,
|
||||||
|
var(--color-maze-cell-user-solution) 0,
|
||||||
|
var(--color-maze-cell-user-solution) 100%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse 33% 33% at center,
|
||||||
|
var(--color-maze-cell-user-solution) 0,
|
||||||
|
var(--color-maze-cell-user-solution) 80%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: radial-gradient(
|
||||||
|
ellipse 33% 33% at center,
|
||||||
|
var(--color-maze-cell-user) 0,
|
||||||
|
var(--color-maze-cell-user) 80%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.marker {
|
||||||
|
display: inline-block;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #fc08;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.userUP .marker.UP {
|
||||||
|
height: 50%;
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user) 33%,
|
||||||
|
var(--color-maze-cell-user) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution.userUP .marker.UP {
|
||||||
|
height: 50%;
|
||||||
|
width: 100%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userRIGHT .marker.RIGHT {
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
left: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user) 33%,
|
||||||
|
var(--color-maze-cell-user) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution.userRIGHT .marker.RIGHT {
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
left: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.userDOWN .marker.DOWN {
|
||||||
|
height: 50%;
|
||||||
|
width: 100%;
|
||||||
|
top: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user) 33%,
|
||||||
|
var(--color-maze-cell-user) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution.userDOWN .marker.DOWN {
|
||||||
|
height: 50%;
|
||||||
|
width: 100%;
|
||||||
|
top: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.userLEFT .marker.LEFT {
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user) 33%,
|
||||||
|
var(--color-maze-cell-user) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.solution.userLEFT .marker.LEFT {
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
background: linear-gradient(
|
||||||
|
0deg,
|
||||||
|
#0000 0,
|
||||||
|
#0000 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 33%,
|
||||||
|
var(--color-maze-cell-user-solution) 66%,
|
||||||
|
#0000 66%,
|
||||||
|
#0000 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import {MazeCell} from "./model/maze.ts";
|
import {MazeCell} from "./model/maze.ts";
|
||||||
import Coordinates from "./model/coordinates.ts";
|
import Coordinates from "./model/coordinates.ts";
|
||||||
import {Action, actionClickedCell} from "./state/action.ts";
|
import {Action, actionClickedCell} from "./state/action.ts";
|
||||||
import styles from "./cell.module.css";
|
import styles from "./cell.module.scss";
|
||||||
import "./cell.css";
|
import "./cell.scss";
|
||||||
import {State} from "./state/state.ts";
|
import {State} from "./state/state.ts";
|
||||||
import {ActionDispatch} from "react";
|
import {ActionDispatch} from "react";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,9 @@
|
||||||
--color-maze-cell-solution: #b1d5b1;
|
--color-maze-cell-solution: #b1d5b1;
|
||||||
--color-maze-cell-solution-highlight: #b9e8b9;
|
--color-maze-cell-solution-highlight: #b9e8b9;
|
||||||
--color-maze-cell-user: #ffcc00;
|
--color-maze-cell-user: #ffcc00;
|
||||||
--color-maze-cell-user-highlight: #ffdd22;
|
--color-maze-cell-user-solution: #47e147;
|
||||||
|
--color-accent: #ffcc00;
|
||||||
|
--color-accent-inverse: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
|
|
@ -29,7 +31,7 @@
|
||||||
--color-maze-cell-solution: #213d21;
|
--color-maze-cell-solution: #213d21;
|
||||||
--color-maze-cell-solution-highlight: #3d6e3d;
|
--color-maze-cell-solution-highlight: #3d6e3d;
|
||||||
--color-maze-cell-user: #ffcc00;
|
--color-maze-cell-user: #ffcc00;
|
||||||
--color-maze-cell-user-highlight: #ffdd22;
|
--color-maze-cell-user-solution: #00a421;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
form {
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
input, select {
|
|
||||||
background-color: var(--color-background);
|
|
||||||
border: 1px solid var(--color-border);
|
|
||||||
color: var(--color-foreground);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:hover, input:focus, select:hover, select:focus {
|
|
||||||
background-color: var(--color-background-highlight);
|
|
||||||
border-color: var(--color-border-highlight);
|
|
||||||
color: var(--color-foreground-highlight);
|
|
||||||
}
|
|
||||||
|
|
||||||
input:invalid {
|
|
||||||
border-color: var(--color-form-error);
|
|
||||||
}
|
|
||||||
|
|
@ -5,8 +5,9 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.submitbutton {
|
.submitbutton {
|
||||||
background-color: #fc0;
|
background-color: var(--color-accent);
|
||||||
border: 1px solid var(--color-foreground);
|
border: 1px solid var(--color-foreground);
|
||||||
|
color: var(--color-accent-inverse);
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
border-radius: 0.5em;
|
border-radius: 0.5em;
|
||||||
margin-top: 2em;
|
margin-top: 2em;
|
||||||
21
src/app/input-form.scss
Normal file
21
src/app/input-form.scss
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
form {
|
||||||
|
display: flex;
|
||||||
|
flex-flow: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select {
|
||||||
|
background-color: var(--color-background);
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
color: var(--color-foreground);
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
background-color: var(--color-background-highlight);
|
||||||
|
border-color: var(--color-border-highlight);
|
||||||
|
color: var(--color-foreground-highlight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input:invalid {
|
||||||
|
border-color: var(--color-form-error);
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import {ActionDispatch, FormEvent, useState} from 'react';
|
import {ActionDispatch, FormEvent, useState} from 'react';
|
||||||
import ValidatingInputNumberField, {ValidatorFunction} from "./validating-input-number-field.tsx";
|
|
||||||
import {
|
import {
|
||||||
Action,
|
Action,
|
||||||
actionLoadedMaze,
|
actionLoadedMaze,
|
||||||
|
|
@ -7,10 +6,14 @@ import {
|
||||||
actionStartedLoading,
|
actionStartedLoading,
|
||||||
actionToggledShowSolution
|
actionToggledShowSolution
|
||||||
} from "./state/action.ts";
|
} from "./state/action.ts";
|
||||||
import styles from "./input-form.module.css";
|
import styles from "./input-form.module.scss";
|
||||||
import "./input-form.css";
|
import "./input-form.scss";
|
||||||
import {State} from "@/app/state/state.ts";
|
import {State} from "@/app/state/state.ts";
|
||||||
import ValidatingInputBigIntField from "@/app/validating-input-bigint-field.tsx";
|
import {
|
||||||
|
ValidatingInputNumberField,
|
||||||
|
ValidatingInputRegExpField,
|
||||||
|
ValidatorFunction
|
||||||
|
} from "@/app/validating-input-field.tsx";
|
||||||
|
|
||||||
export default function InputForm({state, dispatch}: {
|
export default function InputForm({state, dispatch}: {
|
||||||
state: State,
|
state: State,
|
||||||
|
|
@ -18,7 +21,7 @@ export default function InputForm({state, dispatch}: {
|
||||||
}) {
|
}) {
|
||||||
const [width, setWidth] = useState(10);
|
const [width, setWidth] = useState(10);
|
||||||
const [height, setHeight] = useState(10);
|
const [height, setHeight] = useState(10);
|
||||||
const [id, setId] = useState<bigint>();
|
const [id, setId] = useState<string>();
|
||||||
const [algorithm, setAlgorithm] = useState('wilson');
|
const [algorithm, setAlgorithm] = useState('wilson');
|
||||||
|
|
||||||
const handleSubmit = (e: FormEvent) => {
|
const handleSubmit = (e: FormEvent) => {
|
||||||
|
|
@ -36,7 +39,7 @@ export default function InputForm({state, dispatch}: {
|
||||||
dispatch(actionLoadingFailed(reason));
|
dispatch(actionLoadingFailed(reason));
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const validateWidthHeightInput: ValidatorFunction<string, number> = value => {
|
const validateSizeInput: ValidatorFunction<string, number> = value => {
|
||||||
const numberValue = Number(value);
|
const numberValue = Number(value);
|
||||||
if (isNaN(numberValue) || "" === value || (Math.floor(numberValue) !== numberValue)) {
|
if (isNaN(numberValue) || "" === value || (Math.floor(numberValue) !== numberValue)) {
|
||||||
return {
|
return {
|
||||||
|
|
@ -55,24 +58,6 @@ export default function InputForm({state, dispatch}: {
|
||||||
value: numberValue
|
value: numberValue
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
const validateIdInput: ValidatorFunction<string, bigint> = value => {
|
|
||||||
if ("" === value) {
|
|
||||||
return {
|
|
||||||
valid: true
|
|
||||||
};
|
|
||||||
}
|
|
||||||
const numberValue = BigInt(value);
|
|
||||||
if (numberValue.toString() !== value.trim()) {
|
|
||||||
return {
|
|
||||||
valid: false,
|
|
||||||
message: "Must be empty or an integer"
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
valid: true,
|
|
||||||
value: numberValue
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
<div className={styles.inputform}>
|
<div className={styles.inputform}>
|
||||||
|
|
@ -82,7 +67,7 @@ export default function InputForm({state, dispatch}: {
|
||||||
constraints={{
|
constraints={{
|
||||||
min: 2
|
min: 2
|
||||||
}}
|
}}
|
||||||
validatorFn={validateWidthHeightInput}
|
validatorFn={validateSizeInput}
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
onChange={setWidth}
|
onChange={setWidth}
|
||||||
/>
|
/>
|
||||||
|
|
@ -92,16 +77,30 @@ export default function InputForm({state, dispatch}: {
|
||||||
constraints={{
|
constraints={{
|
||||||
min: 2
|
min: 2
|
||||||
}}
|
}}
|
||||||
validatorFn={validateWidthHeightInput}
|
validatorFn={validateSizeInput}
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
onChange={setHeight}
|
onChange={setHeight}
|
||||||
/>
|
/>
|
||||||
<ValidatingInputBigIntField id={"id"}
|
{/*<ValidatingInputBigIntField id={"id"}*/}
|
||||||
|
{/* label={"ID (optional)"}*/}
|
||||||
|
{/* value={id}*/}
|
||||||
|
{/* validatorFn={validateIdInput}*/}
|
||||||
|
{/* disabled={state.loading}*/}
|
||||||
|
{/* onChange={setId}*/}
|
||||||
|
{/* constraints={{*/}
|
||||||
|
{/* min: -9223372036854775808n,*/}
|
||||||
|
{/* max: 9223372036854775807n*/}
|
||||||
|
{/* }}*/}
|
||||||
|
{/*/>*/}
|
||||||
|
<ValidatingInputRegExpField id={"id"}
|
||||||
label={"ID (optional)"}
|
label={"ID (optional)"}
|
||||||
value={id}
|
value={id}
|
||||||
validatorFn={validateIdInput}
|
|
||||||
disabled={state.loading}
|
disabled={state.loading}
|
||||||
onChange={setId}
|
onChange={setId}
|
||||||
|
constraints={[
|
||||||
|
/^[0-9a-fA-F]{0,16}$/
|
||||||
|
]}
|
||||||
|
placeholder={"Hex-Number (without 0x prefix)"}
|
||||||
/>
|
/>
|
||||||
<label htmlFor="algorithm">Algorithm:</label>
|
<label htmlFor="algorithm">Algorithm:</label>
|
||||||
<select id={"algorithm"}
|
<select id={"algorithm"}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import type {Metadata} from "next";
|
import type {Metadata} from "next";
|
||||||
import "./globals.css";
|
import "./globals.scss";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "A-Maze-R! Create your own Maze!",
|
title: "A-Maze-R! Create your own Maze!",
|
||||||
|
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
.page {
|
|
||||||
}
|
|
||||||
|
|
||||||
.page h1.mainheading, .page h2.mainheading {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.page h2.mainheading {
|
|
||||||
font-size: medium;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*.page {*/
|
|
||||||
/* --gray-rgb: 0, 0, 0;*/
|
|
||||||
/* --gray-alpha-200: rgba(var(--gray-rgb), 0.08);*/
|
|
||||||
/* --gray-alpha-100: rgba(var(--gray-rgb), 0.05);*/
|
|
||||||
|
|
||||||
/* --button-primary-hover: #383838;*/
|
|
||||||
/* --button-secondary-hover: #f2f2f2;*/
|
|
||||||
|
|
||||||
/* display: grid;*/
|
|
||||||
/* grid-template-rows: 20px 1fr 20px;*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* justify-items: center;*/
|
|
||||||
/* min-height: 100svh;*/
|
|
||||||
/* padding: 80px;*/
|
|
||||||
/* gap: 64px;*/
|
|
||||||
/* font-family: var(--font-geist-sans);*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*@media (prefers-color-scheme: dark) {*/
|
|
||||||
/* .page {*/
|
|
||||||
/* --gray-rgb: 255, 255, 255;*/
|
|
||||||
/* --gray-alpha-200: rgba(var(--gray-rgb), 0.145);*/
|
|
||||||
/* --gray-alpha-100: rgba(var(--gray-rgb), 0.06);*/
|
|
||||||
|
|
||||||
/* --button-primary-hover: #ccc;*/
|
|
||||||
/* --button-secondary-hover: #1a1a1a;*/
|
|
||||||
/* }*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.main {*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* flex-direction: column;*/
|
|
||||||
/* gap: 32px;*/
|
|
||||||
/* grid-row-start: 2;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.main ol {*/
|
|
||||||
/* font-family: var(--font-geist-mono);*/
|
|
||||||
/* padding-left: 0;*/
|
|
||||||
/* margin: 0;*/
|
|
||||||
/* font-size: 14px;*/
|
|
||||||
/* line-height: 24px;*/
|
|
||||||
/* letter-spacing: -0.01em;*/
|
|
||||||
/* list-style-position: inside;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.main li:not(:last-of-type) {*/
|
|
||||||
/* margin-bottom: 8px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.main code {*/
|
|
||||||
/* font-family: inherit;*/
|
|
||||||
/* background: var(--gray-alpha-100);*/
|
|
||||||
/* padding: 2px 4px;*/
|
|
||||||
/* border-radius: 4px;*/
|
|
||||||
/* font-weight: 600;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.ctas {*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* gap: 16px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.ctas a {*/
|
|
||||||
/* appearance: none;*/
|
|
||||||
/* border-radius: 128px;*/
|
|
||||||
/* height: 48px;*/
|
|
||||||
/* padding: 0 20px;*/
|
|
||||||
/* border: none;*/
|
|
||||||
/* border: 1px solid transparent;*/
|
|
||||||
/* transition:*/
|
|
||||||
/* background 0.2s,*/
|
|
||||||
/* color 0.2s,*/
|
|
||||||
/* border-color 0.2s;*/
|
|
||||||
/* cursor: pointer;*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* justify-content: center;*/
|
|
||||||
/* font-size: 16px;*/
|
|
||||||
/* line-height: 20px;*/
|
|
||||||
/* font-weight: 500;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*a.primary {*/
|
|
||||||
/* background: var(--foreground);*/
|
|
||||||
/* color: var(--background);*/
|
|
||||||
/* gap: 8px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*a.secondary {*/
|
|
||||||
/* border-color: var(--gray-alpha-200);*/
|
|
||||||
/* min-width: 180px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.footer {*/
|
|
||||||
/* grid-row-start: 3;*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* gap: 24px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.footer a {*/
|
|
||||||
/* display: flex;*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* gap: 8px;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*.footer img {*/
|
|
||||||
/* flex-shrink: 0;*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*!* Enable hover only on non-touch devices *!*/
|
|
||||||
/*@media (hover: hover) and (pointer: fine) {*/
|
|
||||||
/* a.primary:hover {*/
|
|
||||||
/* background: var(--button-primary-hover);*/
|
|
||||||
/* border-color: transparent;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* a.secondary:hover {*/
|
|
||||||
/* background: var(--button-secondary-hover);*/
|
|
||||||
/* border-color: transparent;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .footer a:hover {*/
|
|
||||||
/* text-decoration: underline;*/
|
|
||||||
/* text-underline-offset: 4px;*/
|
|
||||||
/* }*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*@media (max-width: 600px) {*/
|
|
||||||
/* .page {*/
|
|
||||||
/* padding: 32px;*/
|
|
||||||
/* padding-bottom: 80px;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .main {*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .main ol {*/
|
|
||||||
/* text-align: center;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .ctas {*/
|
|
||||||
/* flex-direction: column;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .ctas a {*/
|
|
||||||
/* font-size: 14px;*/
|
|
||||||
/* height: 40px;*/
|
|
||||||
/* padding: 0 16px;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* a.secondary {*/
|
|
||||||
/* min-width: auto;*/
|
|
||||||
/* }*/
|
|
||||||
|
|
||||||
/* .footer {*/
|
|
||||||
/* flex-wrap: wrap;*/
|
|
||||||
/* align-items: center;*/
|
|
||||||
/* justify-content: center;*/
|
|
||||||
/* }*/
|
|
||||||
/*}*/
|
|
||||||
|
|
||||||
/*@media (prefers-color-scheme: dark) {*/
|
|
||||||
/* .logo {*/
|
|
||||||
/* filter: invert();*/
|
|
||||||
/* }*/
|
|
||||||
/*}*/
|
|
||||||
22
src/app/page.module.scss
Normal file
22
src/app/page.module.scss
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
.page {
|
||||||
|
h1.mainheading, h2.mainheading {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.mainheading {
|
||||||
|
font-size: medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.downloadlink {
|
||||||
|
background-color: var(--color-accent);
|
||||||
|
border: 1px solid var(--color-foreground);
|
||||||
|
border-radius: 0.5em;
|
||||||
|
color: var(--color-accent-inverse);
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
text-align: center;
|
||||||
|
text-decoration: none;
|
||||||
|
padding: 0.5em;
|
||||||
|
width: 11em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import styles from "./page.module.css";
|
import styles from "./page.module.scss";
|
||||||
import {useReducer} from "react";
|
import {useReducer} from "react";
|
||||||
import reduce from "./state/reducer.ts";
|
import reduce from "./state/reducer.ts";
|
||||||
import {INITIAL_STATE} from "./state/state.ts";
|
import {INITIAL_STATE} from "./state/state.ts";
|
||||||
|
|
@ -24,6 +24,12 @@ export default function Home() {
|
||||||
<>
|
<>
|
||||||
<h1>The Maze ({state.maze!.width}x{state.maze!.height}, Algorithm: {state.maze!.algorithm},
|
<h1>The Maze ({state.maze!.width}x{state.maze!.height}, Algorithm: {state.maze!.algorithm},
|
||||||
ID: {state.maze!.id})</h1>
|
ID: {state.maze!.id})</h1>
|
||||||
|
<a href={"https://manuel.friedli.info/labyrinth/create/pdffile?w="
|
||||||
|
+ state.maze!.width
|
||||||
|
+ "&h=" + state.maze!.height
|
||||||
|
+ "&id=" + state.maze!.id
|
||||||
|
+ "&a=" + state.maze!.algorithm}
|
||||||
|
className={styles.downloadlink}>Download as PDF file</a>
|
||||||
<input type={"checkbox"}
|
<input type={"checkbox"}
|
||||||
checked={state.showSolution}
|
checked={state.showSolution}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import React, {ChangeEventHandler, useState} from 'react';
|
|
||||||
|
|
||||||
export default function ValidatingInputBigIntField({
|
|
||||||
id,
|
|
||||||
label,
|
|
||||||
value = 0n,
|
|
||||||
constraints = undefined,
|
|
||||||
validatorFn = (value) => {
|
|
||||||
return {valid: true, value: BigInt(value)};
|
|
||||||
},
|
|
||||||
disabled = false,
|
|
||||||
onChange = () => {
|
|
||||||
}
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
id: string;
|
|
||||||
label: string;
|
|
||||||
value?: bigint;
|
|
||||||
constraints?: { min?: bigint; max?: bigint; };
|
|
||||||
validatorFn: ValidatorFunction<string, bigint>;
|
|
||||||
disabled: boolean;
|
|
||||||
onChange: (v: bigint) => void;
|
|
||||||
}) {
|
|
||||||
const [error, setError] = useState<string>();
|
|
||||||
|
|
||||||
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const validation = validatorFn(value);
|
|
||||||
if (!validation.valid) {
|
|
||||||
setError(validation.message);
|
|
||||||
} else {
|
|
||||||
setError(undefined);
|
|
||||||
}
|
|
||||||
if (validation.value !== undefined) {
|
|
||||||
onChange(validation.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<label htmlFor={id}>{label}: </label>
|
|
||||||
<input id={id}
|
|
||||||
type={"number"}
|
|
||||||
onChange={handleValueChange}
|
|
||||||
value={value?.toString() || ""}
|
|
||||||
min={constraints?.min?.toString()}
|
|
||||||
max={constraints?.max?.toString()}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
<span>{error}</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Validation<T> {
|
|
||||||
valid: boolean;
|
|
||||||
message?: string;
|
|
||||||
value?: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ValidatorFunction<I, T> = (v: I) => Validation<T>;
|
|
||||||
173
src/app/validating-input-field.tsx
Normal file
173
src/app/validating-input-field.tsx
Normal file
|
|
@ -0,0 +1,173 @@
|
||||||
|
import React, {ChangeEventHandler, useState} from 'react';
|
||||||
|
|
||||||
|
export function ValidatingInputBigIntField({
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
value = 0n,
|
||||||
|
constraints = undefined,
|
||||||
|
validatorFn = (value) => {
|
||||||
|
return {valid: true, value: BigInt(value)};
|
||||||
|
},
|
||||||
|
disabled = false,
|
||||||
|
onChange = () => {
|
||||||
|
}
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
value?: bigint;
|
||||||
|
constraints?: { min?: bigint; max?: bigint; };
|
||||||
|
validatorFn: ValidatorFunction<string, bigint>;
|
||||||
|
disabled: boolean;
|
||||||
|
onChange: (v: bigint) => void;
|
||||||
|
}) {
|
||||||
|
const [error, setError] = useState<string>();
|
||||||
|
|
||||||
|
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
const validation = validatorFn(value);
|
||||||
|
if (!validation.valid) {
|
||||||
|
setError(validation.message);
|
||||||
|
} else {
|
||||||
|
setError(undefined);
|
||||||
|
}
|
||||||
|
if (validation.value !== undefined) {
|
||||||
|
onChange(validation.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={id}>{label}: </label>
|
||||||
|
<input id={id}
|
||||||
|
type={"number"}
|
||||||
|
onChange={handleValueChange}
|
||||||
|
value={value?.toString() || ""}
|
||||||
|
min={constraints?.min?.toString()}
|
||||||
|
max={constraints?.max?.toString()}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<span>{error}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ValidatingInputNumberField({
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
value = 0,
|
||||||
|
constraints = undefined,
|
||||||
|
validatorFn = (value) => {
|
||||||
|
return {valid: true, value: Number(value)};
|
||||||
|
},
|
||||||
|
disabled = false,
|
||||||
|
onChange = () => {
|
||||||
|
}
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
value?: number;
|
||||||
|
constraints?: { min?: number; max?: number; };
|
||||||
|
validatorFn: ValidatorFunction<string, number>;
|
||||||
|
disabled: boolean;
|
||||||
|
onChange: (v: number) => void;
|
||||||
|
}) {
|
||||||
|
const [error, setError] = useState<string>();
|
||||||
|
|
||||||
|
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
const validation = validatorFn(value);
|
||||||
|
if (!validation.valid) {
|
||||||
|
setError(validation.message);
|
||||||
|
} else {
|
||||||
|
setError(undefined);
|
||||||
|
}
|
||||||
|
if (validation.value) {
|
||||||
|
onChange(validation.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={id}>{label}: </label>
|
||||||
|
<input id={id}
|
||||||
|
type={"number"}
|
||||||
|
onChange={handleValueChange}
|
||||||
|
value={value || ""}
|
||||||
|
min={constraints?.min}
|
||||||
|
max={constraints?.max}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<span>{error}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ValidatingInputRegExpField({
|
||||||
|
id,
|
||||||
|
label,
|
||||||
|
value = undefined,
|
||||||
|
constraints = undefined,
|
||||||
|
validatorFn = (value) => {
|
||||||
|
if (constraints === undefined) {
|
||||||
|
console.log("no constraints, returning VALID")
|
||||||
|
return {valid: true, value};
|
||||||
|
}
|
||||||
|
const allValid = constraints
|
||||||
|
.map(expr => expr.test(value))
|
||||||
|
.reduce((prev, curr) => prev && curr)
|
||||||
|
?? true;
|
||||||
|
console.log("valid?", allValid);
|
||||||
|
return {valid: allValid, value: allValid ? value : undefined};
|
||||||
|
},
|
||||||
|
disabled = false,
|
||||||
|
onChange = () => {
|
||||||
|
},
|
||||||
|
placeholder = ""
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
value?: string;
|
||||||
|
constraints?: RegExp[];
|
||||||
|
validatorFn?: ValidatorFunction<string, string>;
|
||||||
|
disabled: boolean;
|
||||||
|
onChange: (v: string) => void;
|
||||||
|
placeholder?: string;
|
||||||
|
}) {
|
||||||
|
const [error, setError] = useState<string>();
|
||||||
|
|
||||||
|
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
||||||
|
const value = e.target.value;
|
||||||
|
const validation = validatorFn(value);
|
||||||
|
if (!validation.valid) {
|
||||||
|
setError(validation.message);
|
||||||
|
} else {
|
||||||
|
setError(undefined);
|
||||||
|
}
|
||||||
|
if (validation.value !== undefined) {
|
||||||
|
console.log("setting value to:", validation.value);
|
||||||
|
onChange(validation.value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<label htmlFor={id}>{label}: </label>
|
||||||
|
<input id={id}
|
||||||
|
type={"text"}
|
||||||
|
placeholder={placeholder}
|
||||||
|
onChange={handleValueChange}
|
||||||
|
value={value?.toString() || ""}
|
||||||
|
disabled={disabled}
|
||||||
|
/>
|
||||||
|
<span>{error}</span>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Validation<T> {
|
||||||
|
valid: boolean;
|
||||||
|
message?: string;
|
||||||
|
value?: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ValidatorFunction<I, T> = (v: I) => Validation<T>;
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
import React, {ChangeEventHandler, useState} from 'react';
|
|
||||||
|
|
||||||
export default function ValidatingInputNumberField({
|
|
||||||
id,
|
|
||||||
label,
|
|
||||||
value = 0,
|
|
||||||
constraints = undefined,
|
|
||||||
validatorFn = (value) => {
|
|
||||||
return {valid: true, value: Number(value)};
|
|
||||||
},
|
|
||||||
disabled = false,
|
|
||||||
onChange = () => {
|
|
||||||
}
|
|
||||||
}:
|
|
||||||
{
|
|
||||||
id: string;
|
|
||||||
label: string;
|
|
||||||
value?: number;
|
|
||||||
constraints?: { min?: number; max?: number; };
|
|
||||||
validatorFn: ValidatorFunction<string, number>;
|
|
||||||
disabled: boolean;
|
|
||||||
onChange: (v: number) => void;
|
|
||||||
}) {
|
|
||||||
const [error, setError] = useState<string>();
|
|
||||||
|
|
||||||
const handleValueChange: ChangeEventHandler<HTMLInputElement> = (e) => {
|
|
||||||
const value = e.target.value;
|
|
||||||
const validation = validatorFn(value);
|
|
||||||
if (!validation.valid) {
|
|
||||||
setError(validation.message);
|
|
||||||
} else {
|
|
||||||
setError(undefined);
|
|
||||||
}
|
|
||||||
if (validation.value) {
|
|
||||||
onChange(validation.value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<label htmlFor={id}>{label}: </label>
|
|
||||||
<input id={id}
|
|
||||||
type={"number"}
|
|
||||||
onChange={handleValueChange}
|
|
||||||
value={value || ""}
|
|
||||||
min={constraints?.min}
|
|
||||||
max={constraints?.max}
|
|
||||||
disabled={disabled}
|
|
||||||
/>
|
|
||||||
<span>{error}</span>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Validation<T> {
|
|
||||||
valid: boolean;
|
|
||||||
message?: string;
|
|
||||||
value?: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ValidatorFunction<I, T> = (v: I) => Validation<T>;
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "ES2020",
|
"target": "ES2020",
|
||||||
"lib": ["dom", "dom.iterable", "esnext"],
|
"lib": [
|
||||||
|
"dom",
|
||||||
|
"dom.iterable",
|
||||||
|
"esnext"
|
||||||
|
],
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"allowImportingTsExtensions": true,
|
"allowImportingTsExtensions": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
|
|
@ -12,7 +16,7 @@
|
||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "preserve",
|
"jsx": "react-jsx",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"plugins": [
|
"plugins": [
|
||||||
{
|
{
|
||||||
|
|
@ -20,11 +24,18 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": [
|
||||||
|
"./src/*"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"next-env.d.ts",
|
||||||
|
"**/*.ts",
|
||||||
|
"**/*.tsx",
|
||||||
|
".next/types/**/*.ts",
|
||||||
|
".next/dev/types/**/*.ts"
|
||||||
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"a-maze-r/node_modules"
|
"a-maze-r/node_modules"
|
||||||
]
|
]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue