Merge branch 'move-to-beer'
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 25 KiB |
@ -1,22 +1,35 @@
|
||||
<div class="field">
|
||||
{#if label}
|
||||
<label>{label}</label>
|
||||
{/if}
|
||||
<div class="field label small" class:suffix>
|
||||
<slot>
|
||||
<input type="text" {placeholder} bind:value on:change />
|
||||
<input id={formId} type="text" bind:value on:change />
|
||||
</slot>
|
||||
{#if label}
|
||||
<label for={formId} class:active>{label}</label>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
import { getContext } from "svelte";
|
||||
|
||||
export let label = "";
|
||||
export let value = "";
|
||||
export let value = true;
|
||||
export let placeholder = label;
|
||||
|
||||
export let suffix = false;
|
||||
export let activeLabel = undefined;
|
||||
export let idPrefix = "formId";
|
||||
|
||||
$: active = typeof activeLabel === "boolean" ? activeLabel : value;
|
||||
|
||||
const genUid = getContext("genUid") ?? (() => "genUid missing");
|
||||
|
||||
const formId = genUid(idPrefix);
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
font-family: var(--main-font-family);
|
||||
}
|
||||
/*
|
||||
div > :global(*) {
|
||||
margin-left: 1em;
|
||||
}
|
||||
@ -29,4 +42,8 @@
|
||||
font-family: Dosis;
|
||||
color: var(--indigo-dye);
|
||||
}
|
||||
*/
|
||||
.field {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
|
@ -15,9 +15,12 @@
|
||||
grid-column: 1 / span 3 !important;
|
||||
align-items: baseline;
|
||||
gap: 1em;
|
||||
margin-bottom: 1em;
|
||||
background-color: var(--primary-background);
|
||||
}
|
||||
h2 {
|
||||
font-weight: bold;
|
||||
font-size: var(--font-scale-12);
|
||||
}
|
||||
hr {
|
||||
flex: 1;
|
||||
|
@ -1,9 +1,7 @@
|
||||
<main>
|
||||
<Identification {...identification} />
|
||||
<Propulsion {...propulsion} />
|
||||
<Structure {...structure} />
|
||||
<Weaponry {...weaponry} />
|
||||
</main>
|
||||
|
||||
<script>
|
||||
import Identification from "./ShipEdit/Identification.svelte";
|
||||
|
@ -1,12 +1,14 @@
|
||||
<div class="identification-row">
|
||||
<div>
|
||||
<Field label="ship class" bind:value={shipClass} />
|
||||
<Field label="ship type">
|
||||
<Field suffix>
|
||||
<select bind:value={shipType}>
|
||||
{#each shipTypes as name (name)}
|
||||
<option>{name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<label class="active">ship type</label>
|
||||
<i>arrow_drop_down</i>
|
||||
</Field>
|
||||
</div>
|
||||
<ShipCost {...reqs} />
|
||||
|
@ -1,7 +1,7 @@
|
||||
<div class="mass">
|
||||
<Field label="ship tonnage">
|
||||
<input class="short" bind:value={mass} type="number" min="10" max="300" />
|
||||
<img class="mass_symbol" src="{base}/mass.svg" alt="mass" />
|
||||
<Field label="ship tonnage" suffix>
|
||||
<input bind:value={mass} type="number" min="10" max="300" />
|
||||
<i>Weight</i>
|
||||
|
||||
<div class="note" class:warning={!withinBudget}>
|
||||
{#if withinBudget}
|
||||
@ -14,8 +14,9 @@
|
||||
</div>
|
||||
|
||||
<div class="cost">
|
||||
<Field label="cost">
|
||||
<span class="cost">{cost}</span>
|
||||
<Field label="total cost" suffix>
|
||||
<input value={cost} disabled />
|
||||
<i>Paid</i>
|
||||
</Field>
|
||||
</div>
|
||||
|
||||
@ -54,10 +55,6 @@
|
||||
grid-column: span 3;
|
||||
justify-content: space-around;
|
||||
}
|
||||
input {
|
||||
width: 5em;
|
||||
display: inline !important;
|
||||
}
|
||||
.mass_symbol {
|
||||
width: 0.75em;
|
||||
display: inline-block;
|
||||
@ -82,8 +79,7 @@
|
||||
div.cost {
|
||||
grid-column: 3;
|
||||
}
|
||||
span.cost:after {
|
||||
content: "\00A4";
|
||||
margin-left: 0.5em;
|
||||
i {
|
||||
top: 65%;
|
||||
}
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div>
|
||||
<Field label="thrust rating">
|
||||
<input
|
||||
class="short"
|
||||
class="engine"
|
||||
type="number"
|
||||
bind:value={rating}
|
||||
min="0"
|
||||
@ -11,7 +11,10 @@
|
||||
/>
|
||||
</Field>
|
||||
|
||||
<label><input type="checkbox" bind:checked={advanced} /> advanced</label>
|
||||
<label class="checkbox">
|
||||
<input type="checkbox" bind:checked={advanced} />
|
||||
<span>advanced</span>
|
||||
</label>
|
||||
</div>
|
||||
</ShipItem>
|
||||
|
||||
@ -29,28 +32,14 @@
|
||||
</script>
|
||||
|
||||
<style>
|
||||
input.engine {
|
||||
width: 9em;
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
align-items: end;
|
||||
}
|
||||
label {
|
||||
font-family: var(--main-font-family);
|
||||
margin-left: 2em;
|
||||
}
|
||||
input[type="number"] {
|
||||
width: 5em;
|
||||
}
|
||||
input {
|
||||
margin-bottom: 0px !important;
|
||||
}
|
||||
input:not([type="checkbox"]) {
|
||||
border: 0px;
|
||||
border-bottom: 1px solid var(--indigo-dye);
|
||||
border-radius: 0px;
|
||||
height: calc(
|
||||
1rem * var(--line-height) + var(--form-element-spacing-vertical) * 1
|
||||
);
|
||||
padding: 0 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,12 +1,13 @@
|
||||
<ShipItem {...reqs}>
|
||||
<Field label="FTL drive">
|
||||
<div>FTL drive</div>
|
||||
<nav>
|
||||
{#each ftlTypes as t (t)}
|
||||
<label
|
||||
><input type="radio" bind:group={type} value={t} />
|
||||
{t}
|
||||
<span>{t}</span>
|
||||
</label>
|
||||
{/each}
|
||||
</Field>
|
||||
</nav>
|
||||
</ShipItem>
|
||||
|
||||
<script lang="ts">
|
||||
|
@ -33,5 +33,6 @@
|
||||
div {
|
||||
display: flex;
|
||||
gap: 2em;
|
||||
align-items: baseline;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,20 +1,19 @@
|
||||
<ShipItem {...reqs}>
|
||||
<Field label="streamlining">
|
||||
<div>
|
||||
<label>
|
||||
<div>streamlining</div>
|
||||
<div class="field middle-align">
|
||||
<label class="radio">
|
||||
<input type="radio" bind:group={type} value="none" />
|
||||
none</label
|
||||
<span>none</span></label
|
||||
>
|
||||
<label>
|
||||
<label class="radio">
|
||||
<input type="radio" bind:group={type} value="partial" />
|
||||
partial</label
|
||||
<span>partial</span></label
|
||||
>
|
||||
<label>
|
||||
<label class="radio">
|
||||
<input type="radio" bind:group={type} value="full" />
|
||||
full</label
|
||||
<span>full</span></label
|
||||
>
|
||||
</div>
|
||||
</Field>
|
||||
</ShipItem>
|
||||
|
||||
<script>
|
||||
@ -36,6 +35,6 @@
|
||||
display: flex;
|
||||
}
|
||||
label {
|
||||
margin-left: 1em;
|
||||
margin-left: 2em !important;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,12 +1,13 @@
|
||||
<div>
|
||||
<Field label="">
|
||||
<button class="button small primary" on:click={addWeapon}>add weapon</button>
|
||||
<Field label="" suffix>
|
||||
<select bind:value={type}>
|
||||
{#each weaponTypes as weapon (weapon.type)}
|
||||
<option value={weapon.type}>{weapon.name}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<i>arrow_drop_down</i>
|
||||
</Field>
|
||||
<button class="button small primary" on:click={addWeapon}>add weapon</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@ -30,6 +31,7 @@
|
||||
button {
|
||||
width: inherit;
|
||||
display: inline-block;
|
||||
margin-right: 2em;
|
||||
}
|
||||
div :global(.field) {
|
||||
display: flex;
|
||||
@ -37,7 +39,8 @@
|
||||
}
|
||||
div {
|
||||
display: flex;
|
||||
margin-left: 5em;
|
||||
margin-left: 0em;
|
||||
margin-bottom: 2em;
|
||||
align-items: baseline;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,20 +1,22 @@
|
||||
<label>beam</label>
|
||||
<span>beam</span>
|
||||
|
||||
<Field label="beam class">
|
||||
<Field label="beam class" suffix>
|
||||
<select bind:value={weaponClass}>
|
||||
<option value={1}>1</option>
|
||||
<option value={2}>2</option>
|
||||
<option value={3}>3</option>
|
||||
<option value={4}>4</option>
|
||||
</select>
|
||||
<i>arrow_drop_down</i>
|
||||
</Field>
|
||||
|
||||
<Field label="arcs">
|
||||
<Field label="arcs" suffix>
|
||||
<select bind:value={nbrArcs}>
|
||||
{#each arc_options[weaponClass] || [] as nbrArcs (nbrArcs)}
|
||||
<option>{nbrArcs}</option>
|
||||
{/each}
|
||||
</select>
|
||||
<i>arrow_drop_down</i>
|
||||
</Field>
|
||||
|
||||
<Arcs selected={arcs} on:clickArc={({ detail }) => setArcs(detail)} />
|
||||
|
@ -1,6 +1,6 @@
|
||||
<ShipItem {...reqs}>
|
||||
<div class="weapon_row">
|
||||
<button class="button small red remove" on:click={remove}>remove </button>
|
||||
<a on:click={remove}><i>Delete</i> </a>
|
||||
|
||||
<svelte:component this={component[type]} {...specs} on:change={update} />
|
||||
</div>
|
||||
|
@ -3,9 +3,12 @@
|
||||
|
||||
<div class="reqs">
|
||||
<div class="mass" bind:this={mass_el}>
|
||||
{mass} <img src="{base}/mass.svg" alt="mass" />
|
||||
{mass} <i>Weight</i>
|
||||
</div>
|
||||
<div class="cost" bind:this={cost_el}>
|
||||
{cost}
|
||||
<i>Paid</i>
|
||||
</div>
|
||||
<div class="cost" bind:this={cost_el}>{cost}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,10 +56,6 @@
|
||||
img {
|
||||
width: 0.75em;
|
||||
}
|
||||
.cost:after {
|
||||
content: "\00A4";
|
||||
margin-left: 0.5em;
|
||||
}
|
||||
.mass img {
|
||||
width: 0.75em;
|
||||
display: inline-block;
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 25 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 125 KiB After Width: | Height: | Size: 132 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 71 KiB |
17
src/lib/store/uids.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { writable, get } from "svelte/store";
|
||||
|
||||
export default () => {
|
||||
const store = writable(0);
|
||||
|
||||
const genUid = (prefix = "") => {
|
||||
store.update((x) => x + 1);
|
||||
return prefix.length
|
||||
? [prefix, "" + get(store)].join("-")
|
||||
: "" + get(store);
|
||||
};
|
||||
|
||||
return {
|
||||
store,
|
||||
genUid,
|
||||
};
|
||||
};
|
8
src/lib/store/uids.test.js
Normal file
@ -0,0 +1,8 @@
|
||||
import uids from "./uids";
|
||||
|
||||
test("basic", () => {
|
||||
const { genUid } = uids();
|
||||
|
||||
expect(genUid()).toEqual("1");
|
||||
expect(genUid("potato")).toEqual("potato-2");
|
||||
});
|
@ -62,52 +62,6 @@ input.short {
|
||||
color: rgb(0, 80, 160);
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
textarea {
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 0.4em;
|
||||
margin: 0 0 0.5em 0;
|
||||
box-sizing: border-box;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
input:disabled {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
input[type="range"] {
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* input, */
|
||||
/* select { */
|
||||
/* border: 0px; */
|
||||
/* border-bottom: 1px solid var(--indigo-dye); */
|
||||
/* } */
|
||||
|
||||
input:focus,
|
||||
select:focus {
|
||||
border: 1px solid var(--indigo-dye);
|
||||
}
|
||||
|
||||
input:not([type="checkbox"]):not([type="radio"]) {
|
||||
border: 0px;
|
||||
border-bottom: 1px solid var(--indigo-dye);
|
||||
border-radius: 0px;
|
||||
height: calc(
|
||||
1rem * var(--line-height) + var(--form-element-spacing-vertical) * 1
|
||||
);
|
||||
padding: 0 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 { font-size: var(--font-scale-15); }
|
||||
h2 { font-size: var(--font-scale-14); }
|
||||
|
@ -5,8 +5,10 @@
|
||||
<script>
|
||||
import { setContext } from "svelte";
|
||||
|
||||
import { createApi } from "$lib/store/api.ts";
|
||||
import { createApi } from "$lib/store/api.js";
|
||||
import uids from "$lib/store/uids.js";
|
||||
import Layout from "$lib/components/MainLayout.svelte";
|
||||
|
||||
setContext("api", createApi());
|
||||
setContext("genUid", uids());
|
||||
</script>
|
||||
|
@ -17,9 +17,9 @@ test("we can pass a store", async () => {
|
||||
|
||||
api.dispatch.updateIdentification({ shipClass: "Bonobo" });
|
||||
|
||||
const { getByPlaceholderText } = render(Page, { context });
|
||||
const { getByLabelText } = render(Page, { context });
|
||||
|
||||
const classInput = getByPlaceholderText("ship class");
|
||||
const classInput = getByLabelText("ship class");
|
||||
await fireEvent.input(classInput, { target: { value: "Tarzan" } });
|
||||
expect(classInput.value).toEqual("Tarzan");
|
||||
|
||||
|