@liiift-studio/mac-os9-ui 0.2.24 → 0.2.26

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
@@ -818,14 +818,24 @@ var styles$6 = {"window":"Window-module_window","window--active":"Window-module_
818
818
  * </Window>
819
819
  * ```
820
820
  */
821
- const Window = React.forwardRef(({ children, title, titleBar, active = true, width = 'auto', height = 'auto', className = '', contentClassName = '', classes, showControls = true, onClose, onMinimize, onMaximize, onMouseEnter, resizable = false, draggable = false, defaultPosition, position: controlledPosition, onPositionChange, }, ref) => {
821
+ const Window = React.forwardRef(({ children, title, titleBar, active = true, width = 'auto', height = 'auto', className = '', contentClassName = '', classes, showControls = true, onClose, onMinimize, onMaximize, onMouseEnter, resizable = false, minWidth = 200, minHeight = 100, maxWidth, maxHeight, onResize, draggable = false, defaultPosition, position: controlledPosition, onPositionChange, }, ref) => {
822
822
  // Drag state management
823
823
  const [internalPosition, setInternalPosition] = React.useState(defaultPosition || null);
824
824
  const [isDragging, setIsDragging] = React.useState(false);
825
825
  const [hasBeenDragged, setHasBeenDragged] = React.useState(!!(defaultPosition || controlledPosition));
826
826
  const dragStartRef = React.useRef(null);
827
+ // Resize state management
828
+ const [internalSize, setInternalSize] = React.useState({
829
+ width,
830
+ height,
831
+ });
832
+ const [isResizing, setIsResizing] = React.useState(false);
833
+ const resizeStartRef = React.useRef(null);
827
834
  // Use controlled position if provided, otherwise use internal state
828
835
  const currentPosition = controlledPosition || internalPosition;
836
+ // Use internal size state for resize tracking
837
+ const currentWidth = isResizing ? internalSize.width : width;
838
+ const currentHeight = isResizing ? internalSize.height : height;
829
839
  // Handle mouse down on title bar to start dragging
830
840
  const handleTitleBarMouseDown = React.useCallback((event) => {
831
841
  if (!draggable)
@@ -839,13 +849,80 @@ const Window = React.forwardRef(({ children, title, titleBar, active = true, wid
839
849
  if (!windowElement)
840
850
  return;
841
851
  const rect = windowElement.getBoundingClientRect();
842
- // Store drag start info
852
+ // Get the parent container to calculate position relative to it
853
+ const parent = windowElement.offsetParent;
854
+ const parentRect = parent ? parent.getBoundingClientRect() : { left: 0, top: 0 };
855
+ // Store drag start info - offset from mouse to window position within parent
856
+ // This accounts for the parent's coordinate system
843
857
  dragStartRef.current = {
844
- x: event.clientX - rect.left,
845
- y: event.clientY - rect.top,
858
+ x: event.clientX - (rect.left - parentRect.left),
859
+ y: event.clientY - (rect.top - parentRect.top),
846
860
  };
847
861
  setIsDragging(true);
848
862
  }, [draggable]);
863
+ // Handle mouse down on resize handle to start resizing
864
+ const handleResizeMouseDown = React.useCallback((event) => {
865
+ if (!resizable)
866
+ return;
867
+ event.preventDefault();
868
+ event.stopPropagation();
869
+ const windowElement = event.currentTarget.closest(`.${styles$6.window}`);
870
+ if (!windowElement)
871
+ return;
872
+ const rect = windowElement.getBoundingClientRect();
873
+ // Store resize start info
874
+ resizeStartRef.current = {
875
+ width: rect.width,
876
+ height: rect.height,
877
+ mouseX: event.clientX,
878
+ mouseY: event.clientY,
879
+ };
880
+ setIsResizing(true);
881
+ }, [resizable]);
882
+ // Handle mouse move during resize
883
+ React.useEffect(() => {
884
+ if (!isResizing || !resizeStartRef.current)
885
+ return;
886
+ const handleMouseMove = (event) => {
887
+ event.preventDefault();
888
+ if (!resizeStartRef.current)
889
+ return;
890
+ // Calculate delta
891
+ const deltaX = event.clientX - resizeStartRef.current.mouseX;
892
+ const deltaY = event.clientY - resizeStartRef.current.mouseY;
893
+ // Calculate new size
894
+ let newWidth = resizeStartRef.current.width + deltaX;
895
+ let newHeight = resizeStartRef.current.height + deltaY;
896
+ // Apply constraints
897
+ if (newWidth < minWidth)
898
+ newWidth = minWidth;
899
+ if (newHeight < minHeight)
900
+ newHeight = minHeight;
901
+ if (maxWidth && newWidth > maxWidth)
902
+ newWidth = maxWidth;
903
+ if (maxHeight && newHeight > maxHeight)
904
+ newHeight = maxHeight;
905
+ // Update size
906
+ setInternalSize({
907
+ width: newWidth,
908
+ height: newHeight,
909
+ });
910
+ // Call callback if provided
911
+ if (onResize) {
912
+ onResize({ width: newWidth, height: newHeight });
913
+ }
914
+ };
915
+ const handleMouseUp = () => {
916
+ setIsResizing(false);
917
+ resizeStartRef.current = null;
918
+ };
919
+ document.addEventListener('mousemove', handleMouseMove);
920
+ document.addEventListener('mouseup', handleMouseUp);
921
+ return () => {
922
+ document.removeEventListener('mousemove', handleMouseMove);
923
+ document.removeEventListener('mouseup', handleMouseUp);
924
+ };
925
+ }, [isResizing, minWidth, minHeight, maxWidth, maxHeight, onResize]);
849
926
  // Handle mouse move during drag
850
927
  React.useEffect(() => {
851
928
  if (!isDragging || !dragStartRef.current)
@@ -854,9 +931,25 @@ const Window = React.forwardRef(({ children, title, titleBar, active = true, wid
854
931
  event.preventDefault();
855
932
  if (!dragStartRef.current)
856
933
  return;
934
+ // Get the window element to find its parent
935
+ const windowElements = document.querySelectorAll(`.${styles$6.window}`);
936
+ let windowElement = null;
937
+ // Find the dragging window (the one with position absolute or the first one)
938
+ for (const el of Array.from(windowElements)) {
939
+ const htmlEl = el;
940
+ if (htmlEl.style.position === 'absolute' || windowElements.length === 1) {
941
+ windowElement = htmlEl;
942
+ break;
943
+ }
944
+ }
945
+ if (!windowElement)
946
+ return;
947
+ // Get parent container to calculate position relative to it
948
+ const parent = windowElement.offsetParent;
949
+ const parentRect = parent ? parent.getBoundingClientRect() : { left: 0, top: 0 };
857
950
  const newPosition = {
858
- x: event.clientX - dragStartRef.current.x,
859
- y: event.clientY - dragStartRef.current.y,
951
+ x: event.clientX - parentRect.left - dragStartRef.current.x,
952
+ y: event.clientY - parentRect.top - dragStartRef.current.y,
860
953
  };
861
954
  // Update position
862
955
  if (controlledPosition && onPositionChange) {
@@ -887,11 +980,13 @@ const Window = React.forwardRef(({ children, title, titleBar, active = true, wid
887
980
  const titleBarClassNames = mergeClasses(styles$6.titleBar, draggable && styles$6['titleBar--draggable'], isDragging && styles$6['titleBar--dragging'], classes?.titleBar);
888
981
  // Window style
889
982
  const windowStyle = {};
890
- if (width !== 'auto') {
891
- windowStyle.width = typeof width === 'number' ? `${width}px` : width;
983
+ // Apply width - use currentWidth during resize, otherwise use prop
984
+ if (currentWidth !== 'auto') {
985
+ windowStyle.width = typeof currentWidth === 'number' ? `${currentWidth}px` : currentWidth;
892
986
  }
893
- if (height !== 'auto') {
894
- windowStyle.height = typeof height === 'number' ? `${height}px` : height;
987
+ // Apply height - use currentHeight during resize, otherwise use prop
988
+ if (currentHeight !== 'auto') {
989
+ windowStyle.height = typeof currentHeight === 'number' ? `${currentHeight}px` : currentHeight;
895
990
  }
896
991
  // Apply position if draggable and has been dragged
897
992
  if (draggable && hasBeenDragged && currentPosition) {
@@ -909,7 +1004,7 @@ const Window = React.forwardRef(({ children, title, titleBar, active = true, wid
909
1004
  }
910
1005
  return null;
911
1006
  };
912
- return (jsxRuntime.jsxs("div", { ref: ref, className: windowClassNames, style: windowStyle, onMouseEnter: onMouseEnter, children: [renderTitleBar(), jsxRuntime.jsx("div", { className: contentClassNames, children: children }), resizable && jsxRuntime.jsx("div", { className: styles$6.resizeHandle, "aria-hidden": "true" })] }));
1007
+ return (jsxRuntime.jsxs("div", { ref: ref, className: windowClassNames, style: windowStyle, onMouseEnter: onMouseEnter, children: [renderTitleBar(), jsxRuntime.jsx("div", { className: contentClassNames, children: children }), resizable && (jsxRuntime.jsx("div", { className: styles$6.resizeHandle, onMouseDown: handleResizeMouseDown, "aria-hidden": "true" }))] }));
913
1008
  });
914
1009
  Window.displayName = 'Window';
915
1010