@inf-monkeys-tech/monkeys-design 1.0.38 → 1.0.39
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/components/agent-workbench/index.js +9 -0
- package/dist/components/agent-workbench/index.js.map +1 -1
- package/dist/components/agent-workbench/index.mjs +9 -0
- package/dist/components/agent-workbench/index.mjs.map +1 -1
- package/dist/components/base/index.js +9 -0
- package/dist/components/base/index.js.map +1 -1
- package/dist/components/base/index.mjs +9 -0
- package/dist/components/base/index.mjs.map +1 -1
- package/dist/components/data-explorer/index.js +9 -0
- package/dist/components/data-explorer/index.js.map +1 -1
- package/dist/components/data-explorer/index.mjs +9 -0
- package/dist/components/data-explorer/index.mjs.map +1 -1
- package/dist/components/layout/index.js +9 -0
- package/dist/components/layout/index.js.map +1 -1
- package/dist/components/layout/index.mjs +9 -0
- package/dist/components/layout/index.mjs.map +1 -1
- package/dist/components/runtime/index.js +9 -0
- package/dist/components/runtime/index.js.map +1 -1
- package/dist/components/runtime/index.mjs +9 -0
- package/dist/components/runtime/index.mjs.map +1 -1
- package/dist/components/toast/index.d.mts +1 -1
- package/dist/components/toast/index.d.ts +1 -1
- package/dist/components/toast/index.js +9 -0
- package/dist/components/toast/index.js.map +1 -1
- package/dist/components/toast/index.mjs +9 -0
- package/dist/components/toast/index.mjs.map +1 -1
- package/dist/components/toolbar/index.js +9 -0
- package/dist/components/toolbar/index.js.map +1 -1
- package/dist/components/toolbar/index.mjs +9 -0
- package/dist/components/toolbar/index.mjs.map +1 -1
- package/dist/components/workbench/index.d.mts +218 -6
- package/dist/components/workbench/index.d.ts +218 -6
- package/dist/components/workbench/index.js +1088 -97
- package/dist/components/workbench/index.js.map +1 -1
- package/dist/components/workbench/index.mjs +1089 -99
- package/dist/components/workbench/index.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +838 -100
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +838 -101
- package/dist/index.mjs.map +1 -1
- package/dist/locale/index.d.mts +20 -2
- package/dist/locale/index.d.ts +20 -2
- package/dist/locale/index.js +22 -0
- package/dist/locale/index.js.map +1 -1
- package/dist/locale/index.mjs +22 -0
- package/dist/locale/index.mjs.map +1 -1
- package/dist/provider/index.d.mts +2 -2
- package/dist/provider/index.d.ts +2 -2
- package/dist/provider/index.js +22 -0
- package/dist/provider/index.js.map +1 -1
- package/dist/provider/index.mjs +22 -0
- package/dist/provider/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/{types-b8d18b1454c2.d.mts → types-453d18eab188.d.mts} +10 -0
- package/dist/{types-b8d18b1454c2.d.ts → types-453d18eab188.d.ts} +10 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { forwardRef, useRef, useState, useEffect, createContext, useCallback, useId, useMemo, createElement, useContext, Children, isValidElement, useLayoutEffect } from 'react';
|
|
1
|
+
import { forwardRef, useRef, useState, useEffect, createContext, useCallback, useId, useMemo, createElement, useContext, Children, isValidElement, useLayoutEffect, Fragment as Fragment$1 } from 'react';
|
|
2
2
|
import { twMerge } from 'tailwind-merge';
|
|
3
3
|
import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
|
|
4
4
|
import * as ContextMenu from '@radix-ui/react-context-menu';
|
|
@@ -469,6 +469,15 @@ var enUS = {
|
|
|
469
469
|
}
|
|
470
470
|
},
|
|
471
471
|
workbench: {
|
|
472
|
+
collection: {
|
|
473
|
+
label: "Collection",
|
|
474
|
+
loading: "Loading items",
|
|
475
|
+
empty: "No items",
|
|
476
|
+
loadError: "Unable to load items",
|
|
477
|
+
refreshError: "Unable to refresh items",
|
|
478
|
+
retry: "Retry",
|
|
479
|
+
loadingMore: "Loading more items"
|
|
480
|
+
},
|
|
472
481
|
interactiveTable: {
|
|
473
482
|
columnActions: "Column actions",
|
|
474
483
|
freezeColumn: "Freeze to left",
|
|
@@ -2201,6 +2210,16 @@ function getBaseButtonToneClassName(theme, tone = "default", active = false) {
|
|
|
2201
2210
|
active && theme.slots.buttonActive
|
|
2202
2211
|
);
|
|
2203
2212
|
}
|
|
2213
|
+
function getBaseNoticeToneClassName(theme, tone = "default") {
|
|
2214
|
+
return cn(
|
|
2215
|
+
tone === "default" && theme.slots.noticeDefault,
|
|
2216
|
+
tone === "primary" && theme.slots.noticePrimary,
|
|
2217
|
+
tone === "success" && theme.slots.noticeSuccess,
|
|
2218
|
+
tone === "warning" && theme.slots.noticeWarning,
|
|
2219
|
+
tone === "danger" && theme.slots.noticeDanger,
|
|
2220
|
+
tone === "muted" && theme.slots.noticeMuted
|
|
2221
|
+
);
|
|
2222
|
+
}
|
|
2204
2223
|
function getBaseMenuItemToneClassName(theme, tone = "default") {
|
|
2205
2224
|
return cn(
|
|
2206
2225
|
tone === "default" && theme.slots.menuItemDefault,
|
|
@@ -3434,6 +3453,98 @@ function BaseDescriptionList({
|
|
|
3434
3453
|
}
|
|
3435
3454
|
);
|
|
3436
3455
|
}
|
|
3456
|
+
function DefaultEmptyIcon() {
|
|
3457
|
+
return /* @__PURE__ */ jsxs(
|
|
3458
|
+
"svg",
|
|
3459
|
+
{
|
|
3460
|
+
"aria-hidden": "true",
|
|
3461
|
+
viewBox: "0 0 24 24",
|
|
3462
|
+
className: "h-6 w-6",
|
|
3463
|
+
fill: "none",
|
|
3464
|
+
stroke: "currentColor",
|
|
3465
|
+
strokeLinecap: "round",
|
|
3466
|
+
strokeLinejoin: "round",
|
|
3467
|
+
strokeWidth: "1.8",
|
|
3468
|
+
children: [
|
|
3469
|
+
/* @__PURE__ */ jsx("rect", { width: "16", height: "12", x: "4", y: "6", rx: "2" }),
|
|
3470
|
+
/* @__PURE__ */ jsx("path", { d: "M8 10h8" }),
|
|
3471
|
+
/* @__PURE__ */ jsx("path", { d: "M8 14h5" })
|
|
3472
|
+
]
|
|
3473
|
+
}
|
|
3474
|
+
);
|
|
3475
|
+
}
|
|
3476
|
+
var BaseEmptyState = forwardRef(
|
|
3477
|
+
function BaseEmptyState2({
|
|
3478
|
+
icon = /* @__PURE__ */ jsx(DefaultEmptyIcon, {}),
|
|
3479
|
+
title,
|
|
3480
|
+
description,
|
|
3481
|
+
actions,
|
|
3482
|
+
appearance,
|
|
3483
|
+
className,
|
|
3484
|
+
classNames,
|
|
3485
|
+
style,
|
|
3486
|
+
...stateProps
|
|
3487
|
+
}, ref) {
|
|
3488
|
+
const resolvedAppearance = useMonkeysBaseAppearance(appearance);
|
|
3489
|
+
const componentAttributes = useMonkeysComponentAttributes();
|
|
3490
|
+
const theme = resolveBaseAppearance(resolvedAppearance);
|
|
3491
|
+
return /* @__PURE__ */ jsxs(
|
|
3492
|
+
"div",
|
|
3493
|
+
{
|
|
3494
|
+
...componentAttributes,
|
|
3495
|
+
...stateProps,
|
|
3496
|
+
ref,
|
|
3497
|
+
"data-monkeys-component": "empty-state",
|
|
3498
|
+
"data-slot": "root",
|
|
3499
|
+
"data-state": "empty",
|
|
3500
|
+
className: cn(theme.slots.stateRoot, classNames?.root, className),
|
|
3501
|
+
style: {
|
|
3502
|
+
...theme.styles.stateRoot,
|
|
3503
|
+
...style
|
|
3504
|
+
},
|
|
3505
|
+
children: [
|
|
3506
|
+
hasRenderableNode(icon) ? /* @__PURE__ */ jsx(
|
|
3507
|
+
"div",
|
|
3508
|
+
{
|
|
3509
|
+
"data-slot": "icon",
|
|
3510
|
+
"data-state": "empty",
|
|
3511
|
+
className: cn(theme.slots.stateIcon, classNames?.icon),
|
|
3512
|
+
style: theme.styles.stateIcon,
|
|
3513
|
+
children: icon
|
|
3514
|
+
}
|
|
3515
|
+
) : null,
|
|
3516
|
+
hasRenderableNode(title) ? /* @__PURE__ */ jsx(
|
|
3517
|
+
"div",
|
|
3518
|
+
{
|
|
3519
|
+
"data-slot": "title",
|
|
3520
|
+
"data-state": "empty",
|
|
3521
|
+
className: cn(theme.slots.stateTitle, classNames?.title),
|
|
3522
|
+
children: title
|
|
3523
|
+
}
|
|
3524
|
+
) : null,
|
|
3525
|
+
hasRenderableNode(description) ? /* @__PURE__ */ jsx(
|
|
3526
|
+
"div",
|
|
3527
|
+
{
|
|
3528
|
+
"data-slot": "description",
|
|
3529
|
+
"data-state": "empty",
|
|
3530
|
+
className: cn(theme.slots.stateDescription, classNames?.description),
|
|
3531
|
+
children: description
|
|
3532
|
+
}
|
|
3533
|
+
) : null,
|
|
3534
|
+
hasRenderableNode(actions) ? /* @__PURE__ */ jsx(
|
|
3535
|
+
"div",
|
|
3536
|
+
{
|
|
3537
|
+
"data-slot": "actions",
|
|
3538
|
+
"data-state": "empty",
|
|
3539
|
+
className: cn(theme.slots.stateActions, classNames?.actions),
|
|
3540
|
+
children: actions
|
|
3541
|
+
}
|
|
3542
|
+
) : null
|
|
3543
|
+
]
|
|
3544
|
+
}
|
|
3545
|
+
);
|
|
3546
|
+
}
|
|
3547
|
+
);
|
|
3437
3548
|
function mergeAriaIds(...values) {
|
|
3438
3549
|
const ids = values.flatMap(
|
|
3439
3550
|
(value) => value?.split(/\s+/).filter(Boolean) ?? []
|
|
@@ -3792,6 +3903,170 @@ var BaseInput = forwardRef(
|
|
|
3792
3903
|
);
|
|
3793
3904
|
}
|
|
3794
3905
|
);
|
|
3906
|
+
function DefaultLoadingIcon({ className }) {
|
|
3907
|
+
return /* @__PURE__ */ jsxs(
|
|
3908
|
+
"svg",
|
|
3909
|
+
{
|
|
3910
|
+
"aria-hidden": "true",
|
|
3911
|
+
viewBox: "0 0 24 24",
|
|
3912
|
+
className,
|
|
3913
|
+
fill: "none",
|
|
3914
|
+
children: [
|
|
3915
|
+
/* @__PURE__ */ jsx(
|
|
3916
|
+
"circle",
|
|
3917
|
+
{
|
|
3918
|
+
cx: "12",
|
|
3919
|
+
cy: "12",
|
|
3920
|
+
r: "9",
|
|
3921
|
+
className: "opacity-25",
|
|
3922
|
+
stroke: "currentColor",
|
|
3923
|
+
strokeWidth: "3"
|
|
3924
|
+
}
|
|
3925
|
+
),
|
|
3926
|
+
/* @__PURE__ */ jsx(
|
|
3927
|
+
"path",
|
|
3928
|
+
{
|
|
3929
|
+
className: "opacity-75",
|
|
3930
|
+
fill: "currentColor",
|
|
3931
|
+
d: "M12 3a9 9 0 0 1 9 9h-3a6 6 0 0 0-6-6V3Z"
|
|
3932
|
+
}
|
|
3933
|
+
)
|
|
3934
|
+
]
|
|
3935
|
+
}
|
|
3936
|
+
);
|
|
3937
|
+
}
|
|
3938
|
+
var BaseLoadingState = forwardRef(function BaseLoadingState2({
|
|
3939
|
+
icon,
|
|
3940
|
+
title,
|
|
3941
|
+
description,
|
|
3942
|
+
actions,
|
|
3943
|
+
appearance,
|
|
3944
|
+
className,
|
|
3945
|
+
classNames,
|
|
3946
|
+
style,
|
|
3947
|
+
role = "status",
|
|
3948
|
+
"aria-live": ariaLive = "polite",
|
|
3949
|
+
"aria-busy": ariaBusy = true,
|
|
3950
|
+
"aria-label": nativeAriaLabel,
|
|
3951
|
+
"aria-labelledby": nativeAriaLabelledBy,
|
|
3952
|
+
...stateProps
|
|
3953
|
+
}, ref) {
|
|
3954
|
+
const resolvedAppearance = useMonkeysBaseAppearance(appearance);
|
|
3955
|
+
const componentAttributes = useMonkeysComponentAttributes();
|
|
3956
|
+
const loadingMessages = useMonkeysLocaleMessages().loading;
|
|
3957
|
+
const theme = resolveBaseAppearance(resolvedAppearance);
|
|
3958
|
+
const resolvedIcon = icon === void 0 ? /* @__PURE__ */ jsx(DefaultLoadingIcon, { className: theme.slots.loadingSpinner }) : icon;
|
|
3959
|
+
const resolvedAriaLabel = nativeAriaLabel ?? (nativeAriaLabelledBy === void 0 ? loadingMessages.spinner : void 0);
|
|
3960
|
+
return /* @__PURE__ */ jsxs(
|
|
3961
|
+
"div",
|
|
3962
|
+
{
|
|
3963
|
+
...componentAttributes,
|
|
3964
|
+
...stateProps,
|
|
3965
|
+
ref,
|
|
3966
|
+
role,
|
|
3967
|
+
"aria-live": ariaLive,
|
|
3968
|
+
"aria-busy": ariaBusy,
|
|
3969
|
+
"aria-label": resolvedAriaLabel,
|
|
3970
|
+
"aria-labelledby": nativeAriaLabelledBy,
|
|
3971
|
+
"data-monkeys-component": "loading-state",
|
|
3972
|
+
"data-slot": "root",
|
|
3973
|
+
"data-state": "loading",
|
|
3974
|
+
className: cn(theme.slots.stateRoot, classNames?.root, className),
|
|
3975
|
+
style: {
|
|
3976
|
+
...theme.styles.stateRoot,
|
|
3977
|
+
...style
|
|
3978
|
+
},
|
|
3979
|
+
children: [
|
|
3980
|
+
hasRenderableNode(resolvedIcon) ? /* @__PURE__ */ jsx(
|
|
3981
|
+
"div",
|
|
3982
|
+
{
|
|
3983
|
+
"data-slot": "icon",
|
|
3984
|
+
"data-state": "loading",
|
|
3985
|
+
className: cn(theme.slots.stateIcon, classNames?.icon),
|
|
3986
|
+
style: theme.styles.stateIcon,
|
|
3987
|
+
children: resolvedIcon
|
|
3988
|
+
}
|
|
3989
|
+
) : null,
|
|
3990
|
+
hasRenderableNode(title) ? /* @__PURE__ */ jsx(
|
|
3991
|
+
"div",
|
|
3992
|
+
{
|
|
3993
|
+
"data-slot": "title",
|
|
3994
|
+
"data-state": "loading",
|
|
3995
|
+
className: cn(theme.slots.stateTitle, classNames?.title),
|
|
3996
|
+
children: title
|
|
3997
|
+
}
|
|
3998
|
+
) : null,
|
|
3999
|
+
hasRenderableNode(description) ? /* @__PURE__ */ jsx(
|
|
4000
|
+
"div",
|
|
4001
|
+
{
|
|
4002
|
+
"data-slot": "description",
|
|
4003
|
+
"data-state": "loading",
|
|
4004
|
+
className: cn(theme.slots.stateDescription, classNames?.description),
|
|
4005
|
+
children: description
|
|
4006
|
+
}
|
|
4007
|
+
) : null,
|
|
4008
|
+
hasRenderableNode(actions) ? /* @__PURE__ */ jsx(
|
|
4009
|
+
"div",
|
|
4010
|
+
{
|
|
4011
|
+
"data-slot": "actions",
|
|
4012
|
+
"data-state": "loading",
|
|
4013
|
+
className: cn(theme.slots.stateActions, classNames?.actions),
|
|
4014
|
+
children: actions
|
|
4015
|
+
}
|
|
4016
|
+
) : null
|
|
4017
|
+
]
|
|
4018
|
+
}
|
|
4019
|
+
);
|
|
4020
|
+
});
|
|
4021
|
+
function BaseNotice({
|
|
4022
|
+
tone,
|
|
4023
|
+
icon,
|
|
4024
|
+
title,
|
|
4025
|
+
description,
|
|
4026
|
+
actions,
|
|
4027
|
+
children,
|
|
4028
|
+
appearance,
|
|
4029
|
+
className,
|
|
4030
|
+
classNames,
|
|
4031
|
+
style,
|
|
4032
|
+
...noticeProps
|
|
4033
|
+
}) {
|
|
4034
|
+
const theme = resolveBaseAppearance(appearance);
|
|
4035
|
+
const resolvedDescription = children ?? description;
|
|
4036
|
+
return /* @__PURE__ */ jsxs(
|
|
4037
|
+
"div",
|
|
4038
|
+
{
|
|
4039
|
+
...noticeProps,
|
|
4040
|
+
className: cn(
|
|
4041
|
+
theme.slots.noticeBase,
|
|
4042
|
+
getBaseNoticeToneClassName(theme, tone),
|
|
4043
|
+
classNames?.root,
|
|
4044
|
+
className
|
|
4045
|
+
),
|
|
4046
|
+
style: {
|
|
4047
|
+
...theme.styles.notice,
|
|
4048
|
+
...style
|
|
4049
|
+
},
|
|
4050
|
+
children: [
|
|
4051
|
+
hasRenderableNode(icon) ? /* @__PURE__ */ jsx("div", { className: cn(theme.slots.noticeIcon, classNames?.icon), children: icon }) : null,
|
|
4052
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
4053
|
+
hasRenderableNode(title) ? /* @__PURE__ */ jsx("div", { className: cn(theme.slots.noticeTitle, classNames?.title), children: title }) : null,
|
|
4054
|
+
hasRenderableNode(resolvedDescription) ? /* @__PURE__ */ jsx(
|
|
4055
|
+
"div",
|
|
4056
|
+
{
|
|
4057
|
+
className: cn(
|
|
4058
|
+
theme.slots.noticeDescription,
|
|
4059
|
+
classNames?.description
|
|
4060
|
+
),
|
|
4061
|
+
children: resolvedDescription
|
|
4062
|
+
}
|
|
4063
|
+
) : null,
|
|
4064
|
+
hasRenderableNode(actions) ? /* @__PURE__ */ jsx("div", { className: cn(theme.slots.noticeActions, classNames?.actions), children: actions }) : null
|
|
4065
|
+
] })
|
|
4066
|
+
]
|
|
4067
|
+
}
|
|
4068
|
+
);
|
|
4069
|
+
}
|
|
3795
4070
|
var typeaheadResetDelay = 500;
|
|
3796
4071
|
function validateSelectProps({
|
|
3797
4072
|
options,
|
|
@@ -7945,6 +8220,7 @@ var DEFAULT_MASONRY_GAP_PX = 12;
|
|
|
7945
8220
|
var DEFAULT_MASONRY_ROW_HEIGHT_PX = 8;
|
|
7946
8221
|
var DEFAULT_MASONRY_COLUMN_WIDTH_PX = 280;
|
|
7947
8222
|
var DEFAULT_MASONRY_ITEM_HEIGHT_PX = 240;
|
|
8223
|
+
var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
|
|
7948
8224
|
function clamp(value, min, max) {
|
|
7949
8225
|
return Math.min(Math.max(value, min), max);
|
|
7950
8226
|
}
|
|
@@ -8049,9 +8325,12 @@ function WorkbenchMasonryLayout({
|
|
|
8049
8325
|
getItemKey = (item, index) => item?.id ?? item?.key ?? index,
|
|
8050
8326
|
getItemSize,
|
|
8051
8327
|
columnWidth = DEFAULT_MASONRY_COLUMN_WIDTH_PX,
|
|
8328
|
+
columnCount: requestedColumnCount,
|
|
8052
8329
|
gap = DEFAULT_MASONRY_GAP_PX,
|
|
8053
8330
|
rowHeight = DEFAULT_MASONRY_ROW_HEIGHT_PX,
|
|
8054
8331
|
placementStrategy = "shelf",
|
|
8332
|
+
containerProps,
|
|
8333
|
+
getItemProps,
|
|
8055
8334
|
className
|
|
8056
8335
|
}) {
|
|
8057
8336
|
const containerRef = useRef(null);
|
|
@@ -8082,8 +8361,9 @@ function WorkbenchMasonryLayout({
|
|
|
8082
8361
|
}, []);
|
|
8083
8362
|
useEffect(() => {
|
|
8084
8363
|
setMeasuredHeights((prev) => {
|
|
8364
|
+
const currentItemKeys = new Set(itemKeys);
|
|
8085
8365
|
const next = Object.fromEntries(
|
|
8086
|
-
Object.entries(prev).filter(([key]) =>
|
|
8366
|
+
Object.entries(prev).filter(([key]) => currentItemKeys.has(key))
|
|
8087
8367
|
);
|
|
8088
8368
|
return areMeasurementMapsEqual(prev, next) ? prev : next;
|
|
8089
8369
|
});
|
|
@@ -8094,7 +8374,8 @@ function WorkbenchMasonryLayout({
|
|
|
8094
8374
|
containerRef.current
|
|
8095
8375
|
);
|
|
8096
8376
|
const isDensePlacement = placementStrategy === "dense";
|
|
8097
|
-
const
|
|
8377
|
+
const normalizedRequestedColumnCount = Number.isFinite(requestedColumnCount) && Number(requestedColumnCount) > 0 ? clamp(Math.round(Number(requestedColumnCount)), 1, 24) : void 0;
|
|
8378
|
+
const columnCount = normalizedRequestedColumnCount || getMasonryColumnCount({
|
|
8098
8379
|
containerWidth,
|
|
8099
8380
|
itemCount: items.length,
|
|
8100
8381
|
targetColumnWidth: resolvedTargetColumnWidth,
|
|
@@ -8140,7 +8421,7 @@ function WorkbenchMasonryLayout({
|
|
|
8140
8421
|
resolvedColumnWidth,
|
|
8141
8422
|
rowHeight
|
|
8142
8423
|
]);
|
|
8143
|
-
|
|
8424
|
+
useIsomorphicLayoutEffect(() => {
|
|
8144
8425
|
const nextMeasurements = {};
|
|
8145
8426
|
itemNodesRef.current.forEach((node, key) => {
|
|
8146
8427
|
const nextHeight = Math.ceil(node.getBoundingClientRect().height);
|
|
@@ -8202,10 +8483,21 @@ function WorkbenchMasonryLayout({
|
|
|
8202
8483
|
const positionedItems = layoutItems.map(({ key, item, columnSpan, rowSpan, size }) => {
|
|
8203
8484
|
const resolvedSpan = clamp(columnSpan, 1, columnCount);
|
|
8204
8485
|
let startColumn = nextColumnIndex;
|
|
8205
|
-
if (
|
|
8206
|
-
|
|
8486
|
+
if (placementStrategy === "shortest") {
|
|
8487
|
+
let shortestBottom = Number.POSITIVE_INFINITY;
|
|
8488
|
+
for (let candidate = 0; candidate <= columnCount - resolvedSpan; candidate += 1) {
|
|
8489
|
+
const candidateBottom = Math.max(...columnBottoms.slice(candidate, candidate + resolvedSpan));
|
|
8490
|
+
if (candidateBottom < shortestBottom) {
|
|
8491
|
+
shortestBottom = candidateBottom;
|
|
8492
|
+
startColumn = candidate;
|
|
8493
|
+
}
|
|
8494
|
+
}
|
|
8495
|
+
} else {
|
|
8496
|
+
if (startColumn + resolvedSpan > columnCount) {
|
|
8497
|
+
startColumn = 0;
|
|
8498
|
+
}
|
|
8499
|
+
startColumn = Math.min(startColumn, columnCount - resolvedSpan);
|
|
8207
8500
|
}
|
|
8208
|
-
startColumn = Math.min(startColumn, columnCount - resolvedSpan);
|
|
8209
8501
|
const itemWidth = resolvedColumnWidth * resolvedSpan + gap * Math.max(resolvedSpan - 1, 0);
|
|
8210
8502
|
const itemHeight = getResolvedItemHeight({
|
|
8211
8503
|
size,
|
|
@@ -8218,9 +8510,11 @@ function WorkbenchMasonryLayout({
|
|
|
8218
8510
|
columnBottoms[columnIndex] = bottom + gap;
|
|
8219
8511
|
}
|
|
8220
8512
|
maxBottom = Math.max(maxBottom, bottom);
|
|
8221
|
-
|
|
8222
|
-
|
|
8223
|
-
nextColumnIndex
|
|
8513
|
+
if (placementStrategy !== "shortest") {
|
|
8514
|
+
nextColumnIndex = startColumn + resolvedSpan;
|
|
8515
|
+
if (nextColumnIndex >= columnCount) {
|
|
8516
|
+
nextColumnIndex = 0;
|
|
8517
|
+
}
|
|
8224
8518
|
}
|
|
8225
8519
|
return {
|
|
8226
8520
|
key,
|
|
@@ -8243,33 +8537,38 @@ function WorkbenchMasonryLayout({
|
|
|
8243
8537
|
"div",
|
|
8244
8538
|
{
|
|
8245
8539
|
ref: containerRef,
|
|
8246
|
-
|
|
8247
|
-
|
|
8540
|
+
...containerProps,
|
|
8541
|
+
className: cn("relative w-full", className, containerProps?.className),
|
|
8542
|
+
style: { ...containerProps?.style, height: `${orderedLayout.containerHeight}px` },
|
|
8248
8543
|
children: orderedLayout.positionedItems.map(({ key, item, columnSpan, rowSpan, size, itemWidth, left, top }) => {
|
|
8249
8544
|
const unresolvedSingleColumnWidth = containerWidth <= 0 && columnCount === 1;
|
|
8250
8545
|
const itemWidthValue = unresolvedSingleColumnWidth ? "100%" : `${itemWidth}px`;
|
|
8546
|
+
const layoutContext = {
|
|
8547
|
+
columnCount,
|
|
8548
|
+
columnSpan,
|
|
8549
|
+
columnWidth: resolvedColumnWidth,
|
|
8550
|
+
containerWidth,
|
|
8551
|
+
gap,
|
|
8552
|
+
itemWidth,
|
|
8553
|
+
placementStrategy,
|
|
8554
|
+
rowSpan,
|
|
8555
|
+
rowHeight,
|
|
8556
|
+
size
|
|
8557
|
+
};
|
|
8558
|
+
const itemProps = getItemProps?.(item, layoutContext);
|
|
8251
8559
|
return /* @__PURE__ */ jsx(
|
|
8252
8560
|
"div",
|
|
8253
8561
|
{
|
|
8254
|
-
|
|
8562
|
+
...itemProps,
|
|
8563
|
+
className: cn("absolute min-w-0", itemProps?.className),
|
|
8255
8564
|
style: {
|
|
8565
|
+
...itemProps?.style,
|
|
8256
8566
|
left: unresolvedSingleColumnWidth ? 0 : `${left}px`,
|
|
8257
8567
|
top: `${top}px`,
|
|
8258
8568
|
width: itemWidthValue,
|
|
8259
8569
|
maxWidth: itemWidthValue
|
|
8260
8570
|
},
|
|
8261
|
-
children: /* @__PURE__ */ jsx("div", { ref: (node) => registerItemNode(key, node), className: "min-w-0", children: renderItem(item,
|
|
8262
|
-
columnCount,
|
|
8263
|
-
columnSpan,
|
|
8264
|
-
columnWidth: resolvedColumnWidth,
|
|
8265
|
-
containerWidth,
|
|
8266
|
-
gap,
|
|
8267
|
-
itemWidth,
|
|
8268
|
-
placementStrategy,
|
|
8269
|
-
rowSpan,
|
|
8270
|
-
rowHeight,
|
|
8271
|
-
size
|
|
8272
|
-
}) })
|
|
8571
|
+
children: /* @__PURE__ */ jsx("div", { ref: (node) => registerItemNode(key, node), role: "presentation", className: "min-w-0", children: renderItem(item, layoutContext) })
|
|
8273
8572
|
},
|
|
8274
8573
|
key
|
|
8275
8574
|
);
|
|
@@ -8281,35 +8580,717 @@ function WorkbenchMasonryLayout({
|
|
|
8281
8580
|
"div",
|
|
8282
8581
|
{
|
|
8283
8582
|
ref: containerRef,
|
|
8284
|
-
|
|
8583
|
+
...containerProps,
|
|
8584
|
+
className: cn("grid w-full items-start", className, containerProps?.className),
|
|
8285
8585
|
style: {
|
|
8586
|
+
...containerProps?.style,
|
|
8286
8587
|
gap: `${gap}px`,
|
|
8287
8588
|
gridAutoFlow: "row dense",
|
|
8288
8589
|
gridAutoRows: `${rowHeight}px`,
|
|
8289
8590
|
gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`
|
|
8290
8591
|
},
|
|
8291
|
-
children: layoutItems.map(({ key, item, columnSpan, rowSpan, size }) =>
|
|
8292
|
-
|
|
8592
|
+
children: layoutItems.map(({ key, item, columnSpan, rowSpan, size }) => {
|
|
8593
|
+
const layoutContext = {
|
|
8594
|
+
columnCount,
|
|
8595
|
+
columnSpan,
|
|
8596
|
+
columnWidth: resolvedColumnWidth,
|
|
8597
|
+
containerWidth,
|
|
8598
|
+
gap,
|
|
8599
|
+
placementStrategy,
|
|
8600
|
+
rowSpan,
|
|
8601
|
+
rowHeight,
|
|
8602
|
+
size
|
|
8603
|
+
};
|
|
8604
|
+
const itemProps = getItemProps?.(item, layoutContext);
|
|
8605
|
+
return /* @__PURE__ */ jsx(
|
|
8606
|
+
"div",
|
|
8607
|
+
{
|
|
8608
|
+
...itemProps,
|
|
8609
|
+
className: cn("min-w-0", itemProps?.className),
|
|
8610
|
+
style: {
|
|
8611
|
+
...itemProps?.style,
|
|
8612
|
+
gridColumn: `span ${columnSpan}`,
|
|
8613
|
+
gridRow: `span ${rowSpan}`
|
|
8614
|
+
},
|
|
8615
|
+
children: /* @__PURE__ */ jsx("div", { ref: (node) => registerItemNode(key, node), role: "presentation", className: "min-w-0", children: renderItem(item, layoutContext) })
|
|
8616
|
+
},
|
|
8617
|
+
key
|
|
8618
|
+
);
|
|
8619
|
+
})
|
|
8620
|
+
}
|
|
8621
|
+
);
|
|
8622
|
+
}
|
|
8623
|
+
var DEFAULT_GAP_PX = 12;
|
|
8624
|
+
var DEFAULT_ROW_HEIGHT_PX = 8;
|
|
8625
|
+
var DEFAULT_CARD_WIDTH_PX = 280;
|
|
8626
|
+
var BREAKPOINT_TABLET_PX = 640;
|
|
8627
|
+
var BREAKPOINT_DESKTOP_PX = 1024;
|
|
8628
|
+
var MAX_COLUMN_COUNT = 24;
|
|
8629
|
+
function clamp2(value, min, max) {
|
|
8630
|
+
return Math.min(Math.max(value, min), max);
|
|
8631
|
+
}
|
|
8632
|
+
function resolveRenderableSlot(slot, context) {
|
|
8633
|
+
return typeof slot === "function" ? slot(context) : slot;
|
|
8634
|
+
}
|
|
8635
|
+
function resolveLengthToPixels2(value, fallback, node) {
|
|
8636
|
+
if (typeof value === "number" && Number.isFinite(value) && value > 0) return value;
|
|
8637
|
+
if (typeof value !== "string") return fallback;
|
|
8638
|
+
const normalized = value.trim().toLowerCase();
|
|
8639
|
+
if (!normalized) return fallback;
|
|
8640
|
+
if (/^\d+(\.\d+)?(px)?$/.test(normalized)) {
|
|
8641
|
+
const parsed = Number.parseFloat(normalized);
|
|
8642
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
8643
|
+
}
|
|
8644
|
+
if (normalized.endsWith("rem")) {
|
|
8645
|
+
const parsed = Number.parseFloat(normalized);
|
|
8646
|
+
const rootFontSize = typeof window === "undefined" ? 16 : Number.parseFloat(window.getComputedStyle(node || document.documentElement).fontSize) || 16;
|
|
8647
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed * rootFontSize : fallback;
|
|
8648
|
+
}
|
|
8649
|
+
return fallback;
|
|
8650
|
+
}
|
|
8651
|
+
function normalizeColumns(value) {
|
|
8652
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
|
|
8653
|
+
return clamp2(Math.round(value), 1, MAX_COLUMN_COUNT);
|
|
8654
|
+
}
|
|
8655
|
+
function resolveResponsiveColumns(columns, containerWidth) {
|
|
8656
|
+
if (columns === "auto" || columns === void 0) return void 0;
|
|
8657
|
+
if (typeof columns === "number") return normalizeColumns(columns);
|
|
8658
|
+
const mobile = normalizeColumns(columns.mobile);
|
|
8659
|
+
const tablet = normalizeColumns(columns.tablet);
|
|
8660
|
+
const desktop = normalizeColumns(columns.desktop);
|
|
8661
|
+
if (containerWidth >= BREAKPOINT_DESKTOP_PX) return desktop ?? tablet ?? mobile;
|
|
8662
|
+
if (containerWidth >= BREAKPOINT_TABLET_PX) return tablet ?? mobile ?? desktop;
|
|
8663
|
+
return mobile ?? tablet ?? desktop;
|
|
8664
|
+
}
|
|
8665
|
+
function resolveColumnCount({
|
|
8666
|
+
containerWidth,
|
|
8667
|
+
itemCount,
|
|
8668
|
+
gap,
|
|
8669
|
+
columns,
|
|
8670
|
+
minCardWidth,
|
|
8671
|
+
idealCardWidth,
|
|
8672
|
+
maxCardWidth,
|
|
8673
|
+
node
|
|
8674
|
+
}) {
|
|
8675
|
+
const fixedColumns = resolveResponsiveColumns(columns, containerWidth);
|
|
8676
|
+
if (fixedColumns) return fixedColumns;
|
|
8677
|
+
if (!containerWidth) return 1;
|
|
8678
|
+
const idealWidth = resolveLengthToPixels2(idealCardWidth, DEFAULT_CARD_WIDTH_PX, node);
|
|
8679
|
+
const minWidth = resolveLengthToPixels2(minCardWidth, idealWidth * 0.78, node);
|
|
8680
|
+
const maxWidth = Math.max(
|
|
8681
|
+
minWidth,
|
|
8682
|
+
resolveLengthToPixels2(maxCardWidth, idealWidth * 1.35, node)
|
|
8683
|
+
);
|
|
8684
|
+
const safeItemCount = Math.max(itemCount, 1);
|
|
8685
|
+
const maxCandidate = Math.max(
|
|
8686
|
+
1,
|
|
8687
|
+
Math.min(
|
|
8688
|
+
safeItemCount,
|
|
8689
|
+
Math.ceil((containerWidth + gap) / (Math.max(minWidth * 0.75, 1) + gap))
|
|
8690
|
+
)
|
|
8691
|
+
);
|
|
8692
|
+
let bestCount = 1;
|
|
8693
|
+
let bestScore = Number.POSITIVE_INFINITY;
|
|
8694
|
+
for (let candidate = 1; candidate <= maxCandidate; candidate += 1) {
|
|
8695
|
+
const width = (containerWidth - gap * Math.max(candidate - 1, 0)) / candidate;
|
|
8696
|
+
if (!Number.isFinite(width) || width <= 0) continue;
|
|
8697
|
+
const score = Math.abs(width - idealWidth) + Math.max(0, minWidth - width) * 3 + Math.max(0, width - maxWidth) * 2;
|
|
8698
|
+
if (score < bestScore) {
|
|
8699
|
+
bestScore = score;
|
|
8700
|
+
bestCount = candidate;
|
|
8701
|
+
}
|
|
8702
|
+
}
|
|
8703
|
+
return bestCount;
|
|
8704
|
+
}
|
|
8705
|
+
function normalizeGap(value) {
|
|
8706
|
+
return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : DEFAULT_GAP_PX;
|
|
8707
|
+
}
|
|
8708
|
+
function normalizeRowHeight(value) {
|
|
8709
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : DEFAULT_ROW_HEIGHT_PX;
|
|
8710
|
+
}
|
|
8711
|
+
function normalizeThreshold(value) {
|
|
8712
|
+
return typeof value === "number" && Number.isFinite(value) ? clamp2(value, 0, 1) : 0;
|
|
8713
|
+
}
|
|
8714
|
+
function normalizeItemSize(size, aspectRatio, columnWidth) {
|
|
8715
|
+
const normalizedAspectRatio = Number.isFinite(aspectRatio) && Number(aspectRatio) > 0 ? Number(aspectRatio) : void 0;
|
|
8716
|
+
const normalizedHeight = size?.height ?? (normalizedAspectRatio ? Math.max(1, columnWidth / normalizedAspectRatio) : void 0);
|
|
8717
|
+
return {
|
|
8718
|
+
...size,
|
|
8719
|
+
height: normalizedHeight
|
|
8720
|
+
};
|
|
8721
|
+
}
|
|
8722
|
+
function getDefaultItemKey(item, index) {
|
|
8723
|
+
if (item && typeof item === "object") {
|
|
8724
|
+
const candidate = item;
|
|
8725
|
+
if (typeof candidate.id === "string" || typeof candidate.id === "number") return candidate.id;
|
|
8726
|
+
if (typeof candidate.key === "string" || typeof candidate.key === "number") return candidate.key;
|
|
8727
|
+
}
|
|
8728
|
+
return index;
|
|
8729
|
+
}
|
|
8730
|
+
function getScrollStorageKey(key) {
|
|
8731
|
+
return `@inf-monkeys-tech/monkeys-design:workbench-collection:${key}`;
|
|
8732
|
+
}
|
|
8733
|
+
function getParentScrollOwner(node) {
|
|
8734
|
+
let current = node?.parentElement ?? null;
|
|
8735
|
+
while (current) {
|
|
8736
|
+
if (typeof window === "undefined") return current;
|
|
8737
|
+
const overflowY = window.getComputedStyle(current).overflowY;
|
|
8738
|
+
if (overflowY === "auto" || overflowY === "scroll") return current;
|
|
8739
|
+
current = current.parentElement;
|
|
8740
|
+
}
|
|
8741
|
+
return null;
|
|
8742
|
+
}
|
|
8743
|
+
function setsEqual(left, right) {
|
|
8744
|
+
if (left.size !== right.size) return false;
|
|
8745
|
+
for (const value of left) {
|
|
8746
|
+
if (!right.has(value)) return false;
|
|
8747
|
+
}
|
|
8748
|
+
return true;
|
|
8749
|
+
}
|
|
8750
|
+
function isInteractiveEventTarget(target, currentTarget) {
|
|
8751
|
+
if (typeof Element === "undefined" || !(target instanceof Element) || target === currentTarget) return false;
|
|
8752
|
+
const control = target.closest(
|
|
8753
|
+
'a, button, input, select, textarea, summary, [contenteditable="true"], [data-collection-action]'
|
|
8754
|
+
);
|
|
8755
|
+
return Boolean(control && currentTarget.contains(control));
|
|
8756
|
+
}
|
|
8757
|
+
function warnOnDuplicateKeys(keys) {
|
|
8758
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production") return;
|
|
8759
|
+
const seen = /* @__PURE__ */ new Set();
|
|
8760
|
+
const duplicates = /* @__PURE__ */ new Set();
|
|
8761
|
+
keys.forEach((key) => {
|
|
8762
|
+
const stringKey = String(key);
|
|
8763
|
+
if (seen.has(stringKey)) duplicates.add(stringKey);
|
|
8764
|
+
seen.add(stringKey);
|
|
8765
|
+
});
|
|
8766
|
+
if (duplicates.size) {
|
|
8767
|
+
console.warn(`WorkbenchCollection received duplicate item keys: ${Array.from(duplicates).join(", ")}`);
|
|
8768
|
+
}
|
|
8769
|
+
}
|
|
8770
|
+
function WorkbenchCollection({
|
|
8771
|
+
items,
|
|
8772
|
+
config,
|
|
8773
|
+
renderItem,
|
|
8774
|
+
slots,
|
|
8775
|
+
callbacks,
|
|
8776
|
+
className,
|
|
8777
|
+
classNames,
|
|
8778
|
+
style,
|
|
8779
|
+
ariaLabel
|
|
8780
|
+
}) {
|
|
8781
|
+
const componentAttributes = useMonkeysComponentAttributes();
|
|
8782
|
+
const localeMessages = useMonkeysLocaleMessages().workbench.collection;
|
|
8783
|
+
const componentId = useId().replace(/:/g, "");
|
|
8784
|
+
const rootRef = useRef(null);
|
|
8785
|
+
const itemsRef = useRef(null);
|
|
8786
|
+
const loadMoreRef = useRef(null);
|
|
8787
|
+
const lastSelectedIndexRef = useRef(null);
|
|
8788
|
+
const loadMoreLockedRef = useRef(false);
|
|
8789
|
+
const layoutReadyRef = useRef(false);
|
|
8790
|
+
const [containerWidth, setContainerWidth] = useState(0);
|
|
8791
|
+
const [itemsNode, setItemsNode] = useState(null);
|
|
8792
|
+
const [internalSelectedKeys, setInternalSelectedKeys] = useState(
|
|
8793
|
+
() => new Set(config.selection?.defaultSelectedKeys ?? [])
|
|
8794
|
+
);
|
|
8795
|
+
const callbacksRef = useRef(callbacks);
|
|
8796
|
+
callbacksRef.current = callbacks;
|
|
8797
|
+
const registerItemsNode = useCallback((node) => {
|
|
8798
|
+
itemsRef.current = node;
|
|
8799
|
+
setItemsNode(node);
|
|
8800
|
+
}, []);
|
|
8801
|
+
const mode = config.layout.mode;
|
|
8802
|
+
if (mode !== "grid" && mode !== "masonry" && mode !== "dense" && mode !== "rail") {
|
|
8803
|
+
throw new TypeError(`WorkbenchCollection layout.mode "${String(mode)}" is not supported.`);
|
|
8804
|
+
}
|
|
8805
|
+
const gap = normalizeGap(config.layout.gap);
|
|
8806
|
+
const rowHeight = normalizeRowHeight(config.layout.rowHeight);
|
|
8807
|
+
const getItemKey = config.getItemKey ?? getDefaultItemKey;
|
|
8808
|
+
const normalizedItems = useMemo(() => items.map((item, index) => {
|
|
8809
|
+
const key = getItemKey(item, index);
|
|
8810
|
+
return { item, index, key, stringKey: String(key) };
|
|
8811
|
+
}), [getItemKey, items]);
|
|
8812
|
+
const keys = useMemo(
|
|
8813
|
+
() => normalizedItems.map(({ key }) => key),
|
|
8814
|
+
[normalizedItems]
|
|
8815
|
+
);
|
|
8816
|
+
const keysSignature = normalizedItems.map(({ stringKey }) => stringKey).join("");
|
|
8817
|
+
useEffect(() => warnOnDuplicateKeys(keys), [keys, keysSignature]);
|
|
8818
|
+
const selectionMode = config.selection?.mode ?? "none";
|
|
8819
|
+
const controlledSelection = config.selection?.selectedKeys !== void 0;
|
|
8820
|
+
const selectedKeys = useMemo(
|
|
8821
|
+
() => selectionMode === "none" ? /* @__PURE__ */ new Set() : controlledSelection ? new Set(config.selection?.selectedKeys ?? []) : internalSelectedKeys,
|
|
8822
|
+
[config.selection?.selectedKeys, controlledSelection, internalSelectedKeys, selectionMode]
|
|
8823
|
+
);
|
|
8824
|
+
useEffect(() => {
|
|
8825
|
+
if (controlledSelection) return;
|
|
8826
|
+
const availableKeys = new Set(keys);
|
|
8827
|
+
setInternalSelectedKeys((previous) => {
|
|
8828
|
+
const next = new Set(Array.from(previous).filter((key) => availableKeys.has(key)));
|
|
8829
|
+
return setsEqual(previous, next) ? previous : next;
|
|
8830
|
+
});
|
|
8831
|
+
}, [controlledSelection, keys, keysSignature]);
|
|
8832
|
+
useEffect(() => {
|
|
8833
|
+
const node = itemsNode;
|
|
8834
|
+
if (!node) return void 0;
|
|
8835
|
+
const updateWidth = () => {
|
|
8836
|
+
const nextWidth = Math.round(node.getBoundingClientRect().width);
|
|
8837
|
+
setContainerWidth((previous) => previous === nextWidth ? previous : nextWidth);
|
|
8838
|
+
};
|
|
8839
|
+
updateWidth();
|
|
8840
|
+
if (typeof ResizeObserver === "function") {
|
|
8841
|
+
const observer = new ResizeObserver(updateWidth);
|
|
8842
|
+
observer.observe(node);
|
|
8843
|
+
return () => observer.disconnect();
|
|
8844
|
+
}
|
|
8845
|
+
if (typeof window === "undefined") return void 0;
|
|
8846
|
+
window.addEventListener("resize", updateWidth);
|
|
8847
|
+
return () => window.removeEventListener("resize", updateWidth);
|
|
8848
|
+
}, [itemsNode]);
|
|
8849
|
+
const columnCount = resolveColumnCount({
|
|
8850
|
+
containerWidth,
|
|
8851
|
+
itemCount: normalizedItems.length,
|
|
8852
|
+
gap,
|
|
8853
|
+
columns: config.layout.columns,
|
|
8854
|
+
minCardWidth: config.layout.minCardWidth,
|
|
8855
|
+
idealCardWidth: config.layout.idealCardWidth ?? config.layout.columnWidth,
|
|
8856
|
+
maxCardWidth: config.layout.maxCardWidth,
|
|
8857
|
+
node: itemsRef.current
|
|
8858
|
+
});
|
|
8859
|
+
const columnWidth = containerWidth > 0 ? Math.max(0, (containerWidth - gap * Math.max(columnCount - 1, 0)) / columnCount) : resolveLengthToPixels2(
|
|
8860
|
+
config.layout.cardWidth ?? config.layout.columnWidth ?? config.layout.idealCardWidth,
|
|
8861
|
+
DEFAULT_CARD_WIDTH_PX,
|
|
8862
|
+
itemsRef.current
|
|
8863
|
+
);
|
|
8864
|
+
const placementStrategy = config.layout.placementStrategy ?? (mode === "dense" ? "dense" : mode === "masonry" ? "shortest" : "shelf");
|
|
8865
|
+
const labels = useMemo(() => ({
|
|
8866
|
+
collection: config.labels?.collection ?? localeMessages.label,
|
|
8867
|
+
loading: config.labels?.loading ?? localeMessages.loading,
|
|
8868
|
+
empty: config.labels?.empty ?? localeMessages.empty,
|
|
8869
|
+
loadError: config.labels?.loadError ?? localeMessages.loadError,
|
|
8870
|
+
refreshError: config.labels?.refreshError ?? localeMessages.refreshError,
|
|
8871
|
+
retry: config.labels?.retry ?? localeMessages.retry,
|
|
8872
|
+
loadingMore: config.labels?.loadingMore ?? localeMessages.loadingMore
|
|
8873
|
+
}), [config.labels, localeMessages]);
|
|
8874
|
+
const virtualizationError = useMemo(() => {
|
|
8875
|
+
const virtualization = config.virtualization;
|
|
8876
|
+
if (virtualization?.enabled !== true || virtualization.fallback !== "error") return null;
|
|
8877
|
+
if (!virtualization.adapter) {
|
|
8878
|
+
return new Error("WorkbenchCollection virtualization requires an adapter.");
|
|
8879
|
+
}
|
|
8880
|
+
if (virtualization.adapter.supports?.(mode) === false) {
|
|
8881
|
+
return new Error(`WorkbenchCollection virtualization adapter does not support mode "${mode}".`);
|
|
8882
|
+
}
|
|
8883
|
+
return null;
|
|
8884
|
+
}, [config.virtualization, mode]);
|
|
8885
|
+
const layoutSnapshot = useMemo(() => ({
|
|
8886
|
+
mode,
|
|
8887
|
+
columnCount,
|
|
8888
|
+
columnWidth,
|
|
8889
|
+
containerWidth,
|
|
8890
|
+
gap,
|
|
8891
|
+
itemCount: normalizedItems.length
|
|
8892
|
+
}), [columnCount, columnWidth, containerWidth, gap, mode, normalizedItems.length]);
|
|
8893
|
+
useEffect(() => {
|
|
8894
|
+
callbacksRef.current?.onLayoutChange?.(layoutSnapshot);
|
|
8895
|
+
if (containerWidth > 0 && !layoutReadyRef.current) {
|
|
8896
|
+
layoutReadyRef.current = true;
|
|
8897
|
+
callbacksRef.current?.onLayoutReady?.(layoutSnapshot);
|
|
8898
|
+
}
|
|
8899
|
+
}, [layoutSnapshot, containerWidth]);
|
|
8900
|
+
useEffect(() => {
|
|
8901
|
+
layoutReadyRef.current = false;
|
|
8902
|
+
}, [mode]);
|
|
8903
|
+
const resolveScrollOwner = useCallback(() => {
|
|
8904
|
+
const requestedOwner = config.layout.scrollOwner;
|
|
8905
|
+
if (requestedOwner && requestedOwner !== "self" && requestedOwner !== "parent") return requestedOwner;
|
|
8906
|
+
if (requestedOwner === "parent") return getParentScrollOwner(rootRef.current);
|
|
8907
|
+
return rootRef.current;
|
|
8908
|
+
}, [config.layout.scrollOwner]);
|
|
8909
|
+
useEffect(() => {
|
|
8910
|
+
const restorationKey = config.scrollRestorationKey?.trim();
|
|
8911
|
+
if (!restorationKey || typeof window === "undefined") return void 0;
|
|
8912
|
+
const owner = resolveScrollOwner();
|
|
8913
|
+
if (!owner) return void 0;
|
|
8914
|
+
const storageKey = getScrollStorageKey(restorationKey);
|
|
8915
|
+
try {
|
|
8916
|
+
const stored = Number.parseFloat(window.sessionStorage.getItem(storageKey) ?? "");
|
|
8917
|
+
if (Number.isFinite(stored) && stored >= 0) owner.scrollTop = stored;
|
|
8918
|
+
} catch {
|
|
8919
|
+
}
|
|
8920
|
+
const saveScrollPosition = () => {
|
|
8921
|
+
try {
|
|
8922
|
+
window.sessionStorage.setItem(storageKey, String(owner.scrollTop));
|
|
8923
|
+
} catch {
|
|
8924
|
+
}
|
|
8925
|
+
};
|
|
8926
|
+
owner.addEventListener("scroll", saveScrollPosition, { passive: true });
|
|
8927
|
+
return () => {
|
|
8928
|
+
saveScrollPosition();
|
|
8929
|
+
owner.removeEventListener("scroll", saveScrollPosition);
|
|
8930
|
+
};
|
|
8931
|
+
}, [config.scrollRestorationKey, resolveScrollOwner]);
|
|
8932
|
+
const state = config.state;
|
|
8933
|
+
const loading = state?.loading === true;
|
|
8934
|
+
const loadingMore = state?.loadingMore === true;
|
|
8935
|
+
const hasMore = state?.hasMore === true;
|
|
8936
|
+
const canLoadMore = typeof callbacks?.onLoadMore === "function";
|
|
8937
|
+
const effectiveError = state?.error ?? virtualizationError;
|
|
8938
|
+
useEffect(() => {
|
|
8939
|
+
if (!loadingMore || !hasMore) loadMoreLockedRef.current = false;
|
|
8940
|
+
}, [hasMore, loadingMore, normalizedItems.length, keysSignature]);
|
|
8941
|
+
useEffect(() => {
|
|
8942
|
+
const sentinel = loadMoreRef.current;
|
|
8943
|
+
if (!sentinel || !canLoadMore || !hasMore || loadingMore) return void 0;
|
|
8944
|
+
if (typeof IntersectionObserver !== "function") return void 0;
|
|
8945
|
+
const owner = resolveScrollOwner();
|
|
8946
|
+
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
|
+
}
|
|
8960
|
+
}, {
|
|
8961
|
+
root: owner === rootRef.current ? owner : owner || null,
|
|
8962
|
+
rootMargin: config.loading?.rootMargin ?? "240px",
|
|
8963
|
+
threshold: normalizeThreshold(config.loading?.threshold)
|
|
8964
|
+
});
|
|
8965
|
+
observer.observe(sentinel);
|
|
8966
|
+
return () => observer.disconnect();
|
|
8967
|
+
}, [canLoadMore, config.loading?.rootMargin, config.loading?.threshold, hasMore, keysSignature, loadingMore, normalizedItems.length, resolveScrollOwner]);
|
|
8968
|
+
const groups = useMemo(() => {
|
|
8969
|
+
if (!config.grouping) {
|
|
8970
|
+
return [{ key: "__all__", stringKey: "__all__", items: normalizedItems }];
|
|
8971
|
+
}
|
|
8972
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
8973
|
+
normalizedItems.forEach((entry) => {
|
|
8974
|
+
const groupKey = config.grouping?.getGroupKey(entry.item, entry.index) ?? "__all__";
|
|
8975
|
+
const stringKey = String(groupKey);
|
|
8976
|
+
const existing = grouped.get(stringKey);
|
|
8977
|
+
if (existing) {
|
|
8978
|
+
existing.items.push(entry);
|
|
8979
|
+
return;
|
|
8980
|
+
}
|
|
8981
|
+
grouped.set(stringKey, {
|
|
8982
|
+
key: groupKey,
|
|
8983
|
+
stringKey,
|
|
8984
|
+
label: config.grouping?.getGroupLabel?.(groupKey, entry.item),
|
|
8985
|
+
items: [entry]
|
|
8986
|
+
});
|
|
8987
|
+
});
|
|
8988
|
+
return Array.from(grouped.values());
|
|
8989
|
+
}, [config.grouping, normalizedItems]);
|
|
8990
|
+
const setSelection = useCallback((entry, behavior = config.selection?.behavior ?? (selectionMode === "multiple" ? "toggle" : "replace")) => {
|
|
8991
|
+
if (selectionMode === "none" || config.selection?.isItemDisabled?.(entry.item, entry.index)) return;
|
|
8992
|
+
const current = new Set(selectedKeys);
|
|
8993
|
+
const next = /* @__PURE__ */ new Set();
|
|
8994
|
+
if (selectionMode === "single") {
|
|
8995
|
+
if (!(behavior === "toggle" && current.has(entry.key))) next.add(entry.key);
|
|
8996
|
+
} else if (behavior === "range" && lastSelectedIndexRef.current !== null) {
|
|
8997
|
+
current.forEach((key) => next.add(key));
|
|
8998
|
+
const start = Math.min(lastSelectedIndexRef.current, entry.index);
|
|
8999
|
+
const end = Math.max(lastSelectedIndexRef.current, entry.index);
|
|
9000
|
+
normalizedItems.slice(start, end + 1).forEach((candidate) => {
|
|
9001
|
+
if (!config.selection?.isItemDisabled?.(candidate.item, candidate.index)) next.add(candidate.key);
|
|
9002
|
+
});
|
|
9003
|
+
} else if (behavior === "replace") {
|
|
9004
|
+
next.add(entry.key);
|
|
9005
|
+
} else {
|
|
9006
|
+
current.forEach((key) => next.add(key));
|
|
9007
|
+
if (next.has(entry.key)) next.delete(entry.key);
|
|
9008
|
+
else next.add(entry.key);
|
|
9009
|
+
}
|
|
9010
|
+
lastSelectedIndexRef.current = entry.index;
|
|
9011
|
+
if (!controlledSelection) setInternalSelectedKeys(next);
|
|
9012
|
+
callbacks?.onSelectionChange?.(next, { item: entry.item, key: entry.key, behavior });
|
|
9013
|
+
}, [callbacks, config.selection, controlledSelection, normalizedItems, selectedKeys, selectionMode]);
|
|
9014
|
+
const createItemContext = useCallback((entry, layout) => {
|
|
9015
|
+
const disabled = config.selection?.isItemDisabled?.(entry.item, entry.index) ?? false;
|
|
9016
|
+
const context = {
|
|
9017
|
+
item: entry.item,
|
|
9018
|
+
index: entry.index,
|
|
9019
|
+
key: entry.key,
|
|
9020
|
+
status: config.getItemStatus?.(entry.item, entry.index) ?? "idle",
|
|
9021
|
+
disabled,
|
|
9022
|
+
selected: selectedKeys.has(entry.key),
|
|
9023
|
+
selectionMode,
|
|
9024
|
+
layout,
|
|
9025
|
+
select: (behavior) => setSelection(entry, behavior),
|
|
9026
|
+
preview: () => callbacks?.onItemPreview?.(entry.item, context),
|
|
9027
|
+
detail: () => callbacks?.onItemDetail?.(entry.item, context),
|
|
9028
|
+
renderSlot: (name) => {
|
|
9029
|
+
return slots?.item?.[name]?.(entry.item, context);
|
|
9030
|
+
},
|
|
9031
|
+
notifyMediaLoad: () => callbacks?.onMediaLoad?.(entry.item, context),
|
|
9032
|
+
notifyMediaError: (error) => callbacks?.onMediaError?.(entry.item, context, error)
|
|
9033
|
+
};
|
|
9034
|
+
return context;
|
|
9035
|
+
}, [callbacks, config.getItemStatus, config.selection, selectedKeys, selectionMode, setSelection, slots?.item]);
|
|
9036
|
+
const getItemInteractionProps = useCallback((entry, context) => {
|
|
9037
|
+
const handleKeyboard = (event) => {
|
|
9038
|
+
if (event.target !== event.currentTarget || event.key !== "Enter" && event.key !== " ") return;
|
|
9039
|
+
event.preventDefault();
|
|
9040
|
+
if (selectionMode !== "none") context.select(event.shiftKey ? "range" : void 0);
|
|
9041
|
+
else callbacks?.onItemClick?.(entry.item, context, event);
|
|
9042
|
+
};
|
|
9043
|
+
return {
|
|
9044
|
+
id: `${componentId}-item-${entry.index}`,
|
|
9045
|
+
"data-monkeys-collection-item": "",
|
|
9046
|
+
"data-item-key": entry.stringKey,
|
|
9047
|
+
"data-selected": context.selected || void 0,
|
|
9048
|
+
"data-disabled": context.disabled || void 0,
|
|
9049
|
+
"data-status": context.status,
|
|
9050
|
+
role: selectionMode === "none" ? "listitem" : "option",
|
|
9051
|
+
"aria-selected": selectionMode === "none" ? void 0 : context.selected,
|
|
9052
|
+
"aria-disabled": context.disabled || void 0,
|
|
9053
|
+
tabIndex: callbacks?.onItemClick || selectionMode !== "none" ? 0 : void 0,
|
|
9054
|
+
draggable: callbacks?.onItemDragStart ? true : void 0,
|
|
9055
|
+
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",
|
|
9058
|
+
config.appearance?.selection === "ring" && context.selected && "ring-2 ring-primary",
|
|
9059
|
+
config.appearance?.selection === "outline" && context.selected && "outline outline-2 outline-primary",
|
|
9060
|
+
classNames?.item
|
|
9061
|
+
),
|
|
9062
|
+
onClick: (event) => {
|
|
9063
|
+
if (isInteractiveEventTarget(event.target, event.currentTarget)) return;
|
|
9064
|
+
if (selectionMode !== "none") context.select(event.shiftKey ? "range" : void 0);
|
|
9065
|
+
callbacks?.onItemClick?.(entry.item, context, event);
|
|
9066
|
+
},
|
|
9067
|
+
onDoubleClick: (event) => {
|
|
9068
|
+
if (isInteractiveEventTarget(event.target, event.currentTarget)) return;
|
|
9069
|
+
callbacks?.onItemDoubleClick?.(entry.item, context, event);
|
|
9070
|
+
},
|
|
9071
|
+
onKeyDown: handleKeyboard,
|
|
9072
|
+
onDragStart: (event) => callbacks?.onItemDragStart?.(entry.item, context, event),
|
|
9073
|
+
onDragOver: callbacks?.onItemDrop ? (event) => event.preventDefault() : void 0,
|
|
9074
|
+
onDrop: (event) => callbacks?.onItemDrop?.(entry.item, context, event)
|
|
9075
|
+
};
|
|
9076
|
+
}, [callbacks, classNames?.item, componentId, config.appearance, selectionMode]);
|
|
9077
|
+
const renderEntry = useCallback((entry, layout, includeShell = true) => {
|
|
9078
|
+
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]);
|
|
9082
|
+
const baseLayoutContext = useMemo(() => ({
|
|
9083
|
+
mode,
|
|
9084
|
+
columnCount,
|
|
9085
|
+
columnWidth,
|
|
9086
|
+
containerWidth,
|
|
9087
|
+
gap,
|
|
9088
|
+
placementStrategy,
|
|
9089
|
+
rowHeight
|
|
9090
|
+
}), [columnCount, columnWidth, containerWidth, gap, mode, placementStrategy, rowHeight]);
|
|
9091
|
+
const renderGroupItems = (group) => {
|
|
9092
|
+
const virtualization = config.virtualization;
|
|
9093
|
+
const adapter = virtualization?.adapter;
|
|
9094
|
+
const virtualizationRequested = virtualization?.enabled === true;
|
|
9095
|
+
if (virtualizationRequested && (!adapter || adapter.supports?.(mode) === false)) {
|
|
9096
|
+
if (virtualization?.fallback === "error") {
|
|
9097
|
+
return null;
|
|
9098
|
+
}
|
|
9099
|
+
}
|
|
9100
|
+
if (virtualizationRequested && adapter && adapter.supports?.(mode) !== false) {
|
|
9101
|
+
return adapter.render({
|
|
9102
|
+
items: group.items.map(({ item }) => item),
|
|
9103
|
+
keys: group.items.map(({ key }) => key),
|
|
9104
|
+
layout: config.layout,
|
|
9105
|
+
scrollOwner: resolveScrollOwner(),
|
|
9106
|
+
renderItem: (item, localIndex, layout) => {
|
|
9107
|
+
const entry = group.items[localIndex];
|
|
9108
|
+
return entry ? renderEntry(entry, layout) : null;
|
|
9109
|
+
}
|
|
9110
|
+
});
|
|
9111
|
+
}
|
|
9112
|
+
if (mode === "masonry" || mode === "dense") {
|
|
9113
|
+
return /* @__PURE__ */ jsx(
|
|
9114
|
+
WorkbenchMasonryLayout,
|
|
8293
9115
|
{
|
|
8294
|
-
|
|
8295
|
-
|
|
8296
|
-
|
|
8297
|
-
|
|
9116
|
+
items: group.items,
|
|
9117
|
+
columnCount,
|
|
9118
|
+
columnWidth: config.layout.cardWidth ?? config.layout.columnWidth ?? config.layout.idealCardWidth,
|
|
9119
|
+
gap,
|
|
9120
|
+
rowHeight,
|
|
9121
|
+
placementStrategy: mode === "dense" ? "dense" : placementStrategy,
|
|
9122
|
+
className: classNames?.layout,
|
|
9123
|
+
containerProps: {
|
|
9124
|
+
role: selectionMode === "none" ? "list" : "listbox",
|
|
9125
|
+
"aria-label": ariaLabel ?? labels.collection,
|
|
9126
|
+
"aria-multiselectable": selectionMode === "multiple" || void 0
|
|
8298
9127
|
},
|
|
8299
|
-
|
|
8300
|
-
|
|
8301
|
-
|
|
8302
|
-
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
|
|
8308
|
-
|
|
8309
|
-
|
|
9128
|
+
getItemProps: (entry, masonryLayout) => {
|
|
9129
|
+
const context = createItemContext(entry, { ...masonryLayout, mode });
|
|
9130
|
+
return getItemInteractionProps(entry, context);
|
|
9131
|
+
},
|
|
9132
|
+
getItemKey: (entry) => entry.key,
|
|
9133
|
+
getItemSize: (entry, masonryLayout) => {
|
|
9134
|
+
const layout = {
|
|
9135
|
+
...masonryLayout,
|
|
9136
|
+
mode
|
|
9137
|
+
};
|
|
9138
|
+
const customSize = config.layout.getItemSize?.(entry.item, layout);
|
|
9139
|
+
const aspectRatio = config.layout.getItemAspectRatio?.(entry.item, entry.index);
|
|
9140
|
+
return normalizeItemSize(customSize, aspectRatio, masonryLayout.columnWidth);
|
|
9141
|
+
},
|
|
9142
|
+
renderItem: (entry, masonryLayout) => renderEntry(entry, {
|
|
9143
|
+
...masonryLayout,
|
|
9144
|
+
mode
|
|
9145
|
+
}, false)
|
|
9146
|
+
}
|
|
9147
|
+
);
|
|
9148
|
+
}
|
|
9149
|
+
if (mode === "rail") {
|
|
9150
|
+
const cardWidth = config.layout.cardWidth ?? config.layout.idealCardWidth ?? DEFAULT_CARD_WIDTH_PX;
|
|
9151
|
+
return /* @__PURE__ */ jsx(
|
|
9152
|
+
"div",
|
|
9153
|
+
{
|
|
9154
|
+
role: selectionMode === "none" ? "list" : "listbox",
|
|
9155
|
+
"aria-label": ariaLabel ?? labels.collection,
|
|
9156
|
+
"aria-multiselectable": selectionMode === "multiple" || void 0,
|
|
9157
|
+
className: cn("grid min-w-0 grid-flow-col items-start overflow-x-auto", classNames?.layout),
|
|
9158
|
+
style: { gap, gridAutoColumns: typeof cardWidth === "number" ? `${cardWidth}px` : cardWidth },
|
|
9159
|
+
children: group.items.map((entry) => /* @__PURE__ */ jsx(Fragment$1, { children: renderEntry(entry, baseLayoutContext) }, entry.stringKey))
|
|
9160
|
+
}
|
|
9161
|
+
);
|
|
9162
|
+
}
|
|
9163
|
+
return /* @__PURE__ */ jsx(
|
|
9164
|
+
"div",
|
|
9165
|
+
{
|
|
9166
|
+
role: selectionMode === "none" ? "list" : "listbox",
|
|
9167
|
+
"aria-label": ariaLabel ?? labels.collection,
|
|
9168
|
+
"aria-multiselectable": selectionMode === "multiple" || void 0,
|
|
9169
|
+
className: cn("grid min-w-0 items-start", classNames?.layout),
|
|
9170
|
+
style: {
|
|
9171
|
+
gap,
|
|
9172
|
+
gridTemplateColumns: `repeat(${columnCount}, minmax(0, 1fr))`
|
|
8310
9173
|
},
|
|
8311
|
-
|
|
8312
|
-
|
|
9174
|
+
children: group.items.map((entry) => {
|
|
9175
|
+
const customSize = config.layout.getItemSize?.(entry.item, baseLayoutContext);
|
|
9176
|
+
const span = clamp2(Math.round(Number(customSize?.columnSpan) || 1), 1, columnCount);
|
|
9177
|
+
const aspectRatio = config.layout.getItemAspectRatio?.(entry.item, entry.index);
|
|
9178
|
+
return /* @__PURE__ */ jsx(
|
|
9179
|
+
"div",
|
|
9180
|
+
{
|
|
9181
|
+
...getItemInteractionProps(
|
|
9182
|
+
entry,
|
|
9183
|
+
createItemContext(entry, { ...baseLayoutContext, columnSpan: span, size: customSize })
|
|
9184
|
+
),
|
|
9185
|
+
style: {
|
|
9186
|
+
gridColumn: span > 1 ? `span ${span}` : void 0,
|
|
9187
|
+
aspectRatio: Number.isFinite(aspectRatio) && Number(aspectRatio) > 0 ? String(aspectRatio) : void 0
|
|
9188
|
+
},
|
|
9189
|
+
children: renderEntry(entry, { ...baseLayoutContext, columnSpan: span, size: customSize }, false)
|
|
9190
|
+
},
|
|
9191
|
+
entry.stringKey
|
|
9192
|
+
);
|
|
9193
|
+
})
|
|
9194
|
+
}
|
|
9195
|
+
);
|
|
9196
|
+
};
|
|
9197
|
+
const slotContext = {
|
|
9198
|
+
items,
|
|
9199
|
+
error: effectiveError,
|
|
9200
|
+
loading,
|
|
9201
|
+
loadingMore,
|
|
9202
|
+
selectedKeys,
|
|
9203
|
+
retry: () => callbacks?.onRetry?.()
|
|
9204
|
+
};
|
|
9205
|
+
const header = resolveRenderableSlot(slots?.header, slotContext);
|
|
9206
|
+
const toolbar = resolveRenderableSlot(slots?.toolbar, slotContext);
|
|
9207
|
+
const selectionToolbar = selectedKeys.size > 0 ? resolveRenderableSlot(slots?.selectionToolbar, slotContext) : null;
|
|
9208
|
+
const beforeItems = resolveRenderableSlot(slots?.beforeItems, slotContext);
|
|
9209
|
+
const footer = resolveRenderableSlot(slots?.footer, slotContext);
|
|
9210
|
+
const showInitialLoading = loading && items.length === 0;
|
|
9211
|
+
const showInitialError = Boolean(effectiveError) && items.length === 0 && !showInitialLoading;
|
|
9212
|
+
const showEmpty = !showInitialLoading && !showInitialError && (state?.empty === true || items.length === 0);
|
|
9213
|
+
const loadingSlot = resolveRenderableSlot(slots?.loading, slotContext);
|
|
9214
|
+
const errorSlot = resolveRenderableSlot(slots?.error, slotContext);
|
|
9215
|
+
const emptySlot = resolveRenderableSlot(slots?.empty, slotContext);
|
|
9216
|
+
const loadMoreSlot = resolveRenderableSlot(slots?.loadMore, slotContext);
|
|
9217
|
+
const selfScrollable = config.layout.scrollOwner === "self" || config.layout.scrollOwner === void 0 && (config.layout.fillHeight || config.layout.maxHeight);
|
|
9218
|
+
const rootStyle = {
|
|
9219
|
+
...style,
|
|
9220
|
+
padding: config.layout.padding ?? style?.padding,
|
|
9221
|
+
height: config.layout.fillHeight ? "100%" : style?.height,
|
|
9222
|
+
maxHeight: config.layout.maxHeight ?? style?.maxHeight,
|
|
9223
|
+
overflow: selfScrollable ? "auto" : style?.overflow
|
|
9224
|
+
};
|
|
9225
|
+
return /* @__PURE__ */ jsxs(
|
|
9226
|
+
"section",
|
|
9227
|
+
{
|
|
9228
|
+
ref: rootRef,
|
|
9229
|
+
...componentAttributes,
|
|
9230
|
+
"data-monkeys-component": "workbench-collection",
|
|
9231
|
+
"data-layout-mode": mode,
|
|
9232
|
+
"data-density": config.appearance?.density,
|
|
9233
|
+
"data-radius": config.appearance?.radius,
|
|
9234
|
+
"data-media-fit": config.appearance?.mediaFit,
|
|
9235
|
+
"aria-label": ariaLabel ?? labels.collection,
|
|
9236
|
+
"aria-busy": loading || loadingMore || void 0,
|
|
9237
|
+
className: cn("min-h-0 min-w-0", config.layout.fillHeight && "h-full", classNames?.root, className),
|
|
9238
|
+
style: rootStyle,
|
|
9239
|
+
children: [
|
|
9240
|
+
hasRenderableNode(header) ? /* @__PURE__ */ jsx("div", { className: classNames?.header, children: header }) : null,
|
|
9241
|
+
hasRenderableNode(toolbar) ? /* @__PURE__ */ jsx("div", { className: classNames?.toolbar, children: toolbar }) : null,
|
|
9242
|
+
hasRenderableNode(selectionToolbar) ? /* @__PURE__ */ jsx("div", { className: classNames?.selectionToolbar, children: selectionToolbar }) : null,
|
|
9243
|
+
hasRenderableNode(beforeItems) ? /* @__PURE__ */ jsx("div", { className: classNames?.beforeItems, children: beforeItems }) : null,
|
|
9244
|
+
showInitialLoading ? hasRenderableNode(loadingSlot) ? loadingSlot : /* @__PURE__ */ jsx(BaseLoadingState, { title: labels.loading }) : showInitialError ? hasRenderableNode(errorSlot) ? errorSlot : /* @__PURE__ */ jsx(
|
|
9245
|
+
BaseNotice,
|
|
9246
|
+
{
|
|
9247
|
+
tone: "danger",
|
|
9248
|
+
role: "alert",
|
|
9249
|
+
"aria-live": "assertive",
|
|
9250
|
+
title: labels.loadError,
|
|
9251
|
+
actions: callbacks?.onRetry ? /* @__PURE__ */ jsx(BaseButton, { size: "sm", label: labels.retry, onClick: callbacks.onRetry }) : void 0
|
|
9252
|
+
}
|
|
9253
|
+
) : showEmpty ? hasRenderableNode(emptySlot) ? emptySlot : /* @__PURE__ */ jsx(BaseEmptyState, { title: labels.empty }) : /* @__PURE__ */ jsx(
|
|
9254
|
+
"div",
|
|
9255
|
+
{
|
|
9256
|
+
ref: registerItemsNode,
|
|
9257
|
+
className: cn("min-w-0", classNames?.items),
|
|
9258
|
+
children: groups.map((group, groupIndex) => {
|
|
9259
|
+
const groupContext = {
|
|
9260
|
+
key: group.key,
|
|
9261
|
+
label: group.label,
|
|
9262
|
+
items: group.items.map(({ item }) => item),
|
|
9263
|
+
groupIndex
|
|
9264
|
+
};
|
|
9265
|
+
const heading = config.grouping ? slots?.groupHeading?.(groupContext, slotContext) ?? group.label : null;
|
|
9266
|
+
const headingId = `${componentId}-group-${groupIndex}`;
|
|
9267
|
+
return /* @__PURE__ */ jsxs(
|
|
9268
|
+
"div",
|
|
9269
|
+
{
|
|
9270
|
+
"data-collection-group": group.stringKey,
|
|
9271
|
+
className: classNames?.group,
|
|
9272
|
+
children: [
|
|
9273
|
+
hasRenderableNode(heading) ? /* @__PURE__ */ jsx("div", { id: headingId, role: "heading", "aria-level": 2, className: classNames?.groupHeading, children: heading }) : null,
|
|
9274
|
+
renderGroupItems(group)
|
|
9275
|
+
]
|
|
9276
|
+
},
|
|
9277
|
+
group.stringKey
|
|
9278
|
+
);
|
|
9279
|
+
})
|
|
9280
|
+
}
|
|
9281
|
+
),
|
|
9282
|
+
items.length > 0 && effectiveError ? /* @__PURE__ */ jsx("div", { className: classNames?.status, children: hasRenderableNode(errorSlot) ? errorSlot : /* @__PURE__ */ jsx(
|
|
9283
|
+
BaseNotice,
|
|
9284
|
+
{
|
|
9285
|
+
tone: "danger",
|
|
9286
|
+
role: "alert",
|
|
9287
|
+
title: labels.refreshError,
|
|
9288
|
+
actions: callbacks?.onRetry ? /* @__PURE__ */ jsx(BaseButton, { size: "sm", label: labels.retry, onClick: callbacks.onRetry }) : void 0
|
|
9289
|
+
}
|
|
9290
|
+
) }) : null,
|
|
9291
|
+
items.length > 0 && (hasMore || loadingMore) ? /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: classNames?.loadMore, "data-collection-load-more": "", children: hasRenderableNode(loadMoreSlot) ? loadMoreSlot : loadingMore ? /* @__PURE__ */ jsx(BaseLoadingState, { title: labels.loadingMore }) : null }) : null,
|
|
9292
|
+
hasRenderableNode(footer) ? /* @__PURE__ */ jsx("div", { className: classNames?.footer, children: footer }) : null
|
|
9293
|
+
]
|
|
8313
9294
|
}
|
|
8314
9295
|
);
|
|
8315
9296
|
}
|
|
@@ -8750,45 +9731,54 @@ function WorkbenchGalleryView({
|
|
|
8750
9731
|
);
|
|
8751
9732
|
if (isMasonry) {
|
|
8752
9733
|
return /* @__PURE__ */ jsx(
|
|
8753
|
-
|
|
9734
|
+
WorkbenchCollection,
|
|
8754
9735
|
{
|
|
8755
9736
|
items: rows,
|
|
8756
|
-
className,
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
|
|
8762
|
-
|
|
8763
|
-
|
|
8764
|
-
|
|
8765
|
-
|
|
8766
|
-
|
|
8767
|
-
|
|
8768
|
-
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
|
|
8777
|
-
|
|
8778
|
-
|
|
8779
|
-
|
|
8780
|
-
|
|
8781
|
-
|
|
8782
|
-
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
|
|
8788
|
-
|
|
8789
|
-
|
|
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
|
+
}
|
|
8790
9780
|
},
|
|
8791
|
-
renderItem: (row) => renderGalleryCard(row,
|
|
9781
|
+
renderItem: (row, context) => renderGalleryCard(row, context.index)
|
|
8792
9782
|
}
|
|
8793
9783
|
);
|
|
8794
9784
|
}
|
|
@@ -9306,7 +10296,7 @@ var getDomain = (values, min, max) => {
|
|
|
9306
10296
|
return lower < upper ? [lower, upper] : [upper, lower];
|
|
9307
10297
|
};
|
|
9308
10298
|
var scale = (value, domain, start, end) => start + (value - domain[0]) / (domain[1] - domain[0]) * (end - start);
|
|
9309
|
-
var
|
|
10299
|
+
var clamp3 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
9310
10300
|
var activatePoint = (event, point, onPointSelect) => {
|
|
9311
10301
|
if (!onPointSelect || event.key !== "Enter" && event.key !== " ") return;
|
|
9312
10302
|
event.preventDefault();
|
|
@@ -9388,9 +10378,9 @@ function WorkbenchScatterPlot({
|
|
|
9388
10378
|
xThreshold === void 0 ? null : /* @__PURE__ */ jsx(
|
|
9389
10379
|
"line",
|
|
9390
10380
|
{
|
|
9391
|
-
x1:
|
|
10381
|
+
x1: clamp3(xThreshold, plotLeft, plotRight),
|
|
9392
10382
|
y1: plotTop,
|
|
9393
|
-
x2:
|
|
10383
|
+
x2: clamp3(xThreshold, plotLeft, plotRight),
|
|
9394
10384
|
y2: plotBottom,
|
|
9395
10385
|
className: "stroke-muted-foreground/50",
|
|
9396
10386
|
strokeDasharray: "5 5"
|
|
@@ -9400,9 +10390,9 @@ function WorkbenchScatterPlot({
|
|
|
9400
10390
|
"line",
|
|
9401
10391
|
{
|
|
9402
10392
|
x1: plotLeft,
|
|
9403
|
-
y1:
|
|
10393
|
+
y1: clamp3(yThreshold, plotTop, plotBottom),
|
|
9404
10394
|
x2: plotRight,
|
|
9405
|
-
y2:
|
|
10395
|
+
y2: clamp3(yThreshold, plotTop, plotBottom),
|
|
9406
10396
|
className: "stroke-muted-foreground/50",
|
|
9407
10397
|
strokeDasharray: "5 5"
|
|
9408
10398
|
}
|
|
@@ -9429,17 +10419,17 @@ function WorkbenchScatterPlot({
|
|
|
9429
10419
|
}
|
|
9430
10420
|
),
|
|
9431
10421
|
validPoints.map((point) => {
|
|
9432
|
-
const x =
|
|
10422
|
+
const x = clamp3(
|
|
9433
10423
|
scale(point.x, xDomain, plotLeft, plotRight),
|
|
9434
10424
|
plotLeft,
|
|
9435
10425
|
plotRight
|
|
9436
10426
|
);
|
|
9437
|
-
const y =
|
|
10427
|
+
const y = clamp3(
|
|
9438
10428
|
scale(point.y, yDomain, plotBottom, plotTop),
|
|
9439
10429
|
plotTop,
|
|
9440
10430
|
plotBottom
|
|
9441
10431
|
);
|
|
9442
|
-
const radius = point.size === void 0 ? 9 :
|
|
10432
|
+
const radius = point.size === void 0 ? 9 : clamp3(scale(point.size, sizeDomain, 7, 18), 7, 18);
|
|
9443
10433
|
const selected = selectedPointId === point.id;
|
|
9444
10434
|
return /* @__PURE__ */ jsxs(
|
|
9445
10435
|
"g",
|
|
@@ -9971,7 +10961,7 @@ var getDomain2 = (values, min, max) => {
|
|
|
9971
10961
|
return lower < upper ? [lower, upper] : [upper, lower];
|
|
9972
10962
|
};
|
|
9973
10963
|
var scale2 = (value, domain, start, end) => start + (value - domain[0]) / (domain[1] - domain[0]) * (end - start);
|
|
9974
|
-
var
|
|
10964
|
+
var clamp4 = (value, min, max) => Math.min(max, Math.max(min, value));
|
|
9975
10965
|
var toneVariable = {
|
|
9976
10966
|
primary: "--radar-series-one",
|
|
9977
10967
|
secondary: "--radar-series-two",
|
|
@@ -10034,7 +11024,7 @@ function WorkbenchRadarMatrix({
|
|
|
10034
11024
|
const plotRight = width;
|
|
10035
11025
|
const plotTop = 0;
|
|
10036
11026
|
const plotBottom = height;
|
|
10037
|
-
const xThreshold =
|
|
11027
|
+
const xThreshold = clamp4(
|
|
10038
11028
|
scale2(
|
|
10039
11029
|
Number.isFinite(thresholds?.x) ? Number(thresholds?.x) : (xDomain[0] + xDomain[1]) / 2,
|
|
10040
11030
|
xDomain,
|
|
@@ -10044,7 +11034,7 @@ function WorkbenchRadarMatrix({
|
|
|
10044
11034
|
plotLeft,
|
|
10045
11035
|
plotRight
|
|
10046
11036
|
);
|
|
10047
|
-
const yThreshold =
|
|
11037
|
+
const yThreshold = clamp4(
|
|
10048
11038
|
scale2(
|
|
10049
11039
|
Number.isFinite(thresholds?.y) ? Number(thresholds?.y) : (yDomain[0] + yDomain[1]) / 2,
|
|
10050
11040
|
yDomain,
|
|
@@ -10152,13 +11142,13 @@ function WorkbenchRadarMatrix({
|
|
|
10152
11142
|
] }, quadrant.id);
|
|
10153
11143
|
}),
|
|
10154
11144
|
validPoints.map((point, index) => {
|
|
10155
|
-
const x =
|
|
10156
|
-
const y =
|
|
11145
|
+
const x = clamp4(scale2(point.x, xDomain, 40, width - 40), 40, width - 40);
|
|
11146
|
+
const y = clamp4(scale2(point.y, yDomain, height - 48, 54), 54, height - 48);
|
|
10157
11147
|
const tone = point.tone || (index % 2 === 0 ? "primary" : "accent");
|
|
10158
11148
|
const selected = selectedPointId === point.id;
|
|
10159
11149
|
const labelled = labelledPointIds.has(point.id);
|
|
10160
|
-
const radius = labelled ?
|
|
10161
|
-
const fontSize = labelled ?
|
|
11150
|
+
const radius = labelled ? clamp4(scale2(point.size ?? 1, sizeDomain, 5, 9), 5, 9) : 3.5;
|
|
11151
|
+
const fontSize = labelled ? clamp4(scale2(point.size ?? 1, sizeDomain, 14, 31), 14, 31) : 0;
|
|
10162
11152
|
const pointStyle = {
|
|
10163
11153
|
fill: toneColor(tone),
|
|
10164
11154
|
stroke: "hsl(var(--foreground) / 0.74)"
|
|
@@ -10260,8 +11250,8 @@ function WorkbenchRadarMatrix({
|
|
|
10260
11250
|
validPoints.map((point, index) => /* @__PURE__ */ jsx(
|
|
10261
11251
|
"circle",
|
|
10262
11252
|
{
|
|
10263
|
-
cx:
|
|
10264
|
-
cy:
|
|
11253
|
+
cx: clamp4(scale2(point.x, xDomain, 40, width - 40), 40, width - 40),
|
|
11254
|
+
cy: clamp4(scale2(point.y, yDomain, height - 48, 54), 54, height - 48),
|
|
10265
11255
|
r: "8",
|
|
10266
11256
|
style: { fill: toneColor(point.tone || (index % 2 === 0 ? "primary" : "accent")) }
|
|
10267
11257
|
},
|
|
@@ -10295,6 +11285,6 @@ function WorkbenchRadarMatrix({
|
|
|
10295
11285
|
);
|
|
10296
11286
|
}
|
|
10297
11287
|
|
|
10298
|
-
export { InteractiveTable, InteractiveTableEditableTextCell, InteractiveTableReadonlyCell, InteractiveTableSelectCell, WorkbenchAssetGallery, WorkbenchContentPane, WorkbenchContentToolbar, WorkbenchDetailSidebar, WorkbenchEvidenceList, WorkbenchGalleryCard, WorkbenchGallerySettingsButton, WorkbenchGallerySettingsPanel, WorkbenchGalleryView, WorkbenchJourneyNavigation, WorkbenchLaneView, WorkbenchMasonryLayout, WorkbenchMetricGrid, WorkbenchRadarFilterChip, WorkbenchRadarInspectorSection, WorkbenchRadarMatrix, WorkbenchRadarNavigation, WorkbenchRadarWorkspace, WorkbenchRankedList, WorkbenchRelationshipGraph, WorkbenchResizableSidebar, WorkbenchScatterPlot, WorkbenchSelectionTray, WorkbenchTableView };
|
|
11288
|
+
export { InteractiveTable, InteractiveTableEditableTextCell, InteractiveTableReadonlyCell, InteractiveTableSelectCell, WorkbenchAssetGallery, WorkbenchCollection, WorkbenchContentPane, WorkbenchContentToolbar, WorkbenchDetailSidebar, WorkbenchEvidenceList, WorkbenchGalleryCard, WorkbenchGallerySettingsButton, WorkbenchGallerySettingsPanel, WorkbenchGalleryView, WorkbenchJourneyNavigation, WorkbenchLaneView, WorkbenchMasonryLayout, WorkbenchMetricGrid, WorkbenchRadarFilterChip, WorkbenchRadarInspectorSection, WorkbenchRadarMatrix, WorkbenchRadarNavigation, WorkbenchRadarWorkspace, WorkbenchRankedList, WorkbenchRelationshipGraph, WorkbenchResizableSidebar, WorkbenchScatterPlot, WorkbenchSelectionTray, WorkbenchTableView };
|
|
10299
11289
|
//# sourceMappingURL=index.mjs.map
|
|
10300
11290
|
//# sourceMappingURL=index.mjs.map
|