@underverse-ui/underverse 2.0.17 → 2.0.18

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,7 +1,7 @@
1
1
  "use client";
2
2
  import {
3
3
  Modal_default
4
- } from "./chunk-HEXF4EOB.js";
4
+ } from "./chunk-NJ53GV74.js";
5
5
  import {
6
6
  DEFAULT_TABLE_ROW_HEIGHT,
7
7
  DEFAULT_UEDITOR_IMAGE_MAX_FILE_SIZE,
@@ -21,11 +21,11 @@ import {
21
21
  sanitizeUEditorUrl,
22
22
  useDropdownMenuClose,
23
23
  useSharedEditorUiRenderState
24
- } from "./chunk-23VKHYEB.js";
24
+ } from "./chunk-RSLY7UU2.js";
25
25
  import {
26
26
  cn,
27
27
  useSmartTranslations
28
- } from "./chunk-EPBYGZHZ.js";
28
+ } from "./chunk-PZCD342B.js";
29
29
  import "./chunk-NSBPE2FW.js";
30
30
 
31
31
  // src/components/UEditor/menu-bar.tsx
@@ -945,4 +945,4 @@ var MenuBar = ({
945
945
  export {
946
946
  MenuBar
947
947
  };
948
- //# sourceMappingURL=menu-bar-7MPCNTHR.js.map
948
+ //# sourceMappingURL=menu-bar-JXYQ5CH5.js.map
package/dist/ueditor.cjs CHANGED
@@ -2061,21 +2061,23 @@ var init_cn = __esm({
2061
2061
  });
2062
2062
 
2063
2063
  // src/utils/animations.ts
2064
- function ensureAnimationStylesInjected() {
2065
- if (typeof document !== "undefined") {
2064
+ function ensureAnimationStylesInjected(targetDocument) {
2065
+ const resolvedDocument = targetDocument ?? (typeof document !== "undefined" ? document : void 0);
2066
+ if (resolvedDocument) {
2066
2067
  const styleId = "shadcn-animations";
2067
- if (!document.getElementById(styleId)) {
2068
- const styleElement = document.createElement("style");
2068
+ if (!resolvedDocument.getElementById(styleId)) {
2069
+ const styleElement = resolvedDocument.createElement("style");
2069
2070
  styleElement.id = styleId;
2070
2071
  styleElement.textContent = shadcnAnimationStyles;
2071
- document.head.appendChild(styleElement);
2072
+ resolvedDocument.head.appendChild(styleElement);
2072
2073
  }
2073
2074
  }
2074
2075
  }
2075
- function useShadCNAnimations() {
2076
+ function useShadCNAnimations(targetDocument) {
2076
2077
  (0, import_react.useEffect)(() => {
2077
- ensureAnimationStylesInjected();
2078
- }, []);
2078
+ if (targetDocument === null) return;
2079
+ ensureAnimationStylesInjected(targetDocument);
2080
+ }, [targetDocument]);
2079
2081
  }
2080
2082
  var import_react, shadcnAnimationStyles;
2081
2083
  var init_animations = __esm({
@@ -2331,11 +2333,13 @@ function UEditorPortalProvider({
2331
2333
  function useUEditorPortalContainerGetter() {
2332
2334
  return React6.useContext(UEditorPortalContext);
2333
2335
  }
2334
- function resolveUEditorPortalContainer(getPortalContainer) {
2336
+ function resolveUEditorPortalContainer(getPortalContainer, fallbackGetPortalContainer) {
2335
2337
  if (typeof document === "undefined") return null;
2336
- if (getPortalContainer) {
2338
+ const getters = [getPortalContainer, fallbackGetPortalContainer];
2339
+ for (const getter of getters) {
2340
+ if (!getter) continue;
2337
2341
  try {
2338
- const container = getPortalContainer();
2342
+ const container = getter();
2339
2343
  if (container) return container;
2340
2344
  } catch {
2341
2345
  }
@@ -2384,20 +2388,30 @@ function overflowAmount(left, width, viewportWidth, padding) {
2384
2388
  return overflowLeft + overflowRight;
2385
2389
  }
2386
2390
  function computePopoverPosition(args) {
2387
- const { triggerRect, contentSize, placement, offset, padding, viewport } = args;
2391
+ const { triggerRect, contentSize, placement, offset, padding, viewport, constrainToAvailableHeight } = args;
2388
2392
  let { side, align } = normalizePlacement(placement);
2393
+ const availableBelow = Math.max(0, viewport.height - padding - triggerRect.bottom - offset);
2394
+ const availableAbove = Math.max(0, triggerRect.top - padding - offset);
2389
2395
  if (side === "bottom") {
2390
- const bottomTop = triggerRect.bottom + offset;
2391
- const overflowsBottom = bottomTop + contentSize.height > viewport.height - padding;
2392
- const topTop = triggerRect.top - offset - contentSize.height;
2393
- const fitsTop = topTop >= padding;
2394
- if (overflowsBottom && fitsTop) side = "top";
2396
+ if (constrainToAvailableHeight) {
2397
+ if (contentSize.height > availableBelow && availableAbove > availableBelow) side = "top";
2398
+ } else {
2399
+ const bottomTop = triggerRect.bottom + offset;
2400
+ const overflowsBottom = bottomTop + contentSize.height > viewport.height - padding;
2401
+ const topTop = triggerRect.top - offset - contentSize.height;
2402
+ const fitsTop = topTop >= padding;
2403
+ if (overflowsBottom && fitsTop) side = "top";
2404
+ }
2395
2405
  } else if (side === "top") {
2396
- const topTop = triggerRect.top - offset - contentSize.height;
2397
- const overflowsTop = topTop < padding;
2398
- const bottomTop = triggerRect.bottom + offset;
2399
- const fitsBottom = bottomTop + contentSize.height <= viewport.height - padding;
2400
- if (overflowsTop && fitsBottom) side = "bottom";
2406
+ if (constrainToAvailableHeight) {
2407
+ if (contentSize.height > availableAbove && availableBelow > availableAbove) side = "bottom";
2408
+ } else {
2409
+ const topTop = triggerRect.top - offset - contentSize.height;
2410
+ const overflowsTop = topTop < padding;
2411
+ const bottomTop = triggerRect.bottom + offset;
2412
+ const fitsBottom = bottomTop + contentSize.height <= viewport.height - padding;
2413
+ if (overflowsTop && fitsBottom) side = "bottom";
2414
+ }
2401
2415
  } else if (side === "right") {
2402
2416
  const rightLeft = triggerRect.right + offset;
2403
2417
  const overflowsRight = rightLeft + contentSize.width > viewport.width - padding;
@@ -2421,16 +2435,18 @@ function computePopoverPosition(args) {
2421
2435
  if (align === "start" && startOverflow > 0 && endOverflow < startOverflow) align = "end";
2422
2436
  if (align === "end" && endOverflow > 0 && startOverflow < endOverflow) align = "start";
2423
2437
  left = align === "end" ? leftEnd : leftStart;
2424
- top = side === "top" ? triggerRect.top - offset - contentSize.height : triggerRect.bottom + offset;
2438
+ const availableHeight = side === "top" ? availableAbove : availableBelow;
2439
+ const renderedHeight = constrainToAvailableHeight ? Math.min(contentSize.height, availableHeight) : contentSize.height;
2440
+ top = side === "top" ? triggerRect.top - offset - renderedHeight : triggerRect.bottom + offset;
2425
2441
  left = clamp(left, padding, viewport.width - contentSize.width - padding);
2426
- top = clamp(top, padding, viewport.height - contentSize.height - padding);
2427
- return { top, left, side, align };
2442
+ top = clamp(top, padding, viewport.height - renderedHeight - padding);
2443
+ return { top, left, side, align, availableHeight };
2428
2444
  }
2429
2445
  top = triggerRect.top;
2430
2446
  left = side === "left" ? triggerRect.left - offset - contentSize.width : triggerRect.right + offset;
2431
2447
  left = clamp(left, padding, viewport.width - contentSize.width - padding);
2432
2448
  top = clamp(top, padding, viewport.height - contentSize.height - padding);
2433
- return { top, left, side, align };
2449
+ return { top, left, side, align, availableHeight: Math.max(0, viewport.height - padding * 2) };
2434
2450
  }
2435
2451
  var React7, import_react_dom, import_jsx_runtime7, clamp, Popover;
2436
2452
  var init_Popover = __esm({
@@ -2461,7 +2477,9 @@ var init_Popover = __esm({
2461
2477
  onOpenChange,
2462
2478
  matchTriggerWidth = false,
2463
2479
  contentWidth,
2464
- borderMode
2480
+ borderMode,
2481
+ getPortalContainer,
2482
+ constrainToAvailableHeight = false
2465
2483
  }) => {
2466
2484
  const isControlled = open !== void 0;
2467
2485
  const [internalOpen, setInternalOpen] = React7.useState(false);
@@ -2469,14 +2487,14 @@ var init_Popover = __esm({
2469
2487
  const positionerRef = React7.useRef(null);
2470
2488
  const panelRef = React7.useRef(null);
2471
2489
  const lastAppliedRef = React7.useRef(null);
2472
- useShadCNAnimations();
2473
2490
  const globalConfig = useUnderverseUIConfig();
2474
2491
  const resolvedBorderMode = borderMode ?? globalConfig.popover?.borderMode ?? globalConfig.borderMode;
2475
2492
  const isOpen = isControlled ? open : internalOpen;
2476
- const getPortalContainer = useUEditorPortalContainerGetter();
2477
- const portalContainer = isOpen ? resolveUEditorPortalContainer(getPortalContainer) : null;
2493
+ const contextGetPortalContainer = useUEditorPortalContainerGetter();
2494
+ const portalContainer = isOpen ? resolveUEditorPortalContainer(getPortalContainer, contextGetPortalContainer) : null;
2478
2495
  const portalDocument = portalContainer?.ownerDocument ?? null;
2479
2496
  const portalWindow = portalDocument?.defaultView ?? null;
2497
+ useShadCNAnimations(portalDocument);
2480
2498
  const setIsOpen = React7.useCallback(
2481
2499
  (next) => {
2482
2500
  if (!isControlled) setInternalOpen(next);
@@ -2486,20 +2504,14 @@ var init_Popover = __esm({
2486
2504
  );
2487
2505
  const offset = 4;
2488
2506
  const padding = 8;
2489
- const triggerSelector = React7.useId();
2490
2507
  const initialPlacement = React7.useMemo(() => normalizePlacement(placement), [placement]);
2491
- React7.useLayoutEffect(() => {
2492
- if (typeof document === "undefined") return;
2493
- const triggerEl = document.querySelector(`[data-underverse-popover-trigger="${triggerSelector}"]`);
2494
- if (triggerEl) {
2495
- triggerRef.current = triggerEl;
2496
- }
2497
- }, [triggerSelector, trigger]);
2498
2508
  const updatePosition = React7.useCallback(() => {
2499
2509
  const triggerEl = triggerRef.current;
2500
2510
  const positionerEl = positionerRef.current;
2501
2511
  const panelEl = panelRef.current;
2502
- if (!triggerEl || !positionerEl || !panelEl) return;
2512
+ if (!triggerEl || !positionerEl || !panelEl || !portalWindow) return;
2513
+ const contentEl = panelEl.firstElementChild;
2514
+ if (!contentEl) return;
2503
2515
  const triggerRect = triggerEl.getBoundingClientRect();
2504
2516
  const widthWanted = matchTriggerWidth ? triggerRect.width : contentWidth;
2505
2517
  const widthPx = widthWanted == null ? void 0 : Math.max(0, Math.round(widthWanted));
@@ -2513,7 +2525,7 @@ var init_Popover = __esm({
2513
2525
  const measuredHeight = positionerEl.offsetHeight;
2514
2526
  const contentRect = positionerEl.getBoundingClientRect();
2515
2527
  const contentBoxWidth = measuredWidth || contentRect.width;
2516
- const contentBoxHeight = measuredHeight || contentRect.height;
2528
+ const contentBoxHeight = Math.max(measuredHeight, contentRect.height, contentEl.scrollHeight);
2517
2529
  const next = computePopoverPosition({
2518
2530
  triggerRect,
2519
2531
  contentSize: { width: contentBoxWidth, height: contentBoxHeight },
@@ -2521,20 +2533,31 @@ var init_Popover = __esm({
2521
2533
  offset,
2522
2534
  padding,
2523
2535
  viewport: {
2524
- width: portalWindow?.innerWidth ?? window.innerWidth,
2525
- height: portalWindow?.innerHeight ?? window.innerHeight
2526
- }
2536
+ width: portalWindow.innerWidth,
2537
+ height: portalWindow.innerHeight
2538
+ },
2539
+ constrainToAvailableHeight
2527
2540
  });
2528
2541
  const top = Math.round(next.top);
2529
2542
  const left = Math.round(next.left);
2530
- const applied = prevApplied && Math.abs(prevApplied.top - top) < 0.5 && Math.abs(prevApplied.left - left) < 0.5 && prevApplied.side === next.side && prevApplied.align === next.align && prevApplied.width === widthPx;
2543
+ const applied = prevApplied && Math.abs(prevApplied.top - top) < 0.5 && Math.abs(prevApplied.left - left) < 0.5 && prevApplied.side === next.side && prevApplied.align === next.align && prevApplied.width === widthPx && prevApplied.availableHeight === next.availableHeight;
2531
2544
  if (applied) return;
2532
- lastAppliedRef.current = { top, left, side: next.side, align: next.align, width: widthPx };
2545
+ lastAppliedRef.current = {
2546
+ top,
2547
+ left,
2548
+ side: next.side,
2549
+ align: next.align,
2550
+ width: widthPx,
2551
+ availableHeight: next.availableHeight
2552
+ };
2533
2553
  positionerEl.style.transform = `translate3d(${left}px, ${top}px, 0)`;
2554
+ positionerEl.style.setProperty("--underverse-popover-available-height", `${next.availableHeight}px`);
2555
+ positionerEl.dataset.side = next.side;
2556
+ positionerEl.dataset.align = next.align;
2534
2557
  panelEl.style.transformOrigin = getTransformOrigin(next.side, next.align);
2535
2558
  if (positionerEl.style.visibility !== "visible") positionerEl.style.visibility = "visible";
2536
2559
  if (positionerEl.style.pointerEvents !== "auto") positionerEl.style.pointerEvents = "auto";
2537
- }, [placement, matchTriggerWidth, contentWidth, portalWindow]);
2560
+ }, [placement, matchTriggerWidth, contentWidth, portalWindow, constrainToAvailableHeight]);
2538
2561
  React7.useLayoutEffect(() => {
2539
2562
  if (!isOpen || !portalWindow) return;
2540
2563
  updatePosition();
@@ -2683,7 +2706,6 @@ var init_Popover = __esm({
2683
2706
  ref: mergeRefs(childRef, (node) => {
2684
2707
  triggerRef.current = node;
2685
2708
  }),
2686
- "data-underverse-popover-trigger": triggerSelector,
2687
2709
  onClick: chainEventHandlers(
2688
2710
  (e) => {
2689
2711
  triggerRef.current = e.currentTarget;