Files
ui-essentials/projects/demo-ui-essentials/src/app/demos/scroll-container-demo/scroll-container-demo.component.ts
skyai_dev 876eb301a0 Restructure layout components architecture
- Move layout components from layouts/ directory to components/layout/
- Reorganize divider component from data-display to layout category
- Add comprehensive layout component collection including aspect-ratio, bento-grid, box, breakpoint-container, center, column, dashboard-shell, feed-layout, flex, grid-container, hstack, list-detail-layout, scroll-container, section, sidebar-layout, stack, supporting-pane-layout, tabs-container, and vstack
- Update all demo components to match new layout structure
- Refactor routing and index exports to reflect reorganized component architecture

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-04 12:28:47 +10:00

327 lines
11 KiB
TypeScript

import { Component, TemplateRef, ViewChild } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ScrollContainerComponent, ScrollVirtualConfig } from '../../../../../ui-essentials/src/lib/components/layout/scroll-container/scroll-container.component';
@Component({
selector: 'ui-scroll-container-demo',
standalone: true,
imports: [CommonModule, ScrollContainerComponent],
template: `
<div class="demo-container">
<h2>ScrollContainer Demo</h2>
<!-- Basic Scrolling -->
<section class="demo-section">
<h3>Basic Vertical Scrolling</h3>
<ui-scroll-container
[style.height.px]="200"
[style.width.px]="400"
direction="vertical"
scrollbarVisibility="auto"
[showScrollIndicators]="true"
(scrolled)="onScroll($event)"
(reachedTop)="onReachedTop()"
(reachedBottom)="onReachedBottom()">
<div class="demo-content">
@for (item of longContent; track item; let i = $index) {
<p>{{ i + 1 }}. {{ item }}</p>
}
</div>
</ui-scroll-container>
<p class="demo-info">Scroll events: Top reached {{ topCount }} times, Bottom reached {{ bottomCount }} times</p>
</section>
<!-- Direction Variants -->
<section class="demo-section">
<h3>Direction Variants</h3>
<div class="demo-row">
<!-- Vertical -->
<div class="demo-item">
<h4>Vertical</h4>
<ui-scroll-container
[style.height.px]="150"
[style.width.px]="200"
direction="vertical">
<div class="demo-content">
@for (item of shortContent; track item; let i = $index) {
<p>{{ i + 1 }}. {{ item }}</p>
}
</div>
</ui-scroll-container>
</div>
<!-- Horizontal -->
<div class="demo-item">
<h4>Horizontal</h4>
<ui-scroll-container
[style.height.px]="100"
[style.width.px]="200"
direction="horizontal">
<div class="demo-horizontal-content">
@for (item of horizontalItems; track item) {
<div class="demo-horizontal-item">{{ item }}</div>
}
</div>
</ui-scroll-container>
</div>
<!-- Both -->
<div class="demo-item">
<h4>Both Directions</h4>
<ui-scroll-container
[style.height.px]="150"
[style.width.px]="200"
direction="both">
<div class="demo-large-content">
<table class="demo-table">
@for (row of tableData; track row.id) {
<tr>
<td>{{ row.id }}</td>
<td>{{ row.name }}</td>
<td>{{ row.description }}</td>
<td>{{ row.value }}</td>
<td>{{ row.status }}</td>
</tr>
}
</table>
</div>
</ui-scroll-container>
</div>
</div>
</section>
<!-- Scrollbar Visibility -->
<section class="demo-section">
<h3>Scrollbar Visibility</h3>
<div class="demo-row">
@for (visibility of scrollbarOptions; track visibility) {
<div class="demo-item">
<h4>{{ visibility | titlecase }}</h4>
<ui-scroll-container
[style.height.px]="120"
[style.width.px]="200"
[scrollbarVisibility]="visibility">
<div class="demo-content">
@for (item of shortContent; track item; let i = $index) {
<p>{{ i + 1 }}. {{ item }}</p>
}
</div>
</ui-scroll-container>
</div>
}
</div>
</section>
<!-- Virtual Scrolling -->
<section class="demo-section">
<h3>Virtual Scrolling</h3>
<div class="demo-item">
<p>Virtual scrolling with {{ largeDataset.length }} items (only visible items are rendered)</p>
<ui-scroll-container
[style.height.px]="300"
[style.width.px]="400"
[virtualScrollConfig]="virtualConfig"
[items]="largeDataset"
[itemTemplate]="itemTemplate"
[trackByFn]="trackByItem">
</ui-scroll-container>
</div>
</section>
<!-- Smooth Scrolling & Controls -->
<section class="demo-section">
<h3>Scroll Controls & Smooth Scrolling</h3>
<div class="demo-controls">
<button (click)="scrollToTop()">Scroll to Top</button>
<button (click)="scrollToBottom()">Scroll to Bottom</button>
<button (click)="scrollToMiddle()">Scroll to Middle</button>
<button (click)="toggleSmoothScroll()">
{{ smoothScrollEnabled ? 'Disable' : 'Enable' }} Smooth Scroll
</button>
</div>
<ui-scroll-container
#controllableScroll
[style.height.px]="250"
[style.width.px]="400"
[scrollBehavior]="smoothScrollEnabled ? 'smooth' : 'auto'"
[showScrollIndicators]="true">
<div class="demo-content">
@for (item of longContent; track item; let i = $index) {
<p [id]="'item-' + i">{{ i + 1 }}. {{ item }}</p>
}
</div>
</ui-scroll-container>
</section>
<!-- Position Restoration -->
<section class="demo-section">
<h3>Scroll Position Restoration</h3>
<p>Scroll position is saved and restored automatically (uses sessionStorage)</p>
<ui-scroll-container
[style.height.px]="200"
[style.width.px]="400"
[restoreScrollPosition]="true"
scrollPositionKey="demo-scroll">
<div class="demo-content">
@for (item of longContent; track item; let i = $index) {
<p>{{ i + 1 }}. {{ item }}</p>
}
</div>
</ui-scroll-container>
</section>
<!-- Interactive Example -->
<section class="demo-section">
<h3>Interactive Example</h3>
<div class="demo-stats">
<p>Current scroll position: {{ currentScrollPosition.top }}px (top), {{ currentScrollPosition.left }}px (left)</p>
<p>Is scrolling: {{ isScrolling ? 'Yes' : 'No' }}</p>
</div>
<ui-scroll-container
[style.height.px]="200"
[style.width.px]="400"
direction="both"
(scrolled)="updateScrollPosition($event)"
(scrollStart)="onScrollStart()"
(scrollEnd)="onScrollEnd()">
<div class="demo-large-content">
<div class="demo-grid">
@for (item of gridData; track item.id) {
<div class="demo-grid-item">
<h4>Item {{ item.id }}</h4>
<p>{{ item.content }}</p>
</div>
}
</div>
</div>
</ui-scroll-container>
</section>
</div>
<!-- Virtual Scrolling Item Template -->
<ng-template #itemTemplate let-item="item" let-index="index">
<div class="virtual-item">
<strong>Item {{ index + 1 }}:</strong> {{ item.name }} - {{ item.description }}
</div>
</ng-template>
`,
styleUrl: './scroll-container-demo.component.scss'
})
export class ScrollContainerDemoComponent {
@ViewChild('controllableScroll') controllableScroll!: ScrollContainerComponent;
@ViewChild('itemTemplate') itemTemplate!: TemplateRef<any>;
// Content data
longContent = [
'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
'Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
'Ut enim ad minim veniam, quis nostrud exercitation ullamco.',
'Duis aute irure dolor in reprehenderit in voluptate velit esse.',
'Excepteur sint occaecat cupidatat non proident, sunt in culpa.',
'Qui officia deserunt mollit anim id est laborum.',
'At vero eos et accusamus et iusto odio dignissimos ducimus.',
'Et harum quidem rerum facilis est et expedita distinctio.',
'Nam libero tempore, cum soluta nobis est eligendi optio.',
'Temporibus autem quibusdam et aut officiis debitis aut rerum.',
'Itaque earum rerum hic tenetur a sapiente delectus.',
'Ut aut reiciendis voluptatibus maiores alias consequatur.',
'Sed ut perspiciatis unde omnis iste natus error sit.',
'Voluptatem accusantium doloremque laudantium, totam rem.',
'Aperiam, eaque ipsa quae ab illo inventore veritatis.',
'Quasi architecto beatae vitae dicta sunt explicabo.',
'Nemo enim ipsam voluptatem quia voluptas sit aspernatur.',
'Neque porro quisquam est, qui dolorem ipsum quia dolor.',
'Consectetur, adipisci velit, sed quia non numquam eius.',
'Modi tempora incidunt ut labore et dolore magnam.'
];
shortContent = this.longContent.slice(0, 8);
horizontalItems = [
'Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5',
'Item 6', 'Item 7', 'Item 8', 'Item 9', 'Item 10'
];
tableData = Array.from({ length: 20 }, (_, i) => ({
id: i + 1,
name: `Row ${i + 1}`,
description: `Description for row ${i + 1} with some longer text`,
value: Math.floor(Math.random() * 1000),
status: i % 3 === 0 ? 'Active' : i % 3 === 1 ? 'Pending' : 'Inactive'
}));
// Virtual scrolling data
largeDataset = Array.from({ length: 10000 }, (_, i) => ({
id: i + 1,
name: `Item ${i + 1}`,
description: `This is a description for item number ${i + 1}. It contains some sample text to demonstrate virtual scrolling.`
}));
virtualConfig: ScrollVirtualConfig = {
itemHeight: 60,
bufferSize: 5,
enabled: true
};
gridData = Array.from({ length: 50 }, (_, i) => ({
id: i + 1,
content: `Grid item content ${i + 1} with some descriptive text that makes it interesting.`
}));
// Options
scrollbarOptions = ['auto', 'always', 'never'] as const;
// State
topCount = 0;
bottomCount = 0;
smoothScrollEnabled = false;
currentScrollPosition = { top: 0, left: 0 };
isScrolling = false;
// Event handlers
onScroll(position: any): void {
// Handle scroll event if needed
}
onReachedTop(): void {
this.topCount++;
}
onReachedBottom(): void {
this.bottomCount++;
}
updateScrollPosition(position: any): void {
this.currentScrollPosition = position;
}
onScrollStart(): void {
this.isScrolling = true;
}
onScrollEnd(): void {
this.isScrolling = false;
}
// Control methods
scrollToTop(): void {
this.controllableScroll?.scrollToTop();
}
scrollToBottom(): void {
this.controllableScroll?.scrollToBottom();
}
scrollToMiddle(): void {
this.controllableScroll?.scrollTo({ top: 1000 });
}
toggleSmoothScroll(): void {
this.smoothScrollEnabled = !this.smoothScrollEnabled;
}
// Virtual scrolling
trackByItem(item: any): any {
return item.id;
}
}