#if os(macOS) import AppKit import SwiftUI struct SheetResizeHandle: NSViewRepresentable { let vertical: Bool let canBegin: () -> Bool let change: (Double) -> Void let finish: () -> Void let cancel: () -> Void var fit: (() -> Void)? = nil func makeNSView(context: Context) -> Handle { Handle() } func updateNSView(_ view: Handle, context: Context) { view.actions = self } final class Handle: NSControl { override func draw(_ dirtyRect: NSRect) { NSColor.secondaryLabelColor.withAlphaComponent(0.15).setFill() // Keep the 8-point mouse target, but paint only the grid boundary. let pixel = 1 / (window?.backingScaleFactor ?? 2) let rule = actions?.vertical == true ? NSRect(x: bounds.minX, y: bounds.minY, width: bounds.width, height: pixel) : NSRect(x: bounds.maxX - pixel, y: bounds.minY, width: pixel, height: bounds.height) rule.fill() } var actions: SheetResizeHandle? private var start: NSPoint? private var moved = false private weak var previousResponder: NSResponder? override var acceptsFirstResponder: Bool { true } override func acceptsFirstMouse(for event: NSEvent?) -> Bool { true } override func resetCursorRects() { addCursorRect(bounds, cursor: actions?.vertical == true ? .resizeUpDown : .resizeLeftRight) } override func mouseDown(with event: NSEvent) { guard actions?.canBegin() == true else { return } if event.clickCount == 2, let fit = actions?.fit { fit(); return } previousResponder = window?.firstResponder window?.makeFirstResponder(self) start = event.locationInWindow; moved = false } override func mouseDragged(with event: NSEvent) { guard let start else { return } let amount = actions?.vertical == true ? start.y - event.locationInWindow.y : event.locationInWindow.x - start.x guard moved || abs(amount) >= 2 else { return } moved = true; actions?.change(amount) } override func mouseUp(with event: NSEvent) { guard start != nil else { return } if moved { actions?.finish() } reset() } override func keyDown(with event: NSEvent) { if event.keyCode == 53 { actions?.cancel(); reset() } else { super.keyDown(with: event) } } override func viewWillMove(toWindow newWindow: NSWindow?) { if newWindow == nil, start != nil { actions?.cancel(); reset() } super.viewWillMove(toWindow: newWindow) } private func reset() { start = nil; moved = false if window?.firstResponder === self { window?.makeFirstResponder(previousResponder) } previousResponder = nil } } } #endif