Gisle Aune
2 years ago
6 changed files with 167 additions and 0 deletions
-
34frontend/src/lib/components/common/TagRow.svelte
-
82frontend/src/lib/components/controls/TagInput.svelte
-
2frontend/src/lib/components/project/ItemSubSection.svelte
-
13frontend/src/lib/modals/ItemCreateModal.svelte
-
4frontend/src/lib/models/item.ts
-
32ports/mysql/items.go
@ -0,0 +1,34 @@ |
|||||
|
<script lang="ts"> |
||||
|
export let names: string[] |
||||
|
</script> |
||||
|
|
||||
|
<div class="tag-row"> |
||||
|
{#each names as name (name)} |
||||
|
<div class="tag">{name}<span class="comma">,</span></div> |
||||
|
{/each} |
||||
|
</div> |
||||
|
|
||||
|
<style lang="sass"> |
||||
|
@import "../../css/colors" |
||||
|
|
||||
|
div.tag-row |
||||
|
display: flex |
||||
|
flex-direction: row |
||||
|
flex-wrap: wrap |
||||
|
|
||||
|
&:empty |
||||
|
display: none |
||||
|
|
||||
|
> div.tag |
||||
|
margin: 0.25em 0.5ch |
||||
|
background-color: $color-entry2 |
||||
|
padding: 0.25em 1ch |
||||
|
border-radius: 0.25em |
||||
|
font-size: 0.75em |
||||
|
|
||||
|
> span.comma |
||||
|
font-size: 0 |
||||
|
|
||||
|
&:first-child |
||||
|
margin-left: 0 |
||||
|
</style> |
@ -0,0 +1,82 @@ |
|||||
|
<script lang="ts"> |
||||
|
import Icon from "../layout/Icon.svelte"; |
||||
|
|
||||
|
export let value: string[]; |
||||
|
|
||||
|
let nextTag = ""; |
||||
|
|
||||
|
function onKey(ev: KeyboardEvent) { |
||||
|
if ((ev.metaKey||ev.ctrlKey) && nextTag === "" && ev.key === "Backspace") { |
||||
|
value = value.slice(0, -1); |
||||
|
} |
||||
|
|
||||
|
if ((ev.metaKey||ev.ctrlKey) && nextTag !== "" && ev.key === "Enter") { |
||||
|
value = [...value, nextTag]; |
||||
|
nextTag = ""; |
||||
|
ev.preventDefault(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
$: while (nextTag.includes(",")) { |
||||
|
const newTags = nextTag.split(",").map(t => t.trim()); |
||||
|
value = [...value, ...newTags.slice(0, -1)]; |
||||
|
nextTag = newTags[newTags.length - 1]; |
||||
|
} |
||||
|
|
||||
|
$: value = (value||[]).filter((e, i) => !value.slice(0, i).includes(e)); |
||||
|
</script> |
||||
|
|
||||
|
<div class="tag-input"> |
||||
|
{#each value as tag (tag)} |
||||
|
<div class="tag"> |
||||
|
<span>{tag}</span> |
||||
|
<span class="comma">,</span> |
||||
|
<span class="x" on:click={() => value = value.filter(v => v !== tag)}> |
||||
|
<Icon name="times" /> |
||||
|
</span> |
||||
|
</div> |
||||
|
{/each} |
||||
|
<input placeholder="Add tag (type , or press Ctrl+Enter to add)" on:keyup={onKey} bind:value={nextTag} /> |
||||
|
</div> |
||||
|
|
||||
|
<style lang="sass"> |
||||
|
@import "../../css/colors" |
||||
|
|
||||
|
div.tag-input |
||||
|
width: calc(100% - 2ch) |
||||
|
margin-bottom: 1em |
||||
|
margin-top: 0.20em |
||||
|
min-height: 2em |
||||
|
|
||||
|
background: $color-entryhalf |
||||
|
color: $color-entry8 |
||||
|
border: none |
||||
|
outline: none |
||||
|
resize: vertical |
||||
|
padding: 0.5em 1ch |
||||
|
|
||||
|
display: flex |
||||
|
flex-direction: row |
||||
|
flex-wrap: wrap |
||||
|
|
||||
|
> div.tag |
||||
|
margin: 0.25em 0.5ch |
||||
|
background-color: $color-entry1 |
||||
|
padding: 0.25em 1ch |
||||
|
border-radius: 0.25em |
||||
|
|
||||
|
span.x |
||||
|
font-size: 0.75em |
||||
|
line-height: 1em |
||||
|
user-select: none |
||||
|
cursor: pointer |
||||
|
|
||||
|
&:hover |
||||
|
color: $color-entry12 |
||||
|
|
||||
|
span.comma |
||||
|
font-size: 0 |
||||
|
|
||||
|
> input |
||||
|
margin-bottom: 0.125em |
||||
|
</style> |
Write
Preview
Loading…
Cancel
Save
Reference in new issue