- 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>
327 lines
11 KiB
TypeScript
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;
|
|
}
|
|
} |