@proulr/sdui-components 0.1.3 → 0.1.5

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.3",
3
+ "version": "0.1.5",
4
4
  "main": "./src/renderer/index.ts",
5
5
  "types": "./src/renderer/index.ts",
6
6
  "exports": {
@@ -17,7 +17,9 @@
17
17
  },
18
18
  "scripts": {
19
19
  "typecheck": "tsc --noEmit",
20
- "prepublishOnly": "npm run typecheck"
20
+ "prepublishOnly": "npm run typecheck",
21
+ "lint": "eslint .",
22
+ "lint:fix": "eslint . --fix"
21
23
  },
22
24
  "publishConfig": {
23
25
  "access": "public"
@@ -52,6 +54,8 @@
52
54
  "devDependencies": {
53
55
  "@types/node": "^22.20.0",
54
56
  "@types/react": "~19.2.2",
57
+ "eslint": "^9.0.0",
58
+ "eslint-config-expo": "~56.0.4",
55
59
  "expo-linear-gradient": "~56.0.4",
56
60
  "react": "19.2.3",
57
61
  "react-native": "0.85.3",
@@ -188,7 +188,7 @@ function DiscoverGridCell({
188
188
  );
189
189
  }
190
190
 
191
- export function SduiDiscoverGridBlock({ block, data, onAction }: SduiBlockRenderProps) {
191
+ function SduiDiscoverGridBlockFallback({ block, data, onAction }: SduiBlockRenderProps) {
192
192
  const itemsRef = readStringProp(block, 'items_ref') ?? 'grid_items';
193
193
  const columns = readNumberProp(block, 'columns', GRID_COLUMNS);
194
194
  const profileActionId = readStringProp(block, 'profile_action_id');
@@ -239,6 +239,23 @@ export function SduiDiscoverGridBlock({ block, data, onAction }: SduiBlockRender
239
239
  );
240
240
  }
241
241
 
242
+ export function SduiDiscoverGridBlock({ block, data, onAction }: SduiBlockRenderProps) {
243
+ const hybrid = useSduiHybridRenderer();
244
+ if (hybrid.renderDiscoverGrid) {
245
+ return (
246
+ <>
247
+ {hybrid.renderDiscoverGrid({
248
+ block,
249
+ data,
250
+ onAction,
251
+ })}
252
+ </>
253
+ );
254
+ }
255
+
256
+ return <SduiDiscoverGridBlockFallback block={block} data={data} onAction={onAction} />;
257
+ }
258
+
242
259
  export function SduiChipBlock({ block, onAction }: SduiBlockRenderProps) {
243
260
  const label = readStringProp(block, 'label') ?? '';
244
261
  const actionId = readStringProp(block, 'action_id');
@@ -98,6 +98,8 @@ export function SduiScrollBlock({ block, children }: SduiBlockRenderProps) {
98
98
  : blockContentStyle
99
99
  }
100
100
  {...(chromeScroll?.scrollInsetProps ?? {})}
101
+ onScroll={chromeScroll?.onScroll}
102
+ scrollEventThrottle={chromeScroll?.onScroll ? 16 : undefined}
101
103
  showsVerticalScrollIndicator={false}
102
104
  >
103
105
  {children}
@@ -32,8 +32,15 @@ export {
32
32
  formatDistanceLabel,
33
33
  getPresenceStatus,
34
34
  profileAgeFromBirthDate,
35
+ readDiscoverGridItems,
36
+ isDiscoverGridItem,
37
+ } from './lib/discover-profile-formatters';
38
+ export type {
39
+ DiscoverNearbyProfileWire,
40
+ DiscoverGridItemWire,
41
+ DiscoverGridProfileItemWire,
42
+ DiscoverGridAdItemWire,
35
43
  } from './lib/discover-profile-formatters';
36
- export type { DiscoverNearbyProfileWire } from './lib/discover-profile-formatters';
37
44
  export {
38
45
  configureNativeAdCatalog,
39
46
  getNativeAdCatalog,
@@ -1,5 +1,5 @@
1
1
  import React, { createContext, useContext, type ReactNode } from 'react';
2
- import type { ViewStyle } from 'react-native';
2
+ import type { NativeScrollEvent, NativeSyntheticEvent, ViewStyle } from 'react-native';
3
3
 
4
4
  export type SduiChromeScrollInsetProps = {
5
5
  contentInset?: { top: number; bottom: number };
@@ -19,6 +19,7 @@ export type SduiChromeScrollConfig = {
19
19
  scrollInsetProps: SduiChromeScrollInsetProps;
20
20
  contentContainerStyle: ViewStyle;
21
21
  chromeInsets: SduiChromeScrollInsets;
22
+ onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void;
22
23
  };
23
24
 
24
25
  const SduiChromeScrollContext = createContext<SduiChromeScrollConfig | null>(null);
@@ -45,6 +45,7 @@ export type SduiHybridRenderers = {
45
45
  renderProfileCompletionBanner?: (props: SduiHybridProfileCompletionBannerProps) => ReactNode;
46
46
  renderDiscoverMap?: (props: SduiHybridDiscoverMapProps) => ReactNode;
47
47
  renderDiscoverProfileCard?: (props: SduiHybridDiscoverProfileCardProps) => ReactNode;
48
+ renderDiscoverGrid?: (props: SduiNativeBlockRenderProps) => ReactNode;
48
49
  renderTextField?: (props: {
49
50
  dataRef: string;
50
51
  placeholder: string;
@@ -1234,6 +1234,79 @@ export function AppChromeSignOutGlyph({ color = m3Colors.primary, size = 24 }: A
1234
1234
  );
1235
1235
  }
1236
1236
 
1237
+ /** Olho aberto — mostrar senha. */
1238
+ export function AppChromeVisibilityGlyph({ color = m3Colors.onSurfaceVariant, size = 24 }: AppChromeGlyphProps) {
1239
+ const stroke = strokeFor(size);
1240
+ const eyeW = size * 0.82;
1241
+ const eyeH = size * 0.46;
1242
+ const pupil = size * 0.18;
1243
+ return (
1244
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
1245
+ <View
1246
+ style={{
1247
+ width: eyeW,
1248
+ height: eyeH,
1249
+ borderRadius: eyeH / 2,
1250
+ borderWidth: stroke,
1251
+ borderColor: color,
1252
+ }}
1253
+ />
1254
+ <View
1255
+ style={{
1256
+ position: 'absolute',
1257
+ width: pupil,
1258
+ height: pupil,
1259
+ borderRadius: pupil / 2,
1260
+ backgroundColor: color,
1261
+ }}
1262
+ />
1263
+ </View>
1264
+ );
1265
+ }
1266
+
1267
+ /** Olho riscado — ocultar senha. */
1268
+ export function AppChromeVisibilityOffGlyph({ color = m3Colors.onSurfaceVariant, size = 24 }: AppChromeGlyphProps) {
1269
+ const stroke = strokeFor(size);
1270
+ const eyeW = size * 0.82;
1271
+ const eyeH = size * 0.46;
1272
+ const pupil = size * 0.18;
1273
+ const slash = size * 0.88;
1274
+ return (
1275
+ <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
1276
+ <View
1277
+ style={{
1278
+ width: eyeW,
1279
+ height: eyeH,
1280
+ borderRadius: eyeH / 2,
1281
+ borderWidth: stroke,
1282
+ borderColor: color,
1283
+ opacity: 0.72,
1284
+ }}
1285
+ />
1286
+ <View
1287
+ style={{
1288
+ position: 'absolute',
1289
+ width: pupil,
1290
+ height: pupil,
1291
+ borderRadius: pupil / 2,
1292
+ backgroundColor: color,
1293
+ opacity: 0.72,
1294
+ }}
1295
+ />
1296
+ <View
1297
+ style={{
1298
+ position: 'absolute',
1299
+ width: slash,
1300
+ height: stroke,
1301
+ backgroundColor: color,
1302
+ borderRadius: 1,
1303
+ transform: [{ rotate: '-35deg' }],
1304
+ }}
1305
+ />
1306
+ </View>
1307
+ );
1308
+ }
1309
+
1237
1310
  const styles = StyleSheet.create({
1238
1311
  crosshair: {
1239
1312
  position: 'absolute',
@@ -46,6 +46,8 @@ import {
46
46
  AppChromeTabDiscoverGlyph,
47
47
  AppChromeTabFlashGlyph,
48
48
  AppChromeTabVibesGlyph,
49
+ AppChromeVisibilityGlyph,
50
+ AppChromeVisibilityOffGlyph,
49
51
  type AppChromeGlyphProps,
50
52
  } from './app-glyphs';
51
53
  import {
@@ -110,7 +112,9 @@ export type AppIconName =
110
112
  | 'pause'
111
113
  | 'plus'
112
114
  | 'followers'
113
- | 'mention';
115
+ | 'mention'
116
+ | 'visibility'
117
+ | 'visibility-off';
114
118
 
115
119
  const ICON_REGISTRY: Record<AppIconName, ComponentType<AppChromeGlyphProps>> = {
116
120
  search: AppChromeSearchGlyph,
@@ -165,6 +169,8 @@ const ICON_REGISTRY: Record<AppIconName, ComponentType<AppChromeGlyphProps>> = {
165
169
  plus: AppChromePlusGlyph,
166
170
  followers: ComposeFollowersGlyph,
167
171
  mention: ComposeMentionGlyph,
172
+ visibility: AppChromeVisibilityGlyph,
173
+ 'visibility-off': AppChromeVisibilityOffGlyph,
168
174
  };
169
175
 
170
176
  export type AppIconProps = {
@@ -7,7 +7,6 @@ type GlyphProps = {
7
7
  };
8
8
 
9
9
  export function ComposeCloseGlyph({ color = m3Colors.onSurface, size = 18 }: GlyphProps) {
10
- const stroke = Math.max(1.5, size * 0.1);
11
10
  return (
12
11
  <View style={{ width: size, height: size, alignItems: 'center', justifyContent: 'center' }}>
13
12
  <View style={[styles.diag, { width: size, backgroundColor: color, transform: [{ rotate: '45deg' }] }]} />
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import { useCallback, useState } from 'react';
3
3
  import { Modal, Pressable, StyleSheet, Text, View } from 'react-native';
4
- import { fonts, m3Colors, m3Elevation, m3Shape, spacing } from '../theme/proulr-theme';
4
+ import { fonts, m3Colors, m3Elevation, spacing } from '../theme/proulr-theme';
5
5
 
6
6
  export type FloatingCreateMenuAction = {
7
7
  id: string;