File: /var/www/quadcode.com/src/components/blocks/glossary/GlossaryElements.svelte
<script lang="ts">
import { onMount } from 'svelte';
import { glossaryAnchor, glossarySearchWord } from '../../../store';
import type { IGlossaryList } from '$type/glossary';
import { localeLink } from '$lib/translations';
export let glossaries: IGlossaryList;
const data: IGlossaryList = glossaries;
let searchWord: string | null = null;
glossarySearchWord.subscribe((data) => {
searchWord = data;
});
$: highlightTitle = (title: string) => {
if (!searchWord) return title;
const regEscape = (v: string) => v.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
const regex = new RegExp(searchWord, "i");
const splitedWords = title.match(regex);
const titles = title.split(new RegExp(regEscape(searchWord), "ig"));
return titles.join(`<span class="highlighted">${splitedWords}</span>`);
}
onMount(() => {
glossaryAnchor.subscribe(data => {
if (!data) return;
const element = document.body.querySelector(`#glossaryAnchor${data.toLocaleUpperCase()}`);
const headerHeight = document.body.querySelector('.header')?.clientHeight || 0;
const glossaryControlsHeight = document.body.querySelector('.glossary-controlls')?.clientHeight || 0;
if (!element) return;
window.scrollTo(0, window.pageYOffset + (element.getBoundingClientRect().y - headerHeight - glossaryControlsHeight));
});
});
</script>
<div class="glossary-elements">
{#each Object.keys(data) as letter}
{#if ((!searchWord || searchWord === '') || ( (searchWord && searchWord !== '') &&
Object.keys(data[letter]).find(post =>
(!searchWord || searchWord === '') || ( (searchWord && searchWord !== '') &&
data[letter][post].word.toLowerCase().indexOf(searchWord.toLocaleLowerCase()) !== null
&& data[letter][post].word.toLowerCase().indexOf(searchWord.toLocaleLowerCase()) !== -1)
) ))}
<div id="glossaryAnchor{letter.toLocaleUpperCase()}" class="glossary-element">
<div class="glossary-element__letter">{letter.toLocaleUpperCase()}</div>
<div class="glossary-element__posts">
{#each Object.keys(data[letter]) as post}
{#if ((!searchWord || searchWord === '') || ( (searchWord && searchWord !== '') &&
data[letter][post].word.toLowerCase().indexOf(searchWord.toLocaleLowerCase()) !== null
&& data[letter][post].word.toLowerCase().indexOf(searchWord.toLocaleLowerCase()) !== -1))}
<a href={`${localeLink()}/glossary/${data[letter][post].slug}`} class="glossary-element__post">{@html highlightTitle(data[letter][post].word) }</a>
{/if}
{/each}
</div>
</div>
{/if}
{/each}
</div>
<style lang="scss">
@import 'src/scss/variables';
@import 'src/scss/media';
@import 'src/scss/mixins';
.glossary-elements{
width: 100%;
display: flex;
flex-direction: column;
gap: 32px;
}
.glossary-element {
display: flex;
flex-direction: column;
gap: 18px;
&__letter{
font-weight: 700;
font-size: 36px;
line-height: 39.6px;
color: $techBluePrimary;
@include breakpoint-down('tabM') {
font-size: 31px;
line-height: 34.1px;
}
}
&__posts{
display: flex;
flex-wrap: wrap;
gap: 18px;
}
&__post {
padding: 22px;
width: fit-content;
height: fit-content;
font-weight: 700;
font-size: 20px;
line-height: 24.36px;
letter-spacing: -1px;
background-color: $techWhite;
color: $fontPrimary;
border: thin solid $techBlue3;
border-radius: 8px;
cursor: pointer;
@include breakpoint-down('deskL') {
padding: 20px;
}
@include breakpoint-down('tabL') {
font-size: 16px;
line-height: 19.49px;
letter-spacing: -1px;
}
@include breakpoint-down('tabM') {
padding: 11px;
font-size: 12px;
line-height: 14.62px;
letter-spacing: normal;
}
}
:global(.highlighted) {
background-color: rgba(231, 44, 57, 1);
}
}
</style>