diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts index b5e9b3a4eab24d..0501e54296d227 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.d.ts @@ -29,26 +29,43 @@ type AnimatableStringValue = string | Animated.AnimatedNode; // [macOS export type CursorValue = - | 'alias' | 'auto' + | 'alias' + | 'all-scroll' + | 'cell' | 'col-resize' | 'context-menu' | 'copy' | 'crosshair' | 'default' - | 'disappearing-item' | 'e-resize' + | 'ew-resize' | 'grab' | 'grabbing' + | 'help' + | 'move' + | 'ne-resize' + | 'nesw-resize' | 'n-resize' + | 'ns-resize' + | 'nw-resize' + | 'nwse-resize' | 'no-drop' + | 'none' | 'not-allowed' | 'pointer' + | 'progress' | 'row-resize' | 's-resize' + | 'se-resize' + | 'sw-resize' | 'text' + | 'url' | 'vertical-text' - | 'w-resize'; + | 'w-resize' + | 'wait' + | 'zoom-in' + | 'zoom-out'; // macOS] /** diff --git a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js index b3dd728e1f18d0..1cbd2bb174b481 100644 --- a/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js +++ b/packages/react-native/Libraries/StyleSheet/StyleSheetTypes.js @@ -39,26 +39,43 @@ export type AnimatableNumericValue = number | AnimatedNode; // [macOS export type CursorValue = - | 'alias' | 'auto' + | 'alias' + | 'all-scroll' + | 'cell' | 'col-resize' | 'context-menu' | 'copy' | 'crosshair' | 'default' - | 'disappearing-item' | 'e-resize' + | 'ew-resize' | 'grab' | 'grabbing' + | 'help' + | 'move' + | 'ne-rsize' + | 'nesw-resize' | 'n-resize' + | 'ns-resize' + | 'ns-resize' + | 'nwse-resize' | 'no-drop' + | 'none' | 'not-allowed' | 'pointer' - | 'row-resize' + | 'progress' + | 'row-esize' | 's-resize' + | 'se-resize' + | 'sw-resize' | 'text' + | 'url' | 'vertical-text' - | 'w-resize'; + | 'w-resize' + | 'wait' + | 'zoom-in' + | 'zoom-out'; // macOS] /** diff --git a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap index 46dfd5e75a7b8d..9312bf6060fa30 100644 --- a/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap +++ b/packages/react-native/Libraries/__tests__/__snapshots__/public-api-test.js.snap @@ -7715,26 +7715,43 @@ export type EdgeInsetsValue = { export type DimensionValue = number | string | \\"auto\\" | AnimatedNode | null; export type AnimatableNumericValue = number | AnimatedNode; export type CursorValue = - | \\"alias\\" | \\"auto\\" + | \\"alias\\" + | \\"all-scroll\\" + | \\"cell\\" | \\"col-resize\\" | \\"context-menu\\" | \\"copy\\" | \\"crosshair\\" | \\"default\\" - | \\"disappearing-item\\" | \\"e-resize\\" + | \\"ew-resize\\" | \\"grab\\" | \\"grabbing\\" + | \\"help\\" + | \\"move\\" + | \\"ne-rsize\\" + | \\"nesw-resize\\" | \\"n-resize\\" + | \\"ns-resize\\" + | \\"ns-resize\\" + | \\"nwse-resize\\" | \\"no-drop\\" + | \\"none\\" | \\"not-allowed\\" | \\"pointer\\" - | \\"row-resize\\" + | \\"progress\\" + | \\"row-esize\\" | \\"s-resize\\" + | \\"se-resize\\" + | \\"sw-resize\\" | \\"text\\" + | \\"url\\" | \\"vertical-text\\" - | \\"w-resize\\"; + | \\"w-resize\\" + | \\"wait\\" + | \\"zoom-in\\" + | \\"zoom-out\\"; type ____LayoutStyle_Internal = $ReadOnly<{ display?: \\"none\\" | \\"flex\\", width?: DimensionValue, diff --git a/packages/react-native/React/Base/RCTConvert.mm b/packages/react-native/React/Base/RCTConvert.mm index 6a003d0e017f2a..dba6ab310545d9 100644 --- a/packages/react-native/React/Base/RCTConvert.mm +++ b/packages/react-native/React/Base/RCTConvert.mm @@ -552,34 +552,51 @@ + (UIKeyboardType)UIKeyboardType:(id)json RCT_DYNAMIC integerValue) #endif // [macOS] -// [macOS [visionOS] +// [macOS RCT_ENUM_CONVERTER( RCTCursor, (@{ - @"alias" : @(RCTCursorAlias), @"auto" : @(RCTCursorAuto), - @"col-resize" : @(RCTCursorColumnResize), - @"context-menu" : @(RCTCursorContextualMenu), + @"alias" : @(RCTCursorAlias), + @"all-scroll" : @(RCTCursorAllScroll), + @"cell" : @(RCTCursorCell), + @"col-resize" : @(RCTCursorColResize), + @"context-menu" : @(RCTCursorContextMenu), @"copy" : @(RCTCursorCopy), @"crosshair" : @(RCTCursorCrosshair), @"default" : @(RCTCursorDefault), - @"disappearing-item" : @(RCTCursorDisappearingItem), - @"e-resize" : @(RCTCursorEastResize), + @"e-resize" : @(RCTCursorEResize), + @"ew-resize" : @(RCTCursorEWResize), @"grab" : @(RCTCursorGrab), @"grabbing" : @(RCTCursorGrabbing), - @"n-resize" : @(RCTCursorNorthResize), + @"help" : @(RCTCursorHelp), + @"move" : @(RCTCursorMove), + @"ne-resize" : @(RCTCursorNEResize), + @"nesw-resize" : @(RCTCursorNESWResize), + @"n-resize" : @(RCTCursorNResize), + @"ns-resize" : @(RCTCursorNSResize), + @"nw-resize" : @(RCTCursorNWResize), + @"nwse-resize" : @(RCTCursorNWSEResize), @"no-drop" : @(RCTCursorNoDrop), + @"none" : @(RCTCursorNone), @"not-allowed" : @(RCTCursorNotAllowed), @"pointer" : @(RCTCursorPointer), + @"progress" : @(RCTCursorProgress), @"row-resize" : @(RCTCursorRowResize), - @"s-resize" : @(RCTCursorSouthResize), + @"s-resize" : @(RCTCursorSResize), + @"se-resize" : @(RCTCursorSEResize), + @"sw-resize" : @(RCTCursorSWResize), @"text" : @(RCTCursorText), + @"url" : @(RCTCursorUrl), @"vertical-text" : @(RCTCursorVerticalText), - @"w-resize" : @(RCTCursorWestResize), + @"w-resize" : @(RCTCursorWResize), + @"wait" : @(RCTCursorWait), + @"zoom-in" : @(RCTCursorZoomIn), + @"zoom-out" : @(RCTCursorZoomOut), }), RCTCursorAuto, integerValue) -// macOS] [visionOS] +// macOS] #if TARGET_OS_OSX // [macOS RCT_MULTI_ENUM_CONVERTER(NSTextCheckingTypes, (@{ diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 1f6b01ec919ca1..4066a6e7ec2839 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -14,7 +14,7 @@ #import #import #import -#import // [macOS] +#import // [macOS] #import #import #import @@ -107,7 +107,7 @@ - (void)resetCursorRects [self discardCursorRects]; if (_props->cursor != Cursor::Auto) { - NSCursor *cursor = NSCursorFromCursor(_props->cursor); + NSCursor *cursor = NSCursorFromRCTCursor(RCTCursorFromCursor(_props->cursor)); [self addCursorRect:self.bounds cursor:cursor]; } } @@ -611,54 +611,87 @@ static RCTBorderStyle RCTBorderStyleFromBorderStyle(BorderStyle borderStyle) } #if TARGET_OS_OSX // [macOS - static NSCursor *NSCursorFromCursor(Cursor cursor) +static RCTCursor RCTCursorFromCursor(Cursor cursor) { switch (cursor) { case Cursor::Auto: - return [NSCursor arrowCursor]; + return RCTCursorAuto; case Cursor::Alias: - return [NSCursor dragLinkCursor]; - case Cursor::ColumnResize: - return [NSCursor resizeLeftRightCursor]; - case Cursor::ContextualMenu: - return [NSCursor contextualMenuCursor]; + return RCTCursorAlias; + case Cursor::AllScroll: + return RCTCursorAllScroll; + case Cursor::Cell: + return RCTCursorCell; + case Cursor::ColResize: + return RCTCursorColResize; + case Cursor::ContextMenu: + return RCTCursorContextMenu; case Cursor::Copy: - return [NSCursor dragCopyCursor]; + return RCTCursorCopy; case Cursor::Crosshair: - return [NSCursor crosshairCursor]; + return RCTCursorCrosshair; case Cursor::Default: - return [NSCursor arrowCursor]; - case Cursor::DisappearingItem: - return [NSCursor disappearingItemCursor]; - case Cursor::EastResize: - return [NSCursor resizeRightCursor]; + return RCTCursorDefault; + case Cursor::EResize: + return RCTCursorEResize; + case Cursor::EWResize: + return RCTCursorEWResize; case Cursor::Grab: - return [NSCursor openHandCursor]; + return RCTCursorGrab; case Cursor::Grabbing: - return [NSCursor closedHandCursor]; - case Cursor::NorthResize: - return [NSCursor resizeUpCursor]; + return RCTCursorGrabbing; + case Cursor::Help: + return RCTCursorHelp; + case Cursor::Move: + return RCTCursorMove; + case Cursor::NEResize: + return RCTCursorNEResize; + case Cursor::NESWResize: + return RCTCursorNESWResize; + case Cursor::NResize: + return RCTCursorNResize; + case Cursor::NSResize: + return RCTCursorNSResize; + case Cursor::NWResize: + return RCTCursorNWResize; + case Cursor::NWSEResize: + return RCTCursorNWSEResize; case Cursor::NoDrop: - return [NSCursor operationNotAllowedCursor]; + return RCTCursorNoDrop; + case Cursor::None: + return RCTCursorNone; case Cursor::NotAllowed: - return [NSCursor operationNotAllowedCursor]; + return RCTCursorNotAllowed; case Cursor::Pointer: - return [NSCursor pointingHandCursor]; + return RCTCursorPointer; + case Cursor::Progress: + return RCTCursorProgress; case Cursor::RowResize: - return [NSCursor resizeUpDownCursor]; - case Cursor::SouthResize: - return [NSCursor resizeDownCursor]; + return RCTCursorRowResize; + case Cursor::SResize: + return RCTCursorSResize; + case Cursor::SEResize: + return RCTCursorSEResize; + case Cursor::SWResize: + return RCTCursorSWResize; case Cursor::Text: - return [NSCursor IBeamCursor]; + return RCTCursorText; + case Cursor::Url: + return RCTCursorUrl; case Cursor::VerticalText: - return [NSCursor IBeamCursorForVerticalLayout]; - case Cursor::WestResize: - return [NSCursor resizeLeftCursor]; + return RCTCursorVerticalText; + case Cursor::WResize: + return RCTCursorWResize; + case Cursor::Wait: + return RCTCursorWait; + case Cursor::ZoomIn: + return RCTCursorZoomIn; + case Cursor::ZoomOut: + return RCTCursorZoomOut; } } #endif // macOS] - - (void)invalidateLayer { CALayer *layer = self.layer; diff --git a/packages/react-native/React/Views/RCTCursor.h b/packages/react-native/React/Views/RCTCursor.h index 5d6727ca2cb1e5..2afacddbef70c4 100644 --- a/packages/react-native/React/Views/RCTCursor.h +++ b/packages/react-native/React/Views/RCTCursor.h @@ -5,76 +5,52 @@ * LICENSE file in the root directory of this source tree. */ - #import +#import +#import // [macOS] typedef NS_ENUM(NSInteger, RCTCursor) { + // [macOS RCTCursorAlias, RCTCursorAuto, - RCTCursorColumnResize, - RCTCursorContextualMenu, + RCTCursorAllScroll, + RCTCursorCell, + RCTCursorColResize, + RCTCursorContextMenu, RCTCursorCopy, RCTCursorCrosshair, RCTCursorDefault, - RCTCursorDisappearingItem, - RCTCursorEastResize, + RCTCursorEResize, + RCTCursorEWResize, RCTCursorGrab, RCTCursorGrabbing, - RCTCursorNorthResize, + RCTCursorHelp, + RCTCursorMove, + RCTCursorNEResize, + RCTCursorNESWResize, + RCTCursorNResize, + RCTCursorNSResize, + RCTCursorNWResize, + RCTCursorNWSEResize, RCTCursorNoDrop, + RCTCursorNone, RCTCursorNotAllowed, RCTCursorPointer, + RCTCursorProgress, RCTCursorRowResize, - RCTCursorSouthResize, + RCTCursorSResize, + RCTCursorSEResize, + RCTCursorSWResize, RCTCursorText, + RCTCursorUrl, RCTCursorVerticalText, - RCTCursorWestResize, + RCTCursorWResize, + RCTCursorWait, + RCTCursorZoomIn, + RCTCursorZoomOut, + // macOS] }; #if TARGET_OS_OSX // [macOS -inline static NSCursor *NSCursorFromRCTCursor(RCTCursor cursor) -{ - switch (cursor) { - case RCTCursorAlias: - return [NSCursor dragLinkCursor]; - case RCTCursorAuto: - return [NSCursor arrowCursor]; - case RCTCursorColumnResize: - return [NSCursor resizeLeftRightCursor]; - case RCTCursorContextualMenu: - return [NSCursor contextualMenuCursor]; - case RCTCursorCopy: - return [NSCursor dragCopyCursor]; - case RCTCursorCrosshair: - return [NSCursor crosshairCursor]; - case RCTCursorDefault: - return [NSCursor arrowCursor]; - case RCTCursorDisappearingItem: - return [NSCursor disappearingItemCursor]; - case RCTCursorEastResize: - return [NSCursor resizeRightCursor]; - case RCTCursorGrab: - return [NSCursor openHandCursor]; - case RCTCursorGrabbing: - return [NSCursor closedHandCursor]; - case RCTCursorNorthResize: - return [NSCursor resizeUpCursor]; - case RCTCursorNoDrop: - return [NSCursor operationNotAllowedCursor]; - case RCTCursorNotAllowed: - return [NSCursor operationNotAllowedCursor]; - case RCTCursorPointer: - return [NSCursor pointingHandCursor]; - case RCTCursorRowResize: - return [NSCursor resizeUpDownCursor]; - case RCTCursorSouthResize: - return [NSCursor resizeDownCursor]; - case RCTCursorText: - return [NSCursor IBeamCursor]; - case RCTCursorVerticalText: - return [NSCursor IBeamCursorForVerticalLayout]; - case RCTCursorWestResize: - return [NSCursor resizeLeftCursor]; - } -} +RCT_EXTERN NSCursor *__nullable NSCursorFromRCTCursor(RCTCursor cursor); #endif // macOS] diff --git a/packages/react-native/React/Views/RCTCursor.m b/packages/react-native/React/Views/RCTCursor.m new file mode 100644 index 00000000000000..05575465fbef9e --- /dev/null +++ b/packages/react-native/React/Views/RCTCursor.m @@ -0,0 +1,233 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// [macOS] + +#import +#import "RCTCursor.h" + +#if defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 150000 /* __MAC_15_0 */ +#define RCT_MAC_OS_15_SDK_AVAILABLE +#endif // __MAC_OS_X_VERSION_MAX_ALLOWED + +#if TARGET_OS_OSX +NSCursor *NSCursorFromRCTCursor(RCTCursor cursor) +{ + NSCursor *resolvedCursor = nil; + switch (cursor) { + case RCTCursorAuto: + break; + case RCTCursorAlias: + resolvedCursor = [NSCursor dragLinkCursor]; + break; + case RCTCursorAllScroll: + // Not supported + break; + case RCTCursorCell: + // Not supported + break; + case RCTCursorColResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor columnResizeCursor]; + } else { + resolvedCursor = [NSCursor resizeLeftRightCursor]; + } +#else + resolvedCursor = [NSCursor resizeLeftRightCursor]; +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorContextMenu: + resolvedCursor = [NSCursor contextualMenuCursor]; + break; + case RCTCursorCopy: + resolvedCursor = [NSCursor dragCopyCursor]; + break; + case RCTCursorCrosshair: + resolvedCursor = [NSCursor crosshairCursor]; + break; + case RCTCursorDefault: + resolvedCursor = [NSCursor arrowCursor]; + break; + case RCTCursorEResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionRight + inDirections:NSCursorFrameResizeDirectionsOutward]; + } else { + resolvedCursor = [NSCursor resizeRightCursor]; + } +#else + resolvedCursor = [NSCursor resizeRightCursor]; +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorEWResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionLeft + inDirections:NSCursorFrameResizeDirectionsAll]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorGrab: + resolvedCursor = [NSCursor openHandCursor]; + break; + case RCTCursorGrabbing: + resolvedCursor = [NSCursor closedHandCursor]; + break; + case RCTCursorHelp: + // Not supported + break; + case RCTCursorMove: + // Not supported + break; + case RCTCursorNEResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTopRight + inDirections:NSCursorFrameResizeDirectionsOutward]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNESWResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTopRight + inDirections:NSCursorFrameResizeDirectionsAll]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNResize: + resolvedCursor = [NSCursor resizeUpCursor]; +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTop + inDirections:NSCursorFrameResizeDirectionsOutward]; + } else { + resolvedCursor = [NSCursor resizeUpCursor]; + } +#else + resolvedCursor = [NSCursor resizeUpCursor]; +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNSResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTop + inDirections:NSCursorFrameResizeDirectionsAll]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNWResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTopLeft + inDirections:NSCursorFrameResizeDirectionsOutward]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNWSEResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionTopLeft + inDirections:NSCursorFrameResizeDirectionsAll]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorNoDrop: + resolvedCursor = [NSCursor operationNotAllowedCursor]; + break; + case RCTCursorNone: + resolvedCursor = [[NSCursor alloc] initWithImage:[[NSImage alloc] initWithSize:NSMakeSize(1, 1)] hotSpot:NSZeroPoint]; + break; + case RCTCursorNotAllowed: + resolvedCursor = [NSCursor operationNotAllowedCursor]; + break; + case RCTCursorPointer: + resolvedCursor = [NSCursor pointingHandCursor]; + break; + case RCTCursorProgress: + // Not supported + break; + case RCTCursorRowResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor rowResizeCursor]; + } else { + resolvedCursor = [NSCursor resizeUpDownCursor]; + } +#else + resolvedCursor = [NSCursor resizeUpDownCursor]; +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorSResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionBottom + inDirections:NSCursorFrameResizeDirectionsOutward]; + } else { + resolvedCursor = [NSCursor resizeDownCursor]; + } +#else + resolvedCursor = [NSCursor resizeDownCursor]; +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorSEResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionBottomRight + inDirections:NSCursorFrameResizeDirectionsOutward]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorSWResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionBottomLeft + inDirections:NSCursorFrameResizeDirectionsOutward]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorText: + resolvedCursor = [NSCursor IBeamCursor]; + break; + case RCTCursorUrl: + // Not supported + break; + case RCTCursorVerticalText: + resolvedCursor = [NSCursor IBeamCursorForVerticalLayout]; + break; + case RCTCursorWResize: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor frameResizeCursorFromPosition:NSCursorFrameResizePositionLeft + inDirections:NSCursorFrameResizeDirectionsOutward]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorWait: + // Not supported + break; + case RCTCursorZoomIn: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor zoomInCursor]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + case RCTCursorZoomOut: +#ifdef RCT_MAC_OS_15_SDK_AVAILABLE + if (@available(macOS 15.0, *)) { + resolvedCursor = [NSCursor zoomOutCursor]; + } +#endif // RCT_MAC_OS_15_SDK_AVAILABLE + break; + } + return resolvedCursor; +} +#endif // TARGET_OS_OSX + diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h index 2b68090a95427d..bc1a2d75d5d12a 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/conversions.h @@ -720,16 +720,24 @@ inline void fromRawValue( result = Cursor::Alias; return; } + if (stringValue == "all-scroll") { + result = Cursor::AllScroll; + return; + } if (stringValue == "auto") { result = Cursor::Auto; return; } + if (stringValue == "cell") { + result = Cursor::Cell; + return; + } if (stringValue == "col-resize") { - result = Cursor::ColumnResize; + result = Cursor::ColResize; return; } if (stringValue == "context-menu") { - result = Cursor::ContextualMenu; + result = Cursor::ContextMenu; return; } if (stringValue == "copy") { @@ -744,12 +752,12 @@ inline void fromRawValue( result = Cursor::Default; return; } - if (stringValue == "disappearing-item") { - result = Cursor::DisappearingItem; + if (stringValue == "e-resize") { + result = Cursor::EResize; return; } - if (stringValue == "e-resize") { - result = Cursor::EastResize; + if (stringValue == "ew-resize") { + result = Cursor::EWResize; return; } if (stringValue == "grab") { @@ -760,14 +768,46 @@ inline void fromRawValue( result = Cursor::Grabbing; return; } + if (stringValue == "help") { + result = Cursor::Help; + return; + } + if (stringValue == "move") { + result = Cursor::Move; + return; + } if (stringValue == "n-resize") { - result = Cursor::NorthResize; + result = Cursor::NResize; + return; + } + if (stringValue == "ne-resize") { + result = Cursor::NEResize; + return; + } + if (stringValue == "nesw-resize") { + result = Cursor::NESWResize; + return; + } + if (stringValue == "ns-resize") { + result = Cursor::NSResize; + return; + } + if (stringValue == "nw-resize") { + result = Cursor::NWResize; + return; + } + if (stringValue == "nwse-resize") { + result = Cursor::NWSEResize; return; } if (stringValue == "no-drop") { result = Cursor::NoDrop; return; } + if (stringValue == "none") { + result = Cursor::None; + return; + } if (stringValue == "not-allowed") { result = Cursor::NotAllowed; return; @@ -776,24 +816,54 @@ inline void fromRawValue( result = Cursor::Pointer; return; } + if (stringValue == "progress") { + result = Cursor::Progress; + return; + } if (stringValue == "row-resize") { result = Cursor::RowResize; return; } if (stringValue == "s-resize") { - result = Cursor::SouthResize; + result = Cursor::SResize; + return; + } + if (stringValue == "se-resize") { + result = Cursor::SEResize; + return; + } + if (stringValue == "sw-resize") { + result = Cursor::SWResize; return; } if (stringValue == "text") { result = Cursor::Text; return; } + if (stringValue == "url") { + result = Cursor::Url; + return; + } + // [macOS if (stringValue == "vertical-text") { result = Cursor::VerticalText; return; } + // macOS] if (stringValue == "w-resize") { - result = Cursor::WestResize; + result = Cursor::WResize; + return; + } + if (stringValue == "wait") { + result = Cursor::Wait; + return; + } + if (stringValue == "zoom-in") { + result = Cursor::ZoomIn; + return; + } + if (stringValue == "zoom-out") { + result = Cursor::ZoomOut; return; } LOG(ERROR) << "Could not parse Cursor:" << stringValue; diff --git a/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h b/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h index b97035e7cde480..4f5f3d48b9a705 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h +++ b/packages/react-native/ReactCommon/react/renderer/components/view/primitives.h @@ -91,30 +91,45 @@ enum class BorderCurve : uint8_t { Circular, Continuous }; enum class BorderStyle : uint8_t { Solid, Dotted, Dashed }; -// [macOS [visionOS] -enum class Cursor : uint8_t { +enum class Cursor : uint8_t { Auto, Alias, - ColumnResize, - ContextualMenu, + AllScroll, + Cell, + ColResize, + ContextMenu, Copy, Crosshair, Default, - DisappearingItem, - EastResize, + EResize, + EWResize, Grab, Grabbing, - NorthResize, + Help, + Move, + NEResize, + NESWResize, + NResize, + NSResize, + NWResize, + NWSEResize, NoDrop, + None, NotAllowed, Pointer, + Progress, RowResize, - SouthResize, + SResize, + SEResize, + SWResize, Text, - VerticalText, - WestResize, + Url, + VerticalText, // [macOS] + WResize, + Wait, + ZoomIn, + ZoomOut, }; -// macOS] [visionOS] enum class LayoutConformance : uint8_t { Undefined, Classic, Strict }; diff --git a/packages/rn-tester/js/examples/Cursor/CursorExample.js b/packages/rn-tester/js/examples/Cursor/CursorExample.js index bba1ed7870850c..c2e8b65e076257 100644 --- a/packages/rn-tester/js/examples/Cursor/CursorExample.js +++ b/packages/rn-tester/js/examples/Cursor/CursorExample.js @@ -41,7 +41,7 @@ const styles = StyleSheet.create({ backgroundColor: 'blue', }, pointer: { - cursor: 'alias', + cursor: 'pointer', }, row: { flexDirection: 'row', @@ -104,61 +104,62 @@ function CursorExampleViewFlattening() { } // [macOS + +function BoxWithCursor({cursor}) { + return ( + + {cursor} + + ); +} + function CursorExampleMacOS() { + const cursors = [ + 'auto', + 'alias', + 'all-scroll', + 'cell', + 'col-resize', + 'context-menu', + 'copy', + 'crosshair', + 'default', + 'e-resize', + 'ew-resize', + 'grab', + 'grabbing', + 'help', + 'move', + 'ne-resize', + 'nesw-resize', + 'n-resize', + 'ns-resize', + 'nw-resize', + 'nwse-resize', + 'no-drop', + 'none', + 'not-allowed', + 'pointer', + 'progress', + 'row-resize', + 's-resize', + 'se-resize', + 'sw-resize', + 'text', + 'url', + 'vertical-text', + 'w-resize', + 'wait', + 'zoom-in', + 'zoom-out', + ]; + return ( <> - - auto - - - default - - - context-menu - - - pointer - - - text - - - vertical-text - - - alias - - - copy - - - not-allowed - - - grab - - - grabbing - - - col-resize - - - row-resize - - - n-resize - - - e-resize - - - s-resize - - - w-resize - + {cursors.map(cursor => ( + + ))} ); @@ -188,7 +189,8 @@ exports.examples = [ // [macOS { title: 'macOS Cursors', - description: 'macOS supports many more cursors', + description: + 'macOS supports many more cursors. Unsupported cursors show the system cursor', render: CursorExampleMacOS, }, // macOS]