@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.
package/dist/index.mjs CHANGED
@@ -22444,13 +22444,15 @@ function resolveColumnCount({
22444
22444
  itemCount,
22445
22445
  gap,
22446
22446
  columns,
22447
+ maxColumns,
22447
22448
  minCardWidth,
22448
22449
  idealCardWidth,
22449
22450
  maxCardWidth,
22450
22451
  node
22451
22452
  }) {
22452
22453
  const fixedColumns = resolveResponsiveColumns(columns, containerWidth);
22453
- if (fixedColumns) return fixedColumns;
22454
+ const resolvedMaxColumns = resolveResponsiveColumns(maxColumns, containerWidth);
22455
+ if (fixedColumns) return resolvedMaxColumns ? Math.min(fixedColumns, resolvedMaxColumns) : fixedColumns;
22454
22456
  if (!containerWidth) return 1;
22455
22457
  const idealWidth = resolveLengthToPixels2(idealCardWidth, DEFAULT_CARD_WIDTH_PX, node);
22456
22458
  const minWidth = resolveLengthToPixels2(minCardWidth, idealWidth * 0.78, node);
@@ -22477,7 +22479,7 @@ function resolveColumnCount({
22477
22479
  bestCount = candidate;
22478
22480
  }
22479
22481
  }
22480
- return bestCount;
22482
+ return resolvedMaxColumns ? Math.min(bestCount, resolvedMaxColumns) : bestCount;
22481
22483
  }
22482
22484
  function normalizeGap(value) {
22483
22485
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : DEFAULT_GAP_PX;
@@ -22544,6 +22546,10 @@ function warnOnDuplicateKeys(keys) {
22544
22546
  console.warn(`WorkbenchCollection received duplicate item keys: ${Array.from(duplicates).join(", ")}`);
22545
22547
  }
22546
22548
  }
22549
+ function normalizeTitleMaxLines(value) {
22550
+ if (!Number.isFinite(value) || Number(value) <= 0) return void 0;
22551
+ return clamp4(Math.round(Number(value)), 1, 12);
22552
+ }
22547
22553
  function WorkbenchCollection({
22548
22554
  items,
22549
22555
  config,
@@ -22628,6 +22634,7 @@ function WorkbenchCollection({
22628
22634
  itemCount: normalizedItems.length,
22629
22635
  gap,
22630
22636
  columns: config.layout.columns,
22637
+ maxColumns: config.layout.maxColumns,
22631
22638
  minCardWidth: config.layout.minCardWidth,
22632
22639
  idealCardWidth: config.layout.idealCardWidth ?? config.layout.columnWidth,
22633
22640
  maxCardWidth: config.layout.maxCardWidth,
@@ -22715,25 +22722,29 @@ function WorkbenchCollection({
22715
22722
  useEffect(() => {
22716
22723
  if (!loadingMore || !hasMore) loadMoreLockedRef.current = false;
22717
22724
  }, [hasMore, loadingMore, normalizedItems.length, keysSignature]);
22725
+ const requestLoadMore = useCallback(() => {
22726
+ if (!canLoadMore || !hasMore || loadingMore || loadMoreLockedRef.current) return;
22727
+ loadMoreLockedRef.current = true;
22728
+ try {
22729
+ const result = callbacksRef.current?.onLoadMore?.();
22730
+ if (result && typeof result.then === "function") {
22731
+ void result.catch(() => {
22732
+ loadMoreLockedRef.current = false;
22733
+ });
22734
+ }
22735
+ } catch (error) {
22736
+ loadMoreLockedRef.current = false;
22737
+ throw error;
22738
+ }
22739
+ }, [canLoadMore, hasMore, loadingMore]);
22718
22740
  useEffect(() => {
22719
22741
  const sentinel = loadMoreRef.current;
22720
22742
  if (!sentinel || !canLoadMore || !hasMore || loadingMore) return void 0;
22721
22743
  if (typeof IntersectionObserver !== "function") return void 0;
22722
22744
  const owner = resolveScrollOwner();
22723
22745
  const observer = new IntersectionObserver((entries) => {
22724
- if (!entries.some((entry) => entry.isIntersecting) || loadMoreLockedRef.current) return;
22725
- loadMoreLockedRef.current = true;
22726
- try {
22727
- const result = callbacksRef.current?.onLoadMore?.();
22728
- if (result && typeof result.then === "function") {
22729
- void result.catch(() => {
22730
- loadMoreLockedRef.current = false;
22731
- });
22732
- }
22733
- } catch (error) {
22734
- loadMoreLockedRef.current = false;
22735
- throw error;
22736
- }
22746
+ if (!entries.some((entry) => entry.isIntersecting)) return;
22747
+ requestLoadMore();
22737
22748
  }, {
22738
22749
  root: owner === rootRef.current ? owner : owner || null,
22739
22750
  rootMargin: config.loading?.rootMargin ?? "240px",
@@ -22741,7 +22752,25 @@ function WorkbenchCollection({
22741
22752
  });
22742
22753
  observer.observe(sentinel);
22743
22754
  return () => observer.disconnect();
22744
- }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, resolveScrollOwner]);
22755
+ }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, requestLoadMore, resolveScrollOwner]);
22756
+ useEffect(() => {
22757
+ if (!config.loading?.autoFill || !canLoadMore || !hasMore || loadingMore) return;
22758
+ const sentinel = loadMoreRef.current;
22759
+ if (!sentinel) return;
22760
+ const owner = resolveScrollOwner() ?? (config.layout.scrollOwner === "parent" ? rootRef.current?.parentElement ?? null : null) ?? rootRef.current;
22761
+ if (!owner || owner.clientHeight <= 0) return;
22762
+ if (owner.scrollHeight <= owner.clientHeight + 1) requestLoadMore();
22763
+ }, [
22764
+ canLoadMore,
22765
+ config.layout.scrollOwner,
22766
+ config.loading?.autoFill,
22767
+ hasMore,
22768
+ keysSignature,
22769
+ loadingMore,
22770
+ normalizedItems.length,
22771
+ requestLoadMore,
22772
+ resolveScrollOwner
22773
+ ]);
22745
22774
  const groups = useMemo(() => {
22746
22775
  if (!config.grouping) {
22747
22776
  return [{ key: "__all__", stringKey: "__all__", items: normalizedItems }];
@@ -22827,11 +22856,16 @@ function WorkbenchCollection({
22827
22856
  role: selectionMode === "none" ? "listitem" : "option",
22828
22857
  "aria-selected": selectionMode === "none" ? void 0 : context.selected,
22829
22858
  "aria-disabled": context.disabled || void 0,
22830
- tabIndex: callbacks?.onItemClick || selectionMode !== "none" ? 0 : void 0,
22859
+ tabIndex: callbacks?.onItemClick || selectionMode !== "none" || config.item?.title?.visibility === "hover" ? 0 : void 0,
22831
22860
  draggable: callbacks?.onItemDragStart ? true : void 0,
22832
22861
  className: cn(
22833
- "min-w-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
22834
- config.appearance?.hover === "lift" && "transition-transform hover:-translate-y-0.5 motion-reduce:transform-none",
22862
+ "min-w-0 group/workbench-collection-item outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
22863
+ config.appearance?.hover && config.appearance.hover !== "none" && "transition-[transform,box-shadow,background-color] duration-200",
22864
+ config.appearance?.hover === "highlight" && "hover:bg-muted/30",
22865
+ config.appearance?.hover === "lift" && "hover:-translate-y-0.5 motion-reduce:transform-none",
22866
+ config.appearance?.hover === "scale" && "hover:scale-[1.01] motion-reduce:transform-none",
22867
+ config.appearance?.hover === "shadow" && "hover:shadow-md",
22868
+ config.appearance?.hover === "lift-shadow" && "hover:-translate-y-0.5 hover:shadow-md motion-reduce:transform-none",
22835
22869
  config.appearance?.selection === "ring" && context.selected && "ring-2 ring-primary",
22836
22870
  config.appearance?.selection === "outline" && context.selected && "outline outline-2 outline-primary",
22837
22871
  classNames?.item
@@ -22845,17 +22879,70 @@ function WorkbenchCollection({
22845
22879
  if (isInteractiveEventTarget(event.target, event.currentTarget)) return;
22846
22880
  callbacks?.onItemDoubleClick?.(entry.item, context, event);
22847
22881
  },
22882
+ onMouseEnter: (event) => callbacks?.onItemHoverChange?.(entry.item, context, true, event),
22883
+ onMouseLeave: (event) => callbacks?.onItemHoverChange?.(entry.item, context, false, event),
22848
22884
  onKeyDown: handleKeyboard,
22849
22885
  onDragStart: (event) => callbacks?.onItemDragStart?.(entry.item, context, event),
22850
22886
  onDragOver: callbacks?.onItemDrop ? (event) => event.preventDefault() : void 0,
22851
22887
  onDrop: (event) => callbacks?.onItemDrop?.(entry.item, context, event)
22852
22888
  };
22853
- }, [callbacks, classNames?.item, componentId, config.appearance, selectionMode]);
22889
+ }, [callbacks, classNames?.item, componentId, config.appearance, config.item?.title?.visibility, selectionMode]);
22890
+ const renderItemContent2 = useCallback((entry, context) => {
22891
+ const content = renderItem(entry.item, context);
22892
+ const titleConfig = config.item?.title;
22893
+ const visibility = titleConfig?.visibility ?? "always";
22894
+ if (!titleConfig || visibility === "never") return content;
22895
+ const title = titleConfig.getContent?.(entry.item, context) ?? context.renderSlot("title");
22896
+ if (!hasRenderableNode(title)) return content;
22897
+ const placement = titleConfig.placement ?? "below";
22898
+ const overlay2 = placement.startsWith("overlay-");
22899
+ const maxLines = normalizeTitleMaxLines(titleConfig.maxLines);
22900
+ const surface = titleConfig.surface ?? (overlay2 ? "scrim" : "none");
22901
+ const titleNode = /* @__PURE__ */ jsx(
22902
+ "div",
22903
+ {
22904
+ "data-collection-item-title": "",
22905
+ "data-title-placement": placement,
22906
+ "data-title-visibility": visibility,
22907
+ className: cn(
22908
+ "min-w-0 px-1 py-2 text-sm font-medium text-foreground",
22909
+ titleConfig.align === "center" && "text-center",
22910
+ titleConfig.align === "end" && "text-right",
22911
+ visibility === "hover" && "opacity-0 transition-opacity group-hover/workbench-collection-item:opacity-100 group-focus-within/workbench-collection-item:opacity-100",
22912
+ overlay2 && "pointer-events-none absolute inset-x-0 z-10 px-3 py-2",
22913
+ placement === "overlay-top" && "top-0",
22914
+ placement === "overlay-center" && "top-1/2 -translate-y-1/2 motion-reduce:transform-none",
22915
+ placement === "overlay-bottom" && "bottom-0",
22916
+ surface === "surface" && "bg-background/90 backdrop-blur-sm",
22917
+ surface === "scrim" && placement === "overlay-top" && "bg-gradient-to-b from-background/90 to-transparent pb-8",
22918
+ surface === "scrim" && placement === "overlay-bottom" && "bg-gradient-to-t from-background/90 to-transparent pt-8",
22919
+ surface === "scrim" && placement === "overlay-center" && "bg-background/75 backdrop-blur-sm",
22920
+ Boolean(maxLines) && "overflow-hidden [display:-webkit-box] [-webkit-box-orient:vertical]",
22921
+ classNames?.itemTitle
22922
+ ),
22923
+ style: maxLines ? { WebkitLineClamp: maxLines } : void 0,
22924
+ children: title
22925
+ }
22926
+ );
22927
+ return /* @__PURE__ */ jsxs(
22928
+ "div",
22929
+ {
22930
+ className: cn("min-w-0", overlay2 && "relative", classNames?.itemContent),
22931
+ "data-collection-item-content": "",
22932
+ children: [
22933
+ placement === "above" ? titleNode : null,
22934
+ content,
22935
+ placement === "below" || overlay2 ? titleNode : null
22936
+ ]
22937
+ }
22938
+ );
22939
+ }, [classNames?.itemContent, classNames?.itemTitle, config.item?.title, renderItem]);
22854
22940
  const renderEntry = useCallback((entry, layout, includeShell = true) => {
22855
22941
  const context = createItemContext(entry, layout);
22856
- if (!includeShell) return renderItem(entry.item, context);
22857
- return /* @__PURE__ */ jsx("div", { ...getItemInteractionProps(entry, context), children: renderItem(entry.item, context) });
22858
- }, [createItemContext, getItemInteractionProps, renderItem]);
22942
+ const content = renderItemContent2(entry, context);
22943
+ if (!includeShell) return content;
22944
+ return /* @__PURE__ */ jsx("div", { ...getItemInteractionProps(entry, context), children: content });
22945
+ }, [createItemContext, getItemInteractionProps, renderItemContent2]);
22859
22946
  const baseLayoutContext = useMemo(() => ({
22860
22947
  mode,
22861
22948
  columnCount,
@@ -22882,7 +22969,7 @@ function WorkbenchCollection({
22882
22969
  scrollOwner: resolveScrollOwner(),
22883
22970
  renderItem: (item, localIndex, layout) => {
22884
22971
  const entry = group.items[localIndex];
22885
- return entry ? renderEntry(entry, layout) : null;
22972
+ return entry ? /* @__PURE__ */ jsx(Fragment$1, { children: renderEntry(entry, layout) }, entry.stringKey) : null;
22886
22973
  }
22887
22974
  });
22888
22975
  }
@@ -23009,6 +23096,7 @@ function WorkbenchCollection({
23009
23096
  "data-density": config.appearance?.density,
23010
23097
  "data-radius": config.appearance?.radius,
23011
23098
  "data-media-fit": config.appearance?.mediaFit,
23099
+ "data-hover-effect": config.appearance?.hover,
23012
23100
  "aria-label": ariaLabel ?? labels.collection,
23013
23101
  "aria-busy": loading || loadingMore || void 0,
23014
23102
  className: cn("min-h-0 min-w-0", config.layout.fillHeight && "h-full", classNames?.root, className),
@@ -23105,14 +23193,6 @@ function getGalleryCardWidthMetrics(density) {
23105
23193
  if (density === "detailed") return { min: 320, ideal: 372, max: 420 };
23106
23194
  return { min: 260, ideal: 304, max: 348 };
23107
23195
  }
23108
- function getGalleryCardWidthForColumnCount({
23109
- containerWidth,
23110
- columnCount,
23111
- gap
23112
- }) {
23113
- if (!containerWidth || !columnCount) return 0;
23114
- return (containerWidth - gap * Math.max(columnCount - 1, 0)) / columnCount;
23115
- }
23116
23196
  function getNormalizedGalleryGridColumns(columns) {
23117
23197
  if (columns === void 0 || columns === null || columns === "" || columns === "auto") {
23118
23198
  return void 0;
@@ -23121,90 +23201,6 @@ function getNormalizedGalleryGridColumns(columns) {
23121
23201
  if (!Number.isFinite(parsedColumns) || parsedColumns <= 0) return void 0;
23122
23202
  return Math.max(1, Math.min(parsedColumns, 8));
23123
23203
  }
23124
- function getGalleryGridColumnCount({
23125
- containerWidth,
23126
- rowCount,
23127
- minCardWidth,
23128
- idealCardWidth,
23129
- maxCardWidth,
23130
- gap
23131
- }) {
23132
- if (!containerWidth) return 1;
23133
- const safeRowCount = Math.max(rowCount, 1);
23134
- const lowerBound = Math.max(1, Math.ceil((containerWidth + gap) / (maxCardWidth + gap)));
23135
- const upperBound = Math.max(1, Math.floor((containerWidth + gap) / (minCardWidth + gap)));
23136
- const idealCount = Math.max(1, Math.round((containerWidth + gap) / (idealCardWidth + gap)));
23137
- const phantomPenalty = Math.round((idealCardWidth - minCardWidth) / 2) + gap;
23138
- const maxCandidate = Math.max(1, lowerBound, upperBound + 1, idealCount + 1);
23139
- let bestCount = 1;
23140
- let bestScore = Number.POSITIVE_INFINITY;
23141
- for (let candidateCount = 1; candidateCount <= maxCandidate; candidateCount += 1) {
23142
- const cardWidth = getGalleryCardWidthForColumnCount({ containerWidth, columnCount: candidateCount, gap });
23143
- const overflowPenalty = Math.max(0, cardWidth - maxCardWidth);
23144
- const underflowPenalty = Math.max(0, minCardWidth - cardWidth);
23145
- const idealPenalty = Math.abs(cardWidth - idealCardWidth);
23146
- const phantomColumns = Math.max(0, candidateCount - safeRowCount);
23147
- const candidateScore = overflowPenalty * 3 + underflowPenalty * 2 + idealPenalty + phantomColumns * phantomPenalty;
23148
- if (candidateScore < bestScore) {
23149
- bestScore = candidateScore;
23150
- bestCount = candidateCount;
23151
- }
23152
- }
23153
- return bestCount;
23154
- }
23155
- function getGalleryGridLayoutStyle({
23156
- isRailLayout,
23157
- railCardWidth,
23158
- fixedCardWidth,
23159
- fixedColumnCount,
23160
- containerWidth,
23161
- rowCount,
23162
- minCardWidth,
23163
- idealCardWidth,
23164
- maxCardWidth
23165
- }) {
23166
- if (isRailLayout) {
23167
- return { gridAutoColumns: `${railCardWidth}px` };
23168
- }
23169
- if (fixedColumnCount) {
23170
- const responsiveColumnCount = containerWidth ? Math.max(1, Math.min(
23171
- fixedColumnCount,
23172
- Math.floor((containerWidth + GALLERY_GRID_GAP_PX) / (minCardWidth + GALLERY_GRID_GAP_PX)) || 1
23173
- )) : fixedColumnCount;
23174
- return {
23175
- gridTemplateColumns: `repeat(${responsiveColumnCount}, minmax(0, 1fr))`,
23176
- justifyContent: "start",
23177
- alignContent: "start"
23178
- };
23179
- }
23180
- if (fixedCardWidth) {
23181
- return {
23182
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${fixedCardWidth}), ${fixedCardWidth}))`,
23183
- justifyContent: "start",
23184
- alignContent: "start"
23185
- };
23186
- }
23187
- if (!containerWidth) {
23188
- return {
23189
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${minCardWidth}px), min(100%, ${maxCardWidth}px)))`,
23190
- justifyContent: "start",
23191
- alignContent: "start"
23192
- };
23193
- }
23194
- const columnCount = getGalleryGridColumnCount({
23195
- containerWidth,
23196
- rowCount,
23197
- minCardWidth,
23198
- idealCardWidth,
23199
- maxCardWidth,
23200
- gap: GALLERY_GRID_GAP_PX
23201
- });
23202
- return {
23203
- gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,
23204
- justifyContent: "start",
23205
- alignContent: "start"
23206
- };
23207
- }
23208
23204
  function getGalleryTextLength(value) {
23209
23205
  if (value === null || value === void 0) return 0;
23210
23206
  const text = String(value).trim();
@@ -23412,8 +23408,6 @@ function WorkbenchGalleryView({
23412
23408
  formatLabel,
23413
23409
  getMasonryItemSize
23414
23410
  }) {
23415
- const containerRef = useRef(null);
23416
- const [containerWidth, setContainerWidth] = useState(0);
23417
23411
  const { min: resolvedMinCardWidth, ideal: resolvedIdealCardWidth, max: resolvedMaxCardWidth } = getGalleryCardWidthMetrics(galleryDensity);
23418
23412
  const resolvedRailCardWidth = galleryRailCardWidth || resolvedMinCardWidth;
23419
23413
  const resolvedGridColumnCount = getNormalizedGalleryGridColumns(galleryGridColumns);
@@ -23433,44 +23427,6 @@ function WorkbenchGalleryView({
23433
23427
  const resolvedIsTitleCandidate = isTitleCandidate || ((column, row) => isDefaultGalleryTitleCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
23434
23428
  const resolvedIsSummaryCandidate = isSummaryCandidate || ((column, row) => isDefaultGallerySummaryCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
23435
23429
  const resolvedRenderFieldValue = renderFieldValue || ((column, row, { compact } = {}) => /* @__PURE__ */ jsx("span", { children: resolvedGetDisplayText(resolvedGetFieldValue(column, row)) }));
23436
- useEffect(() => {
23437
- if (isMasonry || isRailLayout || resolvedGridCardWidth) return void 0;
23438
- const node = containerRef.current;
23439
- if (!node) return void 0;
23440
- const updateWidth = () => {
23441
- const nextWidth = Math.round(node.getBoundingClientRect().width);
23442
- setContainerWidth((prevWidth) => prevWidth === nextWidth ? prevWidth : nextWidth);
23443
- };
23444
- updateWidth();
23445
- if (typeof ResizeObserver === "function") {
23446
- const observer = new ResizeObserver(() => updateWidth());
23447
- observer.observe(node);
23448
- return () => observer.disconnect();
23449
- }
23450
- window.addEventListener("resize", updateWidth);
23451
- return () => window.removeEventListener("resize", updateWidth);
23452
- }, [isMasonry, isRailLayout, resolvedGridCardWidth]);
23453
- const layoutStyle = useMemo(() => getGalleryGridLayoutStyle({
23454
- isRailLayout,
23455
- railCardWidth: resolvedRailCardWidth,
23456
- fixedCardWidth: resolvedGridCardWidth,
23457
- fixedColumnCount: resolvedGridColumnCount,
23458
- containerWidth,
23459
- rowCount: rows.length,
23460
- minCardWidth: resolvedMinCardWidth,
23461
- idealCardWidth: resolvedIdealCardWidth,
23462
- maxCardWidth: resolvedMaxCardWidth
23463
- }), [
23464
- containerWidth,
23465
- isRailLayout,
23466
- resolvedGridCardWidth,
23467
- resolvedGridColumnCount,
23468
- resolvedIdealCardWidth,
23469
- resolvedMaxCardWidth,
23470
- resolvedMinCardWidth,
23471
- resolvedRailCardWidth,
23472
- rows.length
23473
- ]);
23474
23430
  const renderGalleryCard = (row, rowIndex) => /* @__PURE__ */ jsx(
23475
23431
  WorkbenchGalleryCard,
23476
23432
  {
@@ -23506,69 +23462,64 @@ function WorkbenchGalleryView({
23506
23462
  },
23507
23463
  row?.id || row?.linkKey || rowIndex
23508
23464
  );
23509
- if (isMasonry) {
23510
- return /* @__PURE__ */ jsx(
23511
- WorkbenchCollection,
23512
- {
23513
- items: rows,
23514
- classNames: { layout: className },
23515
- config: {
23516
- getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
23517
- layout: {
23518
- mode: masonryPlacementStrategy === "dense" ? "dense" : "masonry",
23519
- gap: GALLERY_GRID_GAP_PX,
23520
- idealCardWidth: resolvedMasonryColumnWidth,
23521
- placementStrategy: masonryPlacementStrategy,
23522
- getItemSize: (row, layout) => {
23523
- const defaultSize = getDefaultGalleryMasonryItemSize({
23524
- row,
23525
- columns,
23526
- galleryFieldKey,
23527
- galleryDensity,
23528
- galleryBentoColumns,
23529
- galleryDetailVisibility,
23530
- galleryDetailLimit,
23531
- getFieldValue: resolvedGetFieldValue,
23532
- isMediaColumn: resolvedIsMediaColumn,
23533
- isTitleCandidate: resolvedIsTitleCandidate,
23534
- isSummaryCandidate: resolvedIsSummaryCandidate,
23535
- getDisplayText: resolvedGetDisplayText,
23536
- isImageField: resolvedIsImageField,
23537
- isAudioField: resolvedIsAudioField,
23538
- cardVariant,
23539
- renderPreview,
23540
- renderLeadingVisual,
23541
- hiddenDetailFieldKeys,
23542
- layout,
23543
- resolveRecordVisual
23544
- });
23545
- if (typeof getMasonryItemSize !== "function") return defaultSize;
23546
- const customSize = getMasonryItemSize(row, {
23547
- ...layout,
23548
- placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
23549
- defaultSize
23550
- }) || {};
23551
- return {
23552
- ...defaultSize,
23553
- ...customSize
23554
- };
23555
- }
23556
- }
23557
- },
23558
- renderItem: (row, context) => renderGalleryCard(row, context.index)
23559
- }
23560
- );
23561
- }
23465
+ const collectionMode = isMasonry ? masonryPlacementStrategy === "dense" ? "dense" : "masonry" : isRailLayout ? "rail" : "grid";
23562
23466
  return /* @__PURE__ */ jsx(
23563
- "div",
23467
+ WorkbenchCollection,
23564
23468
  {
23565
- ref: containerRef,
23566
- className: cn(
23567
- isRailLayout ? "grid grid-flow-col items-center gap-3" : "grid items-start gap-3",
23568
- className
23569
- ),
23570
- style: layoutStyle,
23571
- children: rows.map((row, rowIndex) => renderGalleryCard(row, rowIndex))
23469
+ items: rows,
23470
+ classNames: { layout: className },
23471
+ config: {
23472
+ getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
23473
+ layout: {
23474
+ mode: collectionMode,
23475
+ gap: GALLERY_GRID_GAP_PX,
23476
+ columns: isMasonry ? "auto" : resolvedGridColumnCount ? {
23477
+ mobile: 1,
23478
+ tablet: Math.min(2, resolvedGridColumnCount),
23479
+ desktop: resolvedGridColumnCount
23480
+ } : "auto",
23481
+ cardWidth: isRailLayout ? resolvedRailCardWidth : void 0,
23482
+ minCardWidth: resolvedGridCardWidth ?? resolvedMinCardWidth,
23483
+ idealCardWidth: isMasonry ? resolvedMasonryColumnWidth : resolvedGridCardWidth ?? resolvedIdealCardWidth,
23484
+ maxCardWidth: resolvedGridCardWidth ?? resolvedMaxCardWidth,
23485
+ placementStrategy: masonryPlacementStrategy,
23486
+ getItemSize: isMasonry ? (row, layout) => {
23487
+ const defaultSize = getDefaultGalleryMasonryItemSize({
23488
+ row,
23489
+ columns,
23490
+ galleryFieldKey,
23491
+ galleryDensity,
23492
+ galleryBentoColumns,
23493
+ galleryDetailVisibility,
23494
+ galleryDetailLimit,
23495
+ getFieldValue: resolvedGetFieldValue,
23496
+ isMediaColumn: resolvedIsMediaColumn,
23497
+ isTitleCandidate: resolvedIsTitleCandidate,
23498
+ isSummaryCandidate: resolvedIsSummaryCandidate,
23499
+ getDisplayText: resolvedGetDisplayText,
23500
+ isImageField: resolvedIsImageField,
23501
+ isAudioField: resolvedIsAudioField,
23502
+ cardVariant,
23503
+ renderPreview,
23504
+ renderLeadingVisual,
23505
+ hiddenDetailFieldKeys,
23506
+ layout,
23507
+ resolveRecordVisual
23508
+ });
23509
+ if (typeof getMasonryItemSize !== "function") return defaultSize;
23510
+ const customSize = getMasonryItemSize(row, {
23511
+ ...layout,
23512
+ placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
23513
+ defaultSize
23514
+ }) || {};
23515
+ return {
23516
+ ...defaultSize,
23517
+ ...customSize
23518
+ };
23519
+ } : void 0
23520
+ }
23521
+ },
23522
+ renderItem: (row, context) => renderGalleryCard(row, context.index)
23572
23523
  }
23573
23524
  );
23574
23525
  }
@@ -24485,18 +24436,26 @@ function WorkbenchAssetGallery({
24485
24436
  if (!items.length) {
24486
24437
  return hasRenderableNode(emptyState) ? /* @__PURE__ */ jsx(Fragment, { children: emptyState }) : null;
24487
24438
  }
24488
- return /* @__PURE__ */ jsx(
24489
- "ul",
24439
+ return /* @__PURE__ */ jsx("div", { "data-monkeys-component": "workbench-asset-gallery", children: /* @__PURE__ */ jsx(
24440
+ WorkbenchCollection,
24490
24441
  {
24491
- "aria-label": ariaLabel,
24492
- "data-monkeys-component": "workbench-asset-gallery",
24493
- className: cn(
24494
- "grid min-w-0 gap-3 [grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))]",
24495
- className
24496
- ),
24497
- children: items.map((item) => {
24442
+ items,
24443
+ config: {
24444
+ getItemKey: (item) => item.id,
24445
+ layout: {
24446
+ mode: "grid",
24447
+ columns: "auto",
24448
+ minCardWidth: "12rem",
24449
+ idealCardWidth: "16rem",
24450
+ gap: 12
24451
+ },
24452
+ appearance: { hover: "none" }
24453
+ },
24454
+ ariaLabel,
24455
+ className,
24456
+ renderItem: (item) => {
24498
24457
  const selected = selectedItemId === item.id;
24499
- return /* @__PURE__ */ jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsxs(
24458
+ return /* @__PURE__ */ jsxs(
24500
24459
  "button",
24501
24460
  {
24502
24461
  type: "button",
@@ -24532,10 +24491,10 @@ function WorkbenchAssetGallery({
24532
24491
  ] })
24533
24492
  ]
24534
24493
  }
24535
- ) }, item.id);
24536
- })
24494
+ );
24495
+ }
24537
24496
  }
24538
- );
24497
+ ) });
24539
24498
  }
24540
24499
  var radarWorkspaceStyle = {
24541
24500
  backgroundColor: "hsl(var(--radar-canvas, var(--background)))",