diff --git a/packages/components/FocusZone/macos/FocusZoneViewManager.swift b/packages/components/FocusZone/macos/FocusZoneViewManager.swift new file mode 100644 index 00000000000..48127949998 --- /dev/null +++ b/packages/components/FocusZone/macos/FocusZoneViewManager.swift @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +import AppKit +import Foundation +#if USE_REACT_AS_MODULE +import React +#endif // USE_REACT_AS_MODULE + +@objc(FocusZoneViewManager) +class FocusZoneViewManager: RCTViewManager { + + override func view() -> NSView! { + return RCTFocusZone() + } + + override class func requiresMainQueueSetup() -> Bool { + return true + } +} diff --git a/packages/components/FocusZone/macos/RCTFocusZoneManager.h b/packages/components/FocusZone/macos/RCTFocusZoneManager.h index 3bb04a706f4..fc36ab244fa 100644 --- a/packages/components/FocusZone/macos/RCTFocusZoneManager.h +++ b/packages/components/FocusZone/macos/RCTFocusZoneManager.h @@ -1,6 +1,2 @@ -#pragma once - -#import - -@interface RCTFocusZoneManager : RCTViewManager -@end +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. diff --git a/packages/components/FocusZone/macos/RCTFocusZoneManager.m b/packages/components/FocusZone/macos/RCTFocusZoneManager.m index 68b93f136be..d546d70fa32 100644 --- a/packages/components/FocusZone/macos/RCTFocusZoneManager.m +++ b/packages/components/FocusZone/macos/RCTFocusZoneManager.m @@ -1,11 +1,12 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + #import "RCTFocusZone.h" -#import "RCTFocusZoneManager.h" #import #import +#import -@implementation RCTFocusZoneManager - -RCT_EXPORT_MODULE() +@interface RCT_EXTERN_MODULE(FocusZoneViewManager, RCTViewManager) RCT_EXPORT_VIEW_PROPERTY(disabled, BOOL) @@ -50,9 +51,4 @@ @implementation RCTFocusZoneManager [view setDefaultResponder:defaultResponder]; } -- (RCTView *)view -{ - return [RCTFocusZone new]; -} - @end diff --git a/packages/components/FocusZone/package.json b/packages/components/FocusZone/package.json index c65058cd3a9..8e88837608a 100644 --- a/packages/components/FocusZone/package.json +++ b/packages/components/FocusZone/package.json @@ -34,9 +34,8 @@ }, "dependencies": { "@fluentui-react-native/adapters": "workspace:*", - "@fluentui-react-native/interactive-hooks": "workspace:*", - "@uifabricshared/foundation-composable": "workspace:*", - "@uifabricshared/foundation-settings": "workspace:*" + "@fluentui-react-native/framework": "workspace:*", + "@fluentui-react-native/interactive-hooks": "workspace:*" }, "devDependencies": { "@babel/core": "catalog:", diff --git a/packages/components/FocusZone/src/FocusZone.ts b/packages/components/FocusZone/src/FocusZone.ts index 3735b09ad86..1ddcd476166 100644 --- a/packages/components/FocusZone/src/FocusZone.ts +++ b/packages/components/FocusZone/src/FocusZone.ts @@ -7,18 +7,26 @@ import * as React from 'react'; import { findNodeHandle } from 'react-native'; +import type { UseSlots } from '@fluentui-react-native/framework'; +import { compose, mergeProps } from '@fluentui-react-native/framework'; import { useViewCommandFocus } from '@fluentui-react-native/interactive-hooks'; -import type { IUseStyling } from '@uifabricshared/foundation-composable'; -import { composable } from '@uifabricshared/foundation-composable'; -import { mergeSettings } from '@uifabricshared/foundation-settings'; -import type { FocusZoneProps, FocusZoneSlotProps, FocusZoneType } from './FocusZone.types'; +import type { FocusZoneProps, FocusZoneState, FocusZoneTokens } from './FocusZone.types'; +import { focusZoneName } from './FocusZone.types'; import RCTFocusZone from './FocusZoneNativeComponent'; - -const filterOutComponentRef = (propName) => propName !== 'componentRef'; - -export const FocusZone = composable({ - usePrepareProps: (userProps: FocusZoneProps, useStyling: IUseStyling) => { +import type { NativeProps } from './FocusZoneNativeComponent'; + +interface FocusZoneTypeInternal { + props: FocusZoneProps; + tokens: FocusZoneTokens; + slotProps: { root: React.PropsWithRef }; + state: FocusZoneState; +} + +export const FocusZone = compose({ + displayName: focusZoneName, + slots: { root: RCTFocusZone }, + useRender: (userProps: FocusZoneProps, useSlots: UseSlots) => { const { componentRef, defaultTabbableElement, isCircularNavigation, ...rest } = userProps; const ftzRef = useViewCommandFocus(componentRef); @@ -34,18 +42,18 @@ export const FocusZone = composable({ } }, [defaultTabbableElement]); - return { - slotProps: mergeSettings(useStyling(userProps), { - root: { - navigateAtEnd: isCircularNavigation ? 'NavigateWrap' : 'NavigateStopAtEnds', // let rest override - ...rest, - defaultTabbableElement: targetFirstFocus, - ref: ftzRef, - }, - }), + const rootProps = { + navigateAtEnd: isCircularNavigation ? 'NavigateWrap' : 'NavigateStopAtEnds', + ...rest, + } as NativeProps; + + const Root = useSlots(userProps).root; + return (restProps: FocusZoneProps) => { + return React.createElement(Root, { + ...mergeProps(rootProps, restProps as NativeProps), + defaultTabbableElement: targetFirstFocus, + ref: ftzRef, + }); }; }, - slots: { - root: { slotType: RCTFocusZone, filter: filterOutComponentRef }, - }, }); diff --git a/packages/components/FocusZone/src/FocusZone.types.ts b/packages/components/FocusZone/src/FocusZone.types.ts index 55557ee46c8..50cc3d30375 100644 --- a/packages/components/FocusZone/src/FocusZone.types.ts +++ b/packages/components/FocusZone/src/FocusZone.types.ts @@ -2,7 +2,6 @@ import type * as React from 'react'; import type { IViewProps } from '@fluentui-react-native/adapters'; import type { IFocusable } from '@fluentui-react-native/interactive-hooks'; -import type { IRenderData } from '@uifabricshared/foundation-composable'; export const focusZoneName = 'FocusZone'; @@ -113,8 +112,6 @@ export interface FocusZoneSlotProps { root: NativeProps; } -export type FocusZoneRenderData = IRenderData; - export interface FocusZoneType { props: FocusZoneProps; tokens: FocusZoneTokens; diff --git a/packages/components/FocusZone/src/FocusZoneNativeComponent.ts b/packages/components/FocusZone/src/FocusZoneNativeComponent.ts index b6c7cf2ae50..58f4da680de 100644 --- a/packages/components/FocusZone/src/FocusZoneNativeComponent.ts +++ b/packages/components/FocusZone/src/FocusZoneNativeComponent.ts @@ -19,6 +19,7 @@ export interface NativeProps extends ViewProps { tabKeyNavigation?: WithDefault<'None' | 'NavigateWrap' | 'NavigateStopAtEnds' | 'Normal', 'None'>; disabled?: boolean; isTabNavigation?: boolean; + navigationOrderInRenderOrder?: boolean; } export default codegenNativeComponent('RCTFocusZone'); diff --git a/packages/components/FocusZone/src/__tests__/__snapshots__/FocusZone.test.tsx.snap b/packages/components/FocusZone/src/__tests__/__snapshots__/FocusZone.test.tsx.snap index ee9c7e31f1e..08b1c57c736 100644 --- a/packages/components/FocusZone/src/__tests__/__snapshots__/FocusZone.test.tsx.snap +++ b/packages/components/FocusZone/src/__tests__/__snapshots__/FocusZone.test.tsx.snap @@ -9,382 +9,19 @@ exports[`FocusZone No Props No children 1`] = ` exports[`FocusZone No Props One child 1`] = ` - - - - button - - - - +/> `; exports[`FocusZone No Props Three children 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone No Props Two children 1`] = ` - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props All Props 1`] = ` @@ -393,1124 +30,38 @@ exports[`FocusZone With Props All Props 1`] = ` focusZoneDirection="vertical" navigateAtEnd="NavigateStopAtEnds" use2DNavigation={true} -> - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props defaultTabbableElement Prop 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props disabled Prop 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props focusZoneDirection Prop 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props isCircularNavigation Prop 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; exports[`FocusZone With Props use2DNavigation Prop 1`] = ` - - - - button - - - - - - - button - - - - - - - button - - - - +/> `; diff --git a/packages/components/FocusZone/src/index.ts b/packages/components/FocusZone/src/index.ts index f84aa915751..737cff939cf 100644 --- a/packages/components/FocusZone/src/index.ts +++ b/packages/components/FocusZone/src/index.ts @@ -2,7 +2,6 @@ export { focusZoneName } from './FocusZone.types'; export type { FocusZoneDirection, FocusZoneProps, - FocusZoneRenderData, FocusZoneSlotProps, FocusZoneState, FocusZoneTabNavigation, diff --git a/yarn.lock b/yarn.lock index 9a16db481b9..bddac2e242e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4236,6 +4236,7 @@ __metadata: "@fluentui-react-native/adapters": "workspace:*" "@fluentui-react-native/babel-config": "workspace:*" "@fluentui-react-native/eslint-config-rules": "workspace:*" + "@fluentui-react-native/framework": "workspace:*" "@fluentui-react-native/interactive-hooks": "workspace:*" "@fluentui-react-native/jest-config": "workspace:*" "@fluentui-react-native/kit-config": "workspace:*" @@ -4249,8 +4250,6 @@ __metadata: "@react-native/metro-config": "npm:^0.81.0" "@types/react": "npm:~19.1.4" "@types/react-test-renderer": "npm:^19.1.0" - "@uifabricshared/foundation-composable": "workspace:*" - "@uifabricshared/foundation-settings": "workspace:*" react: "npm:19.1.4" react-native: "npm:^0.81.6" react-native-macos: "npm:^0.81.0"