Skip to content

Commit

Permalink
chore: extract components
Browse files Browse the repository at this point in the history
  • Loading branch information
zyishai committed Dec 18, 2024
1 parent 7ad1f44 commit 6a96e25
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 68 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from "react";
import { StartScreen } from "./components/StartScreen.js";
import { GameScreen } from "./components/GameScreen.js";
import { GameScreen } from "./components/GameScreen/index.js";
import { GameContext } from "./components/GameContext.js";
import { ScoreScreen } from "./components/ScoreScreen.js";
import { HelpScreen } from "./components/HelpScreen.js";
Expand Down
21 changes: 21 additions & 0 deletions src/components/GameScreen/Divider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React, { useState, useEffect } from "react";
import { Text, Box, DOMElement, measureElement } from "ink";

const dividerChar = "─";

export function Divider({ containerRef }: { containerRef: DOMElement | null }) {
const [width, setWidth] = useState(0);

useEffect(() => {
if (containerRef) {
const output = measureElement(containerRef);
setWidth(output.width);
}
}, [containerRef]);

return (
<Box>
<Text>{dividerChar.repeat(width)}</Text>
</Box>
);
}
File renamed without changes.
File renamed without changes.
46 changes: 46 additions & 0 deletions src/components/GameScreen/Typed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React, { useState, useEffect } from "react";
import { Text, type TextProps, useInput } from "ink";
import { GameContext } from "../GameContext.js";

export function Typed({
text,
enabled = true,
children,
...props
}: React.PropsWithChildren<{ text: string; enabled?: boolean } & TextProps>) {
const settings = GameContext.useSelector((snapshot) => snapshot.context.settings);
const [current, setCurrent] = useState(0);
const [finished, setFinished] = useState(false);
const shouldAnimate = !settings.disableAnimations && enabled;

useEffect(() => {
const id = setTimeout(() => {
if (shouldAnimate && current < text.length) {
setCurrent(current + 1);
} else {
clearTimeout(id);
setFinished(true);
}
}, 50);

return () => clearTimeout(id);
}, [text, shouldAnimate, current]);

useInput(
(input) => {
if (input === " ") {
setCurrent(text.length);
}
},
{
isActive: shouldAnimate && current < text.length,
},
);

return (
<>
<Text {...props}>{shouldAnimate ? text.slice(0, current) : text}</Text>
{shouldAnimate ? (finished ? children : null) : children}
</>
);
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React, { useEffect, useState } from "react";
import { Box, DOMElement, measureElement, Text, TextProps, useInput } from "ink";
import React, { useState, useDeferredValue } from "react";
import chalk from "chalk";
import { GameContext } from "./GameContext.js";
import { Box, DOMElement, Text, useInput } from "ink";
import { Alert, Badge, ConfirmInput } from "@inkjs/ui";
import { GameContext } from "../GameContext.js";
import { TextInput } from "./TextInput/index.js";
import { calculateCostForRepair, getAvailableStorage, getShipStatus } from "../store/utils.js";
import { goods, ports } from "../store/constants.js";

const dividerChar = "─";
import { Divider } from "./Divider.js";
import { Typed } from "./Typed.js";
import { calculateCostForRepair, getAvailableStorage, getShipStatus } from "../../store/utils.js";
import { goods, ports } from "../../store/constants.js";

export function GameScreen() {
const [ref, setRef] = useState<DOMElement | null>(null);
Expand Down Expand Up @@ -41,23 +41,6 @@ export function GameScreen() {
);
}

function Divider({ containerRef }: { containerRef: DOMElement | null }) {
const [width, setWidth] = useState(0);

useEffect(() => {
if (containerRef) {
const output = measureElement(containerRef);
setWidth(output.width);
}
}, [containerRef]);

return (
<Box>
<Text>{dividerChar.repeat(width)}</Text>
</Box>
);
}

function StatusBar() {
const context = GameContext.useSelector((snapshot) => snapshot.context);
const shipHealth = getShipStatus(context.ship.health);
Expand Down Expand Up @@ -470,46 +453,3 @@ function RetireAction() {
</Box>
);
}

function Typed({
text,
enabled = true,
children,
...props
}: React.PropsWithChildren<{ text: string; enabled?: boolean } & TextProps>) {
const settings = GameContext.useSelector((snapshot) => snapshot.context.settings);
const [current, setCurrent] = useState(0);
const [finished, setFinished] = useState(false);
const shouldAnimate = !settings.disableAnimations && enabled;

useEffect(() => {
const id = setTimeout(() => {
if (shouldAnimate && current < text.length) {
setCurrent(current + 1);
} else {
clearTimeout(id);
setFinished(true);
}
}, 50);

return () => clearTimeout(id);
}, [text, shouldAnimate, current]);

useInput(
(input) => {
if (input === " ") {
setCurrent(text.length);
}
},
{
isActive: shouldAnimate && current < text.length,
},
);

return (
<>
<Text {...props}>{shouldAnimate ? text.slice(0, current) : text}</Text>
{shouldAnimate ? (finished ? children : null) : children}
</>
);
}

0 comments on commit 6a96e25

Please sign in to comment.