@fluentui-react-native/callout 0.29.6 → 0.29.8
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/CHANGELOG.md +39 -0
- package/README.md +18 -0
- package/lib/index.d.ts +2 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -2
- package/lib/index.js.map +1 -1
- package/package.json +12 -27
- package/src/index.ts +2 -3
- package/.cache/tsconfig.tsbuildinfo +0 -1
- package/FRNCallout.podspec +0 -24
- package/NuGet.config +0 -10
- package/SPEC.md +0 -46
- package/jest.config.cjs +0 -1
- package/lib/Callout.d.ts +0 -6
- package/lib/Callout.d.ts.map +0 -1
- package/lib/Callout.js +0 -64
- package/lib/Callout.js.map +0 -1
- package/lib/Callout.types.d.ts +0 -85
- package/lib/Callout.types.d.ts.map +0 -1
- package/lib/Callout.types.js +0 -2
- package/lib/Callout.types.js.map +0 -1
- package/lib/CalloutNativeComponent.d.ts +0 -49
- package/lib/CalloutNativeComponent.d.ts.map +0 -1
- package/lib/CalloutNativeComponent.js +0 -9
- package/lib/CalloutNativeComponent.js.map +0 -1
- package/lib/__tests__/Callout.test.d.ts +0 -2
- package/lib/__tests__/Callout.test.d.ts.map +0 -1
- package/lib/__tests__/Callout.test.js +0 -96
- package/lib/__tests__/Callout.test.js.map +0 -1
- package/lib/__tests__/Callout.types.test.d.ts +0 -2
- package/lib/__tests__/Callout.types.test.d.ts.map +0 -1
- package/lib/__tests__/Callout.types.test.js +0 -21
- package/lib/__tests__/Callout.types.test.js.map +0 -1
- package/macos/CalloutManager.swift +0 -16
- package/macos/CalloutView.swift +0 -454
- package/macos/CalloutWindow.swift +0 -40
- package/macos/FRNCallout.h +0 -14
- package/macos/FRNCalloutManager.h +0 -5
- package/macos/FRNCalloutManager.m +0 -76
- package/macos/FlippedVisualEffectView.swift +0 -10
- package/macos/GuardedEventMonitor.swift +0 -28
- package/macos/RCTCalloutComponentView.h +0 -12
- package/macos/RCTCalloutComponentView.mm +0 -209
- package/react-native.config.cjs +0 -15
- package/src/Callout.stories.tsx +0 -276
- package/src/Callout.tsx +0 -111
- package/src/Callout.types.ts +0 -106
- package/src/CalloutNativeComponent.ts +0 -74
- package/src/__tests__/Callout.test.tsx +0 -157
- package/src/__tests__/Callout.types.test.ts +0 -30
- package/src/__tests__/__snapshots__/Callout.test.tsx.snap +0 -11
- package/tsconfig.json +0 -19
- package/windows/Callout/Callout.cpp +0 -420
- package/windows/Callout/Callout.def +0 -3
- package/windows/Callout/Callout.h +0 -25
- package/windows/Callout/Callout.vcxproj +0 -152
- package/windows/Callout/ReactPackageProvider.cpp +0 -25
- package/windows/Callout/ReactPackageProvider.h +0 -25
- package/windows/Callout/ReactPackageProvider.idl +0 -12
- package/windows/Callout/codegen/.clang-format +0 -2
- package/windows/Callout/codegen/react/components/FRNCalloutSpec/Callout.g.h +0 -375
- package/windows/Callout/packages.lock.json +0 -151
- package/windows/Callout/pch.cpp +0 -1
- package/windows/Callout/pch.h +0 -28
- package/windows/ExperimentalFeatures.props +0 -33
- package/windows/NuGet.Config +0 -13
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
-
|
|
3
|
-
#import "RCTCalloutComponentView.h"
|
|
4
|
-
|
|
5
|
-
#import <react/renderer/components/FRNCalloutSpec/ComponentDescriptors.h>
|
|
6
|
-
#import <react/renderer/components/FRNCalloutSpec/EventEmitters.h>
|
|
7
|
-
#import <react/renderer/components/FRNCalloutSpec/Props.h>
|
|
8
|
-
#import <react/renderer/components/FRNCalloutSpec/RCTComponentViewHelpers.h>
|
|
9
|
-
|
|
10
|
-
#import <React/RCTComponent.h>
|
|
11
|
-
#import <React/RCTComponentViewProtocol.h>
|
|
12
|
-
#import <React/RCTConversions.h>
|
|
13
|
-
#import <React/RCTSurfaceTouchHandler.h>
|
|
14
|
-
#import <React/RCTView.h>
|
|
15
|
-
|
|
16
|
-
#import "FRNCallout-Swift.h"
|
|
17
|
-
|
|
18
|
-
using namespace facebook::react;
|
|
19
|
-
|
|
20
|
-
static NSRectEdge RCTNSRectEdgeFromDirectionalHint(CalloutDirectionalHint hint)
|
|
21
|
-
{
|
|
22
|
-
// CalloutView uses MinY for placement above the anchor and MaxY for placement below it.
|
|
23
|
-
switch (hint) {
|
|
24
|
-
case CalloutDirectionalHint::LeftTopEdge:
|
|
25
|
-
case CalloutDirectionalHint::LeftCenter:
|
|
26
|
-
case CalloutDirectionalHint::LeftBottomEdge:
|
|
27
|
-
return NSRectEdgeMinX;
|
|
28
|
-
case CalloutDirectionalHint::TopLeftEdge:
|
|
29
|
-
case CalloutDirectionalHint::TopAutoEdge:
|
|
30
|
-
case CalloutDirectionalHint::TopCenter:
|
|
31
|
-
case CalloutDirectionalHint::TopRightEdge:
|
|
32
|
-
return NSRectEdgeMinY;
|
|
33
|
-
case CalloutDirectionalHint::RightTopEdge:
|
|
34
|
-
case CalloutDirectionalHint::RightCenter:
|
|
35
|
-
case CalloutDirectionalHint::RightBottomEdge:
|
|
36
|
-
return NSRectEdgeMaxX;
|
|
37
|
-
case CalloutDirectionalHint::BottomLeftEdge:
|
|
38
|
-
case CalloutDirectionalHint::BottomAutoEdge:
|
|
39
|
-
case CalloutDirectionalHint::BottomCenter:
|
|
40
|
-
case CalloutDirectionalHint::BottomRightEdge:
|
|
41
|
-
return NSRectEdgeMaxY;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static void RCTApplyCalloutAppearance(
|
|
46
|
-
FRNCalloutView *calloutView,
|
|
47
|
-
const CalloutProps &props,
|
|
48
|
-
const LayoutMetrics &layoutMetrics)
|
|
49
|
-
{
|
|
50
|
-
const auto borderMetrics = props.resolveBorderMetrics(layoutMetrics);
|
|
51
|
-
calloutView.backgroundColor = RCTUIColorFromSharedColor(props.backgroundColor) ?: NSColor.clearColor;
|
|
52
|
-
calloutView.borderColor = RCTUIColorFromSharedColor(borderMetrics.borderColors.left) ?: NSColor.clearColor;
|
|
53
|
-
calloutView.borderWidth = borderMetrics.borderWidths.left;
|
|
54
|
-
calloutView.borderRadius = borderMetrics.borderRadii.topLeft.horizontal;
|
|
55
|
-
[calloutView setNeedsDisplay:YES];
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static RCTPlatformView *RCTFindComponentViewWithTag(RCTPlatformView *rootView, NSInteger tag)
|
|
59
|
-
{
|
|
60
|
-
if ([rootView conformsToProtocol:@protocol(RCTComponentViewProtocol)] &&
|
|
61
|
-
[((id<RCTComponentViewProtocol>)rootView).reactTag integerValue] == tag) {
|
|
62
|
-
return rootView;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
for (RCTPlatformView *subview in rootView.subviews) {
|
|
66
|
-
RCTPlatformView *match = RCTFindComponentViewWithTag(subview, tag);
|
|
67
|
-
if (match) {
|
|
68
|
-
return match;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return nil;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
@interface RCTCalloutComponentView () <RCTCalloutViewProtocol>
|
|
76
|
-
@end
|
|
77
|
-
|
|
78
|
-
@implementation RCTCalloutComponentView {
|
|
79
|
-
FRNCalloutView *_calloutView;
|
|
80
|
-
NSInteger _targetTag;
|
|
81
|
-
RCTSurfaceTouchHandler *_touchHandler;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
+ (ComponentDescriptorProvider)componentDescriptorProvider
|
|
85
|
-
{
|
|
86
|
-
// Fabric normalizes the legacy RCT-prefixed view name before component lookup.
|
|
87
|
-
return concreteComponentDescriptorProvider<CalloutComponentDescriptor>();
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
- (instancetype)initWithFrame:(CGRect)frame
|
|
91
|
-
{
|
|
92
|
-
if (self = [super initWithFrame:frame]) {
|
|
93
|
-
static const auto defaultProps = std::make_shared<const CalloutProps>();
|
|
94
|
-
_props = defaultProps;
|
|
95
|
-
|
|
96
|
-
// This view manages content mounted in the Callout window and must not render in the React surface.
|
|
97
|
-
self.hidden = YES;
|
|
98
|
-
|
|
99
|
-
_calloutView = [[FRNCalloutView alloc] initWithFrame:self.bounds];
|
|
100
|
-
|
|
101
|
-
__weak RCTCalloutComponentView *weakSelf = self;
|
|
102
|
-
_calloutView.onShow = ^(__unused NSDictionary *event) {
|
|
103
|
-
[weakSelf emitOnShow];
|
|
104
|
-
};
|
|
105
|
-
_calloutView.onDismiss = ^(__unused NSDictionary *event) {
|
|
106
|
-
[weakSelf emitOnDismiss];
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
_touchHandler = [RCTSurfaceTouchHandler new];
|
|
110
|
-
[_touchHandler attachToView:_calloutView.contentProxyView];
|
|
111
|
-
|
|
112
|
-
self.contentView = _calloutView;
|
|
113
|
-
}
|
|
114
|
-
return self;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
- (void)mountChildComponentView:(RCTUIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
|
|
118
|
-
{
|
|
119
|
-
[_calloutView mountContentSubview:childComponentView at:index];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
- (void)unmountChildComponentView:(RCTUIView<RCTComponentViewProtocol> *)childComponentView index:(__unused NSInteger)index
|
|
123
|
-
{
|
|
124
|
-
[_calloutView unmountContentSubview:childComponentView];
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
- (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &)oldProps
|
|
128
|
-
{
|
|
129
|
-
const auto &newProps = *std::static_pointer_cast<const CalloutProps>(props);
|
|
130
|
-
|
|
131
|
-
_calloutView.directionalHint = RCTNSRectEdgeFromDirectionalHint(newProps.directionalHint);
|
|
132
|
-
_calloutView.setInitialFocus = newProps.setInitialFocus;
|
|
133
|
-
|
|
134
|
-
const auto &rect = newProps.anchorRect;
|
|
135
|
-
_calloutView.anchorRect = NSMakeRect(rect.screenX, rect.screenY, rect.width, rect.height);
|
|
136
|
-
|
|
137
|
-
_targetTag = 0;
|
|
138
|
-
if (newProps.target.isNumber()) {
|
|
139
|
-
_targetTag = (NSInteger)newProps.target.asDouble();
|
|
140
|
-
}
|
|
141
|
-
[self updateAnchorView];
|
|
142
|
-
RCTApplyCalloutAppearance(_calloutView, newProps, _layoutMetrics);
|
|
143
|
-
|
|
144
|
-
[super updateProps:props oldProps:oldProps];
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
- (void)viewDidMoveToWindow
|
|
148
|
-
{
|
|
149
|
-
[super viewDidMoveToWindow];
|
|
150
|
-
[self updateAnchorView];
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
|
|
154
|
-
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics
|
|
155
|
-
{
|
|
156
|
-
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
157
|
-
|
|
158
|
-
const auto size = layoutMetrics.frame.size;
|
|
159
|
-
[_calloutView updateContentSize:NSMakeSize(size.width, size.height)];
|
|
160
|
-
|
|
161
|
-
const auto &props = *std::static_pointer_cast<const CalloutProps>(_props);
|
|
162
|
-
RCTApplyCalloutAppearance(_calloutView, props, layoutMetrics);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
- (void)prepareForRecycle
|
|
166
|
-
{
|
|
167
|
-
[super prepareForRecycle];
|
|
168
|
-
_targetTag = 0;
|
|
169
|
-
[_calloutView setAnchorView:nil];
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
- (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
|
|
173
|
-
{
|
|
174
|
-
RCTCalloutHandleCommand(self, commandName, args);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
- (void)focusWindow
|
|
178
|
-
{
|
|
179
|
-
[_calloutView focusWindow];
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
- (void)blurWindow
|
|
183
|
-
{
|
|
184
|
-
[_calloutView blurWindow];
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
- (void)updateAnchorView
|
|
188
|
-
{
|
|
189
|
-
RCTPlatformView *rootView = self.window.contentView;
|
|
190
|
-
[_calloutView setAnchorView:_targetTag > 0 && rootView ? RCTFindComponentViewWithTag(rootView, _targetTag) : nil];
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
- (void)emitOnShow
|
|
194
|
-
{
|
|
195
|
-
if (_eventEmitter) {
|
|
196
|
-
std::static_pointer_cast<const CalloutEventEmitter>(_eventEmitter)->onShow({.target = 0});
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
- (void)emitOnDismiss
|
|
201
|
-
{
|
|
202
|
-
if (_eventEmitter) {
|
|
203
|
-
std::static_pointer_cast<const CalloutEventEmitter>(_eventEmitter)->onDismiss({.target = 0});
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
@end
|
|
208
|
-
|
|
209
|
-
#endif
|
package/react-native.config.cjs
DELETED
package/src/Callout.stories.tsx
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
/** @jsxImportSource @fluentui-react-native/framework-base */
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { Pressable, StyleSheet, Text, View } from 'react-native';
|
|
4
|
-
|
|
5
|
-
import type { Meta, StoryObj } from '@storybook/react-native';
|
|
6
|
-
|
|
7
|
-
import { Callout } from './Callout';
|
|
8
|
-
import type { CalloutHandle, CalloutProps, DirectionalHint } from './Callout.types';
|
|
9
|
-
|
|
10
|
-
const directionalHints: readonly DirectionalHint[] = [
|
|
11
|
-
'leftTopEdge',
|
|
12
|
-
'leftCenter',
|
|
13
|
-
'leftBottomEdge',
|
|
14
|
-
'topLeftEdge',
|
|
15
|
-
'topAutoEdge',
|
|
16
|
-
'topCenter',
|
|
17
|
-
'topRightEdge',
|
|
18
|
-
'rightTopEdge',
|
|
19
|
-
'rightCenter',
|
|
20
|
-
'rightBottomEdge',
|
|
21
|
-
'bottomLeftEdge',
|
|
22
|
-
'bottomAutoEdge',
|
|
23
|
-
'bottomCenter',
|
|
24
|
-
'bottomRightEdge',
|
|
25
|
-
];
|
|
26
|
-
|
|
27
|
-
type CalloutExampleProps = CalloutProps & {
|
|
28
|
-
defaultVisible?: boolean;
|
|
29
|
-
showWindowCommands?: boolean;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const CalloutExample = ({ defaultVisible = false, onDismiss, onShow, showWindowCommands = false, ...props }: CalloutExampleProps) => {
|
|
33
|
-
const anchorRef = React.useRef<View>(null);
|
|
34
|
-
const calloutRef = React.useRef<CalloutHandle>(null);
|
|
35
|
-
const [visible, setVisible] = React.useState(defaultVisible);
|
|
36
|
-
const [status, setStatus] = React.useState(defaultVisible ? 'Opening' : 'Closed');
|
|
37
|
-
|
|
38
|
-
const dismiss = React.useCallback(() => {
|
|
39
|
-
setVisible(false);
|
|
40
|
-
setStatus('Dismissed');
|
|
41
|
-
onDismiss?.();
|
|
42
|
-
}, [onDismiss]);
|
|
43
|
-
|
|
44
|
-
const show = React.useCallback(() => {
|
|
45
|
-
setStatus('Shown');
|
|
46
|
-
onShow?.();
|
|
47
|
-
}, [onShow]);
|
|
48
|
-
|
|
49
|
-
return (
|
|
50
|
-
<View style={styles.story}>
|
|
51
|
-
<View>
|
|
52
|
-
<Pressable
|
|
53
|
-
accessibilityRole="button"
|
|
54
|
-
onPress={() => {
|
|
55
|
-
setVisible((current) => !current);
|
|
56
|
-
setStatus(visible ? 'Closed' : 'Opening');
|
|
57
|
-
}}
|
|
58
|
-
ref={anchorRef}
|
|
59
|
-
style={({ pressed }) => [styles.trigger, pressed && styles.triggerPressed]}
|
|
60
|
-
testID="agentic-storybook-callout-trigger"
|
|
61
|
-
>
|
|
62
|
-
<Text style={styles.triggerText}>{visible ? 'Close callout' : 'Open callout'}</Text>
|
|
63
|
-
</Pressable>
|
|
64
|
-
</View>
|
|
65
|
-
<Text accessibilityLiveRegion="polite" style={styles.status} testID="agentic-storybook-callout-status">
|
|
66
|
-
Native window: {status}
|
|
67
|
-
</Text>
|
|
68
|
-
{visible && (
|
|
69
|
-
<Callout {...props} componentRef={calloutRef} onDismiss={dismiss} onShow={show} target={anchorRef}>
|
|
70
|
-
<View style={styles.calloutContent} collapsable={false}>
|
|
71
|
-
<Text style={styles.heading}>Fabric Callout</Text>
|
|
72
|
-
<Text style={styles.body}>This content is hosted in a separate native window.</Text>
|
|
73
|
-
{showWindowCommands && (
|
|
74
|
-
<View style={styles.commandRow}>
|
|
75
|
-
<Pressable accessibilityRole="button" onPress={() => calloutRef.current?.focusWindow()} style={styles.command}>
|
|
76
|
-
<Text>Focus window</Text>
|
|
77
|
-
</Pressable>
|
|
78
|
-
<Pressable accessibilityRole="button" onPress={() => calloutRef.current?.blurWindow()} style={styles.command}>
|
|
79
|
-
<Text>Blur window</Text>
|
|
80
|
-
</Pressable>
|
|
81
|
-
</View>
|
|
82
|
-
)}
|
|
83
|
-
</View>
|
|
84
|
-
</Callout>
|
|
85
|
-
)}
|
|
86
|
-
</View>
|
|
87
|
-
);
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
type Placement = {
|
|
91
|
-
hint: DirectionalHint;
|
|
92
|
-
label: string;
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const placements: readonly Placement[] = [
|
|
96
|
-
{ hint: 'topCenter', label: 'Above' },
|
|
97
|
-
{ hint: 'rightCenter', label: 'Right' },
|
|
98
|
-
{ hint: 'bottomCenter', label: 'Below' },
|
|
99
|
-
{ hint: 'leftCenter', label: 'Left' },
|
|
100
|
-
];
|
|
101
|
-
|
|
102
|
-
const PlacementExample = (props: CalloutProps) => {
|
|
103
|
-
const aboveRef = React.useRef<View>(null);
|
|
104
|
-
const rightRef = React.useRef<View>(null);
|
|
105
|
-
const belowRef = React.useRef<View>(null);
|
|
106
|
-
const leftRef = React.useRef<View>(null);
|
|
107
|
-
const targetRefs = [aboveRef, rightRef, belowRef, leftRef] as const;
|
|
108
|
-
const [selectedIndex, setSelectedIndex] = React.useState<number>();
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<View style={styles.placementStory}>
|
|
112
|
-
{placements.map(({ hint, label }, index) => (
|
|
113
|
-
<View key={hint} style={styles.placementAnchor}>
|
|
114
|
-
<Pressable
|
|
115
|
-
accessibilityRole="button"
|
|
116
|
-
onPress={() => setSelectedIndex(index)}
|
|
117
|
-
ref={targetRefs[index]}
|
|
118
|
-
style={({ pressed }) => [styles.trigger, pressed && styles.triggerPressed]}
|
|
119
|
-
testID={`agentic-storybook-callout-placement-${hint}-trigger`}
|
|
120
|
-
>
|
|
121
|
-
<Text style={styles.triggerText}>{label}</Text>
|
|
122
|
-
</Pressable>
|
|
123
|
-
</View>
|
|
124
|
-
))}
|
|
125
|
-
{selectedIndex !== undefined && (
|
|
126
|
-
<Callout
|
|
127
|
-
{...props}
|
|
128
|
-
directionalHint={placements[selectedIndex].hint}
|
|
129
|
-
onDismiss={() => setSelectedIndex(undefined)}
|
|
130
|
-
target={targetRefs[selectedIndex]}
|
|
131
|
-
>
|
|
132
|
-
<View accessible style={styles.calloutContent} collapsable={false} testID="agentic-storybook-callout-placement-content">
|
|
133
|
-
<Text style={styles.heading}>{placements[selectedIndex].label}</Text>
|
|
134
|
-
<Text style={styles.body}>Click outside the native window to dismiss it.</Text>
|
|
135
|
-
</View>
|
|
136
|
-
</Callout>
|
|
137
|
-
)}
|
|
138
|
-
</View>
|
|
139
|
-
);
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
const meta: Meta<typeof Callout> = {
|
|
143
|
-
title: 'Native/Callout',
|
|
144
|
-
component: Callout,
|
|
145
|
-
args: {
|
|
146
|
-
accessibilityLabel: 'Callout example',
|
|
147
|
-
accessibilityRole: 'dialog',
|
|
148
|
-
backgroundColor: '#ffffff',
|
|
149
|
-
borderColor: '#d1d1d1',
|
|
150
|
-
borderRadius: 8,
|
|
151
|
-
borderWidth: 1,
|
|
152
|
-
directionalHint: 'bottomCenter',
|
|
153
|
-
maxWidth: 320,
|
|
154
|
-
setInitialFocus: false,
|
|
155
|
-
testID: 'agentic-storybook-callout',
|
|
156
|
-
},
|
|
157
|
-
argTypes: {
|
|
158
|
-
backgroundColor: { control: 'color' },
|
|
159
|
-
borderColor: { control: 'color' },
|
|
160
|
-
borderRadius: { control: { type: 'number', min: 0, max: 24, step: 1 } },
|
|
161
|
-
borderWidth: { control: { type: 'number', min: 0, max: 8, step: 1 } },
|
|
162
|
-
directionalHint: { control: 'select', options: directionalHints },
|
|
163
|
-
maxHeight: { control: { type: 'number', min: 80, max: 600, step: 20 } },
|
|
164
|
-
maxWidth: { control: { type: 'number', min: 120, max: 600, step: 20 } },
|
|
165
|
-
minWidth: { control: { type: 'number', min: 80, max: 400, step: 20 } },
|
|
166
|
-
setInitialFocus: { control: 'boolean' },
|
|
167
|
-
},
|
|
168
|
-
parameters: {
|
|
169
|
-
docs: {
|
|
170
|
-
description: {
|
|
171
|
-
component:
|
|
172
|
-
'Callout is an unstyled native primitive that presents React content in a transient window positioned relative to a target.',
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
},
|
|
176
|
-
};
|
|
177
|
-
|
|
178
|
-
export default meta;
|
|
179
|
-
|
|
180
|
-
type Story = StoryObj<typeof Callout>;
|
|
181
|
-
|
|
182
|
-
export const Default: Story = {
|
|
183
|
-
render: (args) => <CalloutExample {...args} defaultVisible />,
|
|
184
|
-
};
|
|
185
|
-
|
|
186
|
-
export const Placement: Story = {
|
|
187
|
-
render: (args) => <PlacementExample {...args} />,
|
|
188
|
-
parameters: {
|
|
189
|
-
docs: {
|
|
190
|
-
description: {
|
|
191
|
-
story: 'Each trigger requests one of four placement edges. The native Callout remains within the available work area.',
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
},
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
export const WindowCommands: Story = {
|
|
198
|
-
args: {
|
|
199
|
-
setInitialFocus: true,
|
|
200
|
-
},
|
|
201
|
-
render: (args) => <CalloutExample {...args} defaultVisible showWindowCommands />,
|
|
202
|
-
parameters: {
|
|
203
|
-
docs: {
|
|
204
|
-
description: {
|
|
205
|
-
story: 'The content buttons exercise Fabric touch handling and the imperative focusWindow and blurWindow native commands.',
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const styles = StyleSheet.create({
|
|
212
|
-
body: {
|
|
213
|
-
color: '#424242',
|
|
214
|
-
marginTop: 6,
|
|
215
|
-
},
|
|
216
|
-
calloutContent: {
|
|
217
|
-
backgroundColor: '#ffffff',
|
|
218
|
-
borderColor: '#d1d1d1',
|
|
219
|
-
borderRadius: 8,
|
|
220
|
-
borderWidth: 1,
|
|
221
|
-
padding: 16,
|
|
222
|
-
width: 280,
|
|
223
|
-
},
|
|
224
|
-
command: {
|
|
225
|
-
backgroundColor: '#f5f5f5',
|
|
226
|
-
borderColor: '#d1d1d1',
|
|
227
|
-
borderRadius: 4,
|
|
228
|
-
borderWidth: 1,
|
|
229
|
-
paddingHorizontal: 12,
|
|
230
|
-
paddingVertical: 8,
|
|
231
|
-
},
|
|
232
|
-
commandRow: {
|
|
233
|
-
flexDirection: 'row',
|
|
234
|
-
gap: 8,
|
|
235
|
-
marginTop: 16,
|
|
236
|
-
},
|
|
237
|
-
heading: {
|
|
238
|
-
color: '#242424',
|
|
239
|
-
fontSize: 16,
|
|
240
|
-
fontWeight: '600',
|
|
241
|
-
},
|
|
242
|
-
placementAnchor: {
|
|
243
|
-
margin: 32,
|
|
244
|
-
},
|
|
245
|
-
placementStory: {
|
|
246
|
-
alignItems: 'center',
|
|
247
|
-
flexDirection: 'row',
|
|
248
|
-
flexWrap: 'wrap',
|
|
249
|
-
justifyContent: 'center',
|
|
250
|
-
minHeight: 300,
|
|
251
|
-
width: 520,
|
|
252
|
-
},
|
|
253
|
-
status: {
|
|
254
|
-
color: '#616161',
|
|
255
|
-
marginTop: 12,
|
|
256
|
-
},
|
|
257
|
-
story: {
|
|
258
|
-
alignItems: 'center',
|
|
259
|
-
justifyContent: 'center',
|
|
260
|
-
minHeight: 300,
|
|
261
|
-
width: 520,
|
|
262
|
-
},
|
|
263
|
-
trigger: {
|
|
264
|
-
backgroundColor: '#0f6cbd',
|
|
265
|
-
borderRadius: 4,
|
|
266
|
-
paddingHorizontal: 16,
|
|
267
|
-
paddingVertical: 10,
|
|
268
|
-
},
|
|
269
|
-
triggerPressed: {
|
|
270
|
-
backgroundColor: '#115ea3',
|
|
271
|
-
},
|
|
272
|
-
triggerText: {
|
|
273
|
-
color: '#ffffff',
|
|
274
|
-
fontWeight: '600',
|
|
275
|
-
},
|
|
276
|
-
});
|
package/src/Callout.tsx
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
/** @jsxImportSource @fluentui-react-native/framework-base */
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
import { findNodeHandle, StyleSheet } from 'react-native';
|
|
4
|
-
|
|
5
|
-
import { directComponent, mergeProps, phasedComponent } from '@fluentui-react-native/framework-base';
|
|
6
|
-
|
|
7
|
-
import type { CalloutProps } from './Callout.types';
|
|
8
|
-
import { calloutName } from './Callout.types';
|
|
9
|
-
import NativeCalloutView, { Commands } from './CalloutNativeComponent';
|
|
10
|
-
|
|
11
|
-
const colorTransparent = '#00000000';
|
|
12
|
-
|
|
13
|
-
const styles = StyleSheet.create({
|
|
14
|
-
root: {
|
|
15
|
-
position: 'absolute',
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Renders the native Callout without applying theme or appearance defaults.
|
|
21
|
-
*/
|
|
22
|
-
export const Callout = phasedComponent<CalloutProps>((props) => {
|
|
23
|
-
const { componentRef, target } = props;
|
|
24
|
-
const nativeComponentRef = React.useRef<React.ElementRef<typeof NativeCalloutView> | null>(null);
|
|
25
|
-
const [nativeTarget, setNativeTarget] = React.useState<number | string | undefined>(undefined);
|
|
26
|
-
|
|
27
|
-
React.useImperativeHandle(
|
|
28
|
-
componentRef,
|
|
29
|
-
() => ({
|
|
30
|
-
blurWindow() {
|
|
31
|
-
if (nativeComponentRef.current !== null) {
|
|
32
|
-
Commands.blurWindow(nativeComponentRef.current);
|
|
33
|
-
}
|
|
34
|
-
},
|
|
35
|
-
focusWindow() {
|
|
36
|
-
if (nativeComponentRef.current !== null) {
|
|
37
|
-
Commands.focusWindow(nativeComponentRef.current);
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
}),
|
|
41
|
-
[],
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
React.useLayoutEffect(() => {
|
|
45
|
-
if (typeof target === 'string') {
|
|
46
|
-
setNativeTarget(target);
|
|
47
|
-
} else if (target?.current) {
|
|
48
|
-
setNativeTarget(findNodeHandle(target.current) ?? undefined);
|
|
49
|
-
} else {
|
|
50
|
-
setNativeTarget(undefined);
|
|
51
|
-
}
|
|
52
|
-
}, [target]);
|
|
53
|
-
|
|
54
|
-
return directComponent<CalloutProps>((renderProps) => {
|
|
55
|
-
const {
|
|
56
|
-
anchorRect,
|
|
57
|
-
backgroundColor,
|
|
58
|
-
beakWidth,
|
|
59
|
-
borderColor,
|
|
60
|
-
borderRadius,
|
|
61
|
-
borderWidth,
|
|
62
|
-
componentRef: _componentRef,
|
|
63
|
-
directionalHint,
|
|
64
|
-
dismissBehaviors,
|
|
65
|
-
gapSpace,
|
|
66
|
-
maxHeight,
|
|
67
|
-
maxWidth,
|
|
68
|
-
minPadding,
|
|
69
|
-
minWidth,
|
|
70
|
-
style,
|
|
71
|
-
target: _target,
|
|
72
|
-
...nativeProps
|
|
73
|
-
} = mergeProps(props, renderProps);
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Build the style for the callout based on the props. For `borderColor`, `borderWidth`, `backgroundColor`, and
|
|
77
|
-
* `borderRadius` defaults values are required otherwise crashes in CalloutView.swift:updateLayer() will occur.
|
|
78
|
-
*/
|
|
79
|
-
const calloutStyle = {
|
|
80
|
-
backgroundColor: backgroundColor ?? colorTransparent,
|
|
81
|
-
borderColor: borderColor ?? colorTransparent,
|
|
82
|
-
borderWidth: borderWidth ?? 0,
|
|
83
|
-
borderRadius: borderRadius ?? 0,
|
|
84
|
-
...(maxHeight != null && { maxHeight }),
|
|
85
|
-
...(maxWidth != null && { maxWidth }),
|
|
86
|
-
...(minWidth != null && { minWidth }),
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
return (
|
|
90
|
-
<NativeCalloutView
|
|
91
|
-
{...nativeProps}
|
|
92
|
-
anchorRect={anchorRect}
|
|
93
|
-
beakWidth={beakWidth}
|
|
94
|
-
directionalHint={directionalHint}
|
|
95
|
-
dismissBehaviors={dismissBehaviors}
|
|
96
|
-
gapSpace={gapSpace}
|
|
97
|
-
maxHeight={typeof maxHeight === 'number' ? maxHeight : undefined}
|
|
98
|
-
maxWidth={typeof maxWidth === 'number' ? maxWidth : undefined}
|
|
99
|
-
minPadding={minPadding}
|
|
100
|
-
minWidth={typeof minWidth === 'number' ? minWidth : undefined}
|
|
101
|
-
ref={nativeComponentRef}
|
|
102
|
-
style={[styles.root, calloutStyle, style]}
|
|
103
|
-
{...(nativeTarget !== undefined && { target: nativeTarget })}
|
|
104
|
-
/>
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
Callout.displayName = calloutName;
|
|
110
|
-
|
|
111
|
-
export default Callout;
|