@proulr/sdui-components 0.1.54 → 0.1.56
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 +2 -0
- package/src/bdc/components/native-blocks.tsx +1 -0
- package/src/bdc/index.ts +1 -0
- package/src/renderer/blocks/SduiNativeDomainBlocks.tsx +7 -0
- package/src/renderer/sdui-component-registry.tsx +2 -0
- package/src/renderer/sdui-hybrid-renderer-context.tsx +1 -0
- package/src/renderer/ui/compose-pill-input.tsx +38 -10
- package/src/renderer/ui/index.ts +2 -0
- package/src/renderer/ui/story-surface-picker.tsx +9 -3
package/package.json
CHANGED
|
@@ -29,6 +29,7 @@ import {
|
|
|
29
29
|
DiscoverBrowseLocation,
|
|
30
30
|
NewPostComposer,
|
|
31
31
|
NewStoryComposer,
|
|
32
|
+
StoryViewersPanel,
|
|
32
33
|
PostComments,
|
|
33
34
|
ProfileOnboarding,
|
|
34
35
|
ProfileReport,
|
|
@@ -130,6 +131,7 @@ describe('bdc discover/forms/social/inbox/native', () => {
|
|
|
130
131
|
AlbumDetail,
|
|
131
132
|
NewPostComposer,
|
|
132
133
|
NewStoryComposer,
|
|
134
|
+
StoryViewersPanel,
|
|
133
135
|
PostComments,
|
|
134
136
|
SocialProfile,
|
|
135
137
|
SettingsHome,
|
|
@@ -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
|
@@ -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
|
}
|
|
@@ -50,6 +50,7 @@ import {
|
|
|
50
50
|
SduiChatThreadBlock,
|
|
51
51
|
SduiNewPostComposerBlock,
|
|
52
52
|
SduiNewStoryComposerBlock,
|
|
53
|
+
SduiStoryViewersPanelBlock,
|
|
53
54
|
SduiPostCommentsBlock,
|
|
54
55
|
SduiProfileOnboardingBlock,
|
|
55
56
|
SduiProfileSelfBlock,
|
|
@@ -117,6 +118,7 @@ const REGISTRY: Record<string, SduiBlockComponent> = {
|
|
|
117
118
|
album_detail: SduiAlbumDetailBlock,
|
|
118
119
|
new_post_composer: SduiNewPostComposerBlock,
|
|
119
120
|
new_story_composer: SduiNewStoryComposerBlock,
|
|
121
|
+
story_viewers_panel: SduiStoryViewersPanelBlock,
|
|
120
122
|
post_comments: SduiPostCommentsBlock,
|
|
121
123
|
social_profile: SduiSocialProfileBlock,
|
|
122
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;
|
|
@@ -19,6 +19,8 @@ import { ChromeGlassLayer } from './ChromeGlass';
|
|
|
19
19
|
import { colors, fonts, m3Colors, m3Shape, spacing } from '../theme/proulr-theme';
|
|
20
20
|
|
|
21
21
|
const ACTION_BUTTON_SIZE = 48;
|
|
22
|
+
/** Filled action circle when nested inside the pill (Instagram-style composer). */
|
|
23
|
+
const ACTION_BUTTON_SIZE_INSET = 36;
|
|
22
24
|
const FONT_SIZE = 16;
|
|
23
25
|
const LINE_HEIGHT = 25;
|
|
24
26
|
const MAX_LINES_DEFAULT = 4;
|
|
@@ -216,6 +218,8 @@ export function ComposePillTextField({
|
|
|
216
218
|
);
|
|
217
219
|
}
|
|
218
220
|
|
|
221
|
+
export type ComposePillEndActionPlacement = 'outside' | 'inside';
|
|
222
|
+
|
|
219
223
|
export type ComposePillInputProps = {
|
|
220
224
|
value: string;
|
|
221
225
|
onChangeText: (text: string) => void;
|
|
@@ -229,6 +233,11 @@ export type ComposePillInputProps = {
|
|
|
229
233
|
leading?: ReactNode;
|
|
230
234
|
trailing?: ReactNode;
|
|
231
235
|
endAction?: ReactNode;
|
|
236
|
+
/**
|
|
237
|
+
* `outside` — send/mic circle beside the pill (legacy / story reply).
|
|
238
|
+
* `inside` — action nested in the pill (Instagram-style chat composer).
|
|
239
|
+
*/
|
|
240
|
+
endActionPlacement?: ComposePillEndActionPlacement;
|
|
232
241
|
replyPreview?: ComposePillReplyPreview | null;
|
|
233
242
|
style?: StyleProp<ViewStyle>;
|
|
234
243
|
transparentWrap?: boolean;
|
|
@@ -345,15 +354,23 @@ export function ComposePillActionButton({
|
|
|
345
354
|
children,
|
|
346
355
|
onPress,
|
|
347
356
|
disabled,
|
|
357
|
+
inset = false,
|
|
348
358
|
}: {
|
|
349
359
|
label: string;
|
|
350
360
|
children: ReactNode;
|
|
351
361
|
onPress?: () => void;
|
|
352
362
|
disabled?: boolean;
|
|
363
|
+
/** Smaller filled circle for use inside the composer pill. */
|
|
364
|
+
inset?: boolean;
|
|
353
365
|
}) {
|
|
366
|
+
const size = inset ? ACTION_BUTTON_SIZE_INSET : ACTION_BUTTON_SIZE;
|
|
354
367
|
return (
|
|
355
368
|
<Pressable
|
|
356
|
-
style={[
|
|
369
|
+
style={[
|
|
370
|
+
styles.actionButton,
|
|
371
|
+
{ width: size, height: size, borderRadius: size / 2 },
|
|
372
|
+
disabled && styles.actionButtonDisabled,
|
|
373
|
+
]}
|
|
357
374
|
onPress={onPress}
|
|
358
375
|
disabled={disabled || !onPress}
|
|
359
376
|
accessibilityRole="button"
|
|
@@ -377,6 +394,7 @@ export function ComposePillInput({
|
|
|
377
394
|
leading,
|
|
378
395
|
trailing,
|
|
379
396
|
endAction,
|
|
397
|
+
endActionPlacement = 'outside',
|
|
380
398
|
replyPreview,
|
|
381
399
|
style,
|
|
382
400
|
transparentWrap = false,
|
|
@@ -387,6 +405,7 @@ export function ComposePillInput({
|
|
|
387
405
|
const layout = useComposePillLineLayout(value, { maxLines });
|
|
388
406
|
const { isMultiline, pillHeight, resetLineCount } = layout;
|
|
389
407
|
const variantColors = composePillVariantColors(variant);
|
|
408
|
+
const endActionInside = endActionPlacement === 'inside' && !bare;
|
|
390
409
|
|
|
391
410
|
const handleChange = useCallback(
|
|
392
411
|
(text: string) => {
|
|
@@ -415,6 +434,14 @@ export function ComposePillInput({
|
|
|
415
434
|
/>
|
|
416
435
|
);
|
|
417
436
|
|
|
437
|
+
const trailingSlot =
|
|
438
|
+
trailing || (endActionInside && endAction) ? (
|
|
439
|
+
<View style={[styles.trailingIcons, isMultiline && styles.trailingIconsExpanded]}>
|
|
440
|
+
{trailing}
|
|
441
|
+
{endActionInside ? endAction : null}
|
|
442
|
+
</View>
|
|
443
|
+
) : null;
|
|
444
|
+
|
|
418
445
|
return (
|
|
419
446
|
<View
|
|
420
447
|
style={[
|
|
@@ -446,20 +473,17 @@ export function ComposePillInput({
|
|
|
446
473
|
borderWidth: variant === 'overlay' || variant === 'chrome' ? 1 : 0,
|
|
447
474
|
},
|
|
448
475
|
variantColors.useChromeGlass && styles.inputPillGlass,
|
|
476
|
+
endActionInside && styles.inputPillWithInsetAction,
|
|
449
477
|
]}
|
|
450
478
|
>
|
|
451
479
|
{variantColors.useChromeGlass ? <ChromeGlassLayer /> : null}
|
|
452
480
|
{leading}
|
|
453
481
|
{textField}
|
|
454
|
-
{
|
|
455
|
-
<View style={[styles.trailingIcons, isMultiline && styles.trailingIconsExpanded]}>
|
|
456
|
-
{trailing}
|
|
457
|
-
</View>
|
|
458
|
-
) : null}
|
|
482
|
+
{trailingSlot}
|
|
459
483
|
</View>
|
|
460
484
|
)}
|
|
461
485
|
|
|
462
|
-
{endAction}
|
|
486
|
+
{!endActionInside ? endAction : null}
|
|
463
487
|
</View>
|
|
464
488
|
</View>
|
|
465
489
|
);
|
|
@@ -532,6 +556,11 @@ const styles = StyleSheet.create({
|
|
|
532
556
|
paddingRight: spacing.xs,
|
|
533
557
|
overflow: 'hidden',
|
|
534
558
|
},
|
|
559
|
+
inputPillWithInsetAction: {
|
|
560
|
+
paddingLeft: spacing.xs,
|
|
561
|
+
paddingRight: spacing.xs,
|
|
562
|
+
gap: spacing.xs,
|
|
563
|
+
},
|
|
535
564
|
inputPillGlass: {},
|
|
536
565
|
inputPillSingle: {
|
|
537
566
|
borderRadius: m3Shape.cornerFull,
|
|
@@ -573,12 +602,10 @@ const styles = StyleSheet.create({
|
|
|
573
602
|
paddingBottom: spacing.xs,
|
|
574
603
|
},
|
|
575
604
|
actionButton: {
|
|
576
|
-
width: ACTION_BUTTON_SIZE,
|
|
577
|
-
height: ACTION_BUTTON_SIZE,
|
|
578
|
-
borderRadius: ACTION_BUTTON_SIZE / 2,
|
|
579
605
|
backgroundColor: m3Colors.primary,
|
|
580
606
|
alignItems: 'center',
|
|
581
607
|
justifyContent: 'center',
|
|
608
|
+
zIndex: 1,
|
|
582
609
|
},
|
|
583
610
|
actionButtonDisabled: {
|
|
584
611
|
opacity: 0.45,
|
|
@@ -586,3 +613,4 @@ const styles = StyleSheet.create({
|
|
|
586
613
|
});
|
|
587
614
|
|
|
588
615
|
export const COMPOSE_PILL_ACTION_BUTTON_SIZE = ACTION_BUTTON_SIZE;
|
|
616
|
+
export const COMPOSE_PILL_ACTION_BUTTON_SIZE_INSET = ACTION_BUTTON_SIZE_INSET;
|
package/src/renderer/ui/index.ts
CHANGED
|
@@ -116,9 +116,11 @@ export {
|
|
|
116
116
|
ComposePillReplyBar,
|
|
117
117
|
ComposePillTextField,
|
|
118
118
|
COMPOSE_PILL_ACTION_BUTTON_SIZE,
|
|
119
|
+
COMPOSE_PILL_ACTION_BUTTON_SIZE_INSET,
|
|
119
120
|
countComposePillLines,
|
|
120
121
|
pillHeightForLineCount,
|
|
121
122
|
useComposePillLineLayout,
|
|
123
|
+
type ComposePillEndActionPlacement,
|
|
122
124
|
type ComposePillInputProps,
|
|
123
125
|
type ComposePillLineLayout,
|
|
124
126
|
type ComposePillLineLayoutState,
|
|
@@ -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;
|