<template>
    <ClientOnly>
<AppDoc name="VirtualScrollerDemo" :sources="sources" github="virtualscroller/VirtualScrollerDemo.vue">
        <h5>Imports</h5>
        <pre v-code.script><code>
import VirtualScroller from 'primevue/virtualscroller';

</code></pre>

        <h5>Import via CDN</h5>
        <pre v-code><code>
&lt;script src="https://unpkg.com/primevue@^3/core/core.min.js"&gt;&lt;/script&gt;

</code></pre>

        <h5>Getting Started</h5>
        <p>
            VirtualScroller is used to display huge data. It periodically adds special elements defined according to the scroll's position to the DOM. The <i>item</i> and <i>itemSize</i> properties and <i>item</i> template are required on component.
            In addition, an initial array is required based on the total number of items to display.<br />
            VirtualScroller automatically calculates how many items will be displayed in the view according to <i>itemSize</i> using a specified scroll height. Its scroll height can be adjusted with <i>scrollHeight</i> property or height property of
            CSS.
        </p>

        <pre v-code><code><template v-pre>
&lt;VirtualScroller :items="basicItems" :itemSize="50"&gt;
    &lt;template v-slot:item="{ item, options }"&gt;
        &lt;div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px"&gt;{{ item }}&lt;/div&gt;
    &lt;/template&gt;
&lt;/VirtualScroller&gt;
</template>
</code></pre>

        <pre v-code.script><code>
export default {
    data() {
        return {
            basicItems: null
        }
    },
    mounted() {
        this.basicItems = Array.from({ length: 100000 }).map((_, i) => `Item #${i}`);
    }
}

</code></pre>

        <h5>Loader</h5>
        <p>VirtualScroller has a special loader. It can be activated with the <i>showLoader</i> property. In addition, <i>loader</i> template can be used to add custom loaders to item elements.</p>

        <pre v-code><code><template v-pre>
&lt;VirtualScroller :items="basicItems" :itemSize="50" showLoader :delay="250"&gt;
    &lt;template v-slot:item="{ item, options }"&gt;
        &lt;div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px"&gt;{{ item }}&lt;/div&gt;
    &lt;/template&gt;
    &lt;template v-slot:loader="{ options }"&gt;
        &lt;div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" &gt;
            &lt;Skeleton :width="options.even ? '60%' : '50%'" height="1.3rem" /&gt;
        &lt;/div&gt;
    &lt;/template&gt;
&lt;/VirtualScroller&gt;
</template>
</code></pre>

        <h5>Lazy</h5>
        <p>Lazy mode is handy to deal with large datasets, instead of loading the entire data, small chunks of data is loaded by invoking <i>lazy-load</i> event.</p>

        <pre v-code><code><template v-pre>
&lt;VirtualScroller :items="lazyItems" :itemSize="50" showLoader :delay="250" :loading="lazyLoading" :lazy=true @lazy-load="onLazyLoad"&gt;
    &lt;template v-slot:item="{ item, options }"&gt;
        &lt;div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px"&gt;{{ item }}&lt;/div&gt;
    &lt;/template&gt;
&lt;/VirtualScroller&gt;
</template>
</code></pre>

        <pre v-code.script><code>
export default {
    data() {
        return {
            lazyItems: null,
            lazyLoading: false,
            loadLazyTimeout: null,
        }
    },
    mounted() {
        this.lazyItems = Array.from({ length: 100000 });
    },
    methods: {
        onLazyLoad(event) {
            this.lazyLoading = true;

            if (this.loadLazyTimeout) {
                clearTimeout(this.loadLazyTimeout);
            }

            //imitate delay of a backend call
            this.loadLazyTimeout = setTimeout(() => {
                const { first, last } = event;
                const lazyItems = [...this.lazyItems];

                for (let i = first; i &lt; last; i++) {
                    lazyItems[i] = `Item #${i}`;
                }

                this.lazyItems = lazyItems;
                this.lazyLoading = false;

            }, Math.random() * 1000 + 250);
        }
    }
}

</code></pre>

        <h5>Properties</h5>
        <div class="doc-tablewrapper">
            <table class="doc-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Type</th>
                        <th>Default</th>
                        <th>Description</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>id</td>
                        <td>string</td>
                        <td>null</td>
                        <td>Unique identifier of the element.</td>
                    </tr>
                    <tr>
                        <td>style</td>
                        <td>any</td>
                        <td>null</td>
                        <td>Inline style of the component.</td>
                    </tr>
                    <tr>
                        <td>class</td>
                        <td>string</td>
                        <td>null</td>
                        <td>Style class of the component.</td>
                    </tr>
                    <tr>
                        <td>items</td>
                        <td>array</td>
                        <td>null</td>
                        <td>An array of objects to display.</td>
                    </tr>
                    <tr>
                        <td>itemSize</td>
                        <td>number / [number, number]</td>
                        <td>null</td>
                        <td>The height/width of item according to orientation.</td>
                    </tr>
                    <tr>
                        <td>scrollHeight</td>
                        <td>string</td>
                        <td>null</td>
                        <td>Height of the scroll viewport.</td>
                    </tr>
                    <tr>
                        <td>scrollWidth</td>
                        <td>string</td>
                        <td>null</td>
                        <td>Width of the scroll viewport.</td>
                    </tr>
                    <tr>
                        <td>orientation</td>
                        <td>string</td>
                        <td>'vertical'</td>
                        <td>The orientation of scrollbar, valid values are 'vertical', 'horizontal' and 'both'.</td>
                    </tr>
                    <tr>
                        <td>numToleratedItems</td>
                        <td>number</td>
                        <td>null</td>
                        <td>
                            Determines how many additional elements to add to the DOM outside of the view. <br />
                            According to the scrolls made up and down, extra items are added in a certain algorithm in the form of multiples of this number. <br />
                            Default value is half the number of items shown in the view.
                        </td>
                    </tr>
                    <tr>
                        <td>delay</td>
                        <td>number</td>
                        <td>0</td>
                        <td>Delay in scroll before new data is loaded.</td>
                    </tr>
                    <tr>
                        <td>lazy</td>
                        <td>boolean</td>
                        <td>false</td>
                        <td>Defines if data is loaded and interacted with in lazy manner.</td>
                    </tr>
                    <tr>
                        <td>disabled</td>
                        <td>boolean</td>
                        <td>false</td>
                        <td>If disabled, the VirtualScroller feature is eliminated and the content is displayed directly.</td>
                    </tr>
                    <tr>
                        <td>loaderDisabled</td>
                        <td>boolean</td>
                        <td>false</td>
                        <td>Used to implement a custom loader instead of using the loader feature in the VirtualScroller.</td>
                    </tr>
                    <tr>
                        <td>loading</td>
                        <td>boolean</td>
                        <td>false</td>
                        <td>Whether the data is loaded.</td>
                    </tr>
                    <tr>
                        <td>showSpacer</td>
                        <td>boolean</td>
                        <td>true</td>
                        <td>Used to implement a custom spacer instead of using the spacer feature in the VirtualScroller.</td>
                    </tr>
                    <tr>
                        <td>showLoader</td>
                        <td>boolean</td>
                        <td>false</td>
                        <td>Whether to show loader.</td>
                    </tr>
                    <tr>
                        <td>tabindex</td>
                        <td>number</td>
                        <td>0</td>
                        <td>Index of the element in tabbing order.</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <h5>Events</h5>
        <div class="doc-tablewrapper">
            <table class="doc-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Parameters</th>
                        <th>Description</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>scroll</td>
                        <td>event: Browser event</td>
                        <td>Callback to invoke when scroll position changes.</td>
                    </tr>
                    <tr>
                        <td>scroll-index-change</td>
                        <td>
                            event.first: First index of the new data range to be loaded.<br />
                            event.last: Last index of the new data range to be loaded.
                        </td>
                        <td>Callback to invoke when scroll position and item's range in view changes.</td>
                    </tr>
                    <tr>
                        <td>lazy-load</td>
                        <td>
                            event.first: First index of the new data range to be loaded.<br />
                            event.last: Last index of the new data range to be loaded.
                        </td>
                        <td>Callback to invoke in lazy mode to load new data.</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <h5>Methods</h5>
        <div class="doc-tablewrapper">
            <table class="doc-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Parameters</th>
                        <th>Description</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>scrollTo</td>
                        <td>
                            left: Left position of scroll. <br />
                            top: Top position of scroll <br />
                            behavior: Behavior of scroll, valid values are 'auto' and 'smooth'
                        </td>
                        <td>Scroll to move to a specific position.</td>
                    </tr>
                    <tr>
                        <td>scrollToIndex</td>
                        <td>
                            index: Index of item according to orientation mode. <br />
                            behavior: Behavior of scroll, valid values are 'auto' and 'smooth'
                        </td>
                        <td>Scroll to move to a specific item.</td>
                    </tr>
                    <tr>
                        <td>scrollInView</td>
                        <td>
                            index: Index of item according to orientation mode. <br />
                            to: Defines the location of the item in view, valid values are 'to-start' and 'to-end'. <br />
                            behavior: Behavior of scroll, valid values are 'auto' and 'smooth'
                        </td>
                        <td>It is used to move the specified index into the view. It is a method that will usually be needed when keyboard support is added to the virtualScroller component.</td>
                    </tr>
                    <tr>
                        <td>getRenderedRange</td>
                        <td>-</td>
                        <td>Returns the range of items added to the DOM.</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <h5>Slots</h5>
        <div class="doc-tablewrapper">
            <table class="doc-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Parameters</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>content</td>
                        <td>
                            items: An array of objects to display.<br />
                            styleClass: Style class of the component<br />
                            contentRef: Referance of the content<br />
                            getItemOptions: Options of the items<br />
                            loading: Whether the data is loaded<br />
                            getLoaderOptions: Loader options of the items while the data is loading.<br />
                            itemSize: The height/width of item according to orientation.<br />
                            rows: The number of the rendered rows.<br />
                            columns: The number of the rendered columns.<br />
                            spacerStyle: The style of spacer element.<br />
                            contentStyle: The style of content element.<br />
                            vertical: Whether the orientation is vertical.<br />
                            horizontal: Whether the orientation is horizontal.<br />
                            both: Whether the orientation is both.<br />
                        </td>
                    </tr>
                    <tr>
                        <td>item</td>
                        <td>
                            item: Item instance<br />
                            options: Options of the item instance
                        </td>
                    </tr>
                    <tr>
                        <td>loader</td>
                        <td>options: Options of the loader items</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <h5>Styling</h5>
        <p>Following is the list of structural style classes, for theming classes visit <nuxt-link to="/theming">theming</nuxt-link> page.</p>
        <div class="doc-tablewrapper">
            <table class="doc-table">
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Element</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td>p-virtualscroller</td>
                        <td>Container element.</td>
                    </tr>
                    <tr>
                        <td>p-virtualscroller-content</td>
                        <td>Content element.</td>
                    </tr>
                    <tr>
                        <td>p-virtualscroller-loader</td>
                        <td>Loader element.</td>
                    </tr>
                </tbody>
            </table>
        </div>

        <h5>Dependencies</h5>
        <p>None.</p>
    </AppDoc>
</ClientOnly>
</template>

<script>
export default {
    data() {
        return {
            sources: {
                'options-api': {
                    tabName: 'Options API Source',
                    content: `
<template>
    <div class="virtualscroller-demo">
        <div class="card">
            <h5 class="mb-0">Basic</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>Vertical</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Horizontal</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" orientation="horizontal">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="width: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Both</h6>
                    <VirtualScroller :items="multiItems" :itemSize="[50, 100]" orientation="both">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                <template v-for="(el, index) of item" :key="index">
                                    <div style="width: 100px">{{ el }}</div>
                                </template>
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Scroll Delay</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>0ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>150ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" :delay="150">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>250ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Loading</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>Basic</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Templating</h6>
                    <VirtualScroller class="custom-loading" :items="basicItems" :itemSize="50" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                        <template v-slot:loader="{ options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                <Skeleton :width="options.even ? '60%' : '50%'" height="1.3rem" />
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Lazy</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <VirtualScroller :items="lazyItems" :itemSize="50" showLoader :delay="250" :loading="lazyLoading" :lazy=true @lazy-load="onLazyLoad">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Template</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <VirtualScroller class="custom-loading" :items="basicItems" :itemSize="25 * 7" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Item: \${item}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Index: \${options.index}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Count: \${options.count}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`First: \${options.first}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Last: \${options.last}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Even: \${options.even}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Odd: \${options.odd}\`}}</div>
                            </div>
                        </template>
                        <template v-slot:loader="{ options }">
                            <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data() {
        return {
            basicItems: null,
            multiItems: null,
            lazyItems: null,
            lazyLoading: false,
            loadLazyTimeout: null,
        }
    },
    mounted() {
        this.basicItems = Array.from({ length: 100000 }).map((_, i) => \`Item #\${i}\`);
        this.multiItems = Array.from({ length: 1000 }).map((_, i) => Array.from({ length: 1000 }).map((_j, j) => \`Item #\${i}_\${j}\`));
        this.lazyItems = Array.from({ length: 10000 });
    },
    methods: {
        onLazyLoad(event) {
            this.lazyLoading = true;

            if (this.loadLazyTimeout) {
                clearTimeout(this.loadLazyTimeout);
            }

            //imitate delay of a backend call
            this.loadLazyTimeout = setTimeout(() => {
                const { first, last } = event;
                const lazyItems = [...this.lazyItems];

                for (let i = first; i < last; i++) {
                    lazyItems[i] = \`Item #\${i}\`;
                }

                this.lazyItems = lazyItems;
                this.lazyLoading = false;

            }, Math.random() * 1000 + 250);
        }
    }
}
<\\/script>

<style lang="scss" scoped>
.virtualscroller-demo {
	::v-deep(.p-virtualscroller) {
		height: 200px;
		width: 200px;
		border: 1px solid var(--surface-border);

        .scroll-item {
            background-color: var(--surface-card);
            display: flex;
            align-items: center;
        }

        .custom-scroll-item {
            flex-direction: column;
            align-items: stretch;
        }

        .odd {
            background-color: var(--surface-ground);
        }
	}

    ::v-deep(.p-horizontal-scroll) {
        .p-virtualscroller-content {
            display: flex;
            flex-direction: row;
        }

        .scroll-item {
            writing-mode: vertical-lr;
        }
    }

    ::v-deep(.custom-loading > .p-virtualscroller-loader) {
        display: block;
    }
}
</style>

`
                },
                'composition-api': {
                    tabName: 'Composition API Source',
                    content: `
<template>
    <div class="virtualscroller-demo">
        <div class="card">
            <h5 class="mb-0">Basic</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>Vertical</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Horizontal</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" orientation="horizontal">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="width: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Both</h6>
                    <VirtualScroller :items="multiItems" :itemSize="[50, 100]" orientation="both">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                <template v-for="(el, index) of item" :key="index">
                                    <div style="width: 100px">{{ el }}</div>
                                </template>
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Scroll Delay</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>0ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>150ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" :delay="150">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>250ms Delay</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Loading</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <h6>Basic</h6>
                    <VirtualScroller :items="basicItems" :itemSize="50" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>

                <div class="flex flex-column mr-3 mt-3">
                    <h6>Templating</h6>
                    <VirtualScroller class="custom-loading" :items="basicItems" :itemSize="50" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                        <template v-slot:loader="{ options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                <Skeleton :width="options.even ? '60%' : '50%'" height="1.3rem" />
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Lazy</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <VirtualScroller :items="lazyItems" :itemSize="50" showLoader :delay="250" :loading="lazyLoading" :lazy=true @lazy-load="onLazyLoad">
                        <template v-slot:item="{ item, options }">
                            <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>

        <div class="card">
            <h5 class="mb-0">Template</h5>
            <div class="flex align-items-center flex-wrap">
                <div class="flex flex-column mr-3 mt-3">
                    <VirtualScroller class="custom-loading" :items="basicItems" :itemSize="25 * 7" showLoader :delay="250">
                        <template v-slot:item="{ item, options }">
                            <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Item: \${item}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Index: \${options.index}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Count: \${options.count}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`First: \${options.first}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Last: \${options.last}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Even: \${options.even}\`}}</div>
                                <div class="flex align-items-center px-2" style="height: 25px">{{\`Odd: \${options.odd}\`}}</div>
                            </div>
                        </template>
                        <template v-slot:loader="{ options }">
                            <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="50%" height="1.2rem" /></div>
                                <div class="flex align-items-center px-2" style="height: 25px"><Skeleton width="60%" height="1.2rem" /></div>
                            </div>
                        </template>
                    </VirtualScroller>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
import { ref, onMounted } from 'vue';

export default {
    setup() {
        const basicItems = ref(Array.from({ length: 100000 }).map((_, i) => \`Item #\${i}\`));
        const multiItems = ref(Array.from({ length: 1000 }).map((_, i) => Array.from({ length: 1000 }).map((_j, j) => \`Item #\${i}_\${j}\`)));
        const lazyItems = ref(Array.from({ length: 10000 }));
        const lazyLoading = ref(false);
        const loadLazyTimeout = ref(null);

        const onLazyLoad = (event) => {
            lazyLoading.value = true;

            if (loadLazyTimeout.value) {
                clearTimeout(loadLazyTimeout.value);
            }

            //imitate delay of a backend call
            loadLazyTimeout.value = setTimeout(() => {
                const { first, last } = event;
                const _lazyItems = [...lazyItems.value];

                for (let i = first; i < last; i++) {
                    _lazyItems[i] = \`Item #\${i}\`;
                }

                lazyItems.value = _lazyItems;
                lazyLoading.value = false;

            }, Math.random() * 1000 + 250);
        }

        return { basicItems, multiItems, lazyItems, lazyLoading, onLazyLoad }
    },
    methods: {

    }
}
<\\/script>

<style lang="scss" scoped>
.virtualscroller-demo {
	::v-deep(.p-virtualscroller) {
		height: 200px;
		width: 200px;
		border: 1px solid var(--surface-border);

        .scroll-item {
            background-color: var(--surface-card);
            display: flex;
            align-items: center;
        }

        .custom-scroll-item {
            flex-direction: column;
            align-items: stretch;
        }

        .odd {
            background-color: var(--surface-ground);
        }
	}

    ::v-deep(.p-horizontal-scroll) {
        .p-virtualscroller-content {
            display: flex;
            flex-direction: row;
        }

        .scroll-item {
            writing-mode: vertical-lr;
        }
    }

    ::v-deep(.custom-loading > .p-virtualscroller-loader) {
        display: block;
    }
}
</style>
`
                },
                'browser-source': {
                    tabName: 'Browser Source',
                    imports: `<script src="https://unpkg.com/primevue@^3/skeleton/skeleton.min.js"><\\/script>`,
                    content: `<div id="app">
            <div class="virtualscroller-demo">
                <div class="card">
                    <h5 class="mb-0">Basic</h5>
                    <div class="flex align-items-center flex-wrap">
                        <div class="flex flex-column mr-3 mt-3">
                            <h6>Vertical</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>

                        <div class="flex flex-column mr-3 mt-3">
                            <h6>Horizontal</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50" orientation="horizontal">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="width: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>

                        <div class="flex flex-column mr-3 mt-3">
                            <h6>Both</h6>
                            <p-virtualscroller :items="multiItems" :item-size="[50, 100]" orientation="both">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                        <template v-for="(el, index) of item" :key="index">
                                            <div style="width: 100px">{{ el }}</div>
                                        </template>
                                    </div>
                                </template>
                            </p-virtualscroller>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <h5 class="mb-0">Scroll Delay</h5>
                    <div class="flex align-items-center flex-wrap">
                        <div class="flex flex-column mr-3 mt-3">
                            <h6>0ms Delay</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>

                        <div class="flex flex-column mr-3 mt-3">
                            <h6>150ms Delay</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50" :delay="150">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>

                        <div class="flex flex-column mr-3 mt-3">
                            <h6>250ms Delay</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50" :delay="250">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <h5 class="mb-0">Loading</h5>
                    <div class="flex align-items-center flex-wrap">
                        <div class="flex flex-column mr-3 mt-3">
                            <h6>Basic</h6>
                            <p-virtualscroller :items="basicItems" :item-size="50" show-loader :delay="250">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>

                        <div class="flex flex-column mr-3 mt-3">
                            <h6>Templating</h6>
                            <p-virtualscroller class="custom-loading" :items="basicItems" :item-size="50" show-loader :delay="250">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                                <template v-slot:loader="{ options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px" >
                                        <p-skeleton :width="options.even ? '60%' : '50%'" height="1.3rem"></p-skeleton>
                                    </div>
                                </template>
                            </p-virtualscroller>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <h5 class="mb-0">Lazy</h5>
                    <div class="flex align-items-center flex-wrap">
                        <div class="flex flex-column mr-3 mt-3">
                            <p-virtualscroller :items="lazyItems" :item-size="50" show-loader :delay="250" :loading="lazyLoading" :lazy=true @lazy-load="onLazyLoad">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['scroll-item p-2', {'odd': options.odd}]" style="height: 50px">{{ item }}</div>
                                </template>
                            </p-virtualscroller>
                        </div>
                    </div>
                </div>

                <div class="card">
                    <h5 class="mb-0">Template</h5>
                    <div class="flex align-items-center flex-wrap">
                        <div class="flex flex-column mr-3 mt-3">
                            <p-virtualscroller class="custom-loading" :items="basicItems" :item-size="25 * 7" show-loader :delay="250">
                                <template v-slot:item="{ item, options }">
                                    <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Item: \${item}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Index: \${options.index}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Count: \${options.count}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`First: \${options.first}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Last: \${options.last}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Even: \${options.even}\`}}</div>
                                        <div class="flex align-items-center px-2" style="height: 25px">{{\`Odd: \${options.odd}\`}}</div>
                                    </div>
                                </template>
                                <template v-slot:loader="{ options }">
                                    <div :class="['custom-scroll-item scroll-item', {'odd': options.odd}]">
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="60%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="50%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="60%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="50%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="60%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="50%" height="1.2rem"></p-skeleton></div>
                                        <div class="flex align-items-center px-2" style="height: 25px"><p-skeleton width="60%" height="1.2rem"></p-skeleton></div>
                                    </div>
                                </template>
                            </p-virtualscroller>
                        </div>
                    </div>
                </div>
            </div>
        </div>

        <script type="module">
        const { createApp, ref, onMounted } = Vue;

        const App = {
            setup() {
                const basicItems = ref(Array.from({ length: 100000 }).map((_, i) => \`Item #\${i}\`));
                const multiItems = ref(Array.from({ length: 1000 }).map((_, i) => Array.from({ length: 1000 }).map((_j, j) => \`Item #\${i}_\${j}\`)));
                const lazyItems = ref(Array.from({ length: 10000 }));
                const lazyLoading = ref(false);
                const loadLazyTimeout = ref(null);

                const onLazyLoad = (event) => {
                    lazyLoading.value = true;

                    if (loadLazyTimeout.value) {
                        clearTimeout(loadLazyTimeout.value);
                    }

                    //imitate delay of a backend call
                    loadLazyTimeout.value = setTimeout(() => {
                        const { first, last } = event;
                        const _lazyItems = [...lazyItems.value];

                        for (let i = first; i < last; i++) {
                            _lazyItems[i] = \`Item #\${i}\`;
                        }

                        lazyItems.value = _lazyItems;
                        lazyLoading.value = false;

                    }, Math.random() * 1000 + 250);
                }

                return { basicItems, multiItems, lazyItems, lazyLoading, onLazyLoad }
            },
            components: {
                "p-virtualscroller": primevue.virtualscroller,
                "p-skeleton": primevue.skeleton
            }
        };

        createApp(App)
            .use(primevue.config.default)
            .mount("#app");
        <\\/script>

        <style>
            .virtualscroller-demo .p-virtualscroller {
                height: 200px;
                width: 200px;
                border: 1px solid var(--surface-border);
            }

            .virtualscroller-demo .p-virtualscroller .scroll-item {
                background-color: var(--surface-card);
                display: flex;
                align-items: center;
            }

            .virtualscroller-demo .p-virtualscroller .custom-scroll-item {
                flex-direction: column;
                align-items: stretch;
            }

            .virtualscroller-demo .p-virtualscroller .odd {
                background-color: var(--surface-ground);
            }

            .virtualscroller-demo .p-horizontal-scroll .p-virtualscroller-content {
                display: flex;
                flex-direction: row;
            }

            .virtualscroller-demo .p-horizontal-scroll .scroll-item {
                writing-mode: vertical-lr;
            }

            .virtualscroller-demo .custom-loading > .p-virtualscroller-loader {
                display: block;
            }

        </style>
`
                }
            }
        };
    }
};
</script>
