@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.
@@ -8689,13 +8689,15 @@ function resolveColumnCount({
8689
8689
  itemCount,
8690
8690
  gap,
8691
8691
  columns,
8692
+ maxColumns,
8692
8693
  minCardWidth,
8693
8694
  idealCardWidth,
8694
8695
  maxCardWidth,
8695
8696
  node
8696
8697
  }) {
8697
8698
  const fixedColumns = resolveResponsiveColumns(columns, containerWidth);
8698
- if (fixedColumns) return fixedColumns;
8699
+ const resolvedMaxColumns = resolveResponsiveColumns(maxColumns, containerWidth);
8700
+ if (fixedColumns) return resolvedMaxColumns ? Math.min(fixedColumns, resolvedMaxColumns) : fixedColumns;
8699
8701
  if (!containerWidth) return 1;
8700
8702
  const idealWidth = resolveLengthToPixels2(idealCardWidth, DEFAULT_CARD_WIDTH_PX, node);
8701
8703
  const minWidth = resolveLengthToPixels2(minCardWidth, idealWidth * 0.78, node);
@@ -8722,7 +8724,7 @@ function resolveColumnCount({
8722
8724
  bestCount = candidate;
8723
8725
  }
8724
8726
  }
8725
- return bestCount;
8727
+ return resolvedMaxColumns ? Math.min(bestCount, resolvedMaxColumns) : bestCount;
8726
8728
  }
8727
8729
  function normalizeGap(value) {
8728
8730
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : DEFAULT_GAP_PX;
@@ -8789,6 +8791,10 @@ function warnOnDuplicateKeys(keys) {
8789
8791
  console.warn(`WorkbenchCollection received duplicate item keys: ${Array.from(duplicates).join(", ")}`);
8790
8792
  }
8791
8793
  }
8794
+ function normalizeTitleMaxLines(value) {
8795
+ if (!Number.isFinite(value) || Number(value) <= 0) return void 0;
8796
+ return clamp2(Math.round(Number(value)), 1, 12);
8797
+ }
8792
8798
  function WorkbenchCollection({
8793
8799
  items,
8794
8800
  config,
@@ -8873,6 +8879,7 @@ function WorkbenchCollection({
8873
8879
  itemCount: normalizedItems.length,
8874
8880
  gap,
8875
8881
  columns: config.layout.columns,
8882
+ maxColumns: config.layout.maxColumns,
8876
8883
  minCardWidth: config.layout.minCardWidth,
8877
8884
  idealCardWidth: config.layout.idealCardWidth ?? config.layout.columnWidth,
8878
8885
  maxCardWidth: config.layout.maxCardWidth,
@@ -8960,25 +8967,29 @@ function WorkbenchCollection({
8960
8967
  react.useEffect(() => {
8961
8968
  if (!loadingMore || !hasMore) loadMoreLockedRef.current = false;
8962
8969
  }, [hasMore, loadingMore, normalizedItems.length, keysSignature]);
8970
+ const requestLoadMore = react.useCallback(() => {
8971
+ if (!canLoadMore || !hasMore || loadingMore || loadMoreLockedRef.current) return;
8972
+ loadMoreLockedRef.current = true;
8973
+ try {
8974
+ const result = callbacksRef.current?.onLoadMore?.();
8975
+ if (result && typeof result.then === "function") {
8976
+ void result.catch(() => {
8977
+ loadMoreLockedRef.current = false;
8978
+ });
8979
+ }
8980
+ } catch (error) {
8981
+ loadMoreLockedRef.current = false;
8982
+ throw error;
8983
+ }
8984
+ }, [canLoadMore, hasMore, loadingMore]);
8963
8985
  react.useEffect(() => {
8964
8986
  const sentinel = loadMoreRef.current;
8965
8987
  if (!sentinel || !canLoadMore || !hasMore || loadingMore) return void 0;
8966
8988
  if (typeof IntersectionObserver !== "function") return void 0;
8967
8989
  const owner = resolveScrollOwner();
8968
8990
  const observer = new IntersectionObserver((entries) => {
8969
- if (!entries.some((entry) => entry.isIntersecting) || loadMoreLockedRef.current) return;
8970
- loadMoreLockedRef.current = true;
8971
- try {
8972
- const result = callbacksRef.current?.onLoadMore?.();
8973
- if (result && typeof result.then === "function") {
8974
- void result.catch(() => {
8975
- loadMoreLockedRef.current = false;
8976
- });
8977
- }
8978
- } catch (error) {
8979
- loadMoreLockedRef.current = false;
8980
- throw error;
8981
- }
8991
+ if (!entries.some((entry) => entry.isIntersecting)) return;
8992
+ requestLoadMore();
8982
8993
  }, {
8983
8994
  root: owner === rootRef.current ? owner : owner || null,
8984
8995
  rootMargin: config.loading?.rootMargin ?? "240px",
@@ -8986,7 +8997,25 @@ function WorkbenchCollection({
8986
8997
  });
8987
8998
  observer.observe(sentinel);
8988
8999
  return () => observer.disconnect();
8989
- }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, resolveScrollOwner]);
9000
+ }, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, requestLoadMore, resolveScrollOwner]);
9001
+ react.useEffect(() => {
9002
+ if (!config.loading?.autoFill || !canLoadMore || !hasMore || loadingMore) return;
9003
+ const sentinel = loadMoreRef.current;
9004
+ if (!sentinel) return;
9005
+ const owner = resolveScrollOwner() ?? (config.layout.scrollOwner === "parent" ? rootRef.current?.parentElement ?? null : null) ?? rootRef.current;
9006
+ if (!owner || owner.clientHeight <= 0) return;
9007
+ if (owner.scrollHeight <= owner.clientHeight + 1) requestLoadMore();
9008
+ }, [
9009
+ canLoadMore,
9010
+ config.layout.scrollOwner,
9011
+ config.loading?.autoFill,
9012
+ hasMore,
9013
+ keysSignature,
9014
+ loadingMore,
9015
+ normalizedItems.length,
9016
+ requestLoadMore,
9017
+ resolveScrollOwner
9018
+ ]);
8990
9019
  const groups = react.useMemo(() => {
8991
9020
  if (!config.grouping) {
8992
9021
  return [{ key: "__all__", stringKey: "__all__", items: normalizedItems }];
@@ -9072,11 +9101,16 @@ function WorkbenchCollection({
9072
9101
  role: selectionMode === "none" ? "listitem" : "option",
9073
9102
  "aria-selected": selectionMode === "none" ? void 0 : context.selected,
9074
9103
  "aria-disabled": context.disabled || void 0,
9075
- tabIndex: callbacks?.onItemClick || selectionMode !== "none" ? 0 : void 0,
9104
+ tabIndex: callbacks?.onItemClick || selectionMode !== "none" || config.item?.title?.visibility === "hover" ? 0 : void 0,
9076
9105
  draggable: callbacks?.onItemDragStart ? true : void 0,
9077
9106
  className: cn(
9078
- "min-w-0 outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
9079
- config.appearance?.hover === "lift" && "transition-transform hover:-translate-y-0.5 motion-reduce:transform-none",
9107
+ "min-w-0 group/workbench-collection-item outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
9108
+ config.appearance?.hover && config.appearance.hover !== "none" && "transition-[transform,box-shadow,background-color] duration-200",
9109
+ config.appearance?.hover === "highlight" && "hover:bg-muted/30",
9110
+ config.appearance?.hover === "lift" && "hover:-translate-y-0.5 motion-reduce:transform-none",
9111
+ config.appearance?.hover === "scale" && "hover:scale-[1.01] motion-reduce:transform-none",
9112
+ config.appearance?.hover === "shadow" && "hover:shadow-md",
9113
+ config.appearance?.hover === "lift-shadow" && "hover:-translate-y-0.5 hover:shadow-md motion-reduce:transform-none",
9080
9114
  config.appearance?.selection === "ring" && context.selected && "ring-2 ring-primary",
9081
9115
  config.appearance?.selection === "outline" && context.selected && "outline outline-2 outline-primary",
9082
9116
  classNames?.item
@@ -9090,17 +9124,70 @@ function WorkbenchCollection({
9090
9124
  if (isInteractiveEventTarget(event.target, event.currentTarget)) return;
9091
9125
  callbacks?.onItemDoubleClick?.(entry.item, context, event);
9092
9126
  },
9127
+ onMouseEnter: (event) => callbacks?.onItemHoverChange?.(entry.item, context, true, event),
9128
+ onMouseLeave: (event) => callbacks?.onItemHoverChange?.(entry.item, context, false, event),
9093
9129
  onKeyDown: handleKeyboard,
9094
9130
  onDragStart: (event) => callbacks?.onItemDragStart?.(entry.item, context, event),
9095
9131
  onDragOver: callbacks?.onItemDrop ? (event) => event.preventDefault() : void 0,
9096
9132
  onDrop: (event) => callbacks?.onItemDrop?.(entry.item, context, event)
9097
9133
  };
9098
- }, [callbacks, classNames?.item, componentId, config.appearance, selectionMode]);
9134
+ }, [callbacks, classNames?.item, componentId, config.appearance, config.item?.title?.visibility, selectionMode]);
9135
+ const renderItemContent2 = react.useCallback((entry, context) => {
9136
+ const content = renderItem(entry.item, context);
9137
+ const titleConfig = config.item?.title;
9138
+ const visibility = titleConfig?.visibility ?? "always";
9139
+ if (!titleConfig || visibility === "never") return content;
9140
+ const title = titleConfig.getContent?.(entry.item, context) ?? context.renderSlot("title");
9141
+ if (!hasRenderableNode(title)) return content;
9142
+ const placement = titleConfig.placement ?? "below";
9143
+ const overlay = placement.startsWith("overlay-");
9144
+ const maxLines = normalizeTitleMaxLines(titleConfig.maxLines);
9145
+ const surface = titleConfig.surface ?? (overlay ? "scrim" : "none");
9146
+ const titleNode = /* @__PURE__ */ jsxRuntime.jsx(
9147
+ "div",
9148
+ {
9149
+ "data-collection-item-title": "",
9150
+ "data-title-placement": placement,
9151
+ "data-title-visibility": visibility,
9152
+ className: cn(
9153
+ "min-w-0 px-1 py-2 text-sm font-medium text-foreground",
9154
+ titleConfig.align === "center" && "text-center",
9155
+ titleConfig.align === "end" && "text-right",
9156
+ visibility === "hover" && "opacity-0 transition-opacity group-hover/workbench-collection-item:opacity-100 group-focus-within/workbench-collection-item:opacity-100",
9157
+ overlay && "pointer-events-none absolute inset-x-0 z-10 px-3 py-2",
9158
+ placement === "overlay-top" && "top-0",
9159
+ placement === "overlay-center" && "top-1/2 -translate-y-1/2 motion-reduce:transform-none",
9160
+ placement === "overlay-bottom" && "bottom-0",
9161
+ surface === "surface" && "bg-background/90 backdrop-blur-sm",
9162
+ surface === "scrim" && placement === "overlay-top" && "bg-gradient-to-b from-background/90 to-transparent pb-8",
9163
+ surface === "scrim" && placement === "overlay-bottom" && "bg-gradient-to-t from-background/90 to-transparent pt-8",
9164
+ surface === "scrim" && placement === "overlay-center" && "bg-background/75 backdrop-blur-sm",
9165
+ Boolean(maxLines) && "overflow-hidden [display:-webkit-box] [-webkit-box-orient:vertical]",
9166
+ classNames?.itemTitle
9167
+ ),
9168
+ style: maxLines ? { WebkitLineClamp: maxLines } : void 0,
9169
+ children: title
9170
+ }
9171
+ );
9172
+ return /* @__PURE__ */ jsxRuntime.jsxs(
9173
+ "div",
9174
+ {
9175
+ className: cn("min-w-0", overlay && "relative", classNames?.itemContent),
9176
+ "data-collection-item-content": "",
9177
+ children: [
9178
+ placement === "above" ? titleNode : null,
9179
+ content,
9180
+ placement === "below" || overlay ? titleNode : null
9181
+ ]
9182
+ }
9183
+ );
9184
+ }, [classNames?.itemContent, classNames?.itemTitle, config.item?.title, renderItem]);
9099
9185
  const renderEntry = react.useCallback((entry, layout, includeShell = true) => {
9100
9186
  const context = createItemContext(entry, layout);
9101
- if (!includeShell) return renderItem(entry.item, context);
9102
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ...getItemInteractionProps(entry, context), children: renderItem(entry.item, context) });
9103
- }, [createItemContext, getItemInteractionProps, renderItem]);
9187
+ const content = renderItemContent2(entry, context);
9188
+ if (!includeShell) return content;
9189
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ...getItemInteractionProps(entry, context), children: content });
9190
+ }, [createItemContext, getItemInteractionProps, renderItemContent2]);
9104
9191
  const baseLayoutContext = react.useMemo(() => ({
9105
9192
  mode,
9106
9193
  columnCount,
@@ -9127,7 +9214,7 @@ function WorkbenchCollection({
9127
9214
  scrollOwner: resolveScrollOwner(),
9128
9215
  renderItem: (item, localIndex, layout) => {
9129
9216
  const entry = group.items[localIndex];
9130
- return entry ? renderEntry(entry, layout) : null;
9217
+ return entry ? /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderEntry(entry, layout) }, entry.stringKey) : null;
9131
9218
  }
9132
9219
  });
9133
9220
  }
@@ -9254,6 +9341,7 @@ function WorkbenchCollection({
9254
9341
  "data-density": config.appearance?.density,
9255
9342
  "data-radius": config.appearance?.radius,
9256
9343
  "data-media-fit": config.appearance?.mediaFit,
9344
+ "data-hover-effect": config.appearance?.hover,
9257
9345
  "aria-label": ariaLabel ?? labels.collection,
9258
9346
  "aria-busy": loading || loadingMore || void 0,
9259
9347
  className: cn("min-h-0 min-w-0", config.layout.fillHeight && "h-full", classNames?.root, className),
@@ -9350,14 +9438,6 @@ function getGalleryCardWidthMetrics(density) {
9350
9438
  if (density === "detailed") return { min: 320, ideal: 372, max: 420 };
9351
9439
  return { min: 260, ideal: 304, max: 348 };
9352
9440
  }
9353
- function getGalleryCardWidthForColumnCount({
9354
- containerWidth,
9355
- columnCount,
9356
- gap
9357
- }) {
9358
- if (!containerWidth || !columnCount) return 0;
9359
- return (containerWidth - gap * Math.max(columnCount - 1, 0)) / columnCount;
9360
- }
9361
9441
  function getNormalizedGalleryGridColumns(columns) {
9362
9442
  if (columns === void 0 || columns === null || columns === "" || columns === "auto") {
9363
9443
  return void 0;
@@ -9366,90 +9446,6 @@ function getNormalizedGalleryGridColumns(columns) {
9366
9446
  if (!Number.isFinite(parsedColumns) || parsedColumns <= 0) return void 0;
9367
9447
  return Math.max(1, Math.min(parsedColumns, 8));
9368
9448
  }
9369
- function getGalleryGridColumnCount({
9370
- containerWidth,
9371
- rowCount,
9372
- minCardWidth,
9373
- idealCardWidth,
9374
- maxCardWidth,
9375
- gap
9376
- }) {
9377
- if (!containerWidth) return 1;
9378
- const safeRowCount = Math.max(rowCount, 1);
9379
- const lowerBound = Math.max(1, Math.ceil((containerWidth + gap) / (maxCardWidth + gap)));
9380
- const upperBound = Math.max(1, Math.floor((containerWidth + gap) / (minCardWidth + gap)));
9381
- const idealCount = Math.max(1, Math.round((containerWidth + gap) / (idealCardWidth + gap)));
9382
- const phantomPenalty = Math.round((idealCardWidth - minCardWidth) / 2) + gap;
9383
- const maxCandidate = Math.max(1, lowerBound, upperBound + 1, idealCount + 1);
9384
- let bestCount = 1;
9385
- let bestScore = Number.POSITIVE_INFINITY;
9386
- for (let candidateCount = 1; candidateCount <= maxCandidate; candidateCount += 1) {
9387
- const cardWidth = getGalleryCardWidthForColumnCount({ containerWidth, columnCount: candidateCount, gap });
9388
- const overflowPenalty = Math.max(0, cardWidth - maxCardWidth);
9389
- const underflowPenalty = Math.max(0, minCardWidth - cardWidth);
9390
- const idealPenalty = Math.abs(cardWidth - idealCardWidth);
9391
- const phantomColumns = Math.max(0, candidateCount - safeRowCount);
9392
- const candidateScore = overflowPenalty * 3 + underflowPenalty * 2 + idealPenalty + phantomColumns * phantomPenalty;
9393
- if (candidateScore < bestScore) {
9394
- bestScore = candidateScore;
9395
- bestCount = candidateCount;
9396
- }
9397
- }
9398
- return bestCount;
9399
- }
9400
- function getGalleryGridLayoutStyle({
9401
- isRailLayout,
9402
- railCardWidth,
9403
- fixedCardWidth,
9404
- fixedColumnCount,
9405
- containerWidth,
9406
- rowCount,
9407
- minCardWidth,
9408
- idealCardWidth,
9409
- maxCardWidth
9410
- }) {
9411
- if (isRailLayout) {
9412
- return { gridAutoColumns: `${railCardWidth}px` };
9413
- }
9414
- if (fixedColumnCount) {
9415
- const responsiveColumnCount = containerWidth ? Math.max(1, Math.min(
9416
- fixedColumnCount,
9417
- Math.floor((containerWidth + GALLERY_GRID_GAP_PX) / (minCardWidth + GALLERY_GRID_GAP_PX)) || 1
9418
- )) : fixedColumnCount;
9419
- return {
9420
- gridTemplateColumns: `repeat(${responsiveColumnCount}, minmax(0, 1fr))`,
9421
- justifyContent: "start",
9422
- alignContent: "start"
9423
- };
9424
- }
9425
- if (fixedCardWidth) {
9426
- return {
9427
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${fixedCardWidth}), ${fixedCardWidth}))`,
9428
- justifyContent: "start",
9429
- alignContent: "start"
9430
- };
9431
- }
9432
- if (!containerWidth) {
9433
- return {
9434
- gridTemplateColumns: `repeat(auto-fit, minmax(min(100%, ${minCardWidth}px), min(100%, ${maxCardWidth}px)))`,
9435
- justifyContent: "start",
9436
- alignContent: "start"
9437
- };
9438
- }
9439
- const columnCount = getGalleryGridColumnCount({
9440
- containerWidth,
9441
- rowCount,
9442
- minCardWidth,
9443
- idealCardWidth,
9444
- maxCardWidth,
9445
- gap: GALLERY_GRID_GAP_PX
9446
- });
9447
- return {
9448
- gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`,
9449
- justifyContent: "start",
9450
- alignContent: "start"
9451
- };
9452
- }
9453
9449
  function getGalleryTextLength(value) {
9454
9450
  if (value === null || value === void 0) return 0;
9455
9451
  const text = String(value).trim();
@@ -9657,8 +9653,6 @@ function WorkbenchGalleryView({
9657
9653
  formatLabel,
9658
9654
  getMasonryItemSize
9659
9655
  }) {
9660
- const containerRef = react.useRef(null);
9661
- const [containerWidth, setContainerWidth] = react.useState(0);
9662
9656
  const { min: resolvedMinCardWidth, ideal: resolvedIdealCardWidth, max: resolvedMaxCardWidth } = getGalleryCardWidthMetrics(galleryDensity);
9663
9657
  const resolvedRailCardWidth = galleryRailCardWidth || resolvedMinCardWidth;
9664
9658
  const resolvedGridColumnCount = getNormalizedGalleryGridColumns(galleryGridColumns);
@@ -9678,44 +9672,6 @@ function WorkbenchGalleryView({
9678
9672
  const resolvedIsTitleCandidate = isTitleCandidate || ((column, row) => isDefaultGalleryTitleCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
9679
9673
  const resolvedIsSummaryCandidate = isSummaryCandidate || ((column, row) => isDefaultGallerySummaryCandidate(column, row, { isMediaColumn: resolvedIsMediaColumn }));
9680
9674
  const resolvedRenderFieldValue = renderFieldValue || ((column, row, { compact } = {}) => /* @__PURE__ */ jsxRuntime.jsx("span", { children: resolvedGetDisplayText(resolvedGetFieldValue(column, row)) }));
9681
- react.useEffect(() => {
9682
- if (isMasonry || isRailLayout || resolvedGridCardWidth) return void 0;
9683
- const node = containerRef.current;
9684
- if (!node) return void 0;
9685
- const updateWidth = () => {
9686
- const nextWidth = Math.round(node.getBoundingClientRect().width);
9687
- setContainerWidth((prevWidth) => prevWidth === nextWidth ? prevWidth : nextWidth);
9688
- };
9689
- updateWidth();
9690
- if (typeof ResizeObserver === "function") {
9691
- const observer = new ResizeObserver(() => updateWidth());
9692
- observer.observe(node);
9693
- return () => observer.disconnect();
9694
- }
9695
- window.addEventListener("resize", updateWidth);
9696
- return () => window.removeEventListener("resize", updateWidth);
9697
- }, [isMasonry, isRailLayout, resolvedGridCardWidth]);
9698
- const layoutStyle = react.useMemo(() => getGalleryGridLayoutStyle({
9699
- isRailLayout,
9700
- railCardWidth: resolvedRailCardWidth,
9701
- fixedCardWidth: resolvedGridCardWidth,
9702
- fixedColumnCount: resolvedGridColumnCount,
9703
- containerWidth,
9704
- rowCount: rows.length,
9705
- minCardWidth: resolvedMinCardWidth,
9706
- idealCardWidth: resolvedIdealCardWidth,
9707
- maxCardWidth: resolvedMaxCardWidth
9708
- }), [
9709
- containerWidth,
9710
- isRailLayout,
9711
- resolvedGridCardWidth,
9712
- resolvedGridColumnCount,
9713
- resolvedIdealCardWidth,
9714
- resolvedMaxCardWidth,
9715
- resolvedMinCardWidth,
9716
- resolvedRailCardWidth,
9717
- rows.length
9718
- ]);
9719
9675
  const renderGalleryCard = (row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(
9720
9676
  WorkbenchGalleryCard,
9721
9677
  {
@@ -9751,69 +9707,64 @@ function WorkbenchGalleryView({
9751
9707
  },
9752
9708
  row?.id || row?.linkKey || rowIndex
9753
9709
  );
9754
- if (isMasonry) {
9755
- return /* @__PURE__ */ jsxRuntime.jsx(
9756
- WorkbenchCollection,
9757
- {
9758
- items: rows,
9759
- classNames: { layout: className },
9760
- config: {
9761
- getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
9762
- layout: {
9763
- mode: masonryPlacementStrategy === "dense" ? "dense" : "masonry",
9764
- gap: GALLERY_GRID_GAP_PX,
9765
- idealCardWidth: resolvedMasonryColumnWidth,
9766
- placementStrategy: masonryPlacementStrategy,
9767
- getItemSize: (row, layout) => {
9768
- const defaultSize = getDefaultGalleryMasonryItemSize({
9769
- row,
9770
- columns,
9771
- galleryFieldKey,
9772
- galleryDensity,
9773
- galleryBentoColumns,
9774
- galleryDetailVisibility,
9775
- galleryDetailLimit,
9776
- getFieldValue: resolvedGetFieldValue,
9777
- isMediaColumn: resolvedIsMediaColumn,
9778
- isTitleCandidate: resolvedIsTitleCandidate,
9779
- isSummaryCandidate: resolvedIsSummaryCandidate,
9780
- getDisplayText: resolvedGetDisplayText,
9781
- isImageField: resolvedIsImageField,
9782
- isAudioField: resolvedIsAudioField,
9783
- cardVariant,
9784
- renderPreview,
9785
- renderLeadingVisual,
9786
- hiddenDetailFieldKeys,
9787
- layout,
9788
- resolveRecordVisual
9789
- });
9790
- if (typeof getMasonryItemSize !== "function") return defaultSize;
9791
- const customSize = getMasonryItemSize(row, {
9792
- ...layout,
9793
- placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
9794
- defaultSize
9795
- }) || {};
9796
- return {
9797
- ...defaultSize,
9798
- ...customSize
9799
- };
9800
- }
9801
- }
9802
- },
9803
- renderItem: (row, context) => renderGalleryCard(row, context.index)
9804
- }
9805
- );
9806
- }
9710
+ const collectionMode = isMasonry ? masonryPlacementStrategy === "dense" ? "dense" : "masonry" : isRailLayout ? "rail" : "grid";
9807
9711
  return /* @__PURE__ */ jsxRuntime.jsx(
9808
- "div",
9712
+ WorkbenchCollection,
9809
9713
  {
9810
- ref: containerRef,
9811
- className: cn(
9812
- isRailLayout ? "grid grid-flow-col items-center gap-3" : "grid items-start gap-3",
9813
- className
9814
- ),
9815
- style: layoutStyle,
9816
- children: rows.map((row, rowIndex) => renderGalleryCard(row, rowIndex))
9714
+ items: rows,
9715
+ classNames: { layout: className },
9716
+ config: {
9717
+ getItemKey: (row, rowIndex) => row?.id || row?.linkKey || rowIndex,
9718
+ layout: {
9719
+ mode: collectionMode,
9720
+ gap: GALLERY_GRID_GAP_PX,
9721
+ columns: isMasonry ? "auto" : resolvedGridColumnCount ? {
9722
+ mobile: 1,
9723
+ tablet: Math.min(2, resolvedGridColumnCount),
9724
+ desktop: resolvedGridColumnCount
9725
+ } : "auto",
9726
+ cardWidth: isRailLayout ? resolvedRailCardWidth : void 0,
9727
+ minCardWidth: resolvedGridCardWidth ?? resolvedMinCardWidth,
9728
+ idealCardWidth: isMasonry ? resolvedMasonryColumnWidth : resolvedGridCardWidth ?? resolvedIdealCardWidth,
9729
+ maxCardWidth: resolvedGridCardWidth ?? resolvedMaxCardWidth,
9730
+ placementStrategy: masonryPlacementStrategy,
9731
+ getItemSize: isMasonry ? (row, layout) => {
9732
+ const defaultSize = getDefaultGalleryMasonryItemSize({
9733
+ row,
9734
+ columns,
9735
+ galleryFieldKey,
9736
+ galleryDensity,
9737
+ galleryBentoColumns,
9738
+ galleryDetailVisibility,
9739
+ galleryDetailLimit,
9740
+ getFieldValue: resolvedGetFieldValue,
9741
+ isMediaColumn: resolvedIsMediaColumn,
9742
+ isTitleCandidate: resolvedIsTitleCandidate,
9743
+ isSummaryCandidate: resolvedIsSummaryCandidate,
9744
+ getDisplayText: resolvedGetDisplayText,
9745
+ isImageField: resolvedIsImageField,
9746
+ isAudioField: resolvedIsAudioField,
9747
+ cardVariant,
9748
+ renderPreview,
9749
+ renderLeadingVisual,
9750
+ hiddenDetailFieldKeys,
9751
+ layout,
9752
+ resolveRecordVisual
9753
+ });
9754
+ if (typeof getMasonryItemSize !== "function") return defaultSize;
9755
+ const customSize = getMasonryItemSize(row, {
9756
+ ...layout,
9757
+ placementStrategy: layout.placementStrategy === "dense" ? "dense" : "shelf",
9758
+ defaultSize
9759
+ }) || {};
9760
+ return {
9761
+ ...defaultSize,
9762
+ ...customSize
9763
+ };
9764
+ } : void 0
9765
+ }
9766
+ },
9767
+ renderItem: (row, context) => renderGalleryCard(row, context.index)
9817
9768
  }
9818
9769
  );
9819
9770
  }
@@ -10730,18 +10681,26 @@ function WorkbenchAssetGallery({
10730
10681
  if (!items.length) {
10731
10682
  return hasRenderableNode(emptyState) ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: emptyState }) : null;
10732
10683
  }
10733
- return /* @__PURE__ */ jsxRuntime.jsx(
10734
- "ul",
10684
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-monkeys-component": "workbench-asset-gallery", children: /* @__PURE__ */ jsxRuntime.jsx(
10685
+ WorkbenchCollection,
10735
10686
  {
10736
- "aria-label": ariaLabel,
10737
- "data-monkeys-component": "workbench-asset-gallery",
10738
- className: cn(
10739
- "grid min-w-0 gap-3 [grid-template-columns:repeat(auto-fit,minmax(12rem,1fr))]",
10740
- className
10741
- ),
10742
- children: items.map((item) => {
10687
+ items,
10688
+ config: {
10689
+ getItemKey: (item) => item.id,
10690
+ layout: {
10691
+ mode: "grid",
10692
+ columns: "auto",
10693
+ minCardWidth: "12rem",
10694
+ idealCardWidth: "16rem",
10695
+ gap: 12
10696
+ },
10697
+ appearance: { hover: "none" }
10698
+ },
10699
+ ariaLabel,
10700
+ className,
10701
+ renderItem: (item) => {
10743
10702
  const selected = selectedItemId === item.id;
10744
- return /* @__PURE__ */ jsxRuntime.jsx("li", { className: "min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
10703
+ return /* @__PURE__ */ jsxRuntime.jsxs(
10745
10704
  "button",
10746
10705
  {
10747
10706
  type: "button",
@@ -10777,10 +10736,10 @@ function WorkbenchAssetGallery({
10777
10736
  ] })
10778
10737
  ]
10779
10738
  }
10780
- ) }, item.id);
10781
- })
10739
+ );
10740
+ }
10782
10741
  }
10783
- );
10742
+ ) });
10784
10743
  }
10785
10744
  var radarWorkspaceStyle = {
10786
10745
  backgroundColor: "hsl(var(--radar-canvas, var(--background)))",