Skip to content

Commit

Permalink
Merge branch 'fork-main' into fork-staging
Browse files Browse the repository at this point in the history
  • Loading branch information
Feyko committed Oct 16, 2023
2 parents ed4cc60 + 3c6d247 commit 5b87e28
Showing 1 changed file with 68 additions and 124 deletions.
192 changes: 68 additions & 124 deletions src/lib/components/utils/TagList.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,96 +14,44 @@
export let tags: Tag[] = [];
export let editable = false;
let inputA: InputComponentDev;
let inputElement: InputComponentDev;
const shake = false;
let allTags: Tag[] = [];
let filteredTagsMatched: Tag[] = [];
let filteredTagsUnmatched: Tag[] = [];
let tagSearch = '';
let newTagText = '';
$: allTags = $getAllTags.data?.getTags ?? [];
$: availableTags = allTags.filter((tag) => !tags.some((t) => t.id == tag.id));
$: filteredTagsMatched = availableTags.filter((tag) => tag.name.toLowerCase().includes(tagSearch));
$: filteredTagsUnmatched = availableTags.filter((tag) => !filteredTagsMatched.some((t) => t.id == tag.id));
let newTag: HTMLInputElement;
let newTagContainer: HTMLElement = null;
let surface: MenuSurfaceComponentDev;
let focused = false;
$: newTag = inputA?.getElement();
function filterAvailableTags(tagList: Tag[], currentTags: Tag[], filterText: string): [Tag[], Tag[]] {
if (!tagList || !currentTags || !filterText) {
return [tagList, []];
}
console.log(filterText);
filterText = filterText.toLowerCase();
let unfiltered = tagList.filter((tag) => !currentTags.find((t) => t.id == tag.id));
const filtered = unfiltered.filter((tag) => !newTag || tag.name.toLowerCase().includes(filterText));
unfiltered = unfiltered.filter((tag) => filtered.findIndex((t) => t.id === tag.id) === -1);
return [filtered, unfiltered];
}
let tagBox: HTMLDivElement;
function updateTags() {
tags = tags;
[filteredTagsMatched, filteredTagsUnmatched] = filterAvailableTags(allTags, tags, newTagText);
}
let focused = false;
if (editable) {
query(getAllTags);
getAllTags.subscribe(() => {
if (!getAllTags.fetching && !getAllTags.error) {
allTags = getAllTags.data.getTags;
updateTags();
}
});
}
function addTag(newTagObj: string | Tag) {
if (!allTags) {
return false;
function addTag(newTag: Tag) {
if (!tags.find((tag) => tag.id == newTag.id)) {
tags = [...tags, newTag];
}
const tagToAdd = allTags.find((tag) => {
if (typeof newTagObj == 'string') {
return newTagObj == tag.name || newTagObj == tag.id;
} else {
return newTagObj.id == tag.id;
}
}) as Tag;
if (tagToAdd && !tags.find((tag) => tag.id == tagToAdd.id)) {
tags.push(tagToAdd);
updateTags();
return true;
}
updateTags();
return false;
}
function deleteTag(tag: Tag) {
tags = tags.filter((v) => v != tag);
updateTags();
}
function onFocusLost() {
setTimeout(() => {
if (newTagContainer && !newTagContainer.contains(document.activeElement)) {
if (!tagBox.contains(document.activeElement)) {
surface.setOpen(false);
}
}, 200);
}
function onInput(e) {
//on:input is thrown before the inner text of the input is updated.
// The following if-else ensure the text we search with is up-to-date
if (e.data) {
newTagText += e.data;
} else {
newTagText = newTagText.substring(0, newTagText.length - 1);
}
updateTags();
e.preventDefault();
}
updateTags();
</script>

<div class="tagHolder" on:focusin={() => (focused = true)} on:focusout={() => (focused = false)}>
Expand All @@ -118,66 +66,62 @@
</div>
{/if}
{:else}
<Textfield class="tags" bind:input={inputA} style="z-index: 9999">
<FloatingLabel
class="pb-2"
for="input-manual-a"
slot="label"
floatAbove={(newTag && newTag.value.length > 0) || focused || tags.length > 0}>
Tags
</FloatingLabel>
<div class="flex flex-row flex-wrap text-sm gap-1 mr-2">
{#each tags as tag}
<div class="text-neutral-300 flex removable-tag">
<span class="hashtag text-orange-500">#</span>
<span class="cancel">
<i class="material-icons mdc-chip__icon mdc-chip__icon--trailing" on:click={() => deleteTag(tag)}
>cancel</i>
</span>
<p>{tag.name}</p>
</div>
{/each}
</div>
<div
id="newTagContainer"
class="text-neutral-300 flex"
bind:this={newTagContainer}
on:focusin={() => surface.setOpen(true)}
on:focusout={onFocusLost}>
<Input
id="input-manual-a"
spellcheck="false"
autocomplete="off"
class="addTag inline text-sm text-neutral-300 {shake ? 'shake' : ''}"
style="height: initial"
bind:this={inputA}
bind:value={newTagText}
on:input={onInput} />
</div>
</Textfield>
<MenuSurface bind:this={surface} managed={true} anchorCorner="BOTTOM_LEFT" anchorElement={newTag}>
<div style="margin: 1rem">
<h1>Available Tags</h1>
{#if filteredTagsMatched.length > 0}
<div class="flex flex-nowrap m-1">
<Set chips={filteredTagsMatched} let:chip key={(tag) => tag.name}>
<Chip {chip} on:SMUIChip:interaction={() => addTag(chip.name)}>
<Text>{chip.name}</Text>
</Chip>
</Set>
</div>
{/if}
{#if filteredTagsUnmatched.length > 0}
<div class="flex flex-nowrap m-1">
<Set class="unmatched-tag" chips={filteredTagsUnmatched} let:chip key={(tag) => tag.name}>
<Chip {chip} on:SMUIChip:interaction={() => addTag(chip.name)}>
<Text>{chip.name}</Text>
</Chip>
</Set>
</div>
{/if}
</div>
</MenuSurface>
<div bind:this={tagBox} on:focusin={() => surface.setOpen(true)} on:focusout={onFocusLost}>
<Textfield class="tags" bind:input={inputElement} style="z-index: 9999">
<FloatingLabel
class="pb-2"
for="input-manual-a"
slot="label"
floatAbove={!!tagSearch || focused || tags.length > 0}>
Tags
</FloatingLabel>
<div class="flex flex-row flex-wrap text-sm gap-1 mr-2">
{#each tags as tag}
<div class="text-neutral-300 flex removable-tag">
<span class="hashtag text-orange-500">#</span>
<span class="cancel">
<i class="material-icons mdc-chip__icon mdc-chip__icon--trailing" on:click={() => deleteTag(tag)}
>cancel</i>
</span>
<p>{tag.name}</p>
</div>
{/each}
</div>
<div id="newTagContainer" class="text-neutral-300 flex">
<Input
id="input-manual-a"
spellcheck="false"
autocomplete="off"
class="addTag inline text-sm text-neutral-300 {shake ? 'shake' : ''}"
style="height: initial"
bind:this={inputElement}
bind:value={tagSearch} />
</div>
</Textfield>
<MenuSurface bind:this={surface} managed={true} anchorCorner="BOTTOM_LEFT" on:click={() => inputElement.focus()}>
<div style="margin: 1rem">
<h1>Available Tags</h1>
{#if filteredTagsMatched.length > 0}
<div class="flex flex-nowrap m-1">
<Set chips={filteredTagsMatched} let:chip key={(tag) => tag.name}>
<Chip {chip} on:SMUIChip:interaction={() => addTag(chip)}>
<Text>{chip.name}</Text>
</Chip>
</Set>
</div>
{/if}
{#if filteredTagsUnmatched.length > 0}
<div class="flex flex-nowrap m-1">
<Set class="unmatched-tag" chips={filteredTagsUnmatched} let:chip key={(tag) => tag.name}>
<Chip {chip} on:SMUIChip:interaction={() => addTag(chip)}>
<Text>{chip.name}</Text>
</Chip>
</Set>
</div>
{/if}
</div>
</MenuSurface>
</div>
{/if}
</div>

Expand Down

0 comments on commit 5b87e28

Please sign in to comment.