@inf-monkeys-tech/monkeys-design 1.0.99 → 1.0.100

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.
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
3
  var DropdownMenu4 = require('@radix-ui/react-dropdown-menu');
4
- var react = require('react');
4
+ var React = require('react');
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var tailwindMerge = require('tailwind-merge');
7
7
  var core = require('@dnd-kit/core');
8
8
  var sortable = require('@dnd-kit/sortable');
9
9
  var utilities = require('@dnd-kit/utilities');
10
10
  var reactDom = require('react-dom');
11
- var Popover = require('@radix-ui/react-popover');
12
11
  var lucideReact = require('lucide-react');
12
+ var Popover = require('@radix-ui/react-popover');
13
13
 
14
14
  function _interopNamespace(e) {
15
15
  if (e && e.__esModule) return e;
@@ -30,6 +30,7 @@ function _interopNamespace(e) {
30
30
  }
31
31
 
32
32
  var DropdownMenu4__namespace = /*#__PURE__*/_interopNamespace(DropdownMenu4);
33
+ var React__namespace = /*#__PURE__*/_interopNamespace(React);
33
34
  var Popover__namespace = /*#__PURE__*/_interopNamespace(Popover);
34
35
 
35
36
  // src/components/data-explorer/DataExplorerToolbarActions.tsx
@@ -589,7 +590,7 @@ function LoadingIcon() {
589
590
  }
590
591
  );
591
592
  }
592
- var DataExplorerButton = react.forwardRef(function DataExplorerButton2({
593
+ var DataExplorerButton = React.forwardRef(function DataExplorerButton2({
593
594
  children,
594
595
  label,
595
596
  icon,
@@ -1445,17 +1446,17 @@ var MONKEYS_PROVIDER_CONTEXTS_KEY = /* @__PURE__ */ Symbol.for(
1445
1446
  );
1446
1447
  function createMonkeysProviderContexts() {
1447
1448
  return Object.freeze({
1448
- locale: react.createContext({
1449
+ locale: React.createContext({
1449
1450
  ...defaultMonkeysLocale,
1450
1451
  provided: false
1451
1452
  }),
1452
- theme: react.createContext({
1453
+ theme: React.createContext({
1453
1454
  provided: false
1454
1455
  }),
1455
- direction: react.createContext({
1456
+ direction: React.createContext({
1456
1457
  provided: false
1457
1458
  }),
1458
- environment: react.createContext({
1459
+ environment: React.createContext({
1459
1460
  provided: false,
1460
1461
  environment: EMPTY_ENVIRONMENT,
1461
1462
  portal: EMPTY_PORTAL
@@ -1491,24 +1492,24 @@ function mergeAppearance(inherited, explicit) {
1491
1492
  };
1492
1493
  }
1493
1494
  function useMonkeysLocaleMessages() {
1494
- return react.useContext(MonkeysLocaleContext).messages;
1495
+ return React.useContext(MonkeysLocaleContext).messages;
1495
1496
  }
1496
1497
  function useMonkeysBaseAppearance(explicit) {
1497
- const inherited = react.useContext(MonkeysThemeContext).baseAppearance;
1498
- return react.useMemo(
1498
+ const inherited = React.useContext(MonkeysThemeContext).baseAppearance;
1499
+ return React.useMemo(
1499
1500
  () => mergeAppearance(inherited, explicit),
1500
1501
  [explicit, inherited]
1501
1502
  );
1502
1503
  }
1503
1504
  function useMonkeysListFooter() {
1504
- return react.useContext(MonkeysThemeContext).listFooter ?? {};
1505
+ return React.useContext(MonkeysThemeContext).listFooter ?? {};
1505
1506
  }
1506
1507
  function useMonkeysComponentAttributes() {
1507
- const locale = react.useContext(MonkeysLocaleContext);
1508
- const theme = react.useContext(MonkeysThemeContext);
1509
- const direction = react.useContext(MonkeysDirectionContext);
1508
+ const locale = React.useContext(MonkeysLocaleContext);
1509
+ const theme = React.useContext(MonkeysThemeContext);
1510
+ const direction = React.useContext(MonkeysDirectionContext);
1510
1511
  const providerActive = locale.provided || theme.provided || direction.provided;
1511
- return react.useMemo(
1512
+ return React.useMemo(
1512
1513
  () => providerActive ? {
1513
1514
  dir: direction.direction,
1514
1515
  "data-monkeys-direction": direction.direction,
@@ -3043,7 +3044,7 @@ function getPageItems(currentPage, pageCount, boundaryCount, siblingCount) {
3043
3044
  });
3044
3045
  return items;
3045
3046
  }
3046
- var BasePagination = react.forwardRef(
3047
+ var BasePagination = React.forwardRef(
3047
3048
  function BasePagination2({
3048
3049
  page,
3049
3050
  defaultPage,
@@ -3074,7 +3075,7 @@ var BasePagination = react.forwardRef(
3074
3075
  const resolvedAppearance = useMonkeysBaseAppearance(appearance);
3075
3076
  const componentAttributes = useMonkeysComponentAttributes();
3076
3077
  const theme = resolveBaseAppearance(resolvedAppearance);
3077
- const [uncontrolledPage, setUncontrolledPage] = react.useState(
3078
+ const [uncontrolledPage, setUncontrolledPage] = React.useState(
3078
3079
  () => defaultPage ?? 1
3079
3080
  );
3080
3081
  if (page !== void 0) assertPositiveInteger(page, "page");
@@ -3429,7 +3430,7 @@ function DataExplorerSplitButton({
3429
3430
  className,
3430
3431
  classNames
3431
3432
  }) {
3432
- const [open, setOpen] = react.useState(false);
3433
+ const [open, setOpen] = React.useState(false);
3433
3434
  const theme = resolveDataExplorerAppearance(appearance);
3434
3435
  const hasItems = items.length > 0;
3435
3436
  const resolvedActive = active || open;
@@ -4195,7 +4196,7 @@ function DraggableTreeItem({
4195
4196
  transform: utilities.CSS.Transform.toString(transform),
4196
4197
  transition
4197
4198
  };
4198
- const setRowRef = react.useCallback(
4199
+ const setRowRef = React.useCallback(
4199
4200
  (element) => {
4200
4201
  setNodeRef(element);
4201
4202
  registerNodeElement?.(node.id, element);
@@ -4415,13 +4416,13 @@ function DataExplorerDraggableTree({
4415
4416
  onDragEnd
4416
4417
  }) {
4417
4418
  const theme = resolveDataExplorerAppearance(appearance);
4418
- const [internalExpandedNodeIds, setInternalExpandedNodeIds] = react.useState(
4419
+ const [internalExpandedNodeIds, setInternalExpandedNodeIds] = React.useState(
4419
4420
  () => buildDefaultExpandedNodeIds(nodes, defaultExpandedNodeIds)
4420
4421
  );
4421
- const [activeNodeId, setActiveNodeId] = react.useState();
4422
- const [dragPreviewLayout, setDragPreviewLayout] = react.useState();
4423
- const [overNodeId, setOverNodeId] = react.useState();
4424
- const nodeElementsRef = react.useRef(/* @__PURE__ */ new Map());
4422
+ const [activeNodeId, setActiveNodeId] = React.useState();
4423
+ const [dragPreviewLayout, setDragPreviewLayout] = React.useState();
4424
+ const [overNodeId, setOverNodeId] = React.useState();
4425
+ const nodeElementsRef = React.useRef(/* @__PURE__ */ new Map());
4425
4426
  const itemBorderRadius = resolveTreeItemBorderRadius(itemRadius, theme.radius);
4426
4427
  const itemStyle = itemBorderRadius ? { borderRadius: itemBorderRadius } : void 0;
4427
4428
  const overlayStyle = {
@@ -4433,24 +4434,24 @@ function DataExplorerDraggableTree({
4433
4434
  core.useSensor(core.PointerSensor, { activationConstraint: { distance: 4 } }),
4434
4435
  core.useSensor(core.KeyboardSensor, { coordinateGetter: sortable.sortableKeyboardCoordinates })
4435
4436
  );
4436
- react.useEffect(() => {
4437
+ React.useEffect(() => {
4437
4438
  setInternalExpandedNodeIds(
4438
4439
  buildDefaultExpandedNodeIds(nodes, defaultExpandedNodeIds)
4439
4440
  );
4440
4441
  }, [defaultExpandedNodeIds, resetExpansionKey]);
4441
4442
  const resolvedExpandedNodeIds = expandedNodeIds !== void 0 ? new Set(expandedNodeIds) : internalExpandedNodeIds;
4442
- const flattenedNodes = react.useMemo(
4443
+ const flattenedNodes = React.useMemo(
4443
4444
  () => buildFlattenedTree(nodes, resolvedExpandedNodeIds),
4444
4445
  [nodes, resolvedExpandedNodeIds]
4445
4446
  );
4446
- const flattenedNodeMap = react.useMemo(() => {
4447
+ const flattenedNodeMap = React.useMemo(() => {
4447
4448
  const map = /* @__PURE__ */ new Map();
4448
4449
  for (const entry of flattenedNodes) map.set(entry.node.id, entry);
4449
4450
  return map;
4450
4451
  }, [flattenedNodes]);
4451
4452
  const activeEntry = activeNodeId ? flattenedNodeMap.get(activeNodeId) : void 0;
4452
4453
  const sortableIds = flattenedNodes.map((entry) => entry.node.id);
4453
- const registerNodeElement = react.useCallback(
4454
+ const registerNodeElement = React.useCallback(
4454
4455
  (nodeId, element) => {
4455
4456
  if (element) {
4456
4457
  nodeElementsRef.current.set(nodeId, element);
@@ -4460,7 +4461,7 @@ function DataExplorerDraggableTree({
4460
4461
  },
4461
4462
  []
4462
4463
  );
4463
- const clearDragState = react.useCallback(() => {
4464
+ const clearDragState = React.useCallback(() => {
4464
4465
  setActiveNodeId(void 0);
4465
4466
  setDragPreviewLayout(void 0);
4466
4467
  setOverNodeId(void 0);
@@ -4699,7 +4700,7 @@ function DataExplorerDisplayActionMenu({
4699
4700
  className,
4700
4701
  classNames
4701
4702
  }) {
4702
- const [open, setOpen] = react.useState(false);
4703
+ const [open, setOpen] = React.useState(false);
4703
4704
  const theme = resolveDataExplorerAppearance(appearance);
4704
4705
  const context = {
4705
4706
  itemId,
@@ -5360,13 +5361,13 @@ function DataExplorerViewCollection({
5360
5361
  );
5361
5362
  const measuredGridGap = resolveNonNegativeNumber(measuredGridOptions?.gap, 8);
5362
5363
  const measuredGridMinColumnWidth = measuredGridOptions?.minColumnWidth ?? "220px";
5363
- const measuredElementsRef = react.useRef(/* @__PURE__ */ new Map());
5364
- const measuredCallbacksRef = react.useRef(/* @__PURE__ */ new Map());
5365
- const measuredSpansRef = react.useRef(/* @__PURE__ */ new Map());
5366
- const resizeObserverRef = react.useRef(null);
5367
- const [, setMeasuredLayoutVersion] = react.useState(0);
5364
+ const measuredElementsRef = React.useRef(/* @__PURE__ */ new Map());
5365
+ const measuredCallbacksRef = React.useRef(/* @__PURE__ */ new Map());
5366
+ const measuredSpansRef = React.useRef(/* @__PURE__ */ new Map());
5367
+ const resizeObserverRef = React.useRef(null);
5368
+ const [, setMeasuredLayoutVersion] = React.useState(0);
5368
5369
  const resolveItemStyle = typeof itemStyle === "function" ? (props) => itemStyle(props) : () => itemStyle;
5369
- react.useEffect(() => {
5370
+ React.useEffect(() => {
5370
5371
  if (!measuredGridEnabled || typeof ResizeObserver === "undefined") {
5371
5372
  return void 0;
5372
5373
  }
@@ -5402,7 +5403,7 @@ function DataExplorerViewCollection({
5402
5403
  }
5403
5404
  };
5404
5405
  }, [measuredGridEnabled, measuredGridGap, measuredGridRowHeight]);
5405
- react.useEffect(() => {
5406
+ React.useEffect(() => {
5406
5407
  if (!measuredGridEnabled) {
5407
5408
  measuredElementsRef.current.clear();
5408
5409
  measuredCallbacksRef.current.clear();
@@ -5429,7 +5430,7 @@ function DataExplorerViewCollection({
5429
5430
  setMeasuredLayoutVersion((version) => version + 1);
5430
5431
  }
5431
5432
  }, [measuredGridEnabled, resolvedItems, resolveItemId]);
5432
- const getMeasuredRef = react.useCallback((itemId) => {
5433
+ const getMeasuredRef = React.useCallback((itemId) => {
5433
5434
  const cached = measuredCallbacksRef.current.get(itemId);
5434
5435
  if (cached) return cached;
5435
5436
  const callback = (node) => {
@@ -5540,7 +5541,7 @@ function DataExplorerViewCollection({
5540
5541
  } : resolvedStyle;
5541
5542
  if (!wrapItems) {
5542
5543
  if (!measuredGridEnabled) {
5543
- return /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderedItem }, itemId);
5544
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: renderedItem }, itemId);
5544
5545
  }
5545
5546
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: itemClassName, style: measuredStyle, children: /* @__PURE__ */ jsxRuntime.jsx("div", { ref: getMeasuredRef(itemId), children: renderedItem }) }, itemId);
5546
5547
  }
@@ -5792,21 +5793,21 @@ function DataExplorerImagePreview({
5792
5793
  appearance ?? { background: "dark-stage" }
5793
5794
  );
5794
5795
  const imageSrc = typeof src === "string" ? src.trim() : "";
5795
- const stageRef = react.useRef(null);
5796
- const stageSizeRef = react.useRef(null);
5797
- const viewRef = react.useRef({ scale: 1, translateX: stagePadding, translateY: stagePadding });
5798
- const draggingRef = react.useRef(void 0);
5799
- const [naturalSize, setNaturalSize] = react.useState(null);
5800
- const [dragging, setDragging] = react.useState(false);
5801
- const [{ scale, translateX, translateY }, setView] = react.useState(() => ({
5796
+ const stageRef = React.useRef(null);
5797
+ const stageSizeRef = React.useRef(null);
5798
+ const viewRef = React.useRef({ scale: 1, translateX: stagePadding, translateY: stagePadding });
5799
+ const draggingRef = React.useRef(void 0);
5800
+ const [naturalSize, setNaturalSize] = React.useState(null);
5801
+ const [dragging, setDragging] = React.useState(false);
5802
+ const [{ scale, translateX, translateY }, setView] = React.useState(() => ({
5802
5803
  scale: 1,
5803
5804
  translateX: stagePadding,
5804
5805
  translateY: stagePadding
5805
5806
  }));
5806
- react.useEffect(() => {
5807
+ React.useEffect(() => {
5807
5808
  viewRef.current = { scale, translateX, translateY };
5808
5809
  }, [scale, translateX, translateY]);
5809
- react.useEffect(() => {
5810
+ React.useEffect(() => {
5810
5811
  setNaturalSize(null);
5811
5812
  setView({ scale: 1, translateX: stagePadding, translateY: stagePadding });
5812
5813
  }, [imageSrc, stagePadding]);
@@ -5814,7 +5815,7 @@ function DataExplorerImagePreview({
5814
5815
  const normalizedMaxScale = Number.isFinite(maxScale) ? Math.max(normalizedMinScale, maxScale) : MAX_SAFE_SCALE;
5815
5816
  const normalizedZoomStep = Number.isFinite(zoomStep) && zoomStep > 1 ? zoomStep : DEFAULT_ZOOM_STEP;
5816
5817
  const normalizedStagePadding = Number.isFinite(stagePadding) && stagePadding >= 0 ? stagePadding : DEFAULT_STAGE_PADDING;
5817
- const resetView = react.useCallback(
5818
+ const resetView = React.useCallback(
5818
5819
  (nextNaturalSize) => {
5819
5820
  const stage = stageRef.current;
5820
5821
  const size = nextNaturalSize ?? naturalSize;
@@ -5849,7 +5850,7 @@ function DataExplorerImagePreview({
5849
5850
  },
5850
5851
  [naturalSize, normalizedMaxScale, normalizedMinScale, normalizedStagePadding]
5851
5852
  );
5852
- const compensateStageResize = react.useCallback((width, height) => {
5853
+ const compensateStageResize = React.useCallback((width, height) => {
5853
5854
  if (!Number.isFinite(width) || !Number.isFinite(height)) return;
5854
5855
  if (width <= 0 || height <= 0) return;
5855
5856
  const previous = stageSizeRef.current;
@@ -5864,7 +5865,7 @@ function DataExplorerImagePreview({
5864
5865
  translateY: current.translateY + deltaY
5865
5866
  }));
5866
5867
  }, [imageSrc]);
5867
- react.useLayoutEffect(() => {
5868
+ React.useLayoutEffect(() => {
5868
5869
  const stage = stageRef.current;
5869
5870
  if (!stage) return;
5870
5871
  compensateStageResize(stage.clientWidth, stage.clientHeight);
@@ -5883,7 +5884,7 @@ function DataExplorerImagePreview({
5883
5884
  window.addEventListener("resize", handleResize);
5884
5885
  return () => window.removeEventListener("resize", handleResize);
5885
5886
  }, [compensateStageResize]);
5886
- const zoomAtPoint = react.useCallback(
5887
+ const zoomAtPoint = React.useCallback(
5887
5888
  (factor, stageX, stageY) => {
5888
5889
  if (!Number.isFinite(factor) || factor === 1) return;
5889
5890
  if (!Number.isFinite(stageX) || !Number.isFinite(stageY)) return;
@@ -5906,7 +5907,7 @@ function DataExplorerImagePreview({
5906
5907
  },
5907
5908
  [normalizedMaxScale, normalizedMinScale]
5908
5909
  );
5909
- react.useEffect(() => {
5910
+ React.useEffect(() => {
5910
5911
  const stage = stageRef.current;
5911
5912
  if (!stage || !imageSrc || !naturalSize) return;
5912
5913
  const handleWheel = (event) => {
@@ -5921,7 +5922,7 @@ function DataExplorerImagePreview({
5921
5922
  stage.addEventListener("wheel", handleWheel, { passive: false });
5922
5923
  return () => stage.removeEventListener("wheel", handleWheel);
5923
5924
  }, [imageSrc, naturalSize, normalizedZoomStep, zoomAtPoint]);
5924
- const handlePointerDown = react.useCallback(
5925
+ const handlePointerDown = React.useCallback(
5925
5926
  (event) => {
5926
5927
  if (event.button !== 0) return;
5927
5928
  if (!imageSrc || !naturalSize) return;
@@ -5941,7 +5942,7 @@ function DataExplorerImagePreview({
5941
5942
  },
5942
5943
  [imageSrc, naturalSize]
5943
5944
  );
5944
- const handlePointerMove = react.useCallback((event) => {
5945
+ const handlePointerMove = React.useCallback((event) => {
5945
5946
  const drag = draggingRef.current;
5946
5947
  if (!drag || drag.pointerId !== event.pointerId) return;
5947
5948
  event.preventDefault();
@@ -5951,7 +5952,7 @@ function DataExplorerImagePreview({
5951
5952
  translateY: drag.startTranslateY + event.clientY - drag.startClientY
5952
5953
  });
5953
5954
  }, []);
5954
- const endDrag = react.useCallback((event) => {
5955
+ const endDrag = React.useCallback((event) => {
5955
5956
  const drag = draggingRef.current;
5956
5957
  if (!drag || drag.pointerId !== event.pointerId) return;
5957
5958
  draggingRef.current = void 0;
@@ -5961,7 +5962,7 @@ function DataExplorerImagePreview({
5961
5962
  stage.releasePointerCapture(event.pointerId);
5962
5963
  }
5963
5964
  }, []);
5964
- const handleDoubleClick = react.useCallback(
5965
+ const handleDoubleClick = React.useCallback(
5965
5966
  (event) => {
5966
5967
  if (!imageSrc || !naturalSize) return;
5967
5968
  if (isNoDragTarget(event.target)) return;
@@ -5969,7 +5970,7 @@ function DataExplorerImagePreview({
5969
5970
  },
5970
5971
  [imageSrc, naturalSize, resetView]
5971
5972
  );
5972
- const handleZoomButtonClick = react.useCallback(
5973
+ const handleZoomButtonClick = React.useCallback(
5973
5974
  (factor) => {
5974
5975
  const stage = stageRef.current;
5975
5976
  if (!stage || !naturalSize) return;
@@ -6134,6 +6135,145 @@ function DataExplorerImagePreview({
6134
6135
  }
6135
6136
  );
6136
6137
  }
6138
+ var mediaPreviewFrameClassName = ({
6139
+ aspectRatio = "square",
6140
+ maxSquareHeight = true,
6141
+ className
6142
+ } = {}) => cn2(
6143
+ "w-full overflow-hidden bg-muted",
6144
+ (aspectRatio === "square" || aspectRatio === "1:1") && "aspect-square",
6145
+ (aspectRatio === "square" || aspectRatio === "1:1") && maxSquareHeight && "max-h-[300px]",
6146
+ aspectRatio === "4:3" && "aspect-[4/3]",
6147
+ aspectRatio === "3:4" && "aspect-[3/4]",
6148
+ (aspectRatio === "video" || aspectRatio === "16:9") && "aspect-video",
6149
+ aspectRatio === "9:16" && "aspect-[9/16]",
6150
+ className
6151
+ );
6152
+ var MediaPreviewFrame = React__namespace.forwardRef(
6153
+ ({ aspectRatio = "square", maxSquareHeight = true, className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: mediaPreviewFrameClassName({ aspectRatio, maxSquareHeight, className }), ...props })
6154
+ );
6155
+ MediaPreviewFrame.displayName = "MediaPreviewFrame";
6156
+ var MediaPreviewImage = React__namespace.forwardRef(
6157
+ ({ fit = "contain", className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
6158
+ "img",
6159
+ {
6160
+ ref,
6161
+ className: cn2("block size-full", fit === "contain" ? "object-contain" : "object-cover", className),
6162
+ ...props
6163
+ }
6164
+ )
6165
+ );
6166
+ MediaPreviewImage.displayName = "MediaPreviewImage";
6167
+ function PreviewIcon({ kind }) {
6168
+ const Icon = kind === "image" ? lucideReact.Image : kind === "video" ? lucideReact.Video : kind === "audio" ? lucideReact.Music2 : lucideReact.FileText;
6169
+ return /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "h-6 w-6", "aria-hidden": "true" });
6170
+ }
6171
+ function DataExplorerMediaPreview({
6172
+ src,
6173
+ kind = "image",
6174
+ alt = "Preview",
6175
+ title,
6176
+ aspectRatio = "auto",
6177
+ fit = "contain",
6178
+ controls = true,
6179
+ loading = false,
6180
+ empty = "No preview available",
6181
+ error = "Preview is unavailable right now.",
6182
+ className,
6183
+ classNames,
6184
+ onLoad,
6185
+ onError
6186
+ }) {
6187
+ const [hasError, setHasError] = React.useState(false);
6188
+ const resolvedSrc = typeof src === "string" ? src.trim() : "";
6189
+ React.useEffect(() => {
6190
+ setHasError(false);
6191
+ }, [resolvedSrc, kind]);
6192
+ const renderPlaceholder = (content, placeholderClassName) => /* @__PURE__ */ jsxRuntime.jsx(
6193
+ "div",
6194
+ {
6195
+ className: cn(
6196
+ "flex min-h-24 flex-col items-center justify-center gap-2 bg-muted/30 p-4 text-center text-sm text-muted-foreground",
6197
+ classNames?.placeholder,
6198
+ placeholderClassName
6199
+ ),
6200
+ role: loading ? "status" : "img",
6201
+ "aria-label": typeof content === "string" ? content : void 0,
6202
+ children: content
6203
+ }
6204
+ );
6205
+ if (loading) {
6206
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-w-0 overflow-hidden", classNames?.root, className), "aria-busy": "true", children: /* @__PURE__ */ jsxRuntime.jsxs(
6207
+ "div",
6208
+ {
6209
+ className: cn(
6210
+ "flex min-h-24 flex-col items-center justify-center gap-2 bg-muted/30 p-4 text-sm text-muted-foreground",
6211
+ classNames?.loading
6212
+ ),
6213
+ children: [
6214
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "h-5 w-5 animate-spin", "aria-hidden": "true" }),
6215
+ title || "Loading preview..."
6216
+ ]
6217
+ }
6218
+ ) });
6219
+ }
6220
+ if (!resolvedSrc || hasError) {
6221
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-w-0 overflow-hidden", classNames?.root, className), children: renderPlaceholder(
6222
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6223
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, { kind }),
6224
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("max-w-full truncate", hasError ? classNames?.error : void 0), children: hasError ? error : empty }),
6225
+ title ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate text-xs", children: title }) : null
6226
+ ] })
6227
+ ) });
6228
+ }
6229
+ const handleError = () => {
6230
+ setHasError(true);
6231
+ onError?.();
6232
+ };
6233
+ const media = kind === "image" ? /* @__PURE__ */ jsxRuntime.jsx(
6234
+ MediaPreviewImage,
6235
+ {
6236
+ src: resolvedSrc,
6237
+ alt,
6238
+ fit,
6239
+ className: classNames?.media,
6240
+ loading: "lazy",
6241
+ decoding: "async",
6242
+ draggable: false,
6243
+ onLoad,
6244
+ onError: handleError
6245
+ }
6246
+ ) : kind === "video" ? /* @__PURE__ */ jsxRuntime.jsx(
6247
+ "video",
6248
+ {
6249
+ src: resolvedSrc,
6250
+ className: cn("block h-auto w-full", fit === "cover" ? "object-cover" : "object-contain", classNames?.media),
6251
+ controls,
6252
+ preload: "metadata",
6253
+ onLoadedData: onLoad,
6254
+ onError: handleError
6255
+ }
6256
+ ) : kind === "audio" ? /* @__PURE__ */ jsxRuntime.jsx(
6257
+ "audio",
6258
+ {
6259
+ src: resolvedSrc,
6260
+ className: cn("w-full", classNames?.media),
6261
+ controls,
6262
+ preload: "metadata",
6263
+ onCanPlay: onLoad,
6264
+ onError: handleError
6265
+ }
6266
+ ) : renderPlaceholder(
6267
+ /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6268
+ /* @__PURE__ */ jsxRuntime.jsx(PreviewIcon, { kind: "file" }),
6269
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-full truncate", children: title || resolvedSrc })
6270
+ ] })
6271
+ );
6272
+ if (kind === "image") {
6273
+ return /* @__PURE__ */ jsxRuntime.jsx(MediaPreviewFrame, { aspectRatio, className: cn(classNames?.root, className), children: media });
6274
+ }
6275
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("min-w-0 overflow-hidden", classNames?.root, className), children: media });
6276
+ }
6137
6277
  function DataExplorerPage({
6138
6278
  sidebar,
6139
6279
  tree,
@@ -6481,18 +6621,18 @@ function DataExplorerRecordPicker({
6481
6621
  onValueChange
6482
6622
  }) {
6483
6623
  const theme = resolveDataExplorerAppearance(appearance);
6484
- const [uncontrolledOpen, setUncontrolledOpen] = react.useState(defaultOpen);
6485
- const [uncontrolledSearch, setUncontrolledSearch] = react.useState(defaultSearchValue);
6624
+ const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);
6625
+ const [uncontrolledSearch, setUncontrolledSearch] = React.useState(defaultSearchValue);
6486
6626
  const isControlledOpen = open !== void 0;
6487
6627
  const isOpen = isControlledOpen ? open : uncontrolledOpen;
6488
6628
  const isControlledSearch = searchValue !== void 0;
6489
6629
  const query = isControlledSearch ? searchValue : uncontrolledSearch;
6490
- const selectedValues = react.useMemo(() => normalizeValues(value, multiple), [multiple, value]);
6491
- const selectedSet = react.useMemo(() => new Set(selectedValues), [selectedValues]);
6630
+ const selectedValues = React.useMemo(() => normalizeValues(value, multiple), [multiple, value]);
6631
+ const selectedSet = React.useMemo(() => new Set(selectedValues), [selectedValues]);
6492
6632
  const selectedOptions = selectedValues.map((selectedValue) => options.find((option) => option.value === selectedValue)).filter((option) => Boolean(option));
6493
6633
  const visibleOptions = createOption ? [createOption, ...options] : options;
6494
6634
  const triggerValue = selectedOptions.length ? multiple && selectedOptions.length > 1 ? `${selectedOptions.slice(0, 2).map((option) => getOptionText(option)).join(", ")} +${selectedOptions.length - 2}` : getOptionText(selectedOptions[0]) : placeholder;
6495
- react.useEffect(() => {
6635
+ React.useEffect(() => {
6496
6636
  if (!isOpen) return;
6497
6637
  const handleKeyDown = (event) => {
6498
6638
  if (event.key === "Escape") onOpenChange?.(false);
@@ -6625,6 +6765,90 @@ function DataExplorerRecordPicker({
6625
6765
  ] }, option.value)) }) : null
6626
6766
  ] });
6627
6767
  }
6768
+ function DataExplorerUploadSurface({
6769
+ accept,
6770
+ multiple = false,
6771
+ disabled = false,
6772
+ busy = false,
6773
+ title = "Upload files",
6774
+ description,
6775
+ hint,
6776
+ busyLabel = "Uploading...",
6777
+ icon,
6778
+ className,
6779
+ classNames,
6780
+ onFilesSelected
6781
+ }) {
6782
+ const inputRef = React.useRef(null);
6783
+ const [isDragging, setIsDragging] = React.useState(false);
6784
+ const emitFiles = (files) => {
6785
+ if (disabled || busy) return;
6786
+ const selected = Array.from(files);
6787
+ if (selected.length > 0) onFilesSelected?.(selected);
6788
+ };
6789
+ const handleDrop = (event) => {
6790
+ event.preventDefault();
6791
+ setIsDragging(false);
6792
+ emitFiles(event.dataTransfer.files);
6793
+ };
6794
+ const renderText = (value, fallbackClassName, slot) => value ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-slot": slot, className: cn(fallbackClassName), children: value }) : null;
6795
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6796
+ "div",
6797
+ {
6798
+ "data-monkeys-component": "data-explorer-upload-surface",
6799
+ "data-state": busy ? "busy" : isDragging ? "dragging" : "idle",
6800
+ className: cn(
6801
+ "rounded-[var(--radius)] border border-dashed border-border bg-muted/20 p-6 text-center transition-colors",
6802
+ isDragging && "border-primary/60 bg-primary/5",
6803
+ (disabled || busy) && "pointer-events-none opacity-60",
6804
+ classNames?.root,
6805
+ className
6806
+ ),
6807
+ onDragEnter: (event) => {
6808
+ event.preventDefault();
6809
+ if (!disabled && !busy) setIsDragging(true);
6810
+ },
6811
+ onDragOver: (event) => event.preventDefault(),
6812
+ onDragLeave: (event) => {
6813
+ event.preventDefault();
6814
+ if (event.currentTarget === event.target) setIsDragging(false);
6815
+ },
6816
+ onDrop: handleDrop,
6817
+ children: [
6818
+ /* @__PURE__ */ jsxRuntime.jsx(
6819
+ "input",
6820
+ {
6821
+ ref: inputRef,
6822
+ className: "sr-only",
6823
+ type: "file",
6824
+ accept,
6825
+ multiple,
6826
+ disabled: disabled || busy,
6827
+ onChange: (event) => {
6828
+ emitFiles(event.target.files ?? []);
6829
+ event.target.value = "";
6830
+ }
6831
+ }
6832
+ ),
6833
+ /* @__PURE__ */ jsxRuntime.jsxs(
6834
+ "button",
6835
+ {
6836
+ type: "button",
6837
+ className: cn("mx-auto flex min-w-0 flex-col items-center gap-2 text-center", classNames?.button),
6838
+ disabled: disabled || busy,
6839
+ onClick: () => inputRef.current?.click(),
6840
+ children: [
6841
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-muted-foreground", classNames?.icon), children: busy ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block h-7 w-7 animate-spin rounded-full border-2 border-primary/25 border-t-primary", "aria-hidden": "true" }) : icon ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UploadCloud, { className: "h-7 w-7", "aria-hidden": "true" }) }),
6842
+ renderText(busy ? busyLabel : title, "text-sm font-semibold text-foreground", "title"),
6843
+ renderText(description, "max-w-xl text-xs leading-5 text-muted-foreground", "description"),
6844
+ renderText(hint, "max-w-xl text-xs leading-5 text-muted-foreground", "hint")
6845
+ ]
6846
+ }
6847
+ )
6848
+ ]
6849
+ }
6850
+ );
6851
+ }
6628
6852
  function DefaultSearchIcon() {
6629
6853
  return /* @__PURE__ */ jsxRuntime.jsxs(
6630
6854
  "svg",
@@ -7030,7 +7254,7 @@ function DataExplorerViewTree({
7030
7254
  const loadingContent = loadingNode ?? labels?.loading ?? internalLabels.loading;
7031
7255
  const emptyContent = empty ?? labels?.empty ?? internalLabels.empty;
7032
7256
  const hasExplicitGroups = Array.isArray(groups);
7033
- const resolvedGroups = react.useMemo(
7257
+ const resolvedGroups = React.useMemo(
7034
7258
  () => {
7035
7259
  if (hasExplicitGroups) {
7036
7260
  return groups;
@@ -7046,19 +7270,19 @@ function DataExplorerViewTree({
7046
7270
  },
7047
7271
  [groups, hasExplicitGroups, nodes]
7048
7272
  );
7049
- const flattenedNodeMap = react.useMemo(
7273
+ const flattenedNodeMap = React.useMemo(
7050
7274
  () => buildFlattenedNodeMap(resolvedGroups),
7051
7275
  [resolvedGroups]
7052
7276
  );
7053
- const [internalExpandedNodeIds, setInternalExpandedNodeIds] = react.useState(
7277
+ const [internalExpandedNodeIds, setInternalExpandedNodeIds] = React.useState(
7054
7278
  () => buildDefaultNodeExpandedSet(resolvedGroups, defaultExpandedNodeIds)
7055
7279
  );
7056
- const [internalExpandedGroupIds, setInternalExpandedGroupIds] = react.useState(
7280
+ const [internalExpandedGroupIds, setInternalExpandedGroupIds] = React.useState(
7057
7281
  () => buildDefaultGroupExpandedSet(resolvedGroups, defaultExpandedGroupIds)
7058
7282
  );
7059
- const [draggingNodeId, setDraggingNodeId] = react.useState();
7060
- const [dragOverNodeId, setDragOverNodeId] = react.useState();
7061
- react.useEffect(() => {
7283
+ const [draggingNodeId, setDraggingNodeId] = React.useState();
7284
+ const [dragOverNodeId, setDragOverNodeId] = React.useState();
7285
+ React.useEffect(() => {
7062
7286
  setInternalExpandedNodeIds(
7063
7287
  buildDefaultNodeExpandedSet(resolvedGroups, defaultExpandedNodeIds)
7064
7288
  );
@@ -7722,6 +7946,7 @@ exports.DataExplorerDisplayMedia = DataExplorerDisplayMedia;
7722
7946
  exports.DataExplorerDraggableTree = DataExplorerDraggableTree;
7723
7947
  exports.DataExplorerFilterBar = DataExplorerFilterBar;
7724
7948
  exports.DataExplorerImagePreview = DataExplorerImagePreview;
7949
+ exports.DataExplorerMediaPreview = DataExplorerMediaPreview;
7725
7950
  exports.DataExplorerPage = DataExplorerPage;
7726
7951
  exports.DataExplorerRecordCard = DataExplorerRecordCard;
7727
7952
  exports.DataExplorerRecordPicker = DataExplorerRecordPicker;
@@ -7731,6 +7956,7 @@ exports.DataExplorerToolbarActions = DataExplorerToolbarActions;
7731
7956
  exports.DataExplorerToolbarShell = DataExplorerToolbarShell;
7732
7957
  exports.DataExplorerTree = DataExplorerTree;
7733
7958
  exports.DataExplorerTreeShell = DataExplorerTreeShell;
7959
+ exports.DataExplorerUploadSurface = DataExplorerUploadSurface;
7734
7960
  exports.DataExplorerView = DataExplorerView;
7735
7961
  exports.DataExplorerViewCollection = DataExplorerViewCollection;
7736
7962
  exports.DataExplorerViewItem = DataExplorerViewItem;