ssovee-os-web-ui 0.1.89 → 0.1.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1615,23 +1615,23 @@ var useShortcutFormatter_default = useShortcutFormatter;
1615
1615
  var globalKeyboardShortcuts = [
1616
1616
  {
1617
1617
  command: "exit_app",
1618
- shortcut: ["ctrl", "q"],
1619
- usage: "Exit app"
1618
+ shortcut: ["Ctrl", "E"],
1619
+ usage: "Exit or quit the application"
1620
1620
  },
1621
1621
  {
1622
1622
  command: "minimize_app",
1623
- shortcut: ["ctrl", "m"],
1624
- usage: "Minimize app"
1623
+ shortcut: ["Ctrl", "ArrowDown"],
1624
+ usage: "Minimize the application window"
1625
1625
  },
1626
1626
  {
1627
1627
  command: "maximize_app",
1628
- shortcut: ["ctrl", "shift", "m"],
1629
- usage: "Maximize app"
1628
+ shortcut: ["Ctrl", "ArrowUp"],
1629
+ usage: "Maximize the application window"
1630
1630
  },
1631
1631
  {
1632
1632
  command: "focus_search",
1633
- shortcut: ["ctrl", "k"],
1634
- usage: "Focus search"
1633
+ shortcut: ["Ctrl", "k"],
1634
+ usage: "Focus on current app search"
1635
1635
  }
1636
1636
  ];
1637
1637
  var SearchInput = React23__namespace.default.forwardRef(
@@ -2453,17 +2453,7 @@ function PluginPlayground({
2453
2453
  );
2454
2454
  }
2455
2455
  var SIDEBAR_WIDTH = 200;
2456
- var initialState = {
2457
- position: { x: 0, y: 40 },
2458
- isDragging: false,
2459
- startPosition: { x: 0, y: 40 },
2460
- isMinimized: false,
2461
- isMaximized: false,
2462
- windowSize: { width: 600, height: 300 },
2463
- resizeStart: null,
2464
- defaultSize: { width: 600, height: 300 },
2465
- preMaximizeState: null
2466
- };
2456
+ var TOP_BAR_HEIGHT = 37;
2467
2457
  var reducer = (state, action) => {
2468
2458
  switch (action.type) {
2469
2459
  case "START_DRAG":
@@ -2473,10 +2463,7 @@ var reducer = (state, action) => {
2473
2463
  case "STOP_DRAG":
2474
2464
  return { ...state, isDragging: false };
2475
2465
  case "START_RESIZE":
2476
- return {
2477
- ...state,
2478
- resizeStart: action.payload
2479
- };
2466
+ return { ...state, resizeStart: action.payload };
2480
2467
  case "RESIZE":
2481
2468
  return { ...state, windowSize: action.payload };
2482
2469
  case "STOP_RESIZE":
@@ -2502,7 +2489,7 @@ var reducer = (state, action) => {
2502
2489
  ...state,
2503
2490
  isMaximized: false,
2504
2491
  windowSize: state.preMaximizeState?.windowSize || state.defaultSize,
2505
- position: state.preMaximizeState?.position || { x: 0, y: 40 },
2492
+ position: state.preMaximizeState?.position || { x: 0, y: TOP_BAR_HEIGHT },
2506
2493
  preMaximizeState: null
2507
2494
  };
2508
2495
  }
@@ -2514,11 +2501,28 @@ var reducer = (state, action) => {
2514
2501
  windowSize: state.windowSize
2515
2502
  },
2516
2503
  windowSize: action.payload || {
2517
- width: window.innerWidth,
2518
- height: window.innerHeight
2504
+ width: typeof window !== "undefined" ? window.innerWidth : 600,
2505
+ height: typeof window !== "undefined" ? window.innerHeight - TOP_BAR_HEIGHT : 300
2519
2506
  },
2520
- position: { x: 0, y: 40 }
2507
+ position: { x: 0, y: TOP_BAR_HEIGHT }
2521
2508
  };
2509
+ case "CLAMP_BOUNDS": {
2510
+ const clampedWidth = Math.min(state.windowSize.width, action.payload.maxW);
2511
+ const clampedHeight = Math.min(state.windowSize.height, action.payload.maxH);
2512
+ const clampedX = Math.max(
2513
+ 0,
2514
+ Math.min(state.position.x, action.payload.maxW - clampedWidth)
2515
+ );
2516
+ const clampedY = Math.max(
2517
+ TOP_BAR_HEIGHT,
2518
+ Math.min(state.position.y, action.payload.maxH - clampedHeight)
2519
+ );
2520
+ return {
2521
+ ...state,
2522
+ windowSize: state.isMaximized ? { width: action.payload.maxW, height: action.payload.maxH } : { width: clampedWidth, height: clampedHeight },
2523
+ position: state.isMaximized ? { x: 0, y: TOP_BAR_HEIGHT } : { x: clampedX, y: clampedY }
2524
+ };
2525
+ }
2522
2526
  default:
2523
2527
  return state;
2524
2528
  }
@@ -2537,12 +2541,40 @@ var WindowWithSideMenu = ({
2537
2541
  removeShortcutListener,
2538
2542
  getShortcutByCommand
2539
2543
  } = useShortcutFormatter_default({ globalKeyboardShortcuts });
2544
+ const getInitialDimensions = React23.useCallback(() => {
2545
+ const rawSize = app.windowSize.windowSize ?? defaultSize;
2546
+ if (typeof window === "undefined") return rawSize;
2547
+ return {
2548
+ width: Math.min(rawSize.width, window.innerWidth),
2549
+ height: Math.min(rawSize.height, window.innerHeight - TOP_BAR_HEIGHT)
2550
+ };
2551
+ }, [app.windowSize.windowSize, defaultSize]);
2552
+ const initialDimensions = getInitialDimensions();
2540
2553
  const [state, dispatch] = React23.useReducer(reducer, {
2541
- ...initialState,
2542
- windowSize: app.windowSize.windowSize ?? defaultSize,
2543
- defaultSize: app.windowSize.windowSize ?? defaultSize
2554
+ position: { x: 0, y: TOP_BAR_HEIGHT },
2555
+ isDragging: false,
2556
+ startPosition: { x: 0, y: TOP_BAR_HEIGHT },
2557
+ isMinimized: false,
2558
+ isMaximized: false,
2559
+ windowSize: initialDimensions,
2560
+ resizeStart: null,
2561
+ defaultSize: initialDimensions,
2562
+ preMaximizeState: null
2544
2563
  });
2545
2564
  const windowRef = React23.useRef(null);
2565
+ React23.useEffect(() => {
2566
+ const handleViewportResize = () => {
2567
+ dispatch({
2568
+ type: "CLAMP_BOUNDS",
2569
+ payload: {
2570
+ maxW: window.innerWidth,
2571
+ maxH: window.innerHeight - TOP_BAR_HEIGHT
2572
+ }
2573
+ });
2574
+ };
2575
+ window.addEventListener("resize", handleViewportResize);
2576
+ return () => window.removeEventListener("resize", handleViewportResize);
2577
+ }, []);
2546
2578
  React23.useEffect(() => {
2547
2579
  if (app.isMinimize !== state.isMinimized) {
2548
2580
  dispatch({ type: "SYNC_MINIMIZE_STATE", payload: app.isMinimize });
@@ -2558,48 +2590,66 @@ var WindowWithSideMenu = ({
2558
2590
  }
2559
2591
  });
2560
2592
  };
2561
- const handleMouseMove = (e) => {
2562
- if (state.isDragging) {
2563
- const newX = e.clientX - state.startPosition.x;
2564
- const newY = e.clientY - state.startPosition.y;
2565
- const boundedX = Math.max(
2566
- 0,
2567
- Math.min(newX, window.innerWidth - state.windowSize.width)
2568
- );
2569
- const boundedY = Math.max(
2570
- 0,
2571
- Math.min(newY, window.innerHeight - state.windowSize.height)
2572
- );
2573
- dispatch({ type: "DRAG", payload: { x: boundedX, y: boundedY } });
2574
- }
2575
- if (state.resizeStart && isResizable && app.windowSize.isAppWindowResizing) {
2576
- let newWidth = state.windowSize.width + (e.clientX - (state.resizeStart?.x ?? 0));
2577
- let newHeight = state.windowSize.height + (e.clientY - (state.resizeStart?.y ?? 0));
2578
- newWidth = Math.max(defaultSize.width, newWidth, state.defaultSize.width);
2579
- newHeight = Math.max(
2580
- defaultSize.height,
2581
- newHeight,
2582
- state.defaultSize.height
2583
- );
2584
- const maxWidth = window.innerWidth - state.position.x;
2585
- const maxHeight = window.innerHeight - state.position.y;
2586
- newWidth = Math.min(newWidth, maxWidth);
2587
- newHeight = Math.min(newHeight, maxHeight);
2588
- dispatch({
2589
- type: "RESIZE",
2590
- payload: {
2591
- width: newWidth,
2592
- height: newHeight
2593
- }
2594
- });
2595
- }
2596
- };
2597
- const handleMouseUp = () => {
2593
+ const handleMouseMove = React23.useCallback(
2594
+ (e) => {
2595
+ if (state.isDragging) {
2596
+ const newX = e.clientX - state.startPosition.x;
2597
+ const newY = e.clientY - state.startPosition.y;
2598
+ const boundedX = Math.max(
2599
+ 0,
2600
+ Math.min(newX, window.innerWidth - state.windowSize.width)
2601
+ );
2602
+ const boundedY = Math.max(
2603
+ TOP_BAR_HEIGHT,
2604
+ Math.min(newY, window.innerHeight - state.windowSize.height)
2605
+ );
2606
+ dispatch({ type: "DRAG", payload: { x: boundedX, y: boundedY } });
2607
+ }
2608
+ if (state.resizeStart && isResizable && app.windowSize.isAppWindowResizing) {
2609
+ const effectiveMinWidth = Math.min(
2610
+ Math.max(defaultSize.width, state.defaultSize.width),
2611
+ window.innerWidth
2612
+ );
2613
+ const effectiveMinHeight = Math.min(
2614
+ Math.max(defaultSize.height, state.defaultSize.height),
2615
+ window.innerHeight - TOP_BAR_HEIGHT
2616
+ );
2617
+ let newWidth = state.windowSize.width + (e.clientX - state.resizeStart.x);
2618
+ let newHeight = state.windowSize.height + (e.clientY - state.resizeStart.y);
2619
+ newWidth = Math.max(effectiveMinWidth, newWidth);
2620
+ newHeight = Math.max(effectiveMinHeight, newHeight);
2621
+ const maxWidth = window.innerWidth - state.position.x;
2622
+ const maxHeight = window.innerHeight - state.position.y;
2623
+ newWidth = Math.min(newWidth, maxWidth);
2624
+ newHeight = Math.min(newHeight, maxHeight);
2625
+ dispatch({
2626
+ type: "RESIZE",
2627
+ payload: {
2628
+ width: newWidth,
2629
+ height: newHeight
2630
+ }
2631
+ });
2632
+ }
2633
+ },
2634
+ [
2635
+ state.isDragging,
2636
+ state.resizeStart,
2637
+ state.startPosition,
2638
+ state.windowSize,
2639
+ state.position,
2640
+ state.defaultSize,
2641
+ defaultSize.width,
2642
+ defaultSize.height,
2643
+ isResizable,
2644
+ app.windowSize.isAppWindowResizing
2645
+ ]
2646
+ );
2647
+ const handleMouseUp = React23.useCallback(() => {
2598
2648
  if (state.isDragging) dispatch({ type: "STOP_DRAG" });
2599
2649
  if (state.resizeStart) dispatch({ type: "STOP_RESIZE" });
2600
- };
2650
+ }, [state.isDragging, state.resizeStart]);
2601
2651
  const handleResizeStart = (e) => {
2602
- if (!isResizable && !app.windowSize.isAppWindowResizing) return;
2652
+ if (!isResizable || !app.windowSize.isAppWindowResizing) return;
2603
2653
  e.stopPropagation();
2604
2654
  document.body.style.userSelect = "none";
2605
2655
  dispatch({ type: "START_RESIZE", payload: { x: e.clientX, y: e.clientY } });
@@ -2614,27 +2664,34 @@ var WindowWithSideMenu = ({
2614
2664
  window.removeEventListener("mouseup", handleMouseUp);
2615
2665
  document.body.style.userSelect = "";
2616
2666
  };
2617
- }, [state.isDragging, state.resizeStart]);
2667
+ }, [state.isDragging, state.resizeStart, handleMouseMove, handleMouseUp]);
2618
2668
  React23.useEffect(() => {
2619
- if (windowRef.current) {
2620
- windowRef.current.addEventListener("click", () => {
2621
- if (app?.callback) {
2622
- app?.callback("CLICKED");
2623
- }
2624
- });
2669
+ const currentRef = windowRef.current;
2670
+ const handleActive = () => {
2671
+ if (app?.callback) {
2672
+ app.callback("CLICKED");
2673
+ }
2674
+ };
2675
+ if (currentRef) {
2676
+ currentRef.addEventListener("click", handleActive);
2625
2677
  }
2626
- }, [app?.slug, windowRef]);
2678
+ return () => {
2679
+ if (currentRef) {
2680
+ currentRef.removeEventListener("click", handleActive);
2681
+ }
2682
+ };
2683
+ }, [app?.slug, app]);
2627
2684
  React23.useEffect(() => {
2628
2685
  const handleExitApp = () => {
2629
2686
  if (app?.callback) {
2630
- app?.callback("CLOSE_APP");
2687
+ app.callback("CLOSE_APP");
2631
2688
  }
2632
2689
  };
2633
2690
  addShortcutListener("exit_app", handleExitApp);
2634
2691
  return () => {
2635
2692
  removeShortcutListener("exit_app", handleExitApp);
2636
2693
  };
2637
- }, [app?.slug, app.isActive]);
2694
+ }, [app?.slug, app.isActive, app, addShortcutListener, removeShortcutListener]);
2638
2695
  React23.useEffect(() => {
2639
2696
  const handleMinimize = () => {
2640
2697
  if (app?.slug && app.isActive) {
@@ -2643,7 +2700,7 @@ var WindowWithSideMenu = ({
2643
2700
  payload: state.windowSize
2644
2701
  });
2645
2702
  if (app?.callback) {
2646
- app?.callback("MINIMIZE_APP");
2703
+ app.callback("MINIMIZE_APP");
2647
2704
  }
2648
2705
  }
2649
2706
  };
@@ -2651,7 +2708,7 @@ var WindowWithSideMenu = ({
2651
2708
  return () => {
2652
2709
  removeShortcutListener("minimize_app", handleMinimize);
2653
2710
  };
2654
- }, [app?.slug, app.isActive, state.isMinimized, state.windowSize]);
2711
+ }, [app?.slug, app.isActive, state.isMinimized, state.windowSize, app, addShortcutListener, removeShortcutListener]);
2655
2712
  React23.useEffect(() => {
2656
2713
  const handleMaximize = () => {
2657
2714
  if (app?.slug && app.isActive) {
@@ -2659,7 +2716,7 @@ var WindowWithSideMenu = ({
2659
2716
  type: "TOGGLE_MAXIMIZE",
2660
2717
  payload: {
2661
2718
  width: window.innerWidth,
2662
- height: window.innerHeight - 37
2719
+ height: window.innerHeight - TOP_BAR_HEIGHT
2663
2720
  }
2664
2721
  });
2665
2722
  }
@@ -2668,7 +2725,7 @@ var WindowWithSideMenu = ({
2668
2725
  return () => {
2669
2726
  removeShortcutListener("maximize_app", handleMaximize);
2670
2727
  };
2671
- }, [app?.slug, app.isActive]);
2728
+ }, [app?.slug, app.isActive, addShortcutListener, removeShortcutListener]);
2672
2729
  if (state.isMinimized) {
2673
2730
  return null;
2674
2731
  }
@@ -2676,33 +2733,31 @@ var WindowWithSideMenu = ({
2676
2733
  "div",
2677
2734
  {
2678
2735
  ref: windowRef,
2679
- className: "flex rounded-[10px] overflow-hidden window-drop-shadow ",
2736
+ className: "flex rounded-[10px] overflow-hidden window-drop-shadow",
2680
2737
  style: {
2681
- width: `${state.windowSize.width}px`,
2682
- height: `${state.windowSize.height}px`,
2683
- transform: state.isMaximized ? void 0 : `translate(${state.position.x}px, ${state.position.y - 37}px)`,
2684
- overflow: state.isMinimized ? "hidden" : "auto",
2738
+ width: state.isMaximized ? "100vw" : `${state.windowSize.width}px`,
2739
+ height: state.isMaximized ? `calc(100vh - ${TOP_BAR_HEIGHT}px)` : `${state.windowSize.height}px`,
2740
+ transform: state.isMaximized ? void 0 : `translate(${state.position.x}px, ${state.position.y - TOP_BAR_HEIGHT}px)`,
2685
2741
  position: "absolute",
2686
- minWidth: `${state.defaultSize.width}px`,
2687
- minHeight: `${state.defaultSize.height}px`,
2742
+ minWidth: state.isMaximized ? "100vw" : `min(${state.defaultSize.width}px, 100vw)`,
2743
+ minHeight: state.isMaximized ? `calc(100vh - ${TOP_BAR_HEIGHT}px)` : `min(${state.defaultSize.height}px, 100vh)`,
2688
2744
  zIndex: state.isDragging ? 3 : app?.isActive ? 2 : 1
2689
2745
  },
2690
2746
  children: [
2691
2747
  /* @__PURE__ */ jsxRuntime.jsxs(
2692
2748
  "div",
2693
2749
  {
2694
- className: "bg-primary flex flex-col",
2750
+ className: "bg-primary flex flex-col shrink-0 overflow-y-auto",
2695
2751
  style: {
2696
2752
  width: `${SIDEBAR_WIDTH}px`,
2697
2753
  minWidth: `${SIDEBAR_WIDTH}px`,
2698
- maxWidth: `${SIDEBAR_WIDTH}px`,
2699
- flexShrink: 0
2754
+ maxWidth: `${SIDEBAR_WIDTH}px`
2700
2755
  },
2701
2756
  children: [
2702
2757
  /* @__PURE__ */ jsxRuntime.jsxs(
2703
2758
  "div",
2704
2759
  {
2705
- className: "flex items-center gap-[8px] pl-[20px] pt-[20px]",
2760
+ className: "flex items-center gap-[8px] pl-[20px] pt-[20px] select-none",
2706
2761
  onMouseDown: handleMouseDown,
2707
2762
  style: { cursor: state.isMaximized ? "default" : "move" },
2708
2763
  children: [
@@ -2712,7 +2767,7 @@ var WindowWithSideMenu = ({
2712
2767
  className: "w-[12px] h-[12px] bg-[#FF6157] rounded-full",
2713
2768
  onClick: () => {
2714
2769
  if (app?.callback) {
2715
- app?.callback("CLOSE_APP");
2770
+ app.callback("CLOSE_APP");
2716
2771
  }
2717
2772
  },
2718
2773
  title: `Close ${formatKeys(getShortcutByCommand("exit_app"))}`,
@@ -2730,7 +2785,7 @@ var WindowWithSideMenu = ({
2730
2785
  payload: state.windowSize
2731
2786
  });
2732
2787
  if (app?.callback) {
2733
- app?.callback("MINIMIZE_APP");
2788
+ app.callback("MINIMIZE_APP");
2734
2789
  }
2735
2790
  },
2736
2791
  title: state.isMinimized ? "Restore" : `Minimize ${formatKeys(getShortcutByCommand("minimize_app"))}`,
@@ -2747,7 +2802,7 @@ var WindowWithSideMenu = ({
2747
2802
  type: "TOGGLE_MAXIMIZE",
2748
2803
  payload: {
2749
2804
  width: window.innerWidth,
2750
- height: window.innerHeight - 37
2805
+ height: window.innerHeight - TOP_BAR_HEIGHT
2751
2806
  }
2752
2807
  });
2753
2808
  },
@@ -2774,14 +2829,14 @@ var WindowWithSideMenu = ({
2774
2829
  ]
2775
2830
  }
2776
2831
  ) }),
2777
- menu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-[15px] flex flex-col text-[13px]", children: menu?.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2832
+ menu && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-[15px] flex flex-col text-[13px]", children: menu.items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(
2778
2833
  "button",
2779
2834
  {
2780
- className: `${item.isActive ? "bg-brand-color text-white" : "text-neutral-500"} px-[10px] mx-2 flex items-center gap-[8px] rounded-[6px] h-[30px] text-neutral-400 cursor-pointer transition-all duration-200`,
2835
+ className: `${item.isActive ? "bg-brand-color text-white" : "text-neutral-500"} px-[10px] mx-2 flex items-center gap-[8px] rounded-[6px] h-[30px] cursor-pointer transition-all duration-200`,
2781
2836
  onClick: item.onClick,
2782
2837
  children: [
2783
2838
  item.icon,
2784
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "", children: item.title })
2839
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: item.title })
2785
2840
  ]
2786
2841
  },
2787
2842
  index
@@ -2792,50 +2847,36 @@ var WindowWithSideMenu = ({
2792
2847
  /* @__PURE__ */ jsxRuntime.jsxs(
2793
2848
  "div",
2794
2849
  {
2795
- className: "flex-1 bg-secondary flex flex-col",
2850
+ className: "flex-1 bg-secondary flex flex-col min-w-0 h-full overflow-hidden",
2796
2851
  style: {
2797
- minWidth: 0,
2798
2852
  width: `calc(100% - ${SIDEBAR_WIDTH}px)`
2799
2853
  },
2800
2854
  children: [
2801
2855
  /* @__PURE__ */ jsxRuntime.jsxs(
2802
2856
  "div",
2803
2857
  {
2804
- className: "h-min-[50px] py-2 flex flex-col border-b border-b-surface-1 border-b-[0.5px] justify-center text-[13px] mx-[12px] select-none",
2858
+ className: "h-[50px] py-2 flex flex-col border-b border-b-surface-1 border-b-[0.5px] justify-center text-[13px] px-[12px] select-none shrink-0",
2805
2859
  onMouseDown: handleMouseDown,
2806
2860
  style: {
2807
- userSelect: "none",
2808
- WebkitUserSelect: "none",
2809
- MozUserSelect: "none",
2810
- msUserSelect: "none",
2811
2861
  cursor: state.isMaximized ? "default" : "move"
2812
2862
  },
2813
2863
  children: [
2814
- /* @__PURE__ */ jsxRuntime.jsx(Typography_default, { variant: "p", className: "font-medium text-neutral-500 ", children: app?.name }),
2815
- /* @__PURE__ */ jsxRuntime.jsx(Typography_default, { variant: "p", className: "text-neutral-400 text-[11px]", children: menu?.items.find((item) => item.isActive)?.title })
2864
+ /* @__PURE__ */ jsxRuntime.jsx(Typography_default, { variant: "p", className: "font-medium text-neutral-500 truncate", children: app?.name }),
2865
+ /* @__PURE__ */ jsxRuntime.jsx(Typography_default, { variant: "p", className: "text-neutral-400 text-[11px] truncate", children: menu?.items.find((item) => item.isActive)?.title })
2816
2866
  ]
2817
2867
  }
2818
2868
  ),
2819
- !state.isMinimized && /* @__PURE__ */ jsxRuntime.jsx(
2820
- "div",
2821
- {
2822
- className: "h-full w-full overflow-y-auto",
2823
- style: {
2824
- maxHeight: `${state.windowSize.height - 37}px`
2825
- },
2826
- children: React23.isValidElement(children) && typeof children.type !== "string" ? React23__namespace.default.cloneElement(children, {
2827
- windowSize: state.windowSize,
2828
- isAppWindowResizing: state.resizeStart !== null
2829
- }) : children
2830
- }
2831
- )
2869
+ !state.isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full overflow-y-auto min-h-0", children: React23.isValidElement(children) && typeof children.type !== "string" ? React23__namespace.default.cloneElement(children, {
2870
+ windowSize: state.windowSize,
2871
+ isAppWindowResizing: state.resizeStart !== null
2872
+ }) : children })
2832
2873
  ]
2833
2874
  }
2834
2875
  ),
2835
2876
  isResizable && !state.isMaximized && /* @__PURE__ */ jsxRuntime.jsx(
2836
2877
  "div",
2837
2878
  {
2838
- className: "absolute bottom-0 right-0 w-5 h-5 cursor-se-resize",
2879
+ className: "absolute bottom-0 right-0 w-5 h-5 cursor-se-resize z-10",
2839
2880
  style: {
2840
2881
  borderBottomRightRadius: "10px"
2841
2882
  },
@@ -2847,17 +2888,7 @@ var WindowWithSideMenu = ({
2847
2888
  );
2848
2889
  };
2849
2890
  var WindowWithSideMenu_default = WindowWithSideMenu;
2850
- var initialState2 = {
2851
- position: { x: 0, y: 40 },
2852
- isDragging: false,
2853
- startPosition: { x: 0, y: 40 },
2854
- isMinimized: false,
2855
- isMaximized: false,
2856
- windowSize: { width: 300, height: 300 },
2857
- resizeStart: null,
2858
- defaultSize: { width: 300, height: 300 },
2859
- preMaximizeState: null
2860
- };
2891
+ var TOP_BAR_HEIGHT2 = 37;
2861
2892
  var reducer2 = (state, action) => {
2862
2893
  switch (action.type) {
2863
2894
  case "START_DRAG":
@@ -2867,10 +2898,7 @@ var reducer2 = (state, action) => {
2867
2898
  case "STOP_DRAG":
2868
2899
  return { ...state, isDragging: false };
2869
2900
  case "START_RESIZE":
2870
- return {
2871
- ...state,
2872
- resizeStart: action.payload
2873
- };
2901
+ return { ...state, resizeStart: action.payload };
2874
2902
  case "RESIZE":
2875
2903
  return { ...state, windowSize: action.payload };
2876
2904
  case "STOP_RESIZE":
@@ -2896,7 +2924,10 @@ var reducer2 = (state, action) => {
2896
2924
  ...state,
2897
2925
  isMaximized: false,
2898
2926
  windowSize: state.preMaximizeState?.windowSize || state.defaultSize,
2899
- position: state.preMaximizeState?.position || { x: 0, y: 40 },
2927
+ position: state.preMaximizeState?.position || {
2928
+ x: 0,
2929
+ y: TOP_BAR_HEIGHT2
2930
+ },
2900
2931
  preMaximizeState: null
2901
2932
  };
2902
2933
  }
@@ -2908,11 +2939,34 @@ var reducer2 = (state, action) => {
2908
2939
  windowSize: state.windowSize
2909
2940
  },
2910
2941
  windowSize: action.payload || {
2911
- width: window.innerWidth,
2912
- height: window.innerHeight
2942
+ width: typeof window !== "undefined" ? window.innerWidth : 300,
2943
+ height: typeof window !== "undefined" ? window.innerHeight - TOP_BAR_HEIGHT2 : 300
2913
2944
  },
2914
- position: state.position
2945
+ position: { x: 0, y: TOP_BAR_HEIGHT2 }
2915
2946
  };
2947
+ case "CLAMP_BOUNDS": {
2948
+ const clampedWidth = Math.min(
2949
+ state.windowSize.width,
2950
+ action.payload.maxW
2951
+ );
2952
+ const clampedHeight = Math.min(
2953
+ state.windowSize.height,
2954
+ action.payload.maxH
2955
+ );
2956
+ const clampedX = Math.max(
2957
+ 0,
2958
+ Math.min(state.position.x, action.payload.maxW - clampedWidth)
2959
+ );
2960
+ const clampedY = Math.max(
2961
+ TOP_BAR_HEIGHT2,
2962
+ Math.min(state.position.y, action.payload.maxH - clampedHeight)
2963
+ );
2964
+ return {
2965
+ ...state,
2966
+ windowSize: state.isMaximized ? { width: action.payload.maxW, height: action.payload.maxH } : { width: clampedWidth, height: clampedHeight },
2967
+ position: state.isMaximized ? { x: 0, y: TOP_BAR_HEIGHT2 } : { x: clampedX, y: clampedY }
2968
+ };
2969
+ }
2916
2970
  default:
2917
2971
  return state;
2918
2972
  }
@@ -2929,12 +2983,40 @@ var WindowWithoutSideMenu = ({
2929
2983
  removeShortcutListener,
2930
2984
  getShortcutByCommand
2931
2985
  } = useShortcutFormatter_default({ globalKeyboardShortcuts });
2986
+ const getInitialDimensions = React23.useCallback(() => {
2987
+ const rawSize = app.windowSize.windowSize ?? defaultSize;
2988
+ if (typeof window === "undefined") return rawSize;
2989
+ return {
2990
+ width: Math.min(rawSize.width, window.innerWidth),
2991
+ height: Math.min(rawSize.height, window.innerHeight - TOP_BAR_HEIGHT2)
2992
+ };
2993
+ }, [app.windowSize.windowSize, defaultSize]);
2994
+ const initialDimensions = getInitialDimensions();
2932
2995
  const [state, dispatch] = React23.useReducer(reducer2, {
2933
- ...initialState2,
2934
- windowSize: app.windowSize.windowSize ?? defaultSize,
2935
- defaultSize: app.windowSize.windowSize ?? defaultSize
2996
+ position: { x: 0, y: TOP_BAR_HEIGHT2 },
2997
+ isDragging: false,
2998
+ startPosition: { x: 0, y: TOP_BAR_HEIGHT2 },
2999
+ isMinimized: false,
3000
+ isMaximized: false,
3001
+ windowSize: initialDimensions,
3002
+ resizeStart: null,
3003
+ defaultSize: initialDimensions,
3004
+ preMaximizeState: null
2936
3005
  });
2937
3006
  const windowRef = React23.useRef(null);
3007
+ React23.useEffect(() => {
3008
+ const handleViewportResize = () => {
3009
+ dispatch({
3010
+ type: "CLAMP_BOUNDS",
3011
+ payload: {
3012
+ maxW: window.innerWidth,
3013
+ maxH: window.innerHeight - TOP_BAR_HEIGHT2
3014
+ }
3015
+ });
3016
+ };
3017
+ window.addEventListener("resize", handleViewportResize);
3018
+ return () => window.removeEventListener("resize", handleViewportResize);
3019
+ }, []);
2938
3020
  React23.useEffect(() => {
2939
3021
  if (app.isMinimize !== state.isMinimized) {
2940
3022
  dispatch({ type: "SYNC_MINIMIZE_STATE", payload: app.isMinimize });
@@ -2950,44 +3032,64 @@ var WindowWithoutSideMenu = ({
2950
3032
  }
2951
3033
  });
2952
3034
  };
2953
- const handleMouseMove = (e) => {
2954
- if (state.isDragging) {
2955
- const newX = e.clientX - state.startPosition.x;
2956
- const newY = e.clientY - state.startPosition.y;
2957
- const boundedX = Math.max(
2958
- 0,
2959
- Math.min(newX, window.innerWidth - state.windowSize.width)
2960
- );
2961
- const boundedY = Math.max(
2962
- 0,
2963
- Math.min(newY, window.innerHeight - state.windowSize.height)
2964
- );
2965
- dispatch({ type: "DRAG", payload: { x: boundedX, y: boundedY } });
2966
- }
2967
- if (state.resizeStart && isResizable && app.windowSize.isAppWindowResizing) {
2968
- let newWidth = state.windowSize.width + (e.clientX - (state.resizeStart?.x ?? 0));
2969
- let newHeight = state.windowSize.height + (e.clientY - (state.resizeStart?.y ?? 0));
2970
- newWidth = Math.max(state.defaultSize.width, newWidth);
2971
- newHeight = Math.max(state.defaultSize.height, newHeight);
2972
- const maxWidth = window.innerWidth - state.position.x;
2973
- const maxHeight = window.innerHeight - state.position.y;
2974
- newWidth = Math.min(newWidth, maxWidth);
2975
- newHeight = Math.min(newHeight, maxHeight);
2976
- dispatch({
2977
- type: "RESIZE",
2978
- payload: {
2979
- width: newWidth,
2980
- height: newHeight
2981
- }
2982
- });
2983
- }
2984
- };
2985
- const handleMouseUp = () => {
3035
+ const handleMouseMove = React23.useCallback(
3036
+ (e) => {
3037
+ if (state.isDragging) {
3038
+ const newX = e.clientX - state.startPosition.x;
3039
+ const newY = e.clientY - state.startPosition.y;
3040
+ const boundedX = Math.max(
3041
+ 0,
3042
+ Math.min(newX, window.innerWidth - state.windowSize.width)
3043
+ );
3044
+ const boundedY = Math.max(
3045
+ TOP_BAR_HEIGHT2,
3046
+ Math.min(newY, window.innerHeight - state.windowSize.height)
3047
+ );
3048
+ dispatch({ type: "DRAG", payload: { x: boundedX, y: boundedY } });
3049
+ }
3050
+ if (state.resizeStart && isResizable && app.windowSize.isAppWindowResizing) {
3051
+ const effectiveMinWidth = Math.min(
3052
+ state.defaultSize.width,
3053
+ window.innerWidth
3054
+ );
3055
+ const effectiveMinHeight = Math.min(
3056
+ state.defaultSize.height,
3057
+ window.innerHeight - TOP_BAR_HEIGHT2
3058
+ );
3059
+ let newWidth = state.windowSize.width + (e.clientX - state.resizeStart.x);
3060
+ let newHeight = state.windowSize.height + (e.clientY - state.resizeStart.y);
3061
+ newWidth = Math.max(effectiveMinWidth, newWidth);
3062
+ newHeight = Math.max(effectiveMinHeight, newHeight);
3063
+ const maxWidth = window.innerWidth - state.position.x;
3064
+ const maxHeight = window.innerHeight - state.position.y;
3065
+ newWidth = Math.min(newWidth, maxWidth);
3066
+ newHeight = Math.min(newHeight, maxHeight);
3067
+ dispatch({
3068
+ type: "RESIZE",
3069
+ payload: {
3070
+ width: newWidth,
3071
+ height: newHeight
3072
+ }
3073
+ });
3074
+ }
3075
+ },
3076
+ [
3077
+ state.isDragging,
3078
+ state.resizeStart,
3079
+ state.startPosition,
3080
+ state.windowSize,
3081
+ state.position,
3082
+ state.defaultSize,
3083
+ isResizable,
3084
+ app.windowSize.isAppWindowResizing
3085
+ ]
3086
+ );
3087
+ const handleMouseUp = React23.useCallback(() => {
2986
3088
  if (state.isDragging) dispatch({ type: "STOP_DRAG" });
2987
3089
  if (state.resizeStart) dispatch({ type: "STOP_RESIZE" });
2988
- };
3090
+ }, [state.isDragging, state.resizeStart]);
2989
3091
  const handleResizeStart = (e) => {
2990
- if (!isResizable && !app.windowSize.isAppWindowResizing) return;
3092
+ if (!isResizable || !app.windowSize.isAppWindowResizing) return;
2991
3093
  e.stopPropagation();
2992
3094
  document.body.style.userSelect = "none";
2993
3095
  dispatch({ type: "START_RESIZE", payload: { x: e.clientX, y: e.clientY } });
@@ -3002,27 +3104,40 @@ var WindowWithoutSideMenu = ({
3002
3104
  window.removeEventListener("mouseup", handleMouseUp);
3003
3105
  document.body.style.userSelect = "";
3004
3106
  };
3005
- }, [state.isDragging, state.resizeStart]);
3107
+ }, [state.isDragging, state.resizeStart, handleMouseMove, handleMouseUp]);
3006
3108
  React23.useEffect(() => {
3007
- if (windowRef.current) {
3008
- windowRef.current.addEventListener("click", () => {
3009
- if (app?.callback) {
3010
- app?.callback("CLICKED");
3011
- }
3012
- });
3109
+ const currentRef = windowRef.current;
3110
+ const handleActive = () => {
3111
+ if (app?.callback) {
3112
+ app.callback("CLICKED");
3113
+ }
3114
+ };
3115
+ if (currentRef) {
3116
+ currentRef.addEventListener("click", handleActive);
3013
3117
  }
3014
- }, [app?.slug, windowRef]);
3118
+ return () => {
3119
+ if (currentRef) {
3120
+ currentRef.removeEventListener("click", handleActive);
3121
+ }
3122
+ };
3123
+ }, [app?.slug, app]);
3015
3124
  React23.useEffect(() => {
3016
3125
  const handleExitApp = () => {
3017
3126
  if (app?.callback) {
3018
- app?.callback("CLOSE_APP");
3127
+ app.callback("CLOSE_APP");
3019
3128
  }
3020
3129
  };
3021
3130
  addShortcutListener("exit_app", handleExitApp);
3022
3131
  return () => {
3023
3132
  removeShortcutListener("exit_app", handleExitApp);
3024
3133
  };
3025
- }, [app?.slug, app.isActive]);
3134
+ }, [
3135
+ app?.slug,
3136
+ app.isActive,
3137
+ app,
3138
+ addShortcutListener,
3139
+ removeShortcutListener
3140
+ ]);
3026
3141
  React23.useEffect(() => {
3027
3142
  const handleMinimize = () => {
3028
3143
  if (app?.slug && app.isActive) {
@@ -3031,7 +3146,7 @@ var WindowWithoutSideMenu = ({
3031
3146
  payload: state.windowSize
3032
3147
  });
3033
3148
  if (app?.callback) {
3034
- app?.callback("MINIMIZE_APP");
3149
+ app.callback("MINIMIZE_APP");
3035
3150
  }
3036
3151
  }
3037
3152
  };
@@ -3039,7 +3154,15 @@ var WindowWithoutSideMenu = ({
3039
3154
  return () => {
3040
3155
  removeShortcutListener("minimize_app", handleMinimize);
3041
3156
  };
3042
- }, [app?.slug, app.isActive, state.isMinimized, state.windowSize]);
3157
+ }, [
3158
+ app?.slug,
3159
+ app.isActive,
3160
+ state.isMinimized,
3161
+ state.windowSize,
3162
+ app,
3163
+ addShortcutListener,
3164
+ removeShortcutListener
3165
+ ]);
3043
3166
  React23.useEffect(() => {
3044
3167
  const handleMaximize = () => {
3045
3168
  if (app?.slug && app.isActive) {
@@ -3047,7 +3170,7 @@ var WindowWithoutSideMenu = ({
3047
3170
  type: "TOGGLE_MAXIMIZE",
3048
3171
  payload: {
3049
3172
  width: window.innerWidth,
3050
- height: window.innerHeight - 37
3173
+ height: window.innerHeight - TOP_BAR_HEIGHT2
3051
3174
  }
3052
3175
  });
3053
3176
  }
@@ -3056,7 +3179,7 @@ var WindowWithoutSideMenu = ({
3056
3179
  return () => {
3057
3180
  removeShortcutListener("maximize_app", handleMaximize);
3058
3181
  };
3059
- }, [app?.slug, app.isActive]);
3182
+ }, [app?.slug, app.isActive, addShortcutListener, removeShortcutListener]);
3060
3183
  if (state.isMinimized) {
3061
3184
  return null;
3062
3185
  }
@@ -3064,117 +3187,106 @@ var WindowWithoutSideMenu = ({
3064
3187
  "div",
3065
3188
  {
3066
3189
  ref: windowRef,
3067
- className: "window-drop-shadow rounded-[10px]",
3190
+ className: "window-drop-shadow rounded-[10px] flex flex-col overflow-hidden",
3068
3191
  style: {
3069
- width: `${state.windowSize.width}px`,
3070
- height: `${state.windowSize.height}px`,
3071
- transform: state.isMaximized ? void 0 : `translate(${state.position.x}px, ${state.position.y - 37}px)`,
3072
- overflow: state.isMinimized ? "hidden" : "auto",
3192
+ width: state.isMaximized ? "100vw" : `${state.windowSize.width}px`,
3193
+ height: state.isMaximized ? `calc(100vh - ${TOP_BAR_HEIGHT2}px)` : `${state.windowSize.height}px`,
3194
+ transform: state.isMaximized ? void 0 : `translate(${state.position.x}px, ${state.position.y - TOP_BAR_HEIGHT2}px)`,
3073
3195
  position: "absolute",
3074
- minWidth: `${state.defaultSize.width}px`,
3075
- minHeight: `${state.defaultSize.height}px`,
3196
+ minWidth: state.isMaximized ? "100vw" : `min(${state.defaultSize.width}px, 100vw)`,
3197
+ minHeight: state.isMaximized ? `calc(100vh - ${TOP_BAR_HEIGHT2}px)` : `min(${state.defaultSize.height}px, 100vh)`,
3076
3198
  zIndex: state.isDragging ? 3 : app?.isActive ? 2 : 1
3077
3199
  },
3078
- children: /* @__PURE__ */ jsxRuntime.jsxs(
3079
- "div",
3080
- {
3081
- className: "mx-auto overflow-hidden h-full w-full",
3082
- style: {
3083
- minWidth: `${state.defaultSize.width}px`,
3084
- minHeight: `${state.defaultSize.height}px`,
3085
- position: "relative"
3086
- },
3087
- children: [
3088
- /* @__PURE__ */ jsxRuntime.jsxs(
3089
- "div",
3090
- {
3091
- className: "relative flex items-center bg-primary h-[35px] select-none",
3092
- onMouseDown: handleMouseDown,
3093
- style: { cursor: state.isMaximized ? "default" : "move" },
3094
- children: [
3095
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[8px] pl-[10px]", children: [
3096
- /* @__PURE__ */ jsxRuntime.jsx(
3097
- "button",
3098
- {
3099
- className: "w-[12px] h-[12px] bg-[#FF6157] rounded-full",
3100
- onClick: () => {
3101
- if (app?.callback) {
3102
- app?.callback("CLOSE_APP");
3103
- }
3104
- },
3105
- title: `Close ${formatKeys(getShortcutByCommand("exit_app"))}`,
3106
- style: { outline: "none", border: "none" }
3107
- }
3108
- ),
3109
- /* @__PURE__ */ jsxRuntime.jsx(
3110
- "button",
3111
- {
3112
- className: "w-[12px] h-[12px] bg-[#FFC12F] rounded-full",
3113
- onClick: () => {
3114
- dispatch({
3115
- type: "TOGGLE_MINIMIZE",
3116
- payload: state.windowSize
3117
- });
3118
- if (app?.callback) {
3119
- app?.callback("MINIMIZE_APP");
3120
- }
3121
- },
3122
- title: state.isMinimized ? "Restore" : `Minimize ${formatKeys(
3123
- getShortcutByCommand("minimize_app")
3124
- )}`,
3125
- style: { outline: "none", border: "none" }
3200
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-full w-full relative min-w-0", children: [
3201
+ /* @__PURE__ */ jsxRuntime.jsxs(
3202
+ "div",
3203
+ {
3204
+ className: "relative flex items-center bg-primary h-[35px] select-none shrink-0",
3205
+ onMouseDown: handleMouseDown,
3206
+ style: { cursor: state.isMaximized ? "default" : "move" },
3207
+ children: [
3208
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[8px] pl-[10px]", children: [
3209
+ /* @__PURE__ */ jsxRuntime.jsx(
3210
+ "button",
3211
+ {
3212
+ className: "w-[12px] h-[12px] bg-[#FF6157] rounded-full",
3213
+ onClick: () => {
3214
+ if (app?.callback) {
3215
+ app.callback("CLOSE_APP");
3126
3216
  }
3127
- ),
3128
- isResizable && app.windowSize.isAppWindowResizing && /* @__PURE__ */ jsxRuntime.jsx(
3129
- "button",
3130
- {
3131
- className: "w-[12px] h-[12px] bg-[#2ACB42] rounded-full",
3132
- onClick: () => {
3133
- dispatch({
3134
- type: "TOGGLE_MAXIMIZE",
3135
- payload: {
3136
- width: window.innerWidth,
3137
- height: window.innerHeight - 37
3138
- }
3139
- });
3140
- },
3141
- title: state.isMaximized ? "Restore" : `Maximize ${formatKeys(
3142
- getShortcutByCommand("maximize_app")
3143
- )}`,
3144
- style: { outline: "none", border: "none" }
3217
+ },
3218
+ title: `Close ${formatKeys(getShortcutByCommand("exit_app"))}`,
3219
+ style: { outline: "none", border: "none" },
3220
+ tabIndex: -1
3221
+ }
3222
+ ),
3223
+ /* @__PURE__ */ jsxRuntime.jsx(
3224
+ "button",
3225
+ {
3226
+ className: "w-[12px] h-[12px] bg-[#FFC12F] rounded-full",
3227
+ onClick: () => {
3228
+ dispatch({
3229
+ type: "TOGGLE_MINIMIZE",
3230
+ payload: state.windowSize
3231
+ });
3232
+ if (app?.callback) {
3233
+ app.callback("MINIMIZE_APP");
3145
3234
  }
3146
- )
3147
- ] }),
3148
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2", children: /* @__PURE__ */ jsxRuntime.jsx(Typography_default, { variant: "p", className: "text-neutral-500 text-[15px]", children: app.name }) })
3149
- ]
3150
- }
3151
- ),
3152
- !state.isMinimized && /* @__PURE__ */ jsxRuntime.jsx(
3153
- "div",
3154
- {
3155
- className: "h-full w-full bg-secondary",
3156
- style: {
3157
- maxHeight: `${state.windowSize.height - 37}px`
3158
- },
3159
- children: React23.isValidElement(children) && typeof children.type !== "string" ? React23__namespace.default.cloneElement(children, {
3160
- windowSize: state.windowSize,
3161
- isAppWindowResizing: state.resizeStart !== null
3162
- }) : children
3163
- }
3164
- ),
3165
- isResizable && !state.isMaximized && /* @__PURE__ */ jsxRuntime.jsx(
3166
- "div",
3167
- {
3168
- className: "absolute bottom-0 right-0 w-5 h-5 cursor-se-resize",
3169
- style: {
3170
- borderBottomRightRadius: "10px"
3171
- },
3172
- onMouseDown: handleResizeStart
3173
- }
3174
- )
3175
- ]
3176
- }
3177
- )
3235
+ },
3236
+ title: state.isMinimized ? "Restore" : `Minimize ${formatKeys(
3237
+ getShortcutByCommand("minimize_app")
3238
+ )}`,
3239
+ style: { outline: "none", border: "none" },
3240
+ tabIndex: -1
3241
+ }
3242
+ ),
3243
+ isResizable && app.windowSize.isAppWindowResizing && /* @__PURE__ */ jsxRuntime.jsx(
3244
+ "button",
3245
+ {
3246
+ className: "w-[12px] h-[12px] bg-[#2ACB42] rounded-full",
3247
+ onClick: () => {
3248
+ dispatch({
3249
+ type: "TOGGLE_MAXIMIZE",
3250
+ payload: {
3251
+ width: window.innerWidth,
3252
+ height: window.innerHeight - TOP_BAR_HEIGHT2
3253
+ }
3254
+ });
3255
+ },
3256
+ title: state.isMaximized ? "Restore" : `Maximize ${formatKeys(
3257
+ getShortcutByCommand("maximize_app")
3258
+ )}`,
3259
+ style: { outline: "none", border: "none" },
3260
+ tabIndex: -1
3261
+ }
3262
+ )
3263
+ ] }),
3264
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 max-w-[60%] truncate", children: /* @__PURE__ */ jsxRuntime.jsx(
3265
+ Typography_default,
3266
+ {
3267
+ variant: "p",
3268
+ className: "text-neutral-500 text-[15px] truncate",
3269
+ children: app.name
3270
+ }
3271
+ ) })
3272
+ ]
3273
+ }
3274
+ ),
3275
+ !state.isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 w-full bg-secondary overflow-y-auto min-h-0", children: React23.isValidElement(children) && typeof children.type !== "string" ? React23__namespace.default.cloneElement(children, {
3276
+ windowSize: state.windowSize,
3277
+ isAppWindowResizing: state.resizeStart !== null
3278
+ }) : children }),
3279
+ isResizable && !state.isMaximized && /* @__PURE__ */ jsxRuntime.jsx(
3280
+ "div",
3281
+ {
3282
+ className: "absolute bottom-0 right-0 w-5 h-5 cursor-se-resize z-10",
3283
+ style: {
3284
+ borderBottomRightRadius: "10px"
3285
+ },
3286
+ onMouseDown: handleResizeStart
3287
+ }
3288
+ )
3289
+ ] })
3178
3290
  }
3179
3291
  );
3180
3292
  };