@proulr/sdui-components 0.1.51 → 0.1.55
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/package.json +1 -1
- package/src/bdc/components/bdc-components.test.ts +10 -1
- package/src/bdc/components/forms.tsx +10 -0
- package/src/bdc/components/inbox.tsx +20 -0
- package/src/bdc/components/native-blocks.tsx +1 -0
- package/src/bdc/index.ts +3 -1
- package/src/catalog/block-types.ts +2 -0
- package/src/catalog/catalog.test.ts +2 -0
- package/src/renderer/SduiScreenRenderer.tsx +1 -1
- package/src/renderer/blocks/SduiInboxBlocks.tsx +14 -0
- package/src/renderer/blocks/SduiLayoutBlocks.tsx +25 -0
- package/src/renderer/blocks/SduiNativeDomainBlocks.tsx +7 -0
- package/src/renderer/index.ts +2 -0
- package/src/renderer/sdui-chrome-scroll-context.tsx +115 -7
- package/src/renderer/sdui-component-registry.tsx +6 -0
- package/src/renderer/sdui-hybrid-renderer-context.tsx +12 -0
- package/src/renderer/ui/story-surface-picker.tsx +9 -3
package/package.json
CHANGED
|
@@ -6,12 +6,13 @@ import {
|
|
|
6
6
|
DiscoverMap,
|
|
7
7
|
DiscoverProfileCard,
|
|
8
8
|
} from './discover';
|
|
9
|
-
import { TextField } from './forms';
|
|
9
|
+
import { SelectRow, TextField } from './forms';
|
|
10
10
|
import {
|
|
11
11
|
ChatInboxCapabilities,
|
|
12
12
|
EmptyState,
|
|
13
13
|
FlashInboxCapabilities,
|
|
14
14
|
FloatingCreateMenu,
|
|
15
|
+
InboxHubChrome,
|
|
15
16
|
InboxPersonRow,
|
|
16
17
|
InboxSearchField,
|
|
17
18
|
ProfileVisitsCapabilities,
|
|
@@ -28,6 +29,7 @@ import {
|
|
|
28
29
|
DiscoverBrowseLocation,
|
|
29
30
|
NewPostComposer,
|
|
30
31
|
NewStoryComposer,
|
|
32
|
+
StoryViewersPanel,
|
|
31
33
|
PostComments,
|
|
32
34
|
ProfileOnboarding,
|
|
33
35
|
ProfileReport,
|
|
@@ -85,6 +87,7 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
85
87
|
expect(DiscoverProfileCard({ profileRef: 'p' }).type).toBe('discover_profile_card');
|
|
86
88
|
expect(DiscoverMap({}).type).toBe('discover_map');
|
|
87
89
|
expect(TextField({ placeholder: 'x' }).type).toBe('text_field');
|
|
90
|
+
expect(SelectRow({ label: 'Pick', optionsRef: 'form_options.gender' }).type).toBe('select_row');
|
|
88
91
|
expect(StoryRail({ surface: 'discover' }).type).toBe('story_rail');
|
|
89
92
|
expect(ProfileCompletionBanner({}).type).toBe('profile_completion_banner');
|
|
90
93
|
});
|
|
@@ -97,6 +100,11 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
97
100
|
expect(ChatInboxCapabilities({}).type).toBe('chat_inbox_capabilities');
|
|
98
101
|
expect(FlashInboxCapabilities({}).type).toBe('flash_inbox_capabilities');
|
|
99
102
|
expect(ProfileVisitsCapabilities({}).type).toBe('profile_visits_capabilities');
|
|
103
|
+
expect(InboxHubChrome({}).type).toBe('inbox_hub_chrome');
|
|
104
|
+
expect(InboxHubChrome({}).props).toMatchObject({
|
|
105
|
+
hub_ref: 'hub',
|
|
106
|
+
active_filter_ref: 'active_filter',
|
|
107
|
+
});
|
|
100
108
|
const menu = FloatingCreateMenu({
|
|
101
109
|
id: 'fab',
|
|
102
110
|
closedLabel: '+',
|
|
@@ -123,6 +131,7 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
123
131
|
AlbumDetail,
|
|
124
132
|
NewPostComposer,
|
|
125
133
|
NewStoryComposer,
|
|
134
|
+
StoryViewersPanel,
|
|
126
135
|
PostComments,
|
|
127
136
|
SocialProfile,
|
|
128
137
|
SettingsHome,
|
|
@@ -18,3 +18,13 @@ type TextFieldProps = LayoutProps & {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export const TextField: BdcComponent = (props) => layoutBlock('text_field', props as TextFieldProps);
|
|
21
|
+
|
|
22
|
+
type SelectRowProps = LayoutProps & {
|
|
23
|
+
label?: string;
|
|
24
|
+
dataRef?: string;
|
|
25
|
+
optionsRef?: string;
|
|
26
|
+
changeActionId?: string;
|
|
27
|
+
disabled?: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export const SelectRow: BdcComponent = (props) => layoutBlock('select_row', props as SelectRowProps);
|
|
@@ -81,6 +81,26 @@ type FloatingCreateMenuProps = {
|
|
|
81
81
|
actions: FloatingCreateMenuActionProps[];
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
type InboxHubChromeProps = {
|
|
85
|
+
id?: string;
|
|
86
|
+
hubRef?: string;
|
|
87
|
+
activeFilterRef?: string;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Overlay do seletor/filtros do hub inbox (sibling do Scroll).
|
|
92
|
+
* Hybrid nativo: collapse + badges realtime; actions via onAction.
|
|
93
|
+
*/
|
|
94
|
+
export const InboxHubChrome: BdcComponent = (props) =>
|
|
95
|
+
leafBlock('inbox_hub_chrome', {
|
|
96
|
+
...(typeof (props as InboxHubChromeProps).id === 'string'
|
|
97
|
+
? { id: (props as InboxHubChromeProps).id }
|
|
98
|
+
: {}),
|
|
99
|
+
hub_ref: (props as InboxHubChromeProps).hubRef ?? 'hub',
|
|
100
|
+
active_filter_ref:
|
|
101
|
+
(props as InboxHubChromeProps).activeFilterRef ?? 'active_filter',
|
|
102
|
+
});
|
|
103
|
+
|
|
84
104
|
/** Overlay FAB “+” (sibling do Scroll) — ações via action_id do wire. */
|
|
85
105
|
export const FloatingCreateMenu: BdcComponent = (props) => {
|
|
86
106
|
const menu = props as FloatingCreateMenuProps;
|
|
@@ -30,6 +30,7 @@ export const AlbumGrid: BdcComponent = (props) => nativeBlock('album_grid', prop
|
|
|
30
30
|
export const AlbumDetail: BdcComponent = (props) => nativeBlock('album_detail', props);
|
|
31
31
|
export const NewPostComposer: BdcComponent = (props) => nativeBlock('new_post_composer', props);
|
|
32
32
|
export const NewStoryComposer: BdcComponent = (props) => nativeBlock('new_story_composer', props);
|
|
33
|
+
export const StoryViewersPanel: BdcComponent = (props) => nativeBlock('story_viewers_panel', props);
|
|
33
34
|
export const PostComments: BdcComponent = (props) => nativeBlock('post_comments', props);
|
|
34
35
|
export const SocialProfile: BdcComponent = (props) => nativeBlock('social_profile', props);
|
|
35
36
|
export const SettingsHome: BdcComponent = (props) => nativeBlock('settings_home', props);
|
package/src/bdc/index.ts
CHANGED
|
@@ -23,13 +23,14 @@ export {
|
|
|
23
23
|
EmptyState,
|
|
24
24
|
FlashInboxCapabilities,
|
|
25
25
|
FloatingCreateMenu,
|
|
26
|
+
InboxHubChrome,
|
|
26
27
|
InboxPersonRow,
|
|
27
28
|
InboxSearchField,
|
|
28
29
|
ProfileVisitsCapabilities,
|
|
29
30
|
SegmentedTabs,
|
|
30
31
|
} from './components/inbox';
|
|
31
32
|
export type { FloatingCreateMenuActionProps } from './components/inbox';
|
|
32
|
-
export { TextField } from './components/forms';
|
|
33
|
+
export { TextField, SelectRow } from './components/forms';
|
|
33
34
|
export { ProfileCompletionBanner, StoryRail } from './components/social';
|
|
34
35
|
export {
|
|
35
36
|
AlbumDetail,
|
|
@@ -37,6 +38,7 @@ export {
|
|
|
37
38
|
ChatThread,
|
|
38
39
|
NewPostComposer,
|
|
39
40
|
NewStoryComposer,
|
|
41
|
+
StoryViewersPanel,
|
|
40
42
|
PostComments,
|
|
41
43
|
ProfileOnboarding,
|
|
42
44
|
ProfileReport,
|
|
@@ -32,7 +32,9 @@ import {
|
|
|
32
32
|
describe('block-types', () => {
|
|
33
33
|
it('lists known block types', () => {
|
|
34
34
|
expect(SDUI_BLOCK_TYPES).toContain('text');
|
|
35
|
+
expect(SDUI_BLOCK_TYPES).toContain('inbox_hub_chrome');
|
|
35
36
|
expect(isKnownBlockType('button')).toBe(true);
|
|
37
|
+
expect(isKnownBlockType('inbox_hub_chrome')).toBe(true);
|
|
36
38
|
expect(isKnownBlockType('unknown_block')).toBe(false);
|
|
37
39
|
});
|
|
38
40
|
});
|
|
@@ -11,7 +11,7 @@ type Props = {
|
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
/** Blocos overlay (FAB etc.) — não competem por flex com o Scroll. */
|
|
14
|
-
const OVERLAY_BLOCK_TYPES = new Set(['floating_create_menu']);
|
|
14
|
+
const OVERLAY_BLOCK_TYPES = new Set(['floating_create_menu', 'inbox_hub_chrome']);
|
|
15
15
|
|
|
16
16
|
export function SduiScreenRenderer({ screen, onAction }: Props) {
|
|
17
17
|
return (
|
|
@@ -227,6 +227,20 @@ export function SduiFloatingCreateMenuBlock(props: SduiBlockRenderProps) {
|
|
|
227
227
|
return <>{hybrid.renderFloatingCreateMenu(props)}</>;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
export function SduiInboxHubChromeBlock(props: SduiBlockRenderProps) {
|
|
231
|
+
const hybrid = useSduiHybridRenderer();
|
|
232
|
+
if (typeof hybrid.renderInboxHubChrome !== 'function') return null;
|
|
233
|
+
return (
|
|
234
|
+
<>
|
|
235
|
+
{hybrid.renderInboxHubChrome({
|
|
236
|
+
...props,
|
|
237
|
+
hubRef: readStringProp(props.block, 'hub_ref') ?? 'hub',
|
|
238
|
+
activeFilterRef: readStringProp(props.block, 'active_filter_ref') ?? 'active_filter',
|
|
239
|
+
})}
|
|
240
|
+
</>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
230
244
|
const styles = StyleSheet.create({
|
|
231
245
|
segmentTrack: {
|
|
232
246
|
flexDirection: 'row',
|
|
@@ -5,9 +5,11 @@ import { Card } from '../ui/Card';
|
|
|
5
5
|
import { AppIcon } from '../ui/app-icon';
|
|
6
6
|
import { colors, fonts, m3Colors, m3Type, spacing } from '../theme/proulr-theme';
|
|
7
7
|
import {
|
|
8
|
+
resolveDataRef,
|
|
8
9
|
resolveDataRefBoolean,
|
|
9
10
|
resolveDataRefString,
|
|
10
11
|
} from '../lib/resolve-data-ref';
|
|
12
|
+
import { SelectRow as UiSelectRow } from '../ui/SelectRow';
|
|
11
13
|
import { resolveViewStyleProps } from '../theme/resolve-style-props';
|
|
12
14
|
import type { SduiBlockRenderProps } from './SduiPrimitiveBlocks';
|
|
13
15
|
|
|
@@ -117,6 +119,29 @@ export function SduiToggleRowBlock({ block, data, onAction }: SduiBlockRenderPro
|
|
|
117
119
|
);
|
|
118
120
|
}
|
|
119
121
|
|
|
122
|
+
export function SduiSelectRowBlock({ block, data, onAction }: SduiBlockRenderProps) {
|
|
123
|
+
const label = readStringProp(block, 'label') ?? '';
|
|
124
|
+
const dataRef = readStringProp(block, 'data_ref');
|
|
125
|
+
const optionsRef = readStringProp(block, 'options_ref');
|
|
126
|
+
const changeActionId = readStringProp(block, 'change_action_id');
|
|
127
|
+
const disabled = readBooleanProp(block, 'disabled');
|
|
128
|
+
const value = dataRef ? resolveDataRefString(data, dataRef) : '';
|
|
129
|
+
const optionsRaw = optionsRef ? resolveDataRef(data, optionsRef) : [];
|
|
130
|
+
const options = Array.isArray(optionsRaw) ? optionsRaw.map(String) : [];
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<UiSelectRow
|
|
134
|
+
label={label}
|
|
135
|
+
value={value || null}
|
|
136
|
+
options={options}
|
|
137
|
+
onChange={(next) => {
|
|
138
|
+
if (disabled || !changeActionId) return;
|
|
139
|
+
onAction(changeActionId, { value: next });
|
|
140
|
+
}}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
120
145
|
const styles = StyleSheet.create({
|
|
121
146
|
card: {
|
|
122
147
|
paddingVertical: spacing.xs,
|
|
@@ -30,6 +30,7 @@ function NativeBlockShell({
|
|
|
30
30
|
| 'renderAlbumDetail'
|
|
31
31
|
| 'renderNewPostComposer'
|
|
32
32
|
| 'renderNewStoryComposer'
|
|
33
|
+
| 'renderStoryViewersPanel'
|
|
33
34
|
| 'renderPostComments'
|
|
34
35
|
| 'renderSocialProfile'
|
|
35
36
|
| 'renderSettingsHome'
|
|
@@ -118,6 +119,12 @@ export function SduiNewStoryComposerBlock(props: SduiBlockRenderProps) {
|
|
|
118
119
|
return <NativeBlockShell {...props} rendererKey="renderNewStoryComposer" fallbackLabel="Novo story" />;
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
export function SduiStoryViewersPanelBlock(props: SduiBlockRenderProps) {
|
|
123
|
+
return (
|
|
124
|
+
<NativeBlockShell {...props} rendererKey="renderStoryViewersPanel" fallbackLabel="Story viewers" />
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
121
128
|
export function SduiPostCommentsBlock(props: SduiBlockRenderProps) {
|
|
122
129
|
return <NativeBlockShell {...props} rendererKey="renderPostComments" fallbackLabel="Comentários" />;
|
|
123
130
|
}
|
package/src/renderer/index.ts
CHANGED
|
@@ -12,11 +12,13 @@ export {
|
|
|
12
12
|
export {
|
|
13
13
|
SduiChromeScrollProvider,
|
|
14
14
|
useSduiChromeScroll,
|
|
15
|
+
useSduiChromeScrollOverlayRegistry,
|
|
15
16
|
} from './sdui-chrome-scroll-context';
|
|
16
17
|
export type {
|
|
17
18
|
SduiChromeScrollConfig,
|
|
18
19
|
SduiChromeScrollInsetProps,
|
|
19
20
|
SduiChromeScrollInsets,
|
|
21
|
+
SduiChromeScrollOverlayContribution,
|
|
20
22
|
} from './sdui-chrome-scroll-context';
|
|
21
23
|
export type {
|
|
22
24
|
SduiHybridDiscoverMapProps,
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
-
import React, {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import React, {
|
|
2
|
+
createContext,
|
|
3
|
+
useCallback,
|
|
4
|
+
useContext,
|
|
5
|
+
useMemo,
|
|
6
|
+
useState,
|
|
7
|
+
type ReactElement,
|
|
8
|
+
type ReactNode,
|
|
9
|
+
} from 'react';
|
|
10
|
+
import {
|
|
11
|
+
Platform,
|
|
12
|
+
type NativeScrollEvent,
|
|
13
|
+
type NativeSyntheticEvent,
|
|
14
|
+
type RefreshControlProps,
|
|
15
|
+
type ViewStyle,
|
|
7
16
|
} from 'react-native';
|
|
8
17
|
|
|
9
18
|
export type SduiChromeScrollInsetProps = {
|
|
@@ -31,7 +40,74 @@ export type SduiChromeScrollConfig = {
|
|
|
31
40
|
scrollViewProps?: Record<string, unknown>;
|
|
32
41
|
};
|
|
33
42
|
|
|
43
|
+
export type SduiChromeScrollOverlayContribution = {
|
|
44
|
+
/** Altura reservada abaixo do AppHeader (ex.: seletor + filtros do inbox). */
|
|
45
|
+
extraTopInset?: number;
|
|
46
|
+
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
type OverlayRegistry = {
|
|
50
|
+
register: (id: string, contribution: SduiChromeScrollOverlayContribution) => () => void;
|
|
51
|
+
};
|
|
52
|
+
|
|
34
53
|
const SduiChromeScrollContext = createContext<SduiChromeScrollConfig | null>(null);
|
|
54
|
+
const SduiChromeScrollOverlayRegistryContext = createContext<OverlayRegistry | null>(null);
|
|
55
|
+
|
|
56
|
+
function mergeChromeScrollConfig(
|
|
57
|
+
base: SduiChromeScrollConfig,
|
|
58
|
+
overlays: Map<string, SduiChromeScrollOverlayContribution>,
|
|
59
|
+
): SduiChromeScrollConfig {
|
|
60
|
+
let extraTop = 0;
|
|
61
|
+
const scrollHandlers: ((event: NativeSyntheticEvent<NativeScrollEvent>) => void)[] = [];
|
|
62
|
+
if (base.onScroll) scrollHandlers.push(base.onScroll);
|
|
63
|
+
|
|
64
|
+
for (const contribution of overlays.values()) {
|
|
65
|
+
if (typeof contribution.extraTopInset === 'number' && contribution.extraTopInset > 0) {
|
|
66
|
+
extraTop = Math.max(extraTop, contribution.extraTopInset);
|
|
67
|
+
}
|
|
68
|
+
if (contribution.onScroll) scrollHandlers.push(contribution.onScroll);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (extraTop <= 0 && scrollHandlers.length <= (base.onScroll ? 1 : 0)) {
|
|
72
|
+
return base;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const contentContainerStyle: ViewStyle = { ...base.contentContainerStyle };
|
|
76
|
+
let scrollInsetProps: SduiChromeScrollInsetProps = { ...base.scrollInsetProps };
|
|
77
|
+
|
|
78
|
+
if (extraTop > 0) {
|
|
79
|
+
// Paridade com buildSduiChromeScrollConfig(extraTopInset): iOS reserva header via contentInset.
|
|
80
|
+
const headerTop = base.chromeInsets.top;
|
|
81
|
+
const insetTop = headerTop + extraTop;
|
|
82
|
+
contentContainerStyle.paddingTop = Platform.OS === 'ios' ? extraTop : insetTop;
|
|
83
|
+
if (Platform.OS === 'ios') {
|
|
84
|
+
scrollInsetProps = {
|
|
85
|
+
contentInset: {
|
|
86
|
+
top: insetTop,
|
|
87
|
+
bottom: base.chromeInsets.bottom,
|
|
88
|
+
},
|
|
89
|
+
contentOffset: { x: 0, y: -insetTop },
|
|
90
|
+
automaticallyAdjustContentInsets: false,
|
|
91
|
+
scrollIndicatorInsets: {
|
|
92
|
+
top: insetTop,
|
|
93
|
+
bottom: base.chromeInsets.bottom,
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
...base,
|
|
101
|
+
contentContainerStyle,
|
|
102
|
+
scrollInsetProps,
|
|
103
|
+
onScroll:
|
|
104
|
+
scrollHandlers.length > 0
|
|
105
|
+
? (event) => {
|
|
106
|
+
for (const handler of scrollHandlers) handler(event);
|
|
107
|
+
}
|
|
108
|
+
: undefined,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
35
111
|
|
|
36
112
|
export function SduiChromeScrollProvider({
|
|
37
113
|
value,
|
|
@@ -40,11 +116,43 @@ export function SduiChromeScrollProvider({
|
|
|
40
116
|
value: SduiChromeScrollConfig;
|
|
41
117
|
children: ReactNode;
|
|
42
118
|
}) {
|
|
119
|
+
const [overlays, setOverlays] = useState(
|
|
120
|
+
() => new Map<string, SduiChromeScrollOverlayContribution>(),
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
const register = useCallback((id: string, contribution: SduiChromeScrollOverlayContribution) => {
|
|
124
|
+
setOverlays((prev) => {
|
|
125
|
+
const next = new Map(prev);
|
|
126
|
+
next.set(id, contribution);
|
|
127
|
+
return next;
|
|
128
|
+
});
|
|
129
|
+
return () => {
|
|
130
|
+
setOverlays((prev) => {
|
|
131
|
+
if (!prev.has(id)) return prev;
|
|
132
|
+
const next = new Map(prev);
|
|
133
|
+
next.delete(id);
|
|
134
|
+
return next;
|
|
135
|
+
});
|
|
136
|
+
};
|
|
137
|
+
}, []);
|
|
138
|
+
|
|
139
|
+
const registry = useMemo<OverlayRegistry>(() => ({ register }), [register]);
|
|
140
|
+
const merged = useMemo(() => mergeChromeScrollConfig(value, overlays), [overlays, value]);
|
|
141
|
+
|
|
43
142
|
return (
|
|
44
|
-
<
|
|
143
|
+
<SduiChromeScrollOverlayRegistryContext.Provider value={registry}>
|
|
144
|
+
<SduiChromeScrollContext.Provider value={merged}>{children}</SduiChromeScrollContext.Provider>
|
|
145
|
+
</SduiChromeScrollOverlayRegistryContext.Provider>
|
|
45
146
|
);
|
|
46
147
|
}
|
|
47
148
|
|
|
48
149
|
export function useSduiChromeScroll(): SduiChromeScrollConfig | null {
|
|
49
150
|
return useContext(SduiChromeScrollContext);
|
|
50
151
|
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Hybrids de overlay (ex.: inbox_hub_chrome) registram inset/onScroll sem especializar o shell.
|
|
155
|
+
*/
|
|
156
|
+
export function useSduiChromeScrollOverlayRegistry(): OverlayRegistry | null {
|
|
157
|
+
return useContext(SduiChromeScrollOverlayRegistryContext);
|
|
158
|
+
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
SduiCardBlock,
|
|
17
17
|
SduiListItemBlock,
|
|
18
18
|
SduiSectionHeaderBlock,
|
|
19
|
+
SduiSelectRowBlock,
|
|
19
20
|
SduiToggleRowBlock,
|
|
20
21
|
} from './blocks/SduiLayoutBlocks';
|
|
21
22
|
import {
|
|
@@ -38,6 +39,7 @@ import {
|
|
|
38
39
|
SduiInboxSearchFieldBlock,
|
|
39
40
|
SduiProfileVisitsCapabilitiesBlock,
|
|
40
41
|
SduiFloatingCreateMenuBlock,
|
|
42
|
+
SduiInboxHubChromeBlock,
|
|
41
43
|
SduiSegmentedTabsBlock,
|
|
42
44
|
} from './blocks/SduiInboxBlocks';
|
|
43
45
|
import { SduiNativeAdBlock } from './blocks/SduiNativeAdBlock';
|
|
@@ -48,6 +50,7 @@ import {
|
|
|
48
50
|
SduiChatThreadBlock,
|
|
49
51
|
SduiNewPostComposerBlock,
|
|
50
52
|
SduiNewStoryComposerBlock,
|
|
53
|
+
SduiStoryViewersPanelBlock,
|
|
51
54
|
SduiPostCommentsBlock,
|
|
52
55
|
SduiProfileOnboardingBlock,
|
|
53
56
|
SduiProfileSelfBlock,
|
|
@@ -85,6 +88,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
85
88
|
section_header: SduiSectionHeaderBlock,
|
|
86
89
|
list_item: SduiListItemBlock,
|
|
87
90
|
toggle_row: SduiToggleRowBlock,
|
|
91
|
+
select_row: SduiSelectRowBlock,
|
|
88
92
|
chip: SduiChipBlock,
|
|
89
93
|
chip_row: SduiChipRowBlock,
|
|
90
94
|
segmented_tabs: SduiSegmentedTabsBlock,
|
|
@@ -95,6 +99,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
95
99
|
flash_inbox_capabilities: SduiFlashInboxCapabilitiesBlock,
|
|
96
100
|
profile_visits_capabilities: SduiProfileVisitsCapabilitiesBlock,
|
|
97
101
|
floating_create_menu: SduiFloatingCreateMenuBlock,
|
|
102
|
+
inbox_hub_chrome: SduiInboxHubChromeBlock,
|
|
98
103
|
discover_grid: SduiDiscoverGridBlock,
|
|
99
104
|
discover_profile_card: SduiDiscoverProfileCardBlock,
|
|
100
105
|
discover_map: SduiDiscoverMapBlock,
|
|
@@ -113,6 +118,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
113
118
|
album_detail: SduiAlbumDetailBlock,
|
|
114
119
|
new_post_composer: SduiNewPostComposerBlock,
|
|
115
120
|
new_story_composer: SduiNewStoryComposerBlock,
|
|
121
|
+
story_viewers_panel: SduiStoryViewersPanelBlock,
|
|
116
122
|
post_comments: SduiPostCommentsBlock,
|
|
117
123
|
social_profile: SduiSocialProfileBlock,
|
|
118
124
|
settings_home: SduiSettingsHomeBlock,
|
|
@@ -66,6 +66,7 @@ export type SduiHybridRenderers = {
|
|
|
66
66
|
renderAlbumDetail?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
67
67
|
renderNewPostComposer?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
68
68
|
renderNewStoryComposer?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
69
|
+
renderStoryViewersPanel?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
69
70
|
renderPostComments?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
70
71
|
renderSocialProfile?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
71
72
|
renderSettingsHome?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
@@ -105,6 +106,17 @@ export type SduiHybridRenderers = {
|
|
|
105
106
|
renderFlashInboxCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
106
107
|
renderProfileVisitsCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
107
108
|
renderFloatingCreateMenu?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
109
|
+
renderInboxHubChrome?: (
|
|
110
|
+
props: SduiNativeBlockRenderProps & {
|
|
111
|
+
hubRef?: string;
|
|
112
|
+
activeFilterRef?: string;
|
|
113
|
+
},
|
|
114
|
+
) => ReactNode;
|
|
115
|
+
/**
|
|
116
|
+
* Optional host wrap for screen body (ex.: InboxHubSduiProvider).
|
|
117
|
+
* Keeps domain providers out of the generic shell.
|
|
118
|
+
*/
|
|
119
|
+
wrapScreenBody?: (children: ReactNode) => ReactNode;
|
|
108
120
|
};
|
|
109
121
|
|
|
110
122
|
const SduiHybridRendererContext = createContext<SduiHybridRenderers>({});
|
|
@@ -12,23 +12,29 @@ export function StorySurfacePicker({
|
|
|
12
12
|
visible,
|
|
13
13
|
value,
|
|
14
14
|
options,
|
|
15
|
+
title,
|
|
16
|
+
subtitle,
|
|
17
|
+
closeLabel,
|
|
15
18
|
onClose,
|
|
16
19
|
onSelect,
|
|
17
20
|
}: {
|
|
18
21
|
visible: boolean;
|
|
19
22
|
value: string;
|
|
20
23
|
options: StorySurfaceOption[];
|
|
24
|
+
title: string;
|
|
25
|
+
subtitle: string;
|
|
26
|
+
closeLabel: string;
|
|
21
27
|
onClose: () => void;
|
|
22
28
|
onSelect: (value: string) => void;
|
|
23
29
|
}) {
|
|
24
30
|
return (
|
|
25
31
|
<Modal visible={visible} transparent animationType="slide" onRequestClose={onClose}>
|
|
26
32
|
<View style={styles.backdrop}>
|
|
27
|
-
<Pressable style={styles.backdropPress} onPress={onClose} accessibilityLabel=
|
|
33
|
+
<Pressable style={styles.backdropPress} onPress={onClose} accessibilityLabel={closeLabel} />
|
|
28
34
|
<View style={styles.sheet}>
|
|
29
35
|
<View style={styles.handle} />
|
|
30
|
-
<Text style={styles.title}>
|
|
31
|
-
<Text style={styles.subtitle}>
|
|
36
|
+
<Text style={styles.title}>{title}</Text>
|
|
37
|
+
<Text style={styles.subtitle}>{subtitle}</Text>
|
|
32
38
|
|
|
33
39
|
{options.map((option) => {
|
|
34
40
|
const selected = option.value === value;
|