@inf-monkeys-tech/monkeys-design 1.0.39 → 1.0.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -8667,13 +8667,15 @@ function resolveColumnCount({
8667
8667
  itemCount,
8668
8668
  gap,
8669
8669
  columns,
8670
+ maxColumns,
8670
8671
  minCardWidth,
8671
8672
  idealCardWidth,
8672
8673
  maxCardWidth,
8673
8674
  node
8674
8675
  }) {
8675
8676
  const fixedColumns = resolveResponsiveColumns(columns, containerWidth);
8676
- if (fixedColumns) return fixedColumns;
8677
+ const resolvedMaxColumns = resolveResponsiveColumns(maxColumns, containerWidth);
8678
+ if (fixedColumns) return resolvedMaxColumns ? Math.min(fixedColumns, resolvedMaxColumns) : fixedColumns;
8677
8679
  if (!containerWidth) return 1;
8678
8680
  const idealWidth = resolveLengthToPixels2(idealCardWidth, DEFAULT_CARD_WIDTH_PX, node);
8679
8681
  const minWidth = resolveLengthToPixels2(minCardWidth, idealWidth * 0.78, node);
@@ -8700,7 +8702,7 @@ function resolveColumnCount({
8700
8702
  bestCount = candidate;
8701
8703
  }
8702
8704
  }
8703
- return bestCount;
8705
+ return resolvedMaxColumns ? Math.min(bestCount, resolvedMaxColumns) : bestCount;
8704
8706
  }
8705
8707
  function normalizeGap(value) {
8706
8708
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : DEFAULT_GAP_PX;
@@ -8767,6 +8769,10 @@ function warnOnDuplicateKeys(keys) {
8767
8769
  console.warn(`WorkbenchCollection received duplicate item keys: ${Array.from(duplicates).join(", ")}`);
8768
8770
  }
8769
8771
  }
8772
+ function normalizeTitleMaxLines(value) {
8773
+ if (!Number.isFinite(value) || Number(value) <= 0) return void 0;
8774
+ return clamp2(Math.round(Number(value)), 1, 12);
8775
+ }
8770
8776
  function WorkbenchCollection({
8771
8777
  items,
8772
8778
  config,
@@ -8851,6 +8857,7 @@ function WorkbenchCollection({
8851
8857
  itemCount: normalizedItems.length,
8852
8858
  gap,
8853
8859
  columns: config.layout.columns,
8860
+ maxColumns: config.layout.maxColumns,
8854
8861
  minCardWidth: config.layout.minCardWidth,
8855
8862
  idealCardWidth: config.layout.idealCardWidth ?? config.layout.columnWidth,
8856
8863
  maxCardWidth: config.layout.maxCardWidth,
@@ -8938,25 +8945,29 @@ function WorkbenchCollection({
8938
8945
  useEffect(() => {
8939
8946
  if (!loadingMore || !hasMore) loadMoreLockedRef.current = false;
8940
8947
  }, [hasMore, loadingMore, normalizedItems.length, keysSignature]);
8948
+ const requestLoadMore = useCallback(() => {
8949
+ if (!canLoadMore || !hasMore || loadingMore || loadMoreLockedRef.current) return;
8950
+ loadMoreLockedRef.current = true;
8951
+ try {
8952
+ const result = callbacksRef.current?.onLoadMore?.();
8953
+ if (result && typeof result.then === "function") {
8954
+ void result.catch(() => {
8955
+ loadMoreLockedRef.current = false;
8956
+ });
8957
+ }
8958
+ } catch (error) {
8959
+ loadMoreLockedRef.current = false;
8960
+ throw error;
8961
+ }
8962
+ }, [canLoadMore, hasMore, loadingMore]);
8941
8963
  useEffect(() => {
8942
8964
  const sentinel = loadMoreRef.current;
8943
8965
  if (!sentinel || !canLoadMore || !hasMore || loadingMore) return void 0;
8944
8966
  if (typeof IntersectionObserver !== "function") return void 0;
8945
8967
  const owner = resolveScrollOwner();
8946
8968
  const observer = new IntersectionObserver((entries) => {
8947
- if (!entries.some((entry) => entry.isIntersecting) || loadMoreLockedRef.current) return;
8948
- loadMoreLockedRef.current = true;
8949
- try {
8950
- const result = callbacksRef.current?.onLoadMore?.();
8951
- if (result && typeof result.then === "function") {
8952
- void result.catch(() => {
8953
- loadMoreLockedRef.current = false;
8954
- });
8955
- }
8956
- } catch (error) {
8957
- loadMoreLockedRef.current = false;
8958
- throw error;
8959
- }
8969
+ if (!entries.some((entry) => entry.isIntersecting)) return;
8970
+ requestLoadMore();
8960
8971
  }, {
8961
8972
  root: owner === rootRef.current ? owner : owner || null,
8962
8973
  rootMargin: config.loading?.rootMargin ?? "240px",
@@ -8964,7 +8975,25 @@ function WorkbenchCollection({
8964
8975
  });
8965
8976
  observer.observe(sentinel);
8966
8977
  return () => observer.disconnect();
8967
- }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, resolveScrollOwner]);
8978
+ }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, requestLoadMore, resolveScrollOwner]);
8979
+ useEffect(() => {
8980
+ if (!config.loading?.autoFill || !canLoadMore || !hasMore || loadingMore) return;
8981
+ const sentinel = loadMoreRef.current;
8982
+ if (!sentinel) return;
8983
+ const owner = resolveScrollOwner() ?? (config.layout.scrollOwner === "parent" ? rootRef.current?.parentElement ?? null : null) ?? rootRef.current;
8984
+ if (!owner || owner.clientHeight <= 0) return;
8985
+ if (owner.scrollHeight <= owner.clientHeight + 1) requestLoadMore();
8986
+ }, [
8987
+ canLoadMore,
8988
+ config.layout.scrollOwner,
8989
+ config.loading?.autoFill,
8990
+ hasMore,
8991
+ keysSignature,
8992
+ loadingMore,
8993
+ normalizedItems.length,
8994
+ requestLoadMore,
8995
+ resolveScrollOwner
8996
+ ]);
8968
8997
  const groups = useMemo(() => {
8969
8998
  if (!config.grouping) {
8970
8999
  return [{ key: "__all__", stringKey: "__all__", items: normalizedItems }];
@@ -9050,11 +9079,16 @@ function WorkbenchCollection({
9050
9079
  role: selectionMode === "none" ? "listitem" : "option",
9051
9080
  "aria-selected": selectionMode === "none" ? void 0 : context.selected,
9052
9081
  "aria-disabled": context.disabled || void 0,
9053
- tabIndex: callbacks?.onItemClick || selectionMode !== "none" ? 0 : void 0,
9082
+ tabIndex: callbacks?.onItemClick || selectionMode !== "none" || config.item?.title?.visibility === "hover" ? 0 : void 0,
9054
9083
  draggable: callbacks?.onItemDragStart ? true : void 0,
9055
9084
  className: cn(
9056
- "min-w-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
9057
- config.appearance?.hover === "lift" && "transition-transform hover:-translate-y-0.5 motion-reduce:transform-none",
9085
+ "min-w-0 group/workbench-collection-item outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
9086
+ config.appearance?.hover && config.appearance.hover !== "none" && "transition-[transform,box-shadow,background-color] duration-200",
9087
+ config.appearance?.hover === "highlight" && "hover:bg-muted/30",
9088
+ config.appearance?.hover === "lift" && "hover:-translate-y-0.5 motion-reduce:transform-none",
9089
+ config.appearance?.hover === "scale" && "hover:scale-[1.01] motion-reduce:transform-none",
9090
+ config.appearance?.hover === "shadow" && "hover:shadow-md",
9091
+ config.appearance?.hover === "lift-shadow" && "hover:-translate-y-0.5 hover:shadow-md motion-reduce:transform-none",
9058
9092
  config.appearance?.selection === "ring" && context.selected && "ring-2 ring-primary",
9059
9093
  config.appearance?.selection === "outline" && context.selected && "outline outline-2 outline-primary",
9060
9094
  classNames?.item
@@ -9068,17 +9102,70 @@ function WorkbenchCollection({
9068
9102
  if (isInteractiveEventTarget(event.target, event.currentTarget)) return;
9069
9103
  callbacks?.onItemDoubleClick?.(entry.item, context, event);
9070
9104
  },
9105
+ onMouseEnter: (event) => callbacks?.onItemHoverChange?.(entry.item, context, true, event),
9106
+ onMouseLeave: (event) => callbacks?.onItemHoverChange?.(entry.item, context, false, event),
9071
9107
  onKeyDown: handleKeyboard,
9072
9108
  onDragStart: (event) => callbacks?.onItemDragStart?.(entry.item, context, event),
9073
9109
  onDragOver: callbacks?.onItemDrop ? (event) => event.preventDefault() : void 0,
9074
9110
  onDrop: (event) => callbacks?.onItemDrop?.(entry.item, context, event)
9075
9111
  };
9076
- }, [callbacks, classNames?.item, componentId, config.appearance, selectionMode]);
9112
+ }, [callbacks, classNames?.item, componentId, config.appearance, config.item?.title?.visibility, selectionMode]);
9113
+ const renderItemContent2 = useCallback((entry, context) => {
9114
+ const content = renderItem(entry.item, context);
9115
+ const titleConfig = config.item?.title;
9116
+ const visibility = titleConfig?.visibility ?? "always";
9117
+ if (!titleConfig || visibility === "never") return content;
9118
+ const title = titleConfig.getContent?.(entry.item, context) ?? context.renderSlot("title");
9119
+ if (!hasRenderableNode(title)) return content;
9120
+ const placement = titleConfig.placement ?? "below";
9121
+ const overlay = placement.startsWith("overlay-");
9122
+ const maxLines = normalizeTitleMaxLines(titleConfig.maxLines);
9123
+ const surface = titleConfig.surface ?? (overlay ? "scrim" : "none");
9124
+ const titleNode = /* @__PURE__ */ jsx(
9125
+ "div",
9126
+ {
9127
+ "data-collection-item-title": "",
9128
+ "data-title-placement": placement,
9129
+ "data-title-visibility": visibility,
9130
+ className: cn(
9131
+ "min-w-0 px-1 py-2 text-sm font-medium text-foreground",
9132
+ titleConfig.align === "center" && "text-center",
9133
+ titleConfig.align === "end" && "text-right",
9134
+ visibility === "hover" && "opacity-0 transition-opacity group-hover/workbench-collection-item:opacity-100 group-focus-within/workbench-collection-item:opacity-100",
9135
+ overlay && "pointer-events-none absolute inset-x-0 z-10 px-3 py-2",
9136
+ placement === "overlay-top" && "top-0",
9137
+ placement === "overlay-center" && "top-1/2 -translate-y-1/2 motion-reduce:transform-none",
9138
+ placement === "overlay-bottom" && "bottom-0",
9139
+ surface === "surface" && "bg-background/90 backdrop-blur-sm",
9140
+ surface === "scrim" && placement === "overlay-top" && "bg-gradient-to-b from-background/90 to-transparent pb-8",
9141
+ surface === "scrim" && placement === "overlay-bottom" && "bg-gradient-to-t from-background/90 to-transparent pt-8",
9142
+ surface === "scrim" && placement === "overlay-center" && "bg-background/75 backdrop-blur-sm",
9143
+ Boolean(maxLines) && "overflow-hidden [display:-webkit-box] [-webkit-box-orient:vertical]",
9144
+ classNames?.itemTitle
9145
+ ),
9146
+ style: maxLines ? { WebkitLineClamp: maxLines } : void 0,
9147
+ children: title
9148
+ }
9149
+ );
9150
+ return /* @__PURE__ */ jsxs(
9151
+ "div",
9152
+ {
9153
+ className: cn("min-w-0", overlay && "relative", classNames?.itemContent),
9154
+ "data-collection-item-content": "",
9155
+ children: [
9156
+ placement === "above" ? titleNode : null,
9157
+ content,
9158
+ placement === "below" || overlay ? titleNode : null
9159
+ ]
9160
+ }
9161
+ );
9162
+ }, [classNames?.itemContent, classNames?.itemTitle, config.item?.title, renderItem]);
9077
9163
  const renderEntry = useCallback((entry, layout, includeShell = true) => {
9078
9164
  const context = createItemContext(entry, layout);
9079
- if (!includeShell) return renderItem(entry.item, context);
9080
- return /* @__PURE__ */ jsx("div", { ...getItemInteractionProps(entry, context), children: renderItem(entry.item, context) });
9081
- }, [createItemContext, getItemInteractionProps, renderItem]);
9165
+ const content = renderItemContent2(entry, context);
9166
+ if (!includeShell) return content;
9167
+ return /* @__PURE__ */ jsx("div", { ...getItemInteractionProps(entry, context), children: content });
9168
+ }, [createItemContext, getItemInteractionProps, renderItemContent2]);
9082
9169
  const baseLayoutContext = useMemo(() => ({
9083
9170
  mode,
9084
9171
  columnCount,
@@ -9105,7 +9192,7 @@ function WorkbenchCollection({
9105
9192
  scrollOwner: resolveScrollOwner(),
9106
9193
  renderItem: (item, localIndex, layout) => {
9107
9194
  const entry = group.items[localIndex];
9108
- return entry ? renderEntry(entry, layout) : null;
9195
+ return entry ? /* @__PURE__ */ jsx(Fragment$1, { children: renderEntry(entry, layout) }, entry.stringKey) : null;
9109
9196
  }
9110
9197
  });
9111
9198
  }
@@ -9232,6 +9319,7 @@ function WorkbenchCollection({
9232
9319
  "data-density": config.appearance?.density,
9233
9320
  "data-radius": config.appearance?.radius,
9234
9321
  "data-media-fit": config.appearance?.mediaFit,
9322
+ "data-hover-effect": config.appearance?.hover,
9235
9323
  "aria-label": ariaLabel ?? labels.collection,
9236
9324
  "aria-busy": loading || loadingMore || void 0,
9237
9325
  className: cn("min-h-0 min-w-0", config.layout.fillHeight && "h-full", classNames?.root, className),
@@ -9328,14 +9416,6 @@ function getGalleryCardWidthMetrics(density) {
9328
9416
  if (density === "detailed") return { min: 320, ideal: 372, max: 420 };
9329
9417
  return { min: 260, ideal: 304, max: 348 };
9330
9418
  }
9331
- function getGalleryCardWidthForColumnCount({
9332
- containerWidth,
9333
- columnCount,
9334
- gap
9335
- }) {
9336
- if (!containerWidth || !columnCount) return 0;
9337
- return (containerWidth - gap * Math.max(columnCount - 1, 0)) / columnCount;
9338
- }
9339
9419
  function getNormalizedGalleryGridColumns(columns) {
9340
9420
  if (columns === void 0 || columns === null || columns === "" || columns === "auto") {
9341
9421
  return void 0;
@@ -9344,90 +9424,6 @@ function getNormalizedGalleryGridColumns(columns) {
9344
9424
  if (!Number.isFinite(parsedColumns) || parsedColumns <= 0) return void 0;
9345
9425
  return Math.max(1, Math.min(parsedColumns, 8));
9346
9426
  }
9347
- function getGalleryGridColumnCount({
9348
- containerWidth,
9349
- rowCount,
9350
- minCardWidth,
9351
- idealCardWidth,
9352
- maxCardWidth,
9353
- gap
9354
- }) {
9355
- if (!containerWidth) return 1;
9356
- const safeRowCount = Math.max(rowCount, 1);
9357
- const lowerBound = Math.max(1, Math.ceil((containerWidth + gap) / (maxCardWidth + gap)));
9358
- const upperBound = Math.max(1, Math.floor((containerWidth + gap) / (minCardWidth + gap)));
9359
- const idealCount = Math.max(1, Math.round((containerWidth + gap) / (idealCardWidth + gap)));
9360
- const phantomPenalty = Math.round((idealCardWidth - minCardWidth) / 2) + gap;
9361
- const maxCandidate = Math.max(1, lowerBound, upperBound + 1, idealCount + 1);
9362
- let bestCount = 1;
9363
- let bestScore = Number.POSITIVE_INFINITY;
9364
- for (let candidateCount = 1; candidateCount <= maxCandidate; candidateCount += 1) {
9365
- const cardWidth = getGalleryCardWidthForColumnCount({ containerWidth, columnCount: candidateCount, gap });
9366
- const overflowPenalty = Math.max(0, cardWidth - maxCardWidth);
9367
- const underflowPenalty = Math.max(0, minCardWidth - cardWidth);
9368
- const idealPenalty = Math.abs(cardWidth - idealCardWidth);
9369
- const phantomColumns = Math.max(0, candidateCount - safeRowCount);
9370
- const candidateScore = overflowPenalty * 3 + underflowPenalty * 2 + idealPenalty + phantomColumns * phantomPenalty;
9371
- if (candidateScore < bestScore) {
9372
- bestScore = candidateScore;
9373
- bestCount = candidateCount;
9374
- }
9375
- }
9376
- return bestCount;
9377
- }
9378
- function getGalleryGridLayoutStyle({
9379
- isRailLayout,
9380
- railCardWidth,
9381
- fixedCardWidth,
9382
- fixedColumnCount,
9383
- containerWidth,
9384
- rowCount,
9385
- minCardWidth,
9386
- idealCardWidth,
9387
- maxCardWidth
9388
- }) {
9389
- if (isRailLayout) {
9390
- return { gridAutoColumns: `${railCardWidth}px` };
9391
- }
9392
- if (fixedColumnCount) {
9393
- const responsiveColumnCount = containerWidth ? Math.max(1, Math.min(
9394
- fixedColumnCount,
9395
- Math.floor((containerWidth + GALLERY_GRID_GAP_PX) / (minCardWidth + GALLERY_GRID_GAP_PX)) || 1
9396
- )) : fixedColumnCount;
9397
- return {
9398
- gridTemplateColumns: `repeat(${responsiveColumnCount}, minmax(0, 1fr))`,
9399
- justifyContent: "start",
9400
- alignContent: "start"
9401
- };
9402
- }
9403
- if (fixedCardWidth) {
9404
- return {
9405
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${fixedCardWidth}), ${fixedCardWidth}))`,
9406
- justifyContent: "start",
9407
- alignContent: "start"
9408
- };
9409
- }
9410
- if (!containerWidth) {
9411
- return {
9412
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${minCardWidth}px), min(100%, ${maxCardWidth}px)))`,
9413
- justifyContent: "start",
9414
- alignContent: "start"
9415
- };
9416
- }
9417
- const columnCount = getGalleryGridColumnCount({
9418
- containerWidth,
9419
- rowCount,
9420
- minCardWidth,
9421
- idealCardWidth,
9422
- maxCardWidth,
9423
- gap: GALLERY_GRID_GAP_PX
9424
- });
9425
- return {
9426
- gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,
9427
- justifyContent: "start",
9428
- alignContent: "start"
9429
- };
9430
- }
9431
9427
  function getGalleryTextLength(value) {
9432
9428
  if (value === null || value === void 0) return 0;
9433
9429
  const text = String(value).trim();
@@ -9635,8 +9631,6 @@ function WorkbenchGalleryView({
9635
9631
  formatLabel,
9636
9632
  getMasonryItemSize
9637
9633
  }) {
9638
- const containerRef = useRef(null);
9639
- const [containerWidth, setContainerWidth] = useState(0);
9640
9634
  const { min: resolvedMinCardWidth, ideal: resolvedIdealCardWidth, max: resolvedMaxCardWidth } = getGalleryCardWidthMetrics(galleryDensity);
9641
9635
  const resolvedRailCardWidth = galleryRailCardWidth || resolvedMinCardWidth;
9642
9636
  const resolvedGridColumnCount = getNormalizedGalleryGridColumns(galleryGridColumns);
@@ -9656,44 +9650,6 @@ function WorkbenchGalleryView({
9656
9650
  const resolvedIsTitleCandidate = isTitleCandidate || ((column, row) => isDefaultGalleryTitleCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
9657
9651
  const resolvedIsSummaryCandidate = isSummaryCandidate || ((column, row) => isDefaultGallerySummaryCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
9658
9652
  const resolvedRenderFieldValue = renderFieldValue || ((column, row, { compact } = {}) => /* @__PURE__ */ jsx("span", { children: resolvedGetDisplayText(resolvedGetFieldValue(column, row)) }));
9659
- useEffect(() => {
9660
- if (isMasonry || isRailLayout || resolvedGridCardWidth) return void 0;
9661
- const node = containerRef.current;
9662
- if (!node) return void 0;
9663
- const updateWidth = () => {
9664
- const nextWidth = Math.round(node.getBoundingClientRect().width);
9665
- setContainerWidth((prevWidth) => prevWidth === nextWidth ? prevWidth : nextWidth);
9666
- };
9667
- updateWidth();
9668
- if (typeof ResizeObserver === "function") {
9669
- const observer = new ResizeObserver(() => updateWidth());
9670
- observer.observe(node);
9671
- return () => observer.disconnect();
9672
- }
9673
- window.addEventListener("resize", updateWidth);
9674
- return () => window.removeEventListener("resize", updateWidth);
9675
- }, [isMasonry, isRailLayout, resolvedGridCardWidth]);
9676
- const layoutStyle = useMemo(() => getGalleryGridLayoutStyle({
9677
- isRailLayout,
9678
- railCardWidth: resolvedRailCardWidth,
9679
- fixedCardWidth: resolvedGridCardWidth,
9680
- fixedColumnCount: resolvedGridColumnCount,
9681
- containerWidth,
9682
- rowCount: rows.length,
9683
- minCardWidth: resolvedMinCardWidth,
9684
- idealCardWidth: resolvedIdealCardWidth,
9685
- maxCardWidth: resolvedMaxCardWidth
9686
- }), [
9687
- containerWidth,
9688
- isRailLayout,
9689
- resolvedGridCardWidth,
9690
- resolvedGridColumnCount,
9691
- resolvedIdealCardWidth,
9692
- resolvedMaxCardWidth,
9693
- resolvedMinCardWidth,
9694
- resolvedRailCardWidth,
9695
- rows.length
9696
- ]);
9697
9653
  const renderGalleryCard = (row, rowIndex) => /* @__PURE__ */ jsx(
9698
9654
  WorkbenchGalleryCard,
9699
9655
  {
@@ -9729,69 +9685,64 @@ function WorkbenchGalleryView({
9729
9685
  },
9730
9686
  row?.id || row?.linkKey || rowIndex
9731
9687
  );
9732
- if (isMasonry) {
9733
- return /* @__PURE__ */ jsx(
9734
- WorkbenchCollection,
9735
- {
9736
- items: rows,
9737
- classNames: { layout: className },
9738
- config: {
9739
- getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
9740
- layout: {
9741
- mode: masonryPlacementStrategy === "dense" ? "dense" : "masonry",
9742
- gap: GALLERY_GRID_GAP_PX,
9743
- idealCardWidth: resolvedMasonryColumnWidth,
9744
- placementStrategy: masonryPlacementStrategy,
9745
- getItemSize: (row, layout) => {
9746
- const defaultSize = getDefaultGalleryMasonryItemSize({
9747
- row,
9748
- columns,
9749
- galleryFieldKey,
9750
- galleryDensity,
9751
- galleryBentoColumns,
9752
- galleryDetailVisibility,
9753
- galleryDetailLimit,
9754
- getFieldValue: resolvedGetFieldValue,
9755
- isMediaColumn: resolvedIsMediaColumn,
9756
- isTitleCandidate: resolvedIsTitleCandidate,
9757
- isSummaryCandidate: resolvedIsSummaryCandidate,
9758
- getDisplayText: resolvedGetDisplayText,
9759
- isImageField: resolvedIsImageField,
9760
- isAudioField: resolvedIsAudioField,
9761
- cardVariant,
9762
- renderPreview,
9763
- renderLeadingVisual,
9764
- hiddenDetailFieldKeys,
9765
- layout,
9766
- resolveRecordVisual
9767
- });
9768
- if (typeof getMasonryItemSize !== "function") return defaultSize;
9769
- const customSize = getMasonryItemSize(row, {
9770
- ...layout,
9771
- placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
9772
- defaultSize
9773
- }) || {};
9774
- return {
9775
- ...defaultSize,
9776
- ...customSize
9777
- };
9778
- }
9779
- }
9780
- },
9781
- renderItem: (row, context) => renderGalleryCard(row, context.index)
9782
- }
9783
- );
9784
- }
9688
+ const collectionMode = isMasonry ? masonryPlacementStrategy === "dense" ? "dense" : "masonry" : isRailLayout ? "rail" : "grid";
9785
9689
  return /* @__PURE__ */ jsx(
9786
- "div",
9690
+ WorkbenchCollection,
9787
9691
  {
9788
- ref: containerRef,
9789
- className: cn(
9790
- isRailLayout ? "grid grid-flow-col items-center gap-3" : "grid items-start gap-3",
9791
- className
9792
- ),
9793
- style: layoutStyle,
9794
- children: rows.map((row, rowIndex) => renderGalleryCard(row, rowIndex))
9692
+ items: rows,
9693
+ classNames: { layout: className },
9694
+ config: {
9695
+ getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
9696
+ layout: {
9697
+ mode: collectionMode,
9698
+ gap: GALLERY_GRID_GAP_PX,
9699
+ columns: isMasonry ? "auto" : resolvedGridColumnCount ? {
9700
+ mobile: 1,
9701
+ tablet: Math.min(2, resolvedGridColumnCount),
9702
+ desktop: resolvedGridColumnCount
9703
+ } : "auto",
9704
+ cardWidth: isRailLayout ? resolvedRailCardWidth : void 0,
9705
+ minCardWidth: resolvedGridCardWidth ?? resolvedMinCardWidth,
9706
+ idealCardWidth: isMasonry ? resolvedMasonryColumnWidth : resolvedGridCardWidth ?? resolvedIdealCardWidth,
9707
+ maxCardWidth: resolvedGridCardWidth ?? resolvedMaxCardWidth,
9708
+ placementStrategy: masonryPlacementStrategy,
9709
+ getItemSize: isMasonry ? (row, layout) => {
9710
+ const defaultSize = getDefaultGalleryMasonryItemSize({
9711
+ row,
9712
+ columns,
9713
+ galleryFieldKey,
9714
+ galleryDensity,
9715
+ galleryBentoColumns,
9716
+ galleryDetailVisibility,
9717
+ galleryDetailLimit,
9718
+ getFieldValue: resolvedGetFieldValue,
9719
+ isMediaColumn: resolvedIsMediaColumn,
9720
+ isTitleCandidate: resolvedIsTitleCandidate,
9721
+ isSummaryCandidate: resolvedIsSummaryCandidate,
9722
+ getDisplayText: resolvedGetDisplayText,
9723
+ isImageField: resolvedIsImageField,
9724
+ isAudioField: resolvedIsAudioField,
9725
+ cardVariant,
9726
+ renderPreview,
9727
+ renderLeadingVisual,
9728
+ hiddenDetailFieldKeys,
9729
+ layout,
9730
+ resolveRecordVisual
9731
+ });
9732
+ if (typeof getMasonryItemSize !== "function") return defaultSize;
9733
+ const customSize = getMasonryItemSize(row, {
9734
+ ...layout,
9735
+ placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
9736
+ defaultSize
9737
+ }) || {};
9738
+ return {
9739
+ ...defaultSize,
9740
+ ...customSize
9741
+ };
9742
+ } : void 0
9743
+ }
9744
+ },
9745
+ renderItem: (row, context) => renderGalleryCard(row, context.index)
9795
9746
  }
9796
9747
  );
9797
9748
  }
@@ -10708,18 +10659,26 @@ function WorkbenchAssetGallery({
10708
10659
  if (!items.length) {
10709
10660
  return hasRenderableNode(emptyState) ? /* @__PURE__ */ jsx(Fragment, { children: emptyState }) : null;
10710
10661
  }
10711
- return /* @__PURE__ */ jsx(
10712
- "ul",
10662
+ return /* @__PURE__ */ jsx("div", { "data-monkeys-component": "workbench-asset-gallery", children: /* @__PURE__ */ jsx(
10663
+ WorkbenchCollection,
10713
10664
  {
10714
- "aria-label": ariaLabel,
10715
- "data-monkeys-component": "workbench-asset-gallery",
10716
- className: cn(
10717
- "grid min-w-0 gap-3 [grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))]",
10718
- className
10719
- ),
10720
- children: items.map((item) => {
10665
+ items,
10666
+ config: {
10667
+ getItemKey: (item) => item.id,
10668
+ layout: {
10669
+ mode: "grid",
10670
+ columns: "auto",
10671
+ minCardWidth: "12rem",
10672
+ idealCardWidth: "16rem",
10673
+ gap: 12
10674
+ },
10675
+ appearance: { hover: "none" }
10676
+ },
10677
+ ariaLabel,
10678
+ className,
10679
+ renderItem: (item) => {
10721
10680
  const selected = selectedItemId === item.id;
10722
- return /* @__PURE__ */ jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsxs(
10681
+ return /* @__PURE__ */ jsxs(
10723
10682
  "button",
10724
10683
  {
10725
10684
  type: "button",
@@ -10755,10 +10714,10 @@ function WorkbenchAssetGallery({
10755
10714
  ] })
10756
10715
  ]
10757
10716
  }
10758
- ) }, item.id);
10759
- })
10717
+ );
10718
+ }
10760
10719
  }
10761
- );
10720
+ ) });
10762
10721
  }
10763
10722
  var radarWorkspaceStyle = {
10764
10723
  backgroundColor: "hsl(var(--radar-canvas, var(--background)))",