@proulr/sdui-components 0.1.50 → 0.1.54
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 +8 -1
- package/src/bdc/components/forms.tsx +10 -0
- package/src/bdc/components/inbox.tsx +20 -0
- package/src/bdc/index.ts +2 -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/index.ts +2 -0
- package/src/renderer/sdui-chrome-scroll-context.tsx +115 -7
- package/src/renderer/sdui-component-registry.tsx +4 -0
- package/src/renderer/sdui-hybrid-renderer-context.tsx +11 -0
- package/src/renderer/ui/ChromeGlass.tsx +8 -29
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,
|
|
@@ -85,6 +86,7 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
85
86
|
expect(DiscoverProfileCard({ profileRef: 'p' }).type).toBe('discover_profile_card');
|
|
86
87
|
expect(DiscoverMap({}).type).toBe('discover_map');
|
|
87
88
|
expect(TextField({ placeholder: 'x' }).type).toBe('text_field');
|
|
89
|
+
expect(SelectRow({ label: 'Pick', optionsRef: 'form_options.gender' }).type).toBe('select_row');
|
|
88
90
|
expect(StoryRail({ surface: 'discover' }).type).toBe('story_rail');
|
|
89
91
|
expect(ProfileCompletionBanner({}).type).toBe('profile_completion_banner');
|
|
90
92
|
});
|
|
@@ -97,6 +99,11 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
97
99
|
expect(ChatInboxCapabilities({}).type).toBe('chat_inbox_capabilities');
|
|
98
100
|
expect(FlashInboxCapabilities({}).type).toBe('flash_inbox_capabilities');
|
|
99
101
|
expect(ProfileVisitsCapabilities({}).type).toBe('profile_visits_capabilities');
|
|
102
|
+
expect(InboxHubChrome({}).type).toBe('inbox_hub_chrome');
|
|
103
|
+
expect(InboxHubChrome({}).props).toMatchObject({
|
|
104
|
+
hub_ref: 'hub',
|
|
105
|
+
active_filter_ref: 'active_filter',
|
|
106
|
+
});
|
|
100
107
|
const menu = FloatingCreateMenu({
|
|
101
108
|
id: 'fab',
|
|
102
109
|
closedLabel: '+',
|
|
@@ -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;
|
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,
|
|
@@ -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,
|
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';
|
|
@@ -85,6 +87,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
85
87
|
section_header: SduiSectionHeaderBlock,
|
|
86
88
|
list_item: SduiListItemBlock,
|
|
87
89
|
toggle_row: SduiToggleRowBlock,
|
|
90
|
+
select_row: SduiSelectRowBlock,
|
|
88
91
|
chip: SduiChipBlock,
|
|
89
92
|
chip_row: SduiChipRowBlock,
|
|
90
93
|
segmented_tabs: SduiSegmentedTabsBlock,
|
|
@@ -95,6 +98,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
95
98
|
flash_inbox_capabilities: SduiFlashInboxCapabilitiesBlock,
|
|
96
99
|
profile_visits_capabilities: SduiProfileVisitsCapabilitiesBlock,
|
|
97
100
|
floating_create_menu: SduiFloatingCreateMenuBlock,
|
|
101
|
+
inbox_hub_chrome: SduiInboxHubChromeBlock,
|
|
98
102
|
discover_grid: SduiDiscoverGridBlock,
|
|
99
103
|
discover_profile_card: SduiDiscoverProfileCardBlock,
|
|
100
104
|
discover_map: SduiDiscoverMapBlock,
|
|
@@ -105,6 +105,17 @@ export type SduiHybridRenderers = {
|
|
|
105
105
|
renderFlashInboxCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
106
106
|
renderProfileVisitsCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
107
107
|
renderFloatingCreateMenu?: (props: SduiNativeBlockRenderProps) => ReactNode;
|
|
108
|
+
renderInboxHubChrome?: (
|
|
109
|
+
props: SduiNativeBlockRenderProps & {
|
|
110
|
+
hubRef?: string;
|
|
111
|
+
activeFilterRef?: string;
|
|
112
|
+
},
|
|
113
|
+
) => ReactNode;
|
|
114
|
+
/**
|
|
115
|
+
* Optional host wrap for screen body (ex.: InboxHubSduiProvider).
|
|
116
|
+
* Keeps domain providers out of the generic shell.
|
|
117
|
+
*/
|
|
118
|
+
wrapScreenBody?: (children: ReactNode) => ReactNode;
|
|
108
119
|
};
|
|
109
120
|
|
|
110
121
|
const SduiHybridRendererContext = createContext<SduiHybridRenderers>({});
|
|
@@ -25,34 +25,23 @@ const absoluteFill: ViewStyle = {
|
|
|
25
25
|
type ChromeGlassLayerProps = {
|
|
26
26
|
style?: StyleProp<ViewStyle>;
|
|
27
27
|
pointerEvents?: ViewProps['pointerEvents'];
|
|
28
|
-
/**
|
|
29
|
-
* When false, skip BlurView and keep the solid OLED pill base.
|
|
30
|
-
* Use on Android surfaces that animate (drawer slide) — BlurView + transform
|
|
31
|
-
* over image-heavy screens flashes black.
|
|
32
|
-
*/
|
|
33
|
-
blurEnabled?: boolean;
|
|
34
28
|
};
|
|
35
29
|
|
|
36
30
|
/**
|
|
37
31
|
* Camada de frost única do sistema (igual AppSideDrawer topo/base).
|
|
38
|
-
*
|
|
39
|
-
* never flash pure black. Overlay tint stays transparent (frost limpo).
|
|
32
|
+
* BlurView + `colors.chromeGlassOverlay` — sem cast cinza.
|
|
40
33
|
*/
|
|
41
34
|
export function ChromeGlassLayer({
|
|
42
35
|
style,
|
|
43
36
|
pointerEvents = 'none',
|
|
44
|
-
blurEnabled = true,
|
|
45
37
|
}: ChromeGlassLayerProps) {
|
|
46
38
|
return (
|
|
47
39
|
<View style={[absoluteFill, style]} pointerEvents={pointerEvents}>
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
style={StyleSheet.absoluteFill}
|
|
54
|
-
/>
|
|
55
|
-
) : null}
|
|
40
|
+
<BlurView
|
|
41
|
+
intensity={CHROME_GLASS_BLUR_INTENSITY}
|
|
42
|
+
tint={CHROME_GLASS_BLUR_TINT}
|
|
43
|
+
style={StyleSheet.absoluteFill}
|
|
44
|
+
/>
|
|
56
45
|
<View style={[absoluteFill, styles.tint]} />
|
|
57
46
|
</View>
|
|
58
47
|
);
|
|
@@ -62,31 +51,21 @@ type ChromeGlassShellProps = {
|
|
|
62
51
|
children: ReactNode;
|
|
63
52
|
style?: StyleProp<ViewStyle>;
|
|
64
53
|
contentStyle?: StyleProp<ViewStyle>;
|
|
65
|
-
/** Forwarded to `ChromeGlassLayer` — disable during slide animations on Android. */
|
|
66
|
-
blurEnabled?: boolean;
|
|
67
54
|
};
|
|
68
55
|
|
|
69
56
|
/**
|
|
70
57
|
* Pílula chrome com o mesmo glass do drawer (shell + blur + overlay).
|
|
71
58
|
*/
|
|
72
|
-
export function ChromeGlassShell({
|
|
73
|
-
children,
|
|
74
|
-
style,
|
|
75
|
-
contentStyle,
|
|
76
|
-
blurEnabled = true,
|
|
77
|
-
}: ChromeGlassShellProps) {
|
|
59
|
+
export function ChromeGlassShell({ children, style, contentStyle }: ChromeGlassShellProps) {
|
|
78
60
|
return (
|
|
79
61
|
<View style={[chromePillStyles.shell, styles.shellTransparent, style]}>
|
|
80
|
-
<ChromeGlassLayer
|
|
62
|
+
<ChromeGlassLayer />
|
|
81
63
|
<View style={[styles.content, contentStyle]}>{children}</View>
|
|
82
64
|
</View>
|
|
83
65
|
);
|
|
84
66
|
}
|
|
85
67
|
|
|
86
68
|
const styles = StyleSheet.create({
|
|
87
|
-
solidBase: {
|
|
88
|
-
backgroundColor: colors.chromePillBackground,
|
|
89
|
-
},
|
|
90
69
|
tint: {
|
|
91
70
|
backgroundColor: colors.chromeGlassOverlay,
|
|
92
71
|
},
|