mirror of
https://github.com/divkit/divkit.git
synced 2026-06-06 20:07:59 +00:00
Allow empty grid / pager / gallery
This commit is contained in:
@@ -51,7 +51,6 @@
|
||||
const rightClass = rootCtx.getCustomization('galleryRightClass');
|
||||
|
||||
let prevId: string | undefined;
|
||||
let hasError = false;
|
||||
let columns = 1;
|
||||
let orientation: Orientation = 'horizontal';
|
||||
let align: Align = 'start';
|
||||
@@ -75,7 +74,7 @@
|
||||
padding = '';
|
||||
}
|
||||
|
||||
$: jsonItems = json.items;
|
||||
$: jsonItems = Array.isArray(json.items) && json.items || [];
|
||||
|
||||
$: jsonColumnCount = rootCtx.getDerivedFromVars(json.column_count);
|
||||
$: jsonOrientation = rootCtx.getDerivedFromVars(json.orientation);
|
||||
@@ -88,15 +87,6 @@
|
||||
$: jsonScrollbar = rootCtx.getDerivedFromVars(json.scrollbar);
|
||||
$: jsonDefaultItem = rootCtx.getDerivedFromVars(json.default_item);
|
||||
|
||||
$: {
|
||||
if (!jsonItems?.length || !Array.isArray(jsonItems)) {
|
||||
hasError = true;
|
||||
rootCtx.logError(wrapError(new Error('Incorrect or empty "items" prop for div "gallery"')));
|
||||
} else {
|
||||
hasError = false;
|
||||
}
|
||||
}
|
||||
|
||||
function replaceItems(items: (DivBaseData | undefined)[]): void {
|
||||
json = {
|
||||
...json,
|
||||
@@ -112,7 +102,7 @@
|
||||
origJson: DivBaseData;
|
||||
}
|
||||
|
||||
$: items = (!hasError && jsonItems || []).map(item => {
|
||||
$: items = jsonItems.map(item => {
|
||||
let childJson: DivBaseData = item as DivBaseData;
|
||||
let childContext: TemplateContext = templateContext;
|
||||
|
||||
@@ -128,7 +118,7 @@
|
||||
};
|
||||
});
|
||||
|
||||
$: shouldCheckArrows = $isDesktop && mounted && !hasError;
|
||||
$: shouldCheckArrows = $isDesktop && mounted;
|
||||
$: if (shouldCheckArrows) {
|
||||
if (typeof ResizeObserver !== 'undefined') {
|
||||
// Gallery can contain a dynamic content (e.g. loading images with auto-size)
|
||||
@@ -265,7 +255,7 @@
|
||||
}
|
||||
|
||||
function updateArrowsVisibility(): void {
|
||||
if (!scroller || hasError) {
|
||||
if (!scroller) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -377,7 +367,7 @@
|
||||
prevId = undefined;
|
||||
}
|
||||
|
||||
if (json.id && !hasError && !layoutParams?.fakeElement) {
|
||||
if (json.id && !layoutParams?.fakeElement) {
|
||||
prevId = json.id;
|
||||
rootCtx.registerInstance<SwitchElements>(json.id, {
|
||||
setCurrentItem(item: number) {
|
||||
@@ -428,13 +418,11 @@
|
||||
onMount(() => {
|
||||
mounted = true;
|
||||
|
||||
if (!hasError) {
|
||||
updateArrowsVisibility();
|
||||
updateArrowsVisibility();
|
||||
|
||||
if (defaultItem) {
|
||||
const galleryElements = getItems();
|
||||
scrollToGalleryItem(galleryElements, defaultItem, 'auto');
|
||||
}
|
||||
if (defaultItem) {
|
||||
const galleryElements = getItems();
|
||||
scrollToGalleryItem(galleryElements, defaultItem, 'auto');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -450,70 +438,68 @@
|
||||
|
||||
<svelte:window on:resize={shouldCheckArrows ? updateArrowsVisibilityDebounced : null} />
|
||||
|
||||
{#if !hasError}
|
||||
<Outer
|
||||
cls={genClassName('gallery', css, mods)}
|
||||
{json}
|
||||
{origJson}
|
||||
{templateContext}
|
||||
{layoutParams}
|
||||
customPaddings={true}
|
||||
customActions={'gallery'}
|
||||
parentOf={jsonItems}
|
||||
{replaceItems}
|
||||
<Outer
|
||||
cls={genClassName('gallery', css, mods)}
|
||||
{json}
|
||||
{origJson}
|
||||
{templateContext}
|
||||
{layoutParams}
|
||||
customPaddings={true}
|
||||
customActions={'gallery'}
|
||||
parentOf={jsonItems}
|
||||
{replaceItems}
|
||||
>
|
||||
<div
|
||||
class="{css.gallery__scroller} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
|
||||
bind:this={scroller}
|
||||
on:scroll={shouldCheckArrows ? updateArrowsVisibility : null}
|
||||
style={makeStyle(scrollerStyle)}
|
||||
>
|
||||
<div
|
||||
class="{css.gallery__scroller} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
|
||||
bind:this={scroller}
|
||||
on:scroll={shouldCheckArrows ? updateArrowsVisibility : null}
|
||||
style={makeStyle(scrollerStyle)}
|
||||
bind:this={itemsGridElem}
|
||||
class={css['gallery__items-grid']}
|
||||
style={makeStyle(gridStyle)}
|
||||
>
|
||||
<div
|
||||
bind:this={itemsGridElem}
|
||||
class={css['gallery__items-grid']}
|
||||
style={makeStyle(gridStyle)}
|
||||
>
|
||||
{#each itemsGrid as itemsRow, rowIndex}
|
||||
<div
|
||||
class={css.gallery__items}
|
||||
style={makeStyle(columnStyle)}
|
||||
bind:this={galleryItemsWrappers[rowIndex]}
|
||||
>
|
||||
{#each itemsRow as item}
|
||||
<Unknown
|
||||
layoutParams={childLayoutParams}
|
||||
div={item.json}
|
||||
templateContext={item.templateContext}
|
||||
origJson={item.origJson}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{#each itemsGrid as itemsRow, rowIndex}
|
||||
<div
|
||||
class={css.gallery__items}
|
||||
style={makeStyle(columnStyle)}
|
||||
bind:this={galleryItemsWrappers[rowIndex]}
|
||||
>
|
||||
{#each itemsRow as item}
|
||||
<Unknown
|
||||
layoutParams={childLayoutParams}
|
||||
div={item.json}
|
||||
templateContext={item.templateContext}
|
||||
origJson={item.origJson}
|
||||
/>
|
||||
{/each}
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
{#if orientation === 'horizontal'}
|
||||
{#if hasScrollLeft && shouldCheckArrows}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="{leftClass || `${css.gallery__arrow} ${arrowsCss.arrow} ${arrowsCss.arrow_left}`}" on:click={() => scroll('left')}>
|
||||
{#if !leftClass}
|
||||
<svg class={arrowsCss.arrow__icon} xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<path class={css['gallery__arrow-icon-path']} d="m10 16 8.3 8 1.03-1-4-6-.7-1 .7-1 4-6-1.03-1z"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{#if hasScrollRight && shouldCheckArrows}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="{rightClass || `${css.gallery__arrow} ${arrowsCss.arrow} ${arrowsCss.arrow_right}`}" on:click={() => scroll('right')}>
|
||||
{#if !rightClass}
|
||||
<svg class={arrowsCss.arrow__icon} xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<path class={css['gallery__arrow-icon-path']} d="M22 16l-8.3 8-1.03-1 4-6 .7-1-.7-1-4-6 1.03-1 8.3 8z"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if orientation === 'horizontal'}
|
||||
{#if hasScrollLeft && shouldCheckArrows}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="{leftClass || `${css.gallery__arrow} ${arrowsCss.arrow} ${arrowsCss.arrow_left}`}" on:click={() => scroll('left')}>
|
||||
{#if !leftClass}
|
||||
<svg class={arrowsCss.arrow__icon} xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<path class={css['gallery__arrow-icon-path']} d="m10 16 8.3 8 1.03-1-4-6-.7-1 .7-1 4-6-1.03-1z"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</Outer>
|
||||
{/if}
|
||||
{#if hasScrollRight && shouldCheckArrows}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div class="{rightClass || `${css.gallery__arrow} ${arrowsCss.arrow} ${arrowsCss.arrow_right}`}" on:click={() => scroll('right')}>
|
||||
{#if !rightClass}
|
||||
<svg class={arrowsCss.arrow__icon} xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32" fill="none">
|
||||
<path class={css['gallery__arrow-icon-path']} d="M22 16l-8.3 8-1.03-1 4-6 .7-1-.7-1-4-6 1.03-1 8.3 8z"/>
|
||||
</svg>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</Outer>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
const rootCtx = getContext<RootCtxValue>(ROOT_CTX);
|
||||
|
||||
let hasItemsError = false;
|
||||
let columnCount = 1;
|
||||
let childStore: Readable<ChildInfo[]>;
|
||||
let resultItems: {
|
||||
@@ -53,26 +52,17 @@
|
||||
contentHAlign = 'left';
|
||||
}
|
||||
|
||||
$: jsonItems = json.items;
|
||||
$: jsonItems = Array.isArray(json.items) && json.items || [];
|
||||
|
||||
$: jsonColumnCount = rootCtx.getDerivedFromVars(json.column_count);
|
||||
$: jsonContentVAlign = rootCtx.getDerivedFromVars(json.content_alignment_vertical);
|
||||
$: jsonContentHAlign = rootCtx.getDerivedFromVars(json.content_alignment_horizontal);
|
||||
|
||||
$: {
|
||||
if (!jsonItems?.length || !Array.isArray(jsonItems)) {
|
||||
hasItemsError = true;
|
||||
rootCtx.logError(wrapError(new Error('Incorrect or empty "items" prop for div "grid"')));
|
||||
} else {
|
||||
hasItemsError = false;
|
||||
}
|
||||
}
|
||||
|
||||
$: {
|
||||
columnCount = correctPositiveNumber($jsonColumnCount, columnCount);
|
||||
}
|
||||
|
||||
$: items = (!hasItemsError && jsonItems || []).map(item => {
|
||||
$: items = jsonItems.map(item => {
|
||||
let childJson: DivBaseData = item as DivBaseData;
|
||||
let childContext: TemplateContext = templateContext;
|
||||
|
||||
@@ -232,7 +222,7 @@
|
||||
'grid-template-rows': gridCalcTemplates(rowsWeight, rowsMinHeight, rowCount)
|
||||
};
|
||||
|
||||
$: hasError = hasItemsError || hasLayoutError;
|
||||
$: hasError = hasLayoutError;
|
||||
</script>
|
||||
|
||||
{#if !hasError}
|
||||
|
||||
@@ -149,13 +149,16 @@
|
||||
if (indicatorItemsWrapper) {
|
||||
// if not destroyed yet
|
||||
|
||||
const currentItemOffsetLeft =
|
||||
(indicatorItemsWrapper.children[pagerData.currentItem] as HTMLElement).offsetLeft;
|
||||
const elem = indicatorItemsWrapper.children[pagerData.currentItem] as HTMLElement;
|
||||
|
||||
scroller.scroll({
|
||||
left: currentItemOffsetLeft - scroller.clientWidth / 2,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
if (elem) {
|
||||
const currentItemOffsetLeft = elem.offsetLeft;
|
||||
|
||||
scroller.scroll({
|
||||
left: currentItemOffsetLeft - scroller.clientWidth / 2,
|
||||
behavior: 'smooth'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,8 +46,6 @@
|
||||
let pagerItemsWrapper: HTMLElement;
|
||||
let mounted = false;
|
||||
|
||||
let hasItemsError = false;
|
||||
|
||||
let currentItem = 0;
|
||||
let prevSelectedItem = 0;
|
||||
|
||||
@@ -70,15 +68,6 @@
|
||||
$: jsonPaddings = rootCtx.getDerivedFromVars(json.paddings);
|
||||
$: jsonRestrictParentScroll = rootCtx.getDerivedFromVars(json.restrict_parent_scroll);
|
||||
|
||||
$: {
|
||||
if (!json.items?.length || !Array.isArray(json.items)) {
|
||||
hasItemsError = true;
|
||||
rootCtx.logError(wrapError(new Error('Incorrect or empty "items" prop for div "pager"')));
|
||||
} else {
|
||||
hasItemsError = false;
|
||||
}
|
||||
}
|
||||
|
||||
function replaceItems(items: (DivBaseData | undefined)[]): void {
|
||||
json = {
|
||||
...json,
|
||||
@@ -86,7 +75,7 @@
|
||||
};
|
||||
}
|
||||
|
||||
$: items = (!hasItemsError && json.items || []).map(item => {
|
||||
$: items = (Array.isArray(json.items) && json.items || []).map(item => {
|
||||
let childJson: DivBaseData = item as DivBaseData;
|
||||
let childContext: TemplateContext = templateContext;
|
||||
|
||||
@@ -155,7 +144,7 @@
|
||||
orientation
|
||||
};
|
||||
|
||||
$: hasError = hasItemsError || hasLayoutModeError;
|
||||
$: hasError = hasLayoutModeError;
|
||||
|
||||
$: shouldCheckArrows = $isDesktop && mounted && !hasError;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user