@liiift-studio/mac-os9-ui 0.2.25 → 0.3.1

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.d.ts CHANGED
@@ -963,6 +963,32 @@ interface WindowProps {
963
963
  * @default false
964
964
  */
965
965
  resizable?: boolean;
966
+ /**
967
+ * Minimum width when resizing
968
+ * @default 200
969
+ */
970
+ minWidth?: number;
971
+ /**
972
+ * Minimum height when resizing
973
+ * @default 100
974
+ */
975
+ minHeight?: number;
976
+ /**
977
+ * Maximum width when resizing
978
+ */
979
+ maxWidth?: number;
980
+ /**
981
+ * Maximum height when resizing
982
+ */
983
+ maxHeight?: number;
984
+ /**
985
+ * Callback when window is resized
986
+ * Only called when resizable is true
987
+ */
988
+ onResize?: (size: {
989
+ width: number;
990
+ height: number;
991
+ }) => void;
966
992
  /**
967
993
  * Whether the window can be dragged by its title bar
968
994
  * Window starts in normal flow and becomes absolutely positioned when dragged
package/dist/index.js CHANGED
@@ -816,14 +816,24 @@ var styles$6 = {"window":"Window-module_window","window--active":"Window-module_
816
816
  * </Window>
817
817
  * ```
818
818
  */
819
- const Window = 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) => {
819
+ const Window = 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) => {
820
820
  // Drag state management
821
821
  const [internalPosition, setInternalPosition] = useState(defaultPosition || null);
822
822
  const [isDragging, setIsDragging] = useState(false);
823
823
  const [hasBeenDragged, setHasBeenDragged] = useState(!!(defaultPosition || controlledPosition));
824
824
  const dragStartRef = useRef(null);
825
+ // Resize state management
826
+ const [internalSize, setInternalSize] = useState({
827
+ width,
828
+ height,
829
+ });
830
+ const [isResizing, setIsResizing] = useState(false);
831
+ const resizeStartRef = useRef(null);
825
832
  // Use controlled position if provided, otherwise use internal state
826
833
  const currentPosition = controlledPosition || internalPosition;
834
+ // Use internal size state for resize tracking
835
+ const currentWidth = isResizing ? internalSize.width : width;
836
+ const currentHeight = isResizing ? internalSize.height : height;
827
837
  // Handle mouse down on title bar to start dragging
828
838
  const handleTitleBarMouseDown = useCallback((event) => {
829
839
  if (!draggable)
@@ -848,6 +858,69 @@ const Window = forwardRef(({ children, title, titleBar, active = true, width = '
848
858
  };
849
859
  setIsDragging(true);
850
860
  }, [draggable]);
861
+ // Handle mouse down on resize handle to start resizing
862
+ const handleResizeMouseDown = useCallback((event) => {
863
+ if (!resizable)
864
+ return;
865
+ event.preventDefault();
866
+ event.stopPropagation();
867
+ const windowElement = event.currentTarget.closest(`.${styles$6.window}`);
868
+ if (!windowElement)
869
+ return;
870
+ const rect = windowElement.getBoundingClientRect();
871
+ // Store resize start info
872
+ resizeStartRef.current = {
873
+ width: rect.width,
874
+ height: rect.height,
875
+ mouseX: event.clientX,
876
+ mouseY: event.clientY,
877
+ };
878
+ setIsResizing(true);
879
+ }, [resizable]);
880
+ // Handle mouse move during resize
881
+ useEffect(() => {
882
+ if (!isResizing || !resizeStartRef.current)
883
+ return;
884
+ const handleMouseMove = (event) => {
885
+ event.preventDefault();
886
+ if (!resizeStartRef.current)
887
+ return;
888
+ // Calculate delta
889
+ const deltaX = event.clientX - resizeStartRef.current.mouseX;
890
+ const deltaY = event.clientY - resizeStartRef.current.mouseY;
891
+ // Calculate new size
892
+ let newWidth = resizeStartRef.current.width + deltaX;
893
+ let newHeight = resizeStartRef.current.height + deltaY;
894
+ // Apply constraints
895
+ if (newWidth < minWidth)
896
+ newWidth = minWidth;
897
+ if (newHeight < minHeight)
898
+ newHeight = minHeight;
899
+ if (maxWidth && newWidth > maxWidth)
900
+ newWidth = maxWidth;
901
+ if (maxHeight && newHeight > maxHeight)
902
+ newHeight = maxHeight;
903
+ // Update size
904
+ setInternalSize({
905
+ width: newWidth,
906
+ height: newHeight,
907
+ });
908
+ // Call callback if provided
909
+ if (onResize) {
910
+ onResize({ width: newWidth, height: newHeight });
911
+ }
912
+ };
913
+ const handleMouseUp = () => {
914
+ setIsResizing(false);
915
+ resizeStartRef.current = null;
916
+ };
917
+ document.addEventListener('mousemove', handleMouseMove);
918
+ document.addEventListener('mouseup', handleMouseUp);
919
+ return () => {
920
+ document.removeEventListener('mousemove', handleMouseMove);
921
+ document.removeEventListener('mouseup', handleMouseUp);
922
+ };
923
+ }, [isResizing, minWidth, minHeight, maxWidth, maxHeight, onResize]);
851
924
  // Handle mouse move during drag
852
925
  useEffect(() => {
853
926
  if (!isDragging || !dragStartRef.current)
@@ -905,11 +978,13 @@ const Window = forwardRef(({ children, title, titleBar, active = true, width = '
905
978
  const titleBarClassNames = mergeClasses(styles$6.titleBar, draggable && styles$6['titleBar--draggable'], isDragging && styles$6['titleBar--dragging'], classes?.titleBar);
906
979
  // Window style
907
980
  const windowStyle = {};
908
- if (width !== 'auto') {
909
- windowStyle.width = typeof width === 'number' ? `${width}px` : width;
981
+ // Apply width - use currentWidth during resize, otherwise use prop
982
+ if (currentWidth !== 'auto') {
983
+ windowStyle.width = typeof currentWidth === 'number' ? `${currentWidth}px` : currentWidth;
910
984
  }
911
- if (height !== 'auto') {
912
- windowStyle.height = typeof height === 'number' ? `${height}px` : height;
985
+ // Apply height - use currentHeight during resize, otherwise use prop
986
+ if (currentHeight !== 'auto') {
987
+ windowStyle.height = typeof currentHeight === 'number' ? `${currentHeight}px` : currentHeight;
913
988
  }
914
989
  // Apply position if draggable and has been dragged
915
990
  if (draggable && hasBeenDragged && currentPosition) {
@@ -927,7 +1002,7 @@ const Window = forwardRef(({ children, title, titleBar, active = true, width = '
927
1002
  }
928
1003
  return null;
929
1004
  };
930
- return (jsxs("div", { ref: ref, className: windowClassNames, style: windowStyle, onMouseEnter: onMouseEnter, children: [renderTitleBar(), jsx("div", { className: contentClassNames, children: children }), resizable && jsx("div", { className: styles$6.resizeHandle, "aria-hidden": "true" })] }));
1005
+ return (jsxs("div", { ref: ref, className: windowClassNames, style: windowStyle, onMouseEnter: onMouseEnter, children: [renderTitleBar(), jsx("div", { className: contentClassNames, children: children }), resizable && (jsx("div", { className: styles$6.resizeHandle, onMouseDown: handleResizeMouseDown, "aria-hidden": "true" }))] }));
931
1006
  });
932
1007
  Window.displayName = 'Window';
933
1008