First commit

This commit is contained in:
2020-02-04 18:46:10 +01:00
commit 190e1eb01d
91 changed files with 13411 additions and 0 deletions
@@ -0,0 +1,45 @@
<script context="module">
import { faQuestion } from "@fortawesome/free-solid-svg-icons/faQuestion";
import { faPlus } from "@fortawesome/free-solid-svg-icons/faPlus";
import { faCubes } from "@fortawesome/free-solid-svg-icons/faCubes";
import { faBook } from "@fortawesome/free-solid-svg-icons/faBook";
import { faBookDead } from "@fortawesome/free-solid-svg-icons/faBookDead";
import { faPen } from "@fortawesome/free-solid-svg-icons/faPen";
import { faDiceD20 } from "@fortawesome/free-solid-svg-icons/faDiceD20";
import { faDiceD6 } from "@fortawesome/free-solid-svg-icons/faDiceD6";
import { faDungeon } from "@fortawesome/free-solid-svg-icons/faDungeon";
import { faGamepad } from "@fortawesome/free-solid-svg-icons/faGamepad";
import { faLanguage } from "@fortawesome/free-solid-svg-icons/faLanguage";
import { faCode } from "@fortawesome/free-solid-svg-icons/faCode";
import { faCodeBranch } from "@fortawesome/free-solid-svg-icons/faCodeBranch";
import { faGuitar } from "@fortawesome/free-solid-svg-icons/faGuitar";
import { faMusic } from "@fortawesome/free-solid-svg-icons/faMusic";
const icons = {
"plus": faPlus,
"cubes": faCubes,
"book": faBook,
"book_dead": faBookDead,
"pen": faPen,
"dice_d20": faDiceD20,
"dice_d6": faDiceD6,
"dungeon": faDungeon,
"gamepad": faGamepad,
"language": faLanguage,
"code": faCode,
"code_branch": faCodeBranch,
"guitar": faGuitar,
};
export const iconNames = Object.keys(icons);
</script>
<script>
import Icon from "fa-svelte"
export let name = "";
</script>
<Icon class="activity-icon" icon={icons[name] || faQuestion} />
<style></style>
@@ -0,0 +1,42 @@
<script>
import ActivityIcon, {iconNames} from "./ActivityIcon.svelte";
export let value;
</script>
<div class="icon-select">
{#each iconNames as iconName (iconName)}
<div class="icon-item" class:selected={value===iconName} on:click={() => value = iconName}>
<ActivityIcon name={iconName} />
</div>
{/each}
</div>
<style>
div.icon-select {
background: #222;
margin: 0;
padding: 0;
border-radius: 0.05em;
margin-bottom: 0.5em;
}
div.icon-item {
display: inline-block;
box-sizing: border-box;
width: calc(100% / 8);
padding: 0.35em 0 0.25em 0;
text-align: center;
cursor: pointer;
}
div.icon-item:hover {
background-color: #292929;
}
div.icon-item.selected {
background-color: rgb(18, 63, 75);
}
div.icon-item.selected:hover {
background-color: rgb(24, 83, 99);
}
</style>
+40
View File
@@ -0,0 +1,40 @@
<script>
import Icon from 'fa-svelte'
import { faPlus } from '@fortawesome/free-solid-svg-icons/faPlus'
export let header = "";
export let icon = null;
</script>
<div on:click class="addboi">
<Icon class="addboi-icon" icon={faPlus} />
<slot></slot>
</div>
<style>
div.addboi {
margin: 0.5em 0 4em 0;
padding: 1em 0;
text-align: center;
border: 4px dotted;
color: #333;
font-size: 2em;
font-weight: 100;
cursor: pointer;
transition: 250ms;
}
div.addboi:hover {
color: #777;
transition: 250ms;
}
div.addboi > :global(.addboi-icon) {
position: relative;
top: 0.125em;
}
</style>
+41
View File
@@ -0,0 +1,41 @@
<script>
import ActivityIcon from "./ActivityIcon"
export let header = "";
export let icon = null;
</script>
<div class="boi">
<div class="boi-header">
{#if (icon !== null)}<ActivityIcon name={icon} />{/if}{header}
</div>
<div class="boi-content">
<slot></slot>
</div>
</div>
<style>
div.boi {
margin: auto;
max-width: 100%;
background-color: #222;
margin: 1em 0;
box-shadow: 0.1em 0.1em 0.05em #080808;
}
div.boi > div.boi-header {
background-color: #292929;
color: #aaa;
text-align: center;
font-size: 1.25em;
padding: 0.25em 0;
}
div.boi > div.boi-header > :global(.activity-icon) {
position: relative;
top: 0.125em;
margin-right: 0.5ch;
}
</style>
+51
View File
@@ -0,0 +1,51 @@
<script>
export let size = 1;
</script>
<div class="col col-{size}"><slot></slot></div>
<style>
div.col {
display: inline-block;
box-sizing: border-box;
padding: 0;
margin: 0;
}
div.col-1 {
width: calc((100% / 12) * 1)
}
div.col-2 {
width: calc((100% / 12) * 2)
}
div.col-3 {
width: calc((100% / 12) * 3)
}
div.col-4 {
width: calc((100% / 12) * 4)
}
div.col-5 {
width: calc((100% / 12) * 5)
}
div.col-6 {
width: calc((100% / 12) * 6)
}
div.col-7 {
width: calc((100% / 12) * 7)
}
div.col-8 {
width: calc((100% / 12) * 8)
}
div.col-9 {
width: calc((100% / 12) * 9)
}
div.col-10 {
width: calc((100% / 12) * 10)
}
div.col-11 {
width: calc((100% / 12) * 11)
}
div.col-12 {
width: 100%
}
</style>
+16
View File
@@ -0,0 +1,16 @@
<span on:click><slot></slot></span>
<style>
span {
color: #777;
cursor: pointer;
transition: 250ms;
}
span:hover {
color: #FFF;
text-decoration: underline;
transition: 250ms;
}
</style>
+20
View File
@@ -0,0 +1,20 @@
<div class="menu">
<div class="right">
<slot name="right" />
</div>
<slot />
</div>
<style>
div.right {
position: absolute;
right: 0;
text-align: right;
}
div.menu {
background-color: #222;
margin: 0;
user-select: none;
}
</style>
+28
View File
@@ -0,0 +1,28 @@
<script>
import { link } from "svelte-routing";
export let href = "/";
</script>
<a class="menu-item" href={href} on:click use:link><slot/></a>
<style>
a.menu-item {
display: inline-block;
background-color: #222;
margin: 0;
padding: 0.25em 1ch;
color: #777;
transition: 250ms;
}
a.menu-item:hover {
background-color: #111;
color: #ccc;
text-decoration: none;
transition: 250ms;
}
</style>
+168
View File
@@ -0,0 +1,168 @@
<script>
import { createEventDispatcher } from 'svelte';
export let title = "";
export let wide = false;
export let error = null;
export let closable = false;
const dispatch = createEventDispatcher();
</script>
<div class="modal-background" on:click|self={() => closable ? dispatch("close") : null}>
<div class="modal" class:wide>
<div class="header">
<div class="title" class:noclose={!closable}>{title}</div>
{#if (closable)}
<div class="x">
<div class="button" on:click|self={() => dispatch("close")}>X</div>
</div>
{/if}
</div>
<hr />
{#if (error != null)}
<div class="error">{error}</div>
{/if}
<div class="body">
<slot></slot>
</div>
</div>
</div>
<style>
div.modal-background {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0,0,0,0.3);
}
div.modal {
position: absolute;
left: 50%;
top: 50%;
width: calc(100vw - 4em);
max-width: 40ch;
max-height: calc(100vh - 4em);
overflow: auto;
transform: translate(-50%,-50%);
padding: 1em;
border-radius: 0.2em;
background: #333;
}
div.modal.wide {
max-width: 60ch;
}
div.modal :global(hr) {
border: 0.5px solid gray;
margin: 0;
}
div.error {
margin: 0.5em;
padding: 0.5em;
border: 1px solid rgb(204, 65, 65);
border-radius: 0.2em;
background-color: rgb(133, 39, 39);
color: rgb(211, 141, 141);
animation: fadein 0.5s;
}
div.body {
margin: 1em 0.25ch;
}
div.title {
color: #CCC;
line-height: 1em;
}
div.title.noclose {
margin-bottom: 1.2em;
}
div.x {
position: relative;
line-height: 1em;
top: -1em;
text-align: right;
}
div.x div.button {
color: #CCC;
display: inline-block;
padding: 0em 0.5ch 0.1em 0.5ch;
line-height: 1em;
user-select: none;
cursor: pointer;
}
div.x div.button:hover {
background: #222;
color: #FFF;
}
div.modal :global(button) {
display: inline-block;
padding: 0.25em 0.75ch 0.26em 0.75ch;
margin: 0.75em 0.25ch 0.25em 0.25ch;
background: none;
border: none;
border-radius: 0.2em;
color: #CCC;
cursor: pointer;
}
div.modal :global(button:hover), div.modal :global(button:focus) {
background: #222;
color: #FFF;
}
div.modal :global(label) {
padding: 0 0 0.125em 0.25ch;
font-size: 0.75em;
}
div.modal :global(input), div.modal :global(select) {
width: 100%;
margin-bottom: 0.5em;
background: #222;
color: #777;
border: none;
outline: none;
}
div.modal :global(select) {
padding-left: 0.5ch;
}
div.modal :global(input:last-of-type) {
margin-bottom: 1em;
}
div.modal :global(input.nolast) {
margin-bottom: 0.5em;
}
div.modal :global(input:focus), div.modal :global(select:focus) {
background: #111;
color: #CCC;
border: none;
outline: none;
}
div.modal :global(p) {
margin: 0.25em 1ch 1em 1ch;
font-size: 0.9em;
}
@keyframes fadein {
from { opacity: 0; }
to { opacity: 1; }
}
</style>
+117
View File
@@ -0,0 +1,117 @@
<script>
import { onMount } from "svelte";
export let value;
export let goal;
let smoothValue = value;
let bars = [];
let timeout = null;
function update(value, goal) {
const bars = [];
let gold = (goal / 1000);
let red = gold + 3;
for (let i = 0;; ++i) {
let v = value - (i * 1000);
if (v > 1000) {
v = 1000;
} else if (v < 0) {
v = 0;
}
if (i >= red && v === 0) {
break;
}
bars.push({
green: i < gold,
gold: i >= gold && i < red,
red: i >= red,
value: v,
full: v === 1000,
})
}
return bars;
}
onMount(() => {
return () => clearTimeout(timeout);
})
$: bars = update(smoothValue, goal);
$: if (smoothValue !== value && timeout === null) {
timeout = setInterval(() => {
if (smoothValue < value) {
smoothValue += 100;
if (smoothValue > value) {
smoothValue = value;
}
} else if (smoothValue > value) {
smoothValue -= 100;
if (smoothValue < value) {
smoothValue = value;
}
} else {
clearTimeout(timeout);
timeout = null;
}
}, 1000/30);
}
</script>
{#each bars as bar}
<div class="bar" class:red={bar.red} class:green={bar.green} class:gold={bar.gold} class:full={bar.full}>
<div class="content" style={`height: ${bar.value / 10}%; top: ${(1000 - bar.value) / 10}%`}>
</div>
</div>
{/each}
<style>
div.bar {
display: inline-block;
background: #111;
width: 1.5ch;
height: 1em;
margin-right: 0.5ch;
}
div.bar > div.content {
width: 100%;
position: relative;
}
div.bar.green {
border: 0.1px solid #4da069;
}
div.bar.green > div.content {
background-color: #4da069;
}
div.bar.green.full > div.content {
background-color: #45fc82;
box-shadow: 0px 0px 2px #45fc82;
}
div.bar.gold {
border: 0.1px solid #9b7a1f;
}
div.bar.gold > div.content {
background-color: #9b7a1f;
}
div.bar.gold.full > div.content {
background-color: #ffc936;
box-shadow: 0px 0px 2px #ffc936;
}
div.bar.red {
border: 0.1px solid #880000;
}
div.bar.red > div.content {
background-color: #880000;
}
div.bar.red.full > div.content {
background-color: #bb0000;
box-shadow: 0px 0px 2px #ff0000;
}
</style>
+28
View File
@@ -0,0 +1,28 @@
<script>
export let label = "Label";
export let value = "";
</script>
<div class="property">
<div class="property-label">{label}:</div>
<div class="property-value"><slot>{value}</slot></div>
</div>
<style>
div.property {
padding: 0.5em 1ch;
}
div.property-label {
font-size: 0.75em;
font-weight: 800;
}
div.property-value {
font-size: 1em;
}
:global(form) div.property:last-of-type {
margin-bottom: 1em;
}
</style>
+8
View File
@@ -0,0 +1,8 @@
<div class="row"><slot></slot></div>
<style>
div.row {
display: flex;
flex-wrap: wrap;
}
</style>
@@ -0,0 +1,43 @@
<script>
export let name;
export let value;
</script>
<div class="subgoal-input">
<div><input type="text" bind:value={name} /></div>
<div><input type="text" bind:value={value} /></div>
</div>
<style>
div.subgoal-input {
display: flex;
flex-direction: row;
justify-content: center;
}
div.subgoal-input div {
line-height: 1em;
margin-bottom: 0 !important;
}
div.subgoal div {
display: inline-block;
box-sizing: border-box;
padding: 0.5em;
}
div.subgoal-input div:first-of-type {
width: 75%;
}
div.subgoal-input div:last-of-type {
width: 25%;
}
div.subgoal-input input {
margin-bottom: 0 !important;
border-bottom: 1px solid #333;
}
div.subgoal-input div:first-of-type input {
border-right: 1px solid #333;
}
</style>