Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/pluggableWidgets/gallery-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- We fixed an issue where the column count was not reflected properly in the preview mode.

### Added

- Added a 'horizontal divider' option to Borders design property for Gallery list items, allowing improved visual separation and customization.
Expand Down
104 changes: 52 additions & 52 deletions packages/pluggableWidgets/gallery-web/src/Gallery.editorPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,30 +11,28 @@ import { createElement, ReactElement, ReactNode, useCallback, useMemo } from "re
import { GalleryPreviewProps } from "../typings/GalleryProps";
import { Gallery as GalleryComponent } from "./components/Gallery";
import { useItemEventsController } from "./features/item-interaction/ItemEventsController";
import { useGridPositions } from "./features/useGridPositions";
import { useGridPositionsPreview } from "./features/useGridPositionsPreview";
import { useItemPreviewHelper } from "./helpers/ItemPreviewHelper";
import { useItemSelectHelper } from "./helpers/useItemSelectHelper";
import "./ui/GalleryPreview.scss";

const numberOfItems = 3;

const SortAPI = getGlobalSortContext();

function Preview(props: GalleryPreviewProps): ReactElement {
const { emptyPlaceholder } = props;
const { numberOfColumns, numberOfRows, containerRef, numberOfItems } = useGridPositionsPreview({
phoneItems: props.phoneItems ?? 1,
tabletItems: props.tabletItems ?? 1,
desktopItems: props.desktopItems ?? 1,
totalItems: props.pageSize ?? 3
});

const items: ObjectItem[] = Array.from({ length: numberOfItems }).map((_, index) => ({
id: String(index) as GUID
}));

const selectHelper = useItemSelectHelper(props.itemSelection, undefined);

const { numberOfColumns, numberOfRows } = useGridPositions({
phoneItems: props.phoneItems ?? 1,
tabletItems: props.tabletItems ?? 1,
desktopItems: props.desktopItems ?? 1,
totalItems: items.length
});

const getPositionCallback = useCallback(
(index: number) => getColumnAndRowBasedOnIndex(numberOfColumns, items.length, index),
[numberOfColumns, items.length]
Expand Down Expand Up @@ -66,48 +64,50 @@ function Preview(props: GalleryPreviewProps): ReactElement {
);

return (
<GalleryComponent
className={props.class}
desktopItems={props.content.widgetCount > 0 ? numberOfItems : props.desktopItems!}
emptyPlaceholderRenderer={useCallback(
(renderWrapper: (children: ReactNode) => ReactElement) => (
<emptyPlaceholder.renderer caption="Empty list message: Place widgets here">
{renderWrapper(null)}
</emptyPlaceholder.renderer>
),
[emptyPlaceholder]
)}
header={
<SortAPI.Provider value={sortAPI}>
<props.filtersPlaceholder.renderer caption="Place widgets like filter widget(s) and action button(s) here">
<div />
</props.filtersPlaceholder.renderer>
</SortAPI.Provider>
}
showHeader
hasMoreItems={false}
items={items}
itemHelper={useItemPreviewHelper({
contentValue: props.content,
hasOnClick: props.onClick !== null
})}
numberOfItems={props.pageSize ?? numberOfItems}
page={0}
pageSize={props.pageSize ?? numberOfItems}
paging={props.pagination === "buttons"}
paginationPosition={props.pagingPosition}
paginationType={props.pagination}
showPagingButtons={props.showPagingButtons}
showEmptyStatePreview={props.showEmptyPlaceholder === "custom"}
phoneItems={props.phoneItems!}
tabletItems={props.tabletItems!}
selectHelper={selectHelper}
itemEventsController={itemEventsController}
focusController={focusController}
getPosition={getPositionCallback}
showRefreshIndicator={false}
preview
/>
<div ref={containerRef}>
<GalleryComponent
className={props.class}
desktopItems={props.desktopItems!}
emptyPlaceholderRenderer={useCallback(
(renderWrapper: (children: ReactNode) => ReactElement) => (
<emptyPlaceholder.renderer caption="Empty list message: Place widgets here">
{renderWrapper(null)}
</emptyPlaceholder.renderer>
),
[emptyPlaceholder]
)}
header={
<SortAPI.Provider value={sortAPI}>
<props.filtersPlaceholder.renderer caption="Place widgets like filter widget(s) and action button(s) here">
<div />
</props.filtersPlaceholder.renderer>
</SortAPI.Provider>
}
showHeader
hasMoreItems={false}
items={items}
itemHelper={useItemPreviewHelper({
contentValue: props.content,
hasOnClick: props.onClick !== null
})}
numberOfItems={props.pageSize!}
page={0}
pageSize={props.pageSize!}
paging={props.pagination === "buttons"}
paginationPosition={props.pagingPosition}
paginationType={props.pagination}
showPagingButtons={props.showPagingButtons}
showEmptyStatePreview={props.showEmptyPlaceholder === "custom"}
phoneItems={props.phoneItems!}
tabletItems={props.tabletItems!}
selectHelper={selectHelper}
itemEventsController={itemEventsController}
focusController={focusController}
getPosition={getPositionCallback}
showRefreshIndicator={false}
preview
/>
</div>
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { ObjectItem } from "mendix";
import { useEffect, useRef, useState } from "react";
import { GalleryProps } from "../components/Gallery";

export type GridPositionsProps = Pick<GalleryProps<ObjectItem>, "desktopItems" | "phoneItems" | "tabletItems"> & {
totalItems: number;
};

type GridPositionReturn = {
numberOfColumns: number;
numberOfRows: number;
numberOfItems: number;
};

function useObservedColumns(): [React.RefObject<HTMLDivElement>, number] {
const containerRef = useRef<HTMLDivElement>(null);
const [numberOfColumns, setNumberOfColumns] = useState(12);

useEffect(() => {
if (!containerRef.current) return;

const resizeObserver = new ResizeObserver(() => {
if (!containerRef.current) return;

setNumberOfColumns(
getComputedStyle(containerRef.current.querySelector(".widget-gallery-items")!)
.getPropertyValue("grid-template-columns")
.split(" ").length
);
});

resizeObserver.observe(containerRef.current);

return () => resizeObserver.disconnect();
}, []);

return [containerRef, numberOfColumns];
}

export function useGridPositionsPreview(
config: GridPositionsProps
): GridPositionReturn & { containerRef: React.RefObject<HTMLDivElement> } {
const [containerRef, numberOfColumns] = useObservedColumns();
const maxItems = numberOfColumns * 3;
const numberOfItems = Math.min(maxItems, config.totalItems);
const numberOfRows = Math.ceil(numberOfItems / numberOfColumns);

return {
containerRef,
numberOfColumns,
numberOfRows,
numberOfItems
};
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
.widget-gallery {
.widget-gallery-preview:nth-last-child(2) > div {
opacity: 0.5;
}
.widget-gallery-content {
position: relative;
}

.widget-gallery-preview:last-child > div {
opacity: 0.2;
}
.widget-gallery-content::before {
content: "";
display: block;
position: absolute;
width: 100%;
height: 100%;
background: linear-gradient(
to bottom,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 0) 33.33%,
rgba(255, 255, 255, 0.5) 66.66%,
rgba(255, 255, 255, 0.75) 100%
);
z-index: 1;
}
Loading