@proulr/sdui-components 0.1.0

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.
Files changed (57) hide show
  1. package/README.md +29 -0
  2. package/package.json +60 -0
  3. package/src/bdc/compile-bdc-to-wire.ts +123 -0
  4. package/src/bdc/components/discover.tsx +55 -0
  5. package/src/bdc/components/forms.tsx +20 -0
  6. package/src/bdc/components/native-blocks.tsx +35 -0
  7. package/src/bdc/components/social.tsx +27 -0
  8. package/src/bdc/components/ui.tsx +114 -0
  9. package/src/bdc/index.ts +41 -0
  10. package/src/bdc/jsx-runtime.ts +49 -0
  11. package/src/catalog/block-types.ts +18 -0
  12. package/src/catalog/style-tokens.ts +48 -0
  13. package/src/global.d.ts +1 -0
  14. package/src/renderer/SduiScreenRenderer.tsx +28 -0
  15. package/src/renderer/ads/native-ad-catalog.ts +23 -0
  16. package/src/renderer/blocks/SduiDiscoverBlocks.tsx +470 -0
  17. package/src/renderer/blocks/SduiLayoutBlocks.tsx +177 -0
  18. package/src/renderer/blocks/SduiNativeAdBlock.tsx +201 -0
  19. package/src/renderer/blocks/SduiNativeAdBlock.web.tsx +6 -0
  20. package/src/renderer/blocks/SduiNativeDomainBlocks.tsx +141 -0
  21. package/src/renderer/blocks/SduiPrimitiveBlocks.tsx +158 -0
  22. package/src/renderer/blocks/SduiSocialBlocks.tsx +64 -0
  23. package/src/renderer/index.ts +45 -0
  24. package/src/renderer/lib/brazilian-date-input.ts +22 -0
  25. package/src/renderer/lib/discover-profile-formatters.ts +75 -0
  26. package/src/renderer/lib/resolve-data-ref.ts +21 -0
  27. package/src/renderer/sdui-chrome-scroll-context.tsx +40 -0
  28. package/src/renderer/sdui-component-registry.tsx +129 -0
  29. package/src/renderer/sdui-hybrid-renderer-context.tsx +91 -0
  30. package/src/renderer/sdui-layout-debug.tsx +107 -0
  31. package/src/renderer/theme/proulr-theme.ts +164 -0
  32. package/src/renderer/theme/resolve-style-props.ts +85 -0
  33. package/src/renderer/ui/AppButton.tsx +71 -0
  34. package/src/renderer/ui/AppLoadingSpinner.tsx +38 -0
  35. package/src/renderer/ui/AuthStepShell.tsx +128 -0
  36. package/src/renderer/ui/Card.tsx +13 -0
  37. package/src/renderer/ui/DateField.tsx +36 -0
  38. package/src/renderer/ui/InfoBanner.tsx +51 -0
  39. package/src/renderer/ui/TextField.tsx +81 -0
  40. package/src/renderer/ui/compose-audience-pill.tsx +47 -0
  41. package/src/renderer/ui/compose-glyphs.tsx +400 -0
  42. package/src/renderer/ui/compose-media-carousel.tsx +116 -0
  43. package/src/renderer/ui/compose-media-shortcut.tsx +80 -0
  44. package/src/renderer/ui/compose-recent-media-grid.tsx +268 -0
  45. package/src/renderer/ui/compose-reply-audience-sheet.tsx +155 -0
  46. package/src/renderer/ui/compose-screen-header.tsx +115 -0
  47. package/src/renderer/ui/compose-text-area.tsx +94 -0
  48. package/src/renderer/ui/compose-toolbar-icon.tsx +45 -0
  49. package/src/renderer/ui/compose-toolbar.tsx +57 -0
  50. package/src/renderer/ui/compose-visibility-row.tsx +51 -0
  51. package/src/renderer/ui/floating-create-menu.tsx +165 -0
  52. package/src/renderer/ui/index.ts +44 -0
  53. package/src/renderer/ui/story-compose-header.tsx +72 -0
  54. package/src/renderer/ui/story-create-shortcut-row.tsx +89 -0
  55. package/src/renderer/ui/story-editor-chrome.tsx +231 -0
  56. package/src/renderer/ui/story-glyphs.tsx +144 -0
  57. package/src/renderer/ui/story-surface-picker.tsx +124 -0
@@ -0,0 +1,144 @@
1
+ import { Text, View } from 'react-native';
2
+ import { m3Colors } from '../theme/proulr-theme';
3
+
4
+ type GlyphProps = {
5
+ color?: string;
6
+ size?: number;
7
+ };
8
+
9
+ export function StorySettingsGlyph({ color = m3Colors.onSurface, size = 22 }: GlyphProps) {
10
+ const tooth = size * 0.14;
11
+ return (
12
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
13
+ <View
14
+ style={{
15
+ width: size * 0.72,
16
+ height: size * 0.72,
17
+ borderRadius: size * 0.36,
18
+ borderWidth: 1.8,
19
+ borderColor: color,
20
+ alignItems: 'center',
21
+ justifyContent: 'center',
22
+ }}
23
+ >
24
+ <View style={{ width: tooth, height: tooth, borderRadius: tooth / 2, backgroundColor: color }} />
25
+ </View>
26
+ {[0, 60, 120, 180, 240, 300].map((deg) => (
27
+ <View
28
+ key={deg}
29
+ style={{
30
+ position: 'absolute',
31
+ width: tooth * 0.9,
32
+ height: tooth * 1.4,
33
+ borderRadius: 1,
34
+ backgroundColor: color,
35
+ transform: [{ rotate: `${deg}deg` }, { translateY: -size * 0.36 }],
36
+ }}
37
+ />
38
+ ))}
39
+ </View>
40
+ );
41
+ }
42
+
43
+ export function StoryTextGlyph({ color = m3Colors.onSurface, size = 28 }: GlyphProps) {
44
+ return (
45
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
46
+ <Text style={{ color, fontSize: size * 0.62, fontWeight: '700' }}>Aa</Text>
47
+ </View>
48
+ );
49
+ }
50
+
51
+ export function StoryMusicGlyph({ color = m3Colors.onSurface, size = 28 }: GlyphProps) {
52
+ return (
53
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
54
+ <Text style={{ color, fontSize: size * 0.58 }}>{'\u266A'}</Text>
55
+ </View>
56
+ );
57
+ }
58
+
59
+ export function StoryCollageGlyph({ color = m3Colors.onSurface, size = 28 }: GlyphProps) {
60
+ const cell = size * 0.28;
61
+ return (
62
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
63
+ <View style={{ flexDirection: 'row', gap: 2 }}>
64
+ <View style={{ gap: 2 }}>
65
+ <View style={{ width: cell, height: cell, backgroundColor: color, borderRadius: 2 }} />
66
+ <View style={{ width: cell, height: cell * 0.7, backgroundColor: color, borderRadius: 2 }} />
67
+ </View>
68
+ <View style={{ gap: 2, justifyContent: 'center' }}>
69
+ <View style={{ width: cell, height: cell * 1.2, backgroundColor: color, borderRadius: 2 }} />
70
+ </View>
71
+ </View>
72
+ </View>
73
+ );
74
+ }
75
+
76
+ export function StoryStickerGlyph({ color = m3Colors.onPrimary, size = 22 }: GlyphProps) {
77
+ const frame = size * 0.78;
78
+ return (
79
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
80
+ <View
81
+ style={{
82
+ width: frame,
83
+ height: frame,
84
+ borderRadius: size * 0.12,
85
+ borderWidth: 1.6,
86
+ borderColor: color,
87
+ alignItems: 'center',
88
+ justifyContent: 'center',
89
+ }}
90
+ >
91
+ <View
92
+ style={{
93
+ width: frame * 0.28,
94
+ height: frame * 0.12,
95
+ borderRadius: frame * 0.06,
96
+ backgroundColor: color,
97
+ marginBottom: 2,
98
+ }}
99
+ />
100
+ <View
101
+ style={{
102
+ width: frame * 0.42,
103
+ height: frame * 0.08,
104
+ borderRadius: frame * 0.04,
105
+ backgroundColor: color,
106
+ }}
107
+ />
108
+ </View>
109
+ </View>
110
+ );
111
+ }
112
+
113
+ export function StoryEffectsGlyph({ color = m3Colors.onPrimary, size = 22 }: GlyphProps) {
114
+ return (
115
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
116
+ <Text style={{ color, fontSize: size * 0.62 }}>{'\u2728'}</Text>
117
+ </View>
118
+ );
119
+ }
120
+
121
+ export function StoryMentionGlyph({ color = m3Colors.onPrimary, size = 22 }: GlyphProps) {
122
+ return (
123
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
124
+ <Text style={{ color, fontSize: size * 0.72, fontWeight: '700' }}>@</Text>
125
+ </View>
126
+ );
127
+ }
128
+
129
+ export function StoryBackGlyph({ color = m3Colors.onPrimary, size = 22 }: GlyphProps) {
130
+ return (
131
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
132
+ <View
133
+ style={{
134
+ width: size * 0.34,
135
+ height: size * 0.34,
136
+ borderLeftWidth: 2.2,
137
+ borderBottomWidth: 2.2,
138
+ borderColor: color,
139
+ transform: [{ rotate: '45deg' }, { translateX: size * 0.06 }],
140
+ }}
141
+ />
142
+ </View>
143
+ );
144
+ }
@@ -0,0 +1,124 @@
1
+ import { Modal, Pressable, StyleSheet, Text, View } from 'react-native';
2
+ import { fonts, m3Colors, m3Shape, m3Type, spacing } from '../theme/proulr-theme';
3
+
4
+ export type StorySurfaceOption = {
5
+ value: string;
6
+ label: string;
7
+ hint: string;
8
+ };
9
+
10
+ export function StorySurfacePicker({
11
+ visible,
12
+ value,
13
+ options,
14
+ onClose,
15
+ onSelect,
16
+ }: {
17
+ visible: boolean;
18
+ value: string;
19
+ options: StorySurfaceOption[];
20
+ onClose: () => void;
21
+ onSelect: (value: string) => void;
22
+ }) {
23
+ return (
24
+ <Modal visible={visible} transparent animationType="slide" onRequestClose={onClose}>
25
+ <View style={styles.backdrop}>
26
+ <Pressable style={styles.backdropPress} onPress={onClose} accessibilityLabel="Fechar" />
27
+ <View style={styles.sheet}>
28
+ <View style={styles.handle} />
29
+ <Text style={styles.title}>Onde publicar</Text>
30
+ <Text style={styles.subtitle}>Escolha em qual superfície o story vai aparecer.</Text>
31
+
32
+ {options.map((option) => {
33
+ const selected = option.value === value;
34
+ return (
35
+ <Pressable
36
+ key={option.value}
37
+ onPress={() => {
38
+ onSelect(option.value);
39
+ onClose();
40
+ }}
41
+ accessibilityRole="button"
42
+ accessibilityState={{ selected }}
43
+ style={({ pressed }) => [styles.option, pressed && { opacity: 0.86 }]}
44
+ >
45
+ <View style={styles.optionBody}>
46
+ <Text style={styles.optionLabel}>{option.label}</Text>
47
+ <Text style={styles.optionHint}>{option.hint}</Text>
48
+ </View>
49
+ {selected ? <Text style={styles.check}>{'\u2713'}</Text> : null}
50
+ </Pressable>
51
+ );
52
+ })}
53
+ </View>
54
+ </View>
55
+ </Modal>
56
+ );
57
+ }
58
+
59
+ const styles = StyleSheet.create({
60
+ backdrop: {
61
+ flex: 1,
62
+ justifyContent: 'flex-end',
63
+ },
64
+ backdropPress: {
65
+ ...StyleSheet.absoluteFill,
66
+ backgroundColor: m3Colors.scrim,
67
+ },
68
+ sheet: {
69
+ backgroundColor: m3Colors.surface,
70
+ borderTopLeftRadius: m3Shape.cornerExtraLarge,
71
+ borderTopRightRadius: m3Shape.cornerExtraLarge,
72
+ paddingHorizontal: spacing.lg,
73
+ paddingBottom: spacing.xl,
74
+ borderTopWidth: StyleSheet.hairlineWidth,
75
+ borderTopColor: m3Colors.outlineVariant,
76
+ },
77
+ handle: {
78
+ alignSelf: 'center',
79
+ width: 40,
80
+ height: 4,
81
+ borderRadius: 2,
82
+ backgroundColor: m3Colors.outline,
83
+ marginTop: spacing.sm,
84
+ marginBottom: spacing.md,
85
+ },
86
+ title: {
87
+ color: m3Colors.onSurface,
88
+ ...m3Type.titleSmall,
89
+ fontFamily: fonts.bold,
90
+ marginBottom: spacing.xs,
91
+ },
92
+ subtitle: {
93
+ color: m3Colors.onSurfaceVariant,
94
+ ...m3Type.bodySmall,
95
+ marginBottom: spacing.md,
96
+ },
97
+ option: {
98
+ flexDirection: 'row',
99
+ alignItems: 'center',
100
+ paddingVertical: spacing.md,
101
+ borderBottomWidth: StyleSheet.hairlineWidth,
102
+ borderBottomColor: m3Colors.outlineVariant,
103
+ },
104
+ optionBody: {
105
+ flex: 1,
106
+ minWidth: 0,
107
+ },
108
+ optionLabel: {
109
+ color: m3Colors.onSurface,
110
+ fontFamily: fonts.semibold,
111
+ fontSize: 16,
112
+ },
113
+ optionHint: {
114
+ color: m3Colors.onSurfaceVariant,
115
+ ...m3Type.bodySmall,
116
+ marginTop: 2,
117
+ },
118
+ check: {
119
+ color: m3Colors.primary,
120
+ fontSize: 18,
121
+ fontFamily: fonts.bold,
122
+ marginLeft: spacing.sm,
123
+ },
124
+ });