diff options
author | Jakob Stendahl <14180120+JakobST1n@users.noreply.github.com> | 2021-10-11 20:02:04 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-11 20:02:04 +0200 |
commit | c67531161e56488166a33232f87566309ba8676e (patch) | |
tree | 846e59a020e80bea48557d5a06af5728e44961ff /src_frontend/ComponentLib | |
parent | e6880cd8ccf82d993f222cb14b4860581654acb8 (diff) | |
parent | c1b6eec770b885a9829e1f62bad5cc99389ca429 (diff) | |
download | Luxcena-Neo-c67531161e56488166a33232f87566309ba8676e.tar.gz Luxcena-Neo-c67531161e56488166a33232f87566309ba8676e.zip |
Merge pull request #24 from JakobST1n/rebuild
v1.0.0
Diffstat (limited to 'src_frontend/ComponentLib')
-rw-r--r-- | src_frontend/ComponentLib/Button/Button.svelte | 80 | ||||
-rw-r--r-- | src_frontend/ComponentLib/Button/FloatingButton.svelte | 104 | ||||
-rw-r--r-- | src_frontend/ComponentLib/FloatingSelect.svelte | 45 | ||||
-rw-r--r-- | src_frontend/ComponentLib/Input.svelte | 14 | ||||
-rw-r--r-- | src_frontend/ComponentLib/PrettyVar.svelte | 16 | ||||
-rw-r--r-- | src_frontend/ComponentLib/RoundRange.svelte | 169 |
6 files changed, 428 insertions, 0 deletions
diff --git a/src_frontend/ComponentLib/Button/Button.svelte b/src_frontend/ComponentLib/Button/Button.svelte new file mode 100644 index 0000000..3943ecf --- /dev/null +++ b/src_frontend/ComponentLib/Button/Button.svelte @@ -0,0 +1,80 @@ +<script> + export let faIcon = false; + export let fullWidth = false; + export let backgroundColor = "var(--theme-primary)"; + export let color = "var(--theme-on-primary)"; + + export let loadingPromise = null; + $: listen(loadingPromise); + function listen(promise) { + if (promise != null) { + loading = true; + promise.then(res => { + loading = false; + success = true; + }).catch(err => { + loading = false; + success = false; + }); + } else { + loading = false; + } + } + let loading; + let success; +</script> + +<style> + button { + background-color: var(--bg-color); + color: var(--color); + border: none; + text-decoration: none; + padding: 5px 15px; + font-size: 15px; + + transition: background-color, color 0.1s ease; + border-radius: 15px; + } + button:hover { + filter: brightness(0.95); + } + button:active { + filter: brightness(0.90); + } + .fullWidth { + width: 100%; + } + .iconButton { + display: flex; + } + .iconButton .text { + margin: auto; + } + .active { + background-color: var(--active-bg-color); + color: var(--active-color); + } +</style> + +<button + on:click + class:fullWidth={fullWidth} + class:iconButton={faIcon != false} + style="--bg-color: {backgroundColor}; + --color: {color};"> + + {#if faIcon} + <div class="icon"> + <i class={faIcon}></i> + </div> + {/if} + + {#if loading} + <i class="fas fa-spinner fa-pulse"></i> + {:else} + <div class="text"> + <slot></slot> + </div> + {/if} +</button>
\ No newline at end of file diff --git a/src_frontend/ComponentLib/Button/FloatingButton.svelte b/src_frontend/ComponentLib/Button/FloatingButton.svelte new file mode 100644 index 0000000..123debc --- /dev/null +++ b/src_frontend/ComponentLib/Button/FloatingButton.svelte @@ -0,0 +1,104 @@ +<script> + export let faIcon = false; + export let fullWidth = false; + export let backgroundColor = "white"; + export let color = "black"; + export let activeBackgroundColor = "gray"; + export let activeColor = "white"; + export let active = false; + export let label = null; + + export let loadingPromise = null; + $: listen(loadingPromise); + function listen(promise) { + if (promise != null) { + loading = true; + promise.then(res => { + loading = false; + success = true; + }).catch(err => { + loading = false; + success = false; + }); + } else { + loading = false; + } + } + let loading; + let success; +</script> + +<style> + button { + background-color: var(--bg-color); + color: var(--color); + border: none; + text-decoration: none; + padding: 15px; + font-size: 15px; + + transition: background-color, color 0.1s ease; + border-radius: 50px; + } + button:hover { + filter: brightness(0.95); + } + button:active { + filter: brightness(0.90); + } + .fullWidth { + width: 100%; + } + .iconButton { + display: flex; + } + .iconButton .text { + margin: auto; + } + .active { + background-color: var(--active-bg-color); + color: var(--active-color); + } + .wrapper { + display: flex; + flex-direction: column; + align-items: center; + } + .label { + margin-top: 10px; + color: var(--grey-700); + font-size: 13px; + } +</style> + +<div class="wrapper"> + <button + on:click + class:fullWidth={fullWidth} + class:iconButton={faIcon != false} + class:active={active} + style="--bg-color: {backgroundColor}; + --color: {color}; + --active-bg-color: {activeBackgroundColor}; + --active-color: {activeColor};" + class="drop-shadow" + > + + {#if faIcon} + <div class="icon"> + <i class={faIcon}></i> + </div> + {/if} + + {#if loading} + <i class="fas fa-spinner fa-pulse"></i> + {:else} + <div class="text"> + <slot></slot> + </div> + {/if} + </button> + {#if label != null} + <span class="label">{label}</span> + {/if} +</div>
\ No newline at end of file diff --git a/src_frontend/ComponentLib/FloatingSelect.svelte b/src_frontend/ComponentLib/FloatingSelect.svelte new file mode 100644 index 0000000..0d71ca7 --- /dev/null +++ b/src_frontend/ComponentLib/FloatingSelect.svelte @@ -0,0 +1,45 @@ +<script> + import FloatingButton from "./Button/FloatingButton.svelte"; + export let value; + + export let faIcon = false; + export let backgroundColor = "white"; + export let color = "black"; + export let activeBackgroundColor = "gray"; + export let activeColor = "white"; + export let active = false; + export let label = null; +</script> + +<style> + select { + text-decoration: none; + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + background-color: transparent; + border: none; + margin: auto; + text-align: center; + } + select:focus { + outline: none; + } + .active { + background-color: var(--active-bg-color); + color: var(--active-color); + } +</style> +<FloatingButton fullWidth=true + {faIcon} + {label} + {backgroundColor} + {color} + {activeBackgroundColor} + {activeColor} + {active} > + <select on:change + bind:value={value}> + <slot></slot> + </select> +</FloatingButton>
\ No newline at end of file diff --git a/src_frontend/ComponentLib/Input.svelte b/src_frontend/ComponentLib/Input.svelte new file mode 100644 index 0000000..ecbaefb --- /dev/null +++ b/src_frontend/ComponentLib/Input.svelte @@ -0,0 +1,14 @@ +<script> + export let fullWidth = true; + export let type = "text"; + export let id; + export let value +</script> + +<style> + +</style> + +<div> + <input type={type} id={id} bind:value={value} /> +</div>
\ No newline at end of file diff --git a/src_frontend/ComponentLib/PrettyVar.svelte b/src_frontend/ComponentLib/PrettyVar.svelte new file mode 100644 index 0000000..68f082f --- /dev/null +++ b/src_frontend/ComponentLib/PrettyVar.svelte @@ -0,0 +1,16 @@ +<script> + export let varText; + let prettyVarText; + + function prettify(text) { + try { + prettyVarText = text.replace("_", " "); + prettyVarText = prettyVarText.charAt(0).toUpperCase() + prettyVarText.slice(1); + } catch { + prettyVarText = varText; + } + } + $: prettify(varText); +</script> + +{prettyVarText} diff --git a/src_frontend/ComponentLib/RoundRange.svelte b/src_frontend/ComponentLib/RoundRange.svelte new file mode 100644 index 0000000..42c4d57 --- /dev/null +++ b/src_frontend/ComponentLib/RoundRange.svelte @@ -0,0 +1,169 @@ +<script> + import { onMount } from 'svelte'; + import { createEventDispatcher } from 'svelte'; + const dispatch = createEventDispatcher(); + + export let min = 0; + export let max = 100; + export let value = 0; + export let enabled = true; + + let svg; + let indicator; + let thumb; + let track; + let cVal = value; + let touchActive = false; + + let inputCoordinates; + + function setValue(_value) { + value = _value; + let delta = cVal - _value; + + if (!touchActive && (Math.abs(delta) > 10)) { + let animInterval = setInterval(() => { + cVal = cVal + ((delta < 0) ? 1 : -1); + setThumbAndTrack(cVal); + if ( ((delta < 0) && (cVal >= value)) || ((delta > 0) && (cVal <= value)) ) { + clearInterval(animInterval); + } + }, 1); + } else { + setThumbAndTrack(value); + cVal = value; + } + } + + function setThumbAndTrack(val_pos) { + if (indicator && thumb) { + let indicator_value = (((val_pos - min) * 207) / (max - min)); + indicator.style.strokeDasharray = `${indicator_value},207`; + + let p = indicator.getPointAtLength(indicator_value); + thumb.setAttribute("transform", `translate(${p.x}, ${p.y})`); + } + } + + onMount(async() => { + let lastVal = value; + setValue(value); + setInterval(() => { + if (value != lastVal) { + setValue(value); + lastVal = value; + } + }, 500); + window.indicator = indicator; + + inputCoordinates = svg.createSVGPoint(); + addEventListenersToElement(thumb); + addEventListenersToElement(track); + addEventListenersToElement(indicator); + }); + + function addEventListenersToElement(el) { + el.addEventListener("touchstart", () => { + touchActive = true; + }, { capture: true, passive: false }); + el.addEventListener("touchend", () => { + touchActive = false; + }, { capture: true, passive: true }); + el.addEventListener("touchmove", updateValueFromTouchEvent, { capture: true, passive: false }); + + el.addEventListener("mousedown", (ev) => { + touchActive = true; + updateValueFromMouseEvent(ev); + svg.addEventListener("mousemove", updateValueFromMouseEvent); + }, { capture: true, passive: false }); + el.addEventListener("mouseup", (ev) => { + touchActive = false; + svg.removeEventListener("mousemove", updateValueFromMouseEvent); + }, { capture: true, passive: false }); + } + + function updateValueFromTouchEvent(ev) { + inputCoordinates.x = ev.touches[0].clientX; + inputCoordinates.y = ev.touches[0].clientY; + updateValueFromPoint(inputCoordinates); + ev.preventDefault(); + } + + function updateValueFromMouseEvent(ev) { + inputCoordinates.x = ev.clientX; + inputCoordinates.y = ev.clientY; + updateValueFromPoint(inputCoordinates); + ev.preventDefault(); + } + + function updateValueFromPoint(point) { + inputCoordinates = inputCoordinates.matrixTransform(svg.getScreenCTM().inverse()); + setValue(getValueAtLength(indicator, getPathLangthOfClosestPoint(indicator, inputCoordinates))); + dispatch("change"); + } + + function getPathLangthOfClosestPoint(path, point) { + let pathLength = path.getTotalLength(); + let shortestDistance = Number.MAX_VALUE; + let shortestPathDistance; + + for (let i = 0; i <= pathLength; i += 4) { + let p = path.getPointAtLength(i), + dx = p.x - point.x, + dy = p.y - point.y, + cDistance = dx * dx + dy * dy; + + if (cDistance < shortestDistance) { + shortestDistance = cDistance; + shortestPathDistance = i; + } + } + + return shortestPathDistance; + } + + function getValueAtLength(path, length) { + return Math.floor(((length * (max - min)) / path.getTotalLength()) + min); + } +</script> + +<style> + svg { + --primary-color: var(--yellow-500); + --muted-color: var(--yellow-100); + margin-top: -15px; + } + path { + transition: stroke 0.2s ease; + } + circle { + filter: drop-shadow(0 0 2px #d0d0d0); + transition: stroke 0.2s ease; + } + circle:hover { + stroke: #f9f9f9; + } + circle:active { + fill: var(--yellow-600); + } + .disabled { + --primary-color: var(--grey-200); + --muted-color: var(--grey-50); + } +</style> + + +<svg bind:this={svg} class:disabled={!enabled} viewbox="0 0 100 100"> + <path bind:this={track} fill="none" stroke-linecap="round" stroke-width="10" stroke="var(--muted-color)" + d="M25 85 + a 40 40 0 1 1 50 0 + "> + </path> + <path bind:this={indicator} fill="none" stroke-linecap="round" stroke-width="10" stroke="var(--primary-color)" + stroke-dasharray="207,0" + d="M25 85 + a 40 40 0 1 1 50 0"> + </path> + <circle bind:this={thumb} cx="0" cy="0" r="8" stroke="white" stroke-width="3" fill="var(--primary-color)" /> + <text id="count" x="50" y="55" text-anchor="middle" dy="7" font-size="20">{value}%</text> +</svg>
\ No newline at end of file |