diff --git a/package-lock.json b/package-lock.json
index b522ca5..d6991b8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "hacks-of-mistria",
- "version": "0.2.1",
+ "version": "0.4.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "hacks-of-mistria",
- "version": "0.2.1",
+ "version": "0.4.0",
"hasInstallScript": true,
"dependencies": {
"@chakra-ui/react": "^3.0.2",
@@ -18,7 +18,8 @@
"next-themes": "^0.4.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-icons": "^5.3.0"
+ "react-icons": "^5.3.0",
+ "zustand": "^5.0.1"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.3.1",
@@ -6459,6 +6460,35 @@
"engines": {
"node": ">= 10"
}
+ },
+ "node_modules/zustand": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.1.tgz",
+ "integrity": "sha512-pRET7Lao2z+n5R/HduXMio35TncTlSW68WsYBq2Lg1ASspsNGjpwLAsij3RpouyV6+kHMwwwzP0bZPD70/Jx/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.20.0"
+ },
+ "peerDependencies": {
+ "@types/react": ">=18.0.0",
+ "immer": ">=9.0.6",
+ "react": ">=18.0.0",
+ "use-sync-external-store": ">=1.2.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "use-sync-external-store": {
+ "optional": true
+ }
+ }
}
}
}
diff --git a/package.json b/package.json
index a15fb61..8b15e1d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "hacks-of-mistria",
- "version": "0.3.0",
+ "version": "0.4.0",
"description": "A tool to edit your save files in Fields of Mistria",
"main": "./out/main/index.js",
"author": "arkatsy, dwlim12",
@@ -22,7 +22,8 @@
"next-themes": "^0.4.3",
"react": "^18.3.1",
"react-dom": "^18.3.1",
- "react-icons": "^5.3.0"
+ "react-icons": "^5.3.0",
+ "zustand": "^5.0.1"
},
"devDependencies": {
"@vitejs/plugin-react": "^4.3.1",
diff --git a/src/renderer/src/app.jsx b/src/renderer/src/app.jsx
index 817c65b..9879ce6 100644
--- a/src/renderer/src/app.jsx
+++ b/src/renderer/src/app.jsx
@@ -1,9 +1,9 @@
-import { useState } from "react"
import { Image, Box } from "@chakra-ui/react"
import SaveSelection from "@components/save-selection"
import SaveEditing from "@components/save-editing"
-import fomClouds from "@assets/fom-clouds.png"
import fomLogo from "@assets/fom-logo.webp"
+import background from "@assets/fom-bg1.png"
+import { useStore } from "./store"
function Layout({ children }) {
return (
@@ -16,36 +16,28 @@ function Layout({ children }) {
alignItems="center"
pos="relative"
>
+
+ {children}
-
- {children}
)
}
export function App() {
- const [editingSaveId, setEditingSaveId] = useState(null)
+ const { editingSaveId } = useStore()
- const goToEditing = (saveId) => setEditingSaveId(saveId)
- const goToSelection = () => setEditingSaveId(null)
-
- return (
-
- {editingSaveId ? (
-
- ) : (
-
- )}
-
- )
+ return {editingSaveId ? : }
}
diff --git a/src/renderer/src/components/loading.jsx b/src/renderer/src/components/loading.jsx
index 09d0f16..7510d0c 100644
--- a/src/renderer/src/components/loading.jsx
+++ b/src/renderer/src/components/loading.jsx
@@ -1,10 +1,13 @@
-import { Center, Flex, Text, Spinner } from "@chakra-ui/react"
+import { Center, Flex, Text, Spinner, VStack } from "@chakra-ui/react"
-export default function Loading({ text }) {
+export default function Loading({ text = "", extra = "" }) {
return (
- {text}
+
+ {text}
+ {extra}
+
diff --git a/src/renderer/src/components/number-input.jsx b/src/renderer/src/components/number-input.jsx
index 34b2564..486f0b3 100644
--- a/src/renderer/src/components/number-input.jsx
+++ b/src/renderer/src/components/number-input.jsx
@@ -11,8 +11,9 @@ export default function NumberInput({ value, onValueChange, step, min, label, he
value={+value || 0}
onValueChange={(e) => onValueChange(+e.value)}
w="full"
+ bg="orange.900/10"
>
-
+
diff --git a/src/renderer/src/components/save-card.jsx b/src/renderer/src/components/save-card.jsx
index d02807b..eafb5e3 100644
--- a/src/renderer/src/components/save-card.jsx
+++ b/src/renderer/src/components/save-card.jsx
@@ -49,7 +49,7 @@ const weatherIcons = [
}
]
-function SaveCard({ save, onClick }) {
+export default function SaveCard({ save, onClick }) {
const { header, autosave, id } = save
const data = {
@@ -62,15 +62,46 @@ function SaveCard({ save, onClick }) {
onClick && onClick(id)
}
+ const season = displayCalendarTime(header.calendar_time).split(" ")[2].toLowerCase()
+
+ const styles = {
+ background: {
+ spring: "rose.950",
+ summer: "green.950",
+ fall: "yellow.950",
+ winter: "teal.900"
+ },
+ foreground: {
+ spring: "rose.50",
+ summer: "green.100/90",
+ fall: "yellow.100/75",
+ winter: "teal.50"
+ },
+ border: {
+ spring: "rose.600",
+ summer: "green.600",
+ fall: "yellow.600",
+ winter: "teal.600"
+ }
+ }
+
+ const isSpring = season === "spring"
+ const isSummer = season === "summer"
+ const isFall = season === "fall"
+ const isWinter = season === "winter"
+
return (
@@ -123,5 +154,3 @@ function SaveCard({ save, onClick }) {
)
}
-
-export default memo(SaveCard)
diff --git a/src/renderer/src/components/save-editing.jsx b/src/renderer/src/components/save-editing.jsx
index a3b5205..c8f189f 100644
--- a/src/renderer/src/components/save-editing.jsx
+++ b/src/renderer/src/components/save-editing.jsx
@@ -28,8 +28,12 @@ import { seasonsList, getCalendarTime, PronounsList, formatPronouns } from "@uti
import Loading from "./loading"
import { useSaveData } from "../queries"
import { useSaveDataMutation } from "../mutations"
+import { useStore } from "../store"
+import { LuArrowLeft } from "react-icons/lu"
+
+export default function SaveEditing() {
+ const { goToSelection: onBack, editingSaveId: saveId } = useStore()
-export default function SaveEditing({ saveId, onBack }) {
const { data: saveData, isError: isErrorData } = useSaveData(saveId)
const {
mutate: updateSave,
@@ -100,15 +104,15 @@ export default function SaveEditing({ saveId, onBack }) {
return (
-
- Reload
{visibleSaves.length === 0 ? (
@@ -99,7 +101,7 @@ export default function SaveSelection({ onSaveSelected }) {
{visibleSaves.map((save) => (
))}
-
+
)}
-
+
-
-
-
-
-
+
)
diff --git a/src/renderer/src/components/select-input.jsx b/src/renderer/src/components/select-input.jsx
index 3ea8cf0..70ced86 100644
--- a/src/renderer/src/components/select-input.jsx
+++ b/src/renderer/src/components/select-input.jsx
@@ -9,14 +9,19 @@ import {
export default function SelectInput({ collection, textLabel, currentValue, onValueChange }) {
return (
- onValueChange(e.value[0])}>
+ onValueChange(e.value[0])}>
{textLabel}
-
+
-
+
{collection.items.map((item) => (
-
+
{item.label}
))}
diff --git a/src/renderer/src/components/text-input.jsx b/src/renderer/src/components/text-input.jsx
index fdb495f..db3dd9f 100644
--- a/src/renderer/src/components/text-input.jsx
+++ b/src/renderer/src/components/text-input.jsx
@@ -5,7 +5,7 @@ import { Input } from "@chakra-ui/react"
export default function TextInput({ currentValue, textLabel, onChange, icon }) {
return (
-
+
onChange(e.target.value)} />
diff --git a/src/renderer/src/components/ui/color-picker.jsx b/src/renderer/src/components/ui/color-picker.jsx
new file mode 100644
index 0000000..b245f06
--- /dev/null
+++ b/src/renderer/src/components/ui/color-picker.jsx
@@ -0,0 +1,158 @@
+import {
+ ColorPicker as ChakraColorPicker,
+ For,
+ IconButton,
+ Portal,
+ Span,
+ Stack,
+ Text,
+ VStack
+} from "@chakra-ui/react"
+import { forwardRef } from "react"
+import { LuCheck, LuPipette } from "react-icons/lu"
+
+export const ColorPickerTrigger = forwardRef(function ColorPickerTrigger(props, ref) {
+ const { fitContent, ...rest } = props
+ return (
+
+ {props.children || }
+
+ )
+})
+
+export const ColorPickerInput = forwardRef(function ColorHexInput(props, ref) {
+ return
+})
+
+export const ColorPickerContent = forwardRef(function ColorPickerContent(props, ref) {
+ const { portalled = true, portalRef, ...rest } = props
+ return (
+
+
+
+
+
+ )
+})
+
+export const ColorPickerInlineContent = forwardRef(function ColorPickerInlineContent(props, ref) {
+ return (
+
+ )
+})
+
+export const ColorPickerSliders = forwardRef(function ColorPickerSliders(props, ref) {
+ return (
+
+
+
+
+ )
+})
+
+export const ColorPickerArea = forwardRef(function ColorPickerArea(props, ref) {
+ return (
+
+
+
+
+ )
+})
+
+export const ColorPickerEyeDropper = forwardRef(function ColorPickerEyeDropper(props, ref) {
+ return (
+
+
+
+
+
+ )
+})
+
+export const ColorPickerChannelSlider = forwardRef(function ColorPickerSlider(props, ref) {
+ return (
+
+
+
+
+
+ )
+})
+
+export const ColorPickerSwatchTrigger = forwardRef(function ColorPickerSwatchTrigger(props, ref) {
+ const { swatchSize, children, ...rest } = props
+ return (
+
+ {children || (
+
+
+
+
+
+ )}
+
+ )
+})
+
+export const ColorPickerRoot = forwardRef(function ColorPickerRoot(props, ref) {
+ return (
+
+ {props.children}
+
+
+ )
+})
+
+const formatMap = {
+ rgba: ["red", "green", "blue", "alpha"],
+ hsla: ["hue", "saturation", "lightness", "alpha"],
+ hsba: ["hue", "saturation", "brightness", "alpha"],
+ hexa: ["hex", "alpha"]
+}
+
+export const ColorPickerChannelInputs = forwardRef(function ColorPickerChannelInputs(props, ref) {
+ const channels = formatMap[props.format]
+ return (
+
+ {channels.map((channel) => (
+
+
+
+ {channel.charAt(0).toUpperCase()}
+
+
+ ))}
+
+ )
+})
+
+export const ColorPickerChannelSliders = forwardRef(function ColorPickerChannelSliders(props, ref) {
+ const channels = formatMap[props.format]
+ return (
+
+
+ {(channel) => (
+
+
+ {channel}
+
+
+
+ )}
+
+
+ )
+})
+
+export const ColorPickerLabel = ChakraColorPicker.Label
+export const ColorPickerControl = ChakraColorPicker.Control
+export const ColorPickerValueText = ChakraColorPicker.ValueText
+export const ColorPickerValueSwatch = ChakraColorPicker.ValueSwatch
+export const ColorPickerChannelInput = ChakraColorPicker.ChannelInput
+export const ColorPickerSwatchGroup = ChakraColorPicker.SwatchGroup
diff --git a/src/renderer/src/components/ui/number-input.jsx b/src/renderer/src/components/ui/number-input.jsx
index 1c8afe4..d569465 100644
--- a/src/renderer/src/components/ui/number-input.jsx
+++ b/src/renderer/src/components/ui/number-input.jsx
@@ -7,8 +7,16 @@ export const NumberInputRoot = forwardRef(function NumberInput(props, ref) {
{children}
-
-
+
+
)
diff --git a/src/renderer/src/components/ui/provider.jsx b/src/renderer/src/components/ui/provider.jsx
index 5c18de2..7f90bf1 100644
--- a/src/renderer/src/components/ui/provider.jsx
+++ b/src/renderer/src/components/ui/provider.jsx
@@ -1,10 +1,13 @@
-import { ChakraProvider, defaultSystem } from "@chakra-ui/react"
+import { ChakraProvider, Theme } from "@chakra-ui/react"
import { ColorModeProvider } from "./color-mode"
+import { system } from "../../theme"
export function Provider(props) {
return (
-
-
+
+
+
+
)
}
diff --git a/src/renderer/src/components/unpacking-measurement.jsx b/src/renderer/src/components/unpacking-measurement.jsx
index dc512f4..8728696 100644
--- a/src/renderer/src/components/unpacking-measurement.jsx
+++ b/src/renderer/src/components/unpacking-measurement.jsx
@@ -1,5 +1,5 @@
-import { Box, HStack, Stack, Text } from "@chakra-ui/react"
import { useState, useEffect } from "react"
+import { Stack, Text, HStack, Box } from "@chakra-ui/react"
import InputNumber from "@components/number-input"
import { Button } from "@components/ui/button"
@@ -27,8 +27,10 @@ export default function UnpackingMeasurement() {
}
return (
-
- Measure Unpacking Time
+
+
+ Measure Unpacking Time
+
-
+
Test!
- {report && {report}}
+ {report && (
+
+ {report}
+
+ )}
)
}
diff --git a/src/renderer/src/main.jsx b/src/renderer/src/main.jsx
index 8744f38..e32f54f 100644
--- a/src/renderer/src/main.jsx
+++ b/src/renderer/src/main.jsx
@@ -1,4 +1,3 @@
-import "./styles/globals.css"
import { StrictMode } from "react"
import { createRoot } from "react-dom/client"
import { App } from "./app"
@@ -11,7 +10,7 @@ const queryClient = new QueryClient()
createRoot(document.getElementById("root")).render(
-
+
diff --git a/src/renderer/src/store.js b/src/renderer/src/store.js
new file mode 100644
index 0000000..c9fc1d1
--- /dev/null
+++ b/src/renderer/src/store.js
@@ -0,0 +1,7 @@
+import { create } from "zustand";
+
+export const useStore = create((set) => ({
+ editingSaveId: null,
+ setEditingSaveId: (saveId) => set({ editingSaveId: saveId }),
+ goToSelection: () => set({ editingSaveId: null })
+}))
diff --git a/src/renderer/src/styles/globals.css b/src/renderer/src/styles/globals.css
deleted file mode 100644
index fcc0b4a..0000000
--- a/src/renderer/src/styles/globals.css
+++ /dev/null
@@ -1,22 +0,0 @@
-::selection {
- background-color: #f4e1d2;
- color: #000;
-}
-
-*,
-*::before,
-*::after {
- font-family: cursive, system-ui;
-}
-
-::-webkit-scrollbar {
- display: none;
-}
-
-::-webkit-scrollbar-button {
- display: none;
-}
-
-body {
- -ms-overflow-style: none;
-}
diff --git a/src/renderer/src/theme.js b/src/renderer/src/theme.js
new file mode 100644
index 0000000..9e20400
--- /dev/null
+++ b/src/renderer/src/theme.js
@@ -0,0 +1,120 @@
+import { defineConfig, defaultConfig, createSystem } from "@chakra-ui/react"
+
+const config = defineConfig({
+ cssVarsRoot: ":where(html)",
+ globalCss: {
+ "*::selection": {
+ bg: "rose.500",
+ color: "white"
+ },
+ "*::-webkit-scrollbar": {
+ display: "none"
+ },
+ "*::-webkit-scrollbar-button": {
+ display: "none"
+ },
+ "*, *::before, *::after": {
+ fontFamily: "cursive, system-ui, sans-serif"
+ }
+ },
+ theme: {
+ tokens: {
+ colors: {
+ indigo: {
+ 50: { value: "#eef2ff" },
+ 100: { value: "#e0e7ff" },
+ 200: { value: "#c7d2fe" },
+ 300: { value: "#a5b4fc" },
+ 400: { value: "#818cf8" },
+ 500: { value: "#6366f1" },
+ 600: { value: "#4f46e5" },
+ 700: { value: "#4338ca" },
+ 800: { value: "#3730a3" },
+ 900: { value: "#312e81" },
+ 950: { value: "#1e1b4b" }
+ },
+ violet: {
+ 50: { value: "#f5f3ff" },
+ 100: { value: "#ede9fe" },
+ 200: { value: "#ddd6fe" },
+ 300: { value: "#c4b5fd" },
+ 400: { value: "#a78bfa" },
+ 500: { value: "#8b5cf6" },
+ 600: { value: "#7c3aed" },
+ 700: { value: "#6d28d9" },
+ 800: { value: "#5b21b6" },
+ 900: { value: "#4c1d95" },
+ 950: { value: "#2e1065" }
+ },
+ rose: {
+ 50: { value: "#fff1f2" },
+ 100: { value: "#ffe4e6" },
+ 200: { value: "#fecdd3" },
+ 300: { value: "#fda4af" },
+ 400: { value: "#fb7185" },
+ 500: { value: "#f43f5e" },
+ 600: { value: "#e11d48" },
+ 700: { value: "#be123c" },
+ 800: { value: "#9f1239" },
+ 900: { value: "#881337" },
+ 950: { value: "#4c0519" }
+ },
+ slate: {
+ 50: { value: "#f8fafc" },
+ 100: { value: "#f1f5f9" },
+ 200: { value: "#e2e8f0" },
+ 300: { value: "#cbd5e1" },
+ 400: { value: "#94a3b8" },
+ 500: { vaue: "#64748b" },
+ 600: { value: "#475569" },
+ 700: { value: "#334155" },
+ 800: { value: "#1e293b" },
+ 900: { value: "#0f172a" },
+ 950: { value: "#020617" }
+ }
+ }
+ },
+ semanticTokens: {
+ colors: {
+ rose: {
+ solid: { value: "{colors.rose.500}" },
+ contrast: { value: "{colors.rose.100}" },
+ fg: { value: "{colors.rose.700}" },
+ muted: { value: "{colors.rose.100}" },
+ subtle: { value: "{colors.rose.200}" },
+ emphasized: { value: "{colors.rose.300}" },
+ focusRing: { value: "{colors.rose.500}" }
+ },
+ violet: {
+ solid: { value: "{colors.violet.500}" },
+ contrast: { value: "{colors.violet.100}" },
+ fg: { value: "{colors.violet.700}" },
+ muted: { value: "{colors.violet.100}" },
+ subtle: { value: "{colors.violet.200}" },
+ emphasized: { value: "{colors.violet.300}" },
+ focusRing: { value: "{colors.violet.500}" }
+ },
+ indigo: {
+ solid: { value: "{colors.indigo.500}" },
+ contrast: { value: "{colors.indigo.100}" },
+ fg: { value: "{colors.indigo.700}" },
+ muted: { value: "{colors.indigo.100}" },
+ subtle: { value: "{colors.indigo.200}" },
+ emphasized: { value: "{colors.indigo.300}" },
+ focusRing: { value: "{colors.indigo.500}" }
+ },
+ slate: {
+ solid: { value: "{colors.slate.500}" },
+ contrast: { value: "{colors.slate.100}" },
+ fg: { value: "{colors.slate.700}" },
+ muted: { value: "{colors.slate.100}" },
+ subtle: { value: "{colors.slate.200}" },
+ emphasized: { value: "{colors.slate.300}" },
+ focusRing: { value: "{colors.slate.500}" }
+ }
+ }
+ }
+ }
+})
+
+export const system = createSystem(config, defaultConfig)