@proulr/sdui-components 0.1.71 → 0.1.75

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proulr/sdui-components",
3
- "version": "0.1.71",
3
+ "version": "0.1.75",
4
4
  "type": "module",
5
5
  "main": "./src/renderer/index.ts",
6
6
  "types": "./src/renderer/index.ts",
@@ -71,7 +71,7 @@ function readProfile(data: Record<string, unknown>, ref?: string): DiscoverNearb
71
71
 
72
72
  function PresenceDot({ status }: { status: ReturnType<typeof getPresenceStatus> }) {
73
73
  const dotColor =
74
- status === 'online' ? m3Colors.online : status === 'recent' ? m3Colors.secondary : m3Colors.outline;
74
+ status === 'online' ? m3Colors.online : status === 'recent' ? m3Colors.presenceRecent : m3Colors.outline;
75
75
  return <View style={[styles.presenceDot, { backgroundColor: dotColor }]} />;
76
76
  }
77
77
 
@@ -89,9 +89,15 @@ export function SduiScrollBlock({ block, children }: SduiBlockRenderProps) {
89
89
  ? { paddingHorizontal: padding, gap }
90
90
  : { padding, gap };
91
91
 
92
+ const scrollViewProps = chromeScroll?.scrollViewProps ?? {};
93
+ const { ref: scrollRef, ...restScrollViewProps } = scrollViewProps as {
94
+ ref?: React.Ref<ScrollView>;
95
+ } & Record<string, unknown>;
96
+
92
97
  return (
93
98
  <SduiLayoutDebugFrame layer="scroll" style={{ flex: 1, minHeight: 0, alignSelf: 'stretch' }}>
94
99
  <ScrollView
100
+ ref={scrollRef}
95
101
  style={[
96
102
  styles.scroll,
97
103
  resolveViewStyleProps(block.props.style as Record<string, unknown>),
@@ -105,7 +111,7 @@ export function SduiScrollBlock({ block, children }: SduiBlockRenderProps) {
105
111
  : blockContentStyle
106
112
  }
107
113
  {...(chromeScroll?.scrollInsetProps ?? {})}
108
- {...(chromeScroll?.scrollViewProps ?? {})}
114
+ {...restScrollViewProps}
109
115
  onScroll={chromeScroll?.onScroll}
110
116
  scrollEventThrottle={chromeScroll?.onScroll || chromeScroll?.scrollViewProps ? 16 : undefined}
111
117
  refreshControl={chromeScroll?.refreshControl}
@@ -32,6 +32,8 @@ export const m3Colors = {
32
32
  scrim: 'rgba(0,0,0,0.78)',
33
33
  storyInteractionScrim: 'rgba(0,0,0,0.48)',
34
34
  online: '#34FF88',
35
+ /** Saiu recentemente (≤24h) — laranja, distinto do online verde e do ciano de marca. */
36
+ presenceRecent: '#FF9F0A',
35
37
  } as const;
36
38
 
37
39
  /** Accent/soft por reação Flash (conteúdo) — fonte única, sem hex solto nos apps. */
@@ -96,6 +98,9 @@ export const colors = {
96
98
  headerEnd: '#D946EF',
97
99
  online: '#34FF88',
98
100
  onlineSoft: 'rgba(52,255,136,0.18)',
101
+ /** Presence: recently active (not online). */
102
+ presenceRecent: '#FF9F0A',
103
+ presenceRecentSoft: 'rgba(255,159,10,0.22)',
99
104
  danger: '#FF4444',
100
105
  dangerSoft: 'rgba(255,68,68,0.22)',
101
106
  dangerSoft18: 'rgba(239,68,68,0.18)',
@@ -1,5 +1,6 @@
1
1
  import React, { useState } from 'react';
2
2
  import {
3
+ Platform,
3
4
  Pressable,
4
5
  StyleSheet,
5
6
  StyleProp,
@@ -11,6 +12,14 @@ import {
11
12
  import { AppIcon, type AppIconName } from './app-icon';
12
13
  import { fonts, m3Colors, m3Shape, spacing } from '../theme/proulr-theme';
13
14
 
15
+ const webInputLock =
16
+ Platform.OS === 'web'
17
+ ? ({
18
+ WebkitTextFillColor: m3Colors.onSurface,
19
+ caretColor: m3Colors.onSurface,
20
+ } as object)
21
+ : null;
22
+
14
23
  export function TextField(
15
24
  props: TextInputProps & {
16
25
  containerStyle?: StyleProp<ViewStyle>;
@@ -18,11 +27,12 @@ export function TextField(
18
27
  inputRef?: React.Ref<TextInput>;
19
28
  },
20
29
  ) {
21
- const { containerStyle, focused, inputRef, ...rest } = props;
30
+ const { containerStyle, focused, inputRef, style, multiline, ...rest } = props;
22
31
  return (
23
32
  <View
24
33
  style={[
25
34
  styles.field,
35
+ multiline && styles.fieldMultiline,
26
36
  focused && { borderColor: m3Colors.primary, borderWidth: 2 },
27
37
  containerStyle,
28
38
  ]}
@@ -30,7 +40,9 @@ export function TextField(
30
40
  <TextInput
31
41
  ref={inputRef}
32
42
  placeholderTextColor={m3Colors.onSurfaceVariant}
33
- style={styles.fieldInput}
43
+ multiline={multiline}
44
+ textAlignVertical={multiline ? 'top' : 'center'}
45
+ style={[styles.fieldInput, multiline && styles.fieldInputMultiline, webInputLock, style]}
34
46
  {...rest}
35
47
  />
36
48
  </View>
@@ -51,7 +63,7 @@ export function PasswordField(
51
63
  <TextInput
52
64
  ref={inputRef}
53
65
  placeholderTextColor={m3Colors.onSurfaceVariant}
54
- style={[styles.fieldInput, styles.passwordInput]}
66
+ style={[styles.fieldInput, styles.passwordInput, webInputLock]}
55
67
  secureTextEntry={!visible}
56
68
  {...rest}
57
69
  />
@@ -82,7 +94,18 @@ const styles = StyleSheet.create({
82
94
  paddingHorizontal: spacing.sm,
83
95
  justifyContent: 'center',
84
96
  },
97
+ fieldMultiline: {
98
+ minHeight: 128,
99
+ justifyContent: 'flex-start',
100
+ paddingVertical: spacing.md,
101
+ },
85
102
  fieldInput: { color: m3Colors.onSurface, fontSize: 16, fontFamily: fonts.regular },
103
+ fieldInputMultiline: {
104
+ fontSize: 18,
105
+ lineHeight: 26,
106
+ minHeight: 96,
107
+ width: '100%',
108
+ },
86
109
  passwordField: { flexDirection: 'row', alignItems: 'center', paddingRight: spacing.sm },
87
110
  passwordInput: { flex: 1 },
88
111
  passwordToggle: {
@@ -219,6 +219,8 @@ export function ComposePillTextField({
219
219
  outlineStyle: 'none',
220
220
  resize: 'none',
221
221
  overflow: 'hidden',
222
+ WebkitTextFillColor: variantColors.text,
223
+ caretColor: variantColors.text,
222
224
  } as object)
223
225
  : {})}
224
226
  {...rest}
@@ -8,7 +8,7 @@ export function ComposeTextArea(props: TextInputProps) {
8
8
  placeholder="O que está acontecendo?"
9
9
  placeholderTextColor={m3Colors.onSurfaceVariant}
10
10
  multiline
11
- style={styles.input}
11
+ style={[styles.input, Platform.OS === 'web' ? styles.inputWeb : null]}
12
12
  {...(Platform.OS === 'android' ? { includeFontPadding: false } : {})}
13
13
  {...props}
14
14
  />
@@ -56,6 +56,12 @@ const styles = StyleSheet.create({
56
56
  textAlignVertical: 'top',
57
57
  paddingTop: spacing.xs,
58
58
  },
59
+ // Samsung/Xiaomi force-dark can leave caret text black on OLED — lock fill color on web.
60
+ inputWeb: {
61
+ WebkitTextFillColor: m3Colors.onSurface,
62
+ caretColor: m3Colors.onSurface,
63
+ outlineStyle: 'none',
64
+ } as object,
59
65
  previewWrap: {
60
66
  position: 'relative',
61
67
  marginTop: spacing.xs,