basic functionality!
This commit is contained in:
parent
f462002407
commit
b6d12c7e47
2 changed files with 167 additions and 40 deletions
89
src/App.css
89
src/App.css
|
@ -19,6 +19,15 @@
|
||||||
color: var(--color-foreground);
|
color: var(--color-foreground);
|
||||||
background-color: var(--color-background);
|
background-color: var(--color-background);
|
||||||
|
|
||||||
|
/* --group-blue: lch(78.8% 23.7 270.9);
|
||||||
|
--group-yellow: lch(74.83% 54.18 117.22);
|
||||||
|
--group-green: lch(89.36% 57.75 90.6);
|
||||||
|
--group-purple: lch(61.69% 41.01 319.57); */
|
||||||
|
--group-blue: lch(80% 23.7 270.9);
|
||||||
|
--group-yellow: lch(80% 54.18 117.22);
|
||||||
|
--group-green: lch(80% 57.75 90.6);
|
||||||
|
--group-purple: lch(80% 41.01 319.57);
|
||||||
|
|
||||||
font-synthesis: none;
|
font-synthesis: none;
|
||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
|
@ -34,6 +43,11 @@
|
||||||
--foreground-lightness: 90%;
|
--foreground-lightness: 90%;
|
||||||
--foreground-chroma: 0;
|
--foreground-chroma: 0;
|
||||||
--foreground-hue: 0;
|
--foreground-hue: 0;
|
||||||
|
|
||||||
|
--group-blue: lch(30% 23.7 270.9);
|
||||||
|
--group-yellow: lch(30% 54.18 117.22);
|
||||||
|
--group-green: lch(30% 57.75 90.6);
|
||||||
|
--group-purple: lch(30% 41.01 319.57);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,18 +66,21 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.puzzle {
|
.puzzle {
|
||||||
|
--unit: 0.5rem;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 1vmin;
|
gap: calc(1 * var(--unit));
|
||||||
font-size: 3vmin;
|
font-size: calc(3 * var(--unit));
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
|
width: calc((20 * 4 + 3) * var(--unit));
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.puzzle-row {
|
.puzzle-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 15vmin;
|
height: calc(15 * var(--unit));
|
||||||
gap: 1vmin;
|
gap: calc(1 * var(--unit));
|
||||||
}
|
}
|
||||||
.puzzle-item {
|
.puzzle-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -71,17 +88,44 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
user-select: none;
|
user-select: none;
|
||||||
width: 20vmin;
|
flex-basis: 0;
|
||||||
border-radius: 1vmin;
|
flex-grow: 1;
|
||||||
flex-grow: 0;
|
padding: 0;
|
||||||
|
border-radius: calc(1 * var(--unit));
|
||||||
background-color: var(--color-foreground-trace);
|
background-color: var(--color-foreground-trace);
|
||||||
}
|
}
|
||||||
.puzzle-item:hover, .puzzle-item:focus-visible {
|
|
||||||
box-shadow: 0 0 3vmin -1vmin inset var(--color-foreground);
|
|
||||||
}
|
|
||||||
.puzzle-item.is-selected {
|
.puzzle-item.is-selected {
|
||||||
background-color: var(--color-foreground-faint);
|
background-color: var(--color-foreground-faint);
|
||||||
outline: 0.33vmin solid var(--color-foreground);
|
outline: calc(0.33 * var(--unit)) solid var(--color-foreground);
|
||||||
|
}
|
||||||
|
.puzzle-group {
|
||||||
|
flex-grow: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: calc(1 * var(--unit));
|
||||||
|
|
||||||
|
&[data-level="0"] {
|
||||||
|
background-color: var(--group-blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-level="1"] {
|
||||||
|
background-color: var(--group-yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-level="2"] {
|
||||||
|
background-color: var(--group-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
&[data-level="3"] {
|
||||||
|
background-color: var(--group-purple);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.puzzle-actions {
|
||||||
|
display: flex;
|
||||||
|
margin-top: calc(1 * var(--unit));
|
||||||
|
gap: calc(1 * var(--unit));
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
|
@ -97,3 +141,26 @@ a:hover {
|
||||||
h1 {
|
h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
appearance: none;
|
||||||
|
overflow: visible;
|
||||||
|
background: var(--color-foreground-faint);
|
||||||
|
color: var(--color-foreground);
|
||||||
|
font-size: inherit;
|
||||||
|
border: none;
|
||||||
|
padding: 0.5em 1.5em;
|
||||||
|
border-radius: calc(1 * var(--unit, 0.5em));
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
button:focus-visible, button:hover {
|
||||||
|
box-shadow: 0 0 3em -1.5em inset var(--color-foreground)
|
||||||
|
}
|
||||||
|
button:active {
|
||||||
|
box-shadow: 0 0 3em -1.5em inset var(--color-foreground)
|
||||||
|
}
|
||||||
|
#submitButton {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
88
src/App.tsx
88
src/App.tsx
|
@ -3,6 +3,9 @@ import connections from "./assets/connections.json";
|
||||||
import "./App.css";
|
import "./App.css";
|
||||||
import { shuffleArray } from "./utils";
|
import { shuffleArray } from "./utils";
|
||||||
|
|
||||||
|
type Connection = typeof connections[number]
|
||||||
|
type Answer = Connection["answers"][number]
|
||||||
|
|
||||||
function fromIndex(index: number): [number, number] {
|
function fromIndex(index: number): [number, number] {
|
||||||
const col = index % 4;
|
const col = index % 4;
|
||||||
const row = (index - col) / 4;
|
const row = (index - col) / 4;
|
||||||
|
@ -11,52 +14,109 @@ function fromIndex(index: number): [number, number] {
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [puzzleIndex, setPuzzleIndex] = createSignal(0);
|
const [puzzleIndex, setPuzzleIndex] = createSignal(0);
|
||||||
|
// const [pinnedCount, setPinnedCount] = createSignal(0);
|
||||||
const [selected, setSelected] = createSignal<number[]>([]);
|
const [selected, setSelected] = createSignal<number[]>([]);
|
||||||
const puzzle = createMemo(() =>
|
const [solvedGroups, setSolvedGroups] = createSignal<Answer[]>([])
|
||||||
|
const [puzzle, setPuzzle] = createSignal(
|
||||||
shuffleArray(
|
shuffleArray(
|
||||||
Array(16)
|
Array(16)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map((_, i) => i)
|
.map((_, i) => i)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const answers = () => connections[puzzleIndex()].answers;
|
const answers = () => connections[puzzleIndex()].answers;
|
||||||
|
const getFromPuzzle = (index: number) => {
|
||||||
|
const puzzleIndex = puzzle()[index];
|
||||||
|
const [groupIndex, memberIndex] = fromIndex(puzzleIndex);
|
||||||
|
const group = answers()[groupIndex];
|
||||||
|
return {
|
||||||
|
group: group.group,
|
||||||
|
level: group.level,
|
||||||
|
answer: answers()[groupIndex].members[memberIndex],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
const handleGuess = () => {
|
||||||
|
const selectedAnswers = selected().map((x) => getFromPuzzle(x));
|
||||||
|
const { level } = selectedAnswers[0];
|
||||||
|
const isCorrect = selectedAnswers.every(
|
||||||
|
x => x.level === level
|
||||||
|
);
|
||||||
|
if (!isCorrect) {
|
||||||
|
// TODO you got it wrong
|
||||||
|
alert("wrong");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setPuzzle(puzzle().filter((x) => selected().every(s => puzzle()[s] !== x)));
|
||||||
|
setSelected([]);
|
||||||
|
const newSolvedGroup = answers().find((x) => x.level === level);
|
||||||
|
if (newSolvedGroup != null) {
|
||||||
|
setSolvedGroups([...solvedGroups(), newSolvedGroup])
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// const handlePinUnpin = () => {
|
||||||
|
// const sel = selected()
|
||||||
|
// if (sel.every(x => x <= pinnedCount())) {
|
||||||
|
// // we are unpinning
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// // we are pinning
|
||||||
|
// }
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main class="container">
|
<main class="container">
|
||||||
<h1>Slick Connections</h1>
|
<h1>Slick Connections</h1>
|
||||||
<div class="puzzle">
|
<div class="puzzle">
|
||||||
<For each={[0, 1, 2, 3]}>
|
<For each={solvedGroups()}>
|
||||||
|
{({group, level, members}) => (
|
||||||
|
<div class="puzzle-row">
|
||||||
|
<div class="puzzle-group" data-level={level}>
|
||||||
|
<strong>{group}</strong>
|
||||||
|
<div>{members.join(', ')}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
<For each={[0, 1, 2, 3].slice(0, puzzle().length / 4)}>
|
||||||
{(row) => (
|
{(row) => (
|
||||||
<div class="puzzle-row">
|
<div class="puzzle-row">
|
||||||
<For each={[0, 1, 2, 3]}>
|
{[0, 1, 2, 3].map((col) => {
|
||||||
{(col) => {
|
|
||||||
const index = 4 * row + col;
|
const index = 4 * row + col;
|
||||||
const puzzleIndex = puzzle()[index];
|
|
||||||
const [groupIndex, memberIndex] = fromIndex(puzzleIndex);
|
|
||||||
const answer = answers()[groupIndex].members[memberIndex];
|
|
||||||
return (
|
return (
|
||||||
<div
|
<button
|
||||||
classList={{
|
classList={{
|
||||||
"puzzle-item": true,
|
"puzzle-item": true,
|
||||||
"is-selected": selected().includes(index),
|
"is-selected": selected().includes(index),
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
type="button"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
setSelected(
|
setSelected(
|
||||||
selected().includes(index)
|
selected().includes(index)
|
||||||
? selected().filter(x => x !== index)
|
? selected().filter((x) => x !== index)
|
||||||
: [...selected(), index]
|
: [...selected(), index]
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{answer}
|
{getFromPuzzle(index).answer}
|
||||||
</div>
|
</button>
|
||||||
);
|
);
|
||||||
}}
|
})}
|
||||||
</For>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
|
<div class="puzzle-actions">
|
||||||
|
<button type="button" disabled={selected().length === 0}>
|
||||||
|
Pin
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
id="submitButton"
|
||||||
|
type="button"
|
||||||
|
on:click={handleGuess}
|
||||||
|
disabled={selected().length !== 4}
|
||||||
|
>
|
||||||
|
Submit
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue