2026-01-30 17:40:11 +03:00
|
|
|
<!--
|
|
|
|
|
Component: Section
|
|
|
|
|
Provides a container for a page widget with snippets for a title
|
|
|
|
|
-->
|
|
|
|
|
<script lang="ts">
|
|
|
|
|
import { cn } from '$shared/shadcn/utils/shadcn-utils';
|
|
|
|
|
import type { Snippet } from 'svelte';
|
|
|
|
|
import { cubicOut } from 'svelte/easing';
|
|
|
|
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
|
|
|
import {
|
|
|
|
|
type FlyParams,
|
|
|
|
|
fly,
|
|
|
|
|
} from 'svelte/transition';
|
2026-02-25 10:04:25 +03:00
|
|
|
|
|
|
|
|
import SectionHeader from './SectionHeader/SectionHeader.svelte';
|
|
|
|
|
import SectionTitle from './SectionTitle/SectionTitle.svelte';
|
2026-01-30 17:40:11 +03:00
|
|
|
|
|
|
|
|
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'title'> {
|
2026-02-10 21:17:50 +03:00
|
|
|
/**
|
|
|
|
|
* ID of the section
|
|
|
|
|
*/
|
|
|
|
|
id?: string;
|
2026-01-30 17:40:11 +03:00
|
|
|
/**
|
|
|
|
|
* Additional CSS classes to apply to the section container.
|
|
|
|
|
*/
|
|
|
|
|
class?: string;
|
|
|
|
|
/**
|
2026-02-25 10:04:25 +03:00
|
|
|
* Title of the section
|
2026-01-30 17:40:11 +03:00
|
|
|
*/
|
2026-02-25 10:04:25 +03:00
|
|
|
title: string;
|
2026-02-04 10:47:04 +03:00
|
|
|
/**
|
|
|
|
|
* Snippet for a title description
|
|
|
|
|
*/
|
|
|
|
|
description?: Snippet<[{ className?: string }]>;
|
2026-02-25 10:04:25 +03:00
|
|
|
headerTitle?: string;
|
|
|
|
|
headerSubtitle?: string;
|
2026-01-30 17:40:11 +03:00
|
|
|
/**
|
|
|
|
|
* Index of the section
|
|
|
|
|
*/
|
|
|
|
|
index?: number;
|
2026-02-02 12:11:48 +03:00
|
|
|
/**
|
|
|
|
|
* Callback function to notify when the title visibility status changes
|
|
|
|
|
*
|
|
|
|
|
* @param index - Index of the section
|
|
|
|
|
* @param isPast - Whether the section is past the current scroll position
|
|
|
|
|
* @param title - Snippet for a title itself
|
2026-02-10 21:17:50 +03:00
|
|
|
* @param id - ID of the section
|
2026-02-02 12:11:48 +03:00
|
|
|
* @returns Cleanup callback
|
|
|
|
|
*/
|
2026-02-10 21:17:50 +03:00
|
|
|
onTitleStatusChange?: (
|
|
|
|
|
index: number,
|
|
|
|
|
isPast: boolean,
|
|
|
|
|
title?: Snippet<[{ className?: string }]>,
|
|
|
|
|
id?: string,
|
|
|
|
|
) => () => void;
|
2026-01-30 17:40:11 +03:00
|
|
|
/**
|
|
|
|
|
* Snippet for the section content
|
|
|
|
|
*/
|
2026-02-18 17:36:38 +03:00
|
|
|
content?: Snippet<[{ className?: string }]>;
|
2026-01-30 17:40:11 +03:00
|
|
|
}
|
|
|
|
|
|
2026-02-18 17:36:38 +03:00
|
|
|
const {
|
|
|
|
|
class: className,
|
|
|
|
|
title,
|
2026-02-25 10:04:25 +03:00
|
|
|
headerTitle,
|
|
|
|
|
headerSubtitle,
|
2026-02-18 17:36:38 +03:00
|
|
|
description,
|
|
|
|
|
index = 0,
|
|
|
|
|
onTitleStatusChange,
|
|
|
|
|
id,
|
|
|
|
|
content,
|
|
|
|
|
}: Props = $props();
|
2026-01-30 17:40:11 +03:00
|
|
|
|
2026-02-18 17:36:38 +03:00
|
|
|
const flyParams: FlyParams = {
|
|
|
|
|
y: 0,
|
|
|
|
|
x: -50,
|
|
|
|
|
duration: 300,
|
|
|
|
|
easing: cubicOut,
|
|
|
|
|
opacity: 0.2,
|
|
|
|
|
};
|
2026-01-30 17:40:11 +03:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<section
|
2026-02-18 17:36:38 +03:00
|
|
|
{id}
|
2026-02-25 10:04:25 +03:00
|
|
|
class="w-full max-w-7xl mx-auto px-4 md:px-6 pb-32 md:pb-48"
|
2026-01-30 17:40:11 +03:00
|
|
|
in:fly={flyParams}
|
|
|
|
|
out:fly={flyParams}
|
|
|
|
|
>
|
2026-02-25 10:04:25 +03:00
|
|
|
<div>
|
|
|
|
|
{#if headerTitle}
|
|
|
|
|
<SectionHeader title={headerTitle} subtitle={headerSubtitle} index={index} />
|
2026-01-30 17:40:11 +03:00
|
|
|
{/if}
|
2026-02-25 10:04:25 +03:00
|
|
|
<SectionTitle text={title} />
|
2026-01-30 17:40:11 +03:00
|
|
|
</div>
|
2026-02-25 10:04:25 +03:00
|
|
|
{@render content?.({})}
|
2026-01-30 17:40:11 +03:00
|
|
|
</section>
|