story for ShipItem

This commit is contained in:
Yanick Champoux 2023-03-20 11:59:50 -04:00
parent 0c0351cbb3
commit b18017d753
37 changed files with 209 additions and 147 deletions

6
histoire.config.js Normal file
View File

@ -0,0 +1,6 @@
import { defineConfig } from "histoire";
import { HstSvelte } from "@histoire/plugin-svelte";
export default defineConfig({
plugins: [HstSvelte()],
});

View File

@ -11,6 +11,7 @@
"format": "prettier --write ." "format": "prettier --write ."
}, },
"devDependencies": { "devDependencies": {
"@histoire/plugin-svelte": "^0.15.9",
"@sveltejs/adapter-static": "^1.0.0-next.28", "@sveltejs/adapter-static": "^1.0.0-next.28",
"@sveltejs/kit": "^1.10.0", "@sveltejs/kit": "^1.10.0",
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.38", "@sveltejs/vite-plugin-svelte": "^1.0.0-next.38",
@ -28,11 +29,13 @@
"vitest-svelte-kit": "^0.0.6" "vitest-svelte-kit": "^0.0.6"
}, },
"dependencies": { "dependencies": {
"@picocss/pico": "^1.5.7",
"@reduxjs/toolkit": "^1.9.3", "@reduxjs/toolkit": "^1.9.3",
"@sveltejs/adapter-node": "^1.0.0-next.0", "@sveltejs/adapter-node": "^1.0.0-next.0",
"@yanick/updeep-remeda": "^2.1.0", "@yanick/updeep-remeda": "^2.1.0",
"chota": "^0.8.0", "chota": "^0.8.0",
"effector": "^22.5.2", "effector": "^22.5.2",
"histoire": "^0.15.9",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"redux": "^4.1.2", "redux": "^4.1.2",
"remeda": "^1.1.0", "remeda": "^1.1.0",

View File

@ -0,0 +1,9 @@
<Hst.Story title="CostMass">
<CostMass mass={12} cost={21} />
</Hst.Story>
<script>
export let Hst;
import CostMass from "./index.svelte";
</script>

View File

@ -2,7 +2,7 @@
<div class="cost">{cost}</div> <div class="cost">{cost}</div>
<script> <script>
import { base } from '$app/paths'; import { base } from "$app/paths";
export let mass; export let mass;
export let cost; export let cost;
</script> </script>

View File

@ -27,8 +27,8 @@
$: if (shipTypes.length > 0 && !shipTypes.includes(shipType)) $: if (shipTypes.length > 0 && !shipTypes.includes(shipType))
shipType = shipTypes[0]; shipType = shipTypes[0];
$: ship.dispatch.setShipType(shipType); $: ship.dispatch(ship.actions.setShipType(shipType));
$: ship.dispatch.setShipClass(shipClass); $: ship.dispatch(ship.actions.setShipClass(shipClass));
</script> </script>
<style> <style>

View File

@ -1,7 +1,14 @@
<ShipItem {...reqs}> <ShipItem {...reqs}>
<div> <div>
<Field label="thrust rating"> <Field label="thrust rating">
<input class="short" type="number" bind:value={rating} min="0" max="20" step="1" /> <input
class="short"
type="number"
bind:value={rating}
min="0"
max="20"
step="1"
/>
</Field> </Field>
<label><input type="checkbox" bind:checked={advanced} /> advanced</label> <label><input type="checkbox" bind:checked={advanced} /> advanced</label>
@ -19,7 +26,7 @@
const ship = getContext("ship"); const ship = getContext("ship");
$: ship.dispatch.setDrive({ rating, advanced }); $: ship.dispatch(ship.actions.setDrive({ rating, advanced }));
</script> </script>
<style> <style>

View File

@ -20,7 +20,7 @@
</div> </div>
<script> <script>
import { base } from '$app/paths'; import { base } from "$app/paths";
import { getContext } from "svelte"; import { getContext } from "svelte";
import Field from "$lib/components/Field/index.svelte"; import Field from "$lib/components/Field/index.svelte";
@ -33,7 +33,7 @@
$: massUnused = mass - usedMass; $: massUnused = mass - usedMass;
$: withinBudget = massUnused >= 0; $: withinBudget = massUnused >= 0;
$: ship.dispatch.setShipMass(mass); $: ship.dispatch(ship.actions.setShipMass(mass));
/* const change_tonnage = ({ target: { value } }) => */ /* const change_tonnage = ({ target: { value } }) => */
/* ship.dispatch(ship.actions.set_ship_mass(parseInt(value))); */ /* ship.dispatch(ship.actions.set_ship_mass(parseInt(value))); */

View File

@ -0,0 +1,14 @@
<Hst.Story>
<ShipItem {mass} {cost}>Thingy</ShipItem>
<svelte:fragment slot="controls">
<Hst.Number bind:value={mass} title="Mass" />
<Hst.Number bind:value={cost} title="Cost" />
</svelte:fragment>
</Hst.Story>
<script>
export let Hst;
import ShipItem from "./ShipItem.svelte";
let mass = 1;
let cost = 3;
</script>

View File

@ -2,14 +2,15 @@
<div><slot /></div> <div><slot /></div>
<div class="reqs"> <div class="reqs">
<div class="mass" bind:this={mass_el}>{mass} <img src="{base}/mass.svg" <div class="mass" bind:this={mass_el}>
alt="mass"/></div> {mass} <img src="{base}/mass.svg" alt="mass" />
</div>
<div class="cost" bind:this={cost_el}>{cost}</div> <div class="cost" bind:this={cost_el}>{cost}</div>
</div> </div>
</div> </div>
<script> <script>
import { base } from '$app/paths'; import { base } from "$app/paths";
import { tick } from "svelte"; import { tick } from "svelte";
export let mass; export let mass;

View File

@ -26,6 +26,8 @@ const engine = createSlice({
}, },
}); });
export const { actions, reducer } = engine;
export function calcDriveReqs( export function calcDriveReqs(
shipMass: number, shipMass: number,
rating: number, rating: number,

View File

@ -1,28 +1,32 @@
import { Updux } from "updux"; import { createSlice, type PayloadAction } from "@reduxjs/toolkit";
import u from "updeep"; import * as carrier from "./carrier.js";
import carrier from "./carrier.js"; const initialState = {
const dux = new Updux({
actions: {
setShipType: null,
setShipClass: null,
setCarrierBays: carrier.actions.setCarrierBays,
},
initial: {
shipType: "", shipType: "",
shipClass: "", shipClass: "",
isCarrier: false, isCarrier: false,
mass: 10, mass: 10,
};
const identification = createSlice({
name: "identification",
initialState,
reducers: {
setShipType(state, action: PayloadAction<string>) {
state.shipType = action.payload;
},
setShipClass(state, action: PayloadAction<string>) {
state.shipClass = action.payload;
},
},
extraReducers(builder) {
builder.addCase(
carrier.actions.setCarrierBays,
(state, action: PayloadAction<number>) => {
state.isCarrier = action.payload > 0;
}
);
}, },
}); });
dux.setMutation("setShipType", (shipType) => u({ shipType })); export const { actions, reducer } = identification;
dux.setMutation("setShipClass", (shipClass) => u({ shipClass }));
dux.setMutation("setCarrierBays", (bays) =>
u({
isCarrier: bays > 0,
})
);
export default dux;

View File

@ -5,6 +5,9 @@ import * as propulsion from "./propulsion";
import * as structure from "./structure"; import * as structure from "./structure";
import * as weaponry from "./weaponry/index.js"; import * as weaponry from "./weaponry/index.js";
import * as carrier from "./carrier"; import * as carrier from "./carrier";
import * as identification from "./identification.js";
import * as shipReqs from "./shipReqs";
import * as engine from "./engine";
const shipSlice = createSlice({ const shipSlice = createSlice({
name: "ship", name: "ship",
@ -14,10 +17,12 @@ const shipSlice = createSlice({
builder.addMatcher( builder.addMatcher(
() => true, () => true,
combineReducers({ combineReducers({
identification: identification.reducer,
propulsion: propulsion.reducer, propulsion: propulsion.reducer,
structure: structure.reducer, structure: structure.reducer,
weaponry: weaponry.reducer, weaponry: weaponry.reducer,
carrier: carrier.reducer, carrier: carrier.reducer,
engine: engine.reducer,
}) })
); );
}, },
@ -29,11 +34,16 @@ export function createStore() {
}); });
} }
export const actions = shipSlice.actions; export const actions = {
...shipReqs.actions,
...shipSlice.actions,
...identification.actions,
...engine.actions,
...propulsion.actions,
};
/** /**
import * as propulsion from "./propulsion/index.js"; import * as propulsion from "./propulsion/index.js";
import * as identification from "./identification.js";
import { calculateDriveReqs } from "./propulsion/drive.js"; import { calculateDriveReqs } from "./propulsion/drive.js";
import { ftlReqsReaction } from "./propulsion/ftl.js"; import { ftlReqsReaction } from "./propulsion/ftl.js";
import * as structure from "./structure/index.js"; import * as structure from "./structure/index.js";

View File

@ -11,3 +11,8 @@ export const initialState = {
drive: drive.initialState, drive: drive.initialState,
ftl: ftl.initialState, ftl: ftl.initialState,
}; };
export const actions = {
...drive.actions,
...ftl.actions,
};

View File

@ -22,3 +22,5 @@ const shipReqs = createSlice({
}, },
}, },
}); });
export const { actions, reducer } = shipReqs;

View File

@ -2,7 +2,7 @@ import { browser, dev } from "$app/environment";
import { readable, get, derived } from "svelte/store"; import { readable, get, derived } from "svelte/store";
import { compose, applyMiddleware } from "redux"; import { compose, applyMiddleware } from "redux";
import shipDux from "../shipDux/index"; import { createStore, actions } from "../shipDux/index";
import { initial } from "lodash"; import { initial } from "lodash";
let composeEnhancers = compose; let composeEnhancers = compose;
@ -18,9 +18,7 @@ export default (initialState = undefined) => {
if (i) initialState = JSON.parse(localStorage.getItem("ship")); if (i) initialState = JSON.parse(localStorage.getItem("ship"));
} }
const duxStore = shipDux.createStore(initialState, (mw) => const duxStore = createStore();
composeEnhancers(applyMiddleware(mw))
);
let previous; let previous;
const state = readable(duxStore.getState(), (set) => { const state = readable(duxStore.getState(), (set) => {
@ -35,6 +33,7 @@ export default (initialState = undefined) => {
return { return {
dispatch: duxStore.dispatch, dispatch: duxStore.dispatch,
state, state,
actions,
shipMass: derived(state, (state) => state.reqs.mass), shipMass: derived(state, (state) => state.reqs.mass),
}; };
}; };

View File

@ -4,7 +4,7 @@ import { sveltekit } from "@sveltejs/kit/vite";
/** @type {import('vite').UserConfig} */ /** @type {import('vite').UserConfig} */
const config = { const config = {
plugins: [sveltekit()], plugins: [sveltekit()],
publicDir: "./static",
ssr: {}, ssr: {},
optimizeDeps: {}, optimizeDeps: {},
}; };