@oxyhq/services 6.9.31 → 6.9.33

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.
@@ -6,29 +6,13 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = exports.FollowButton = void 0;
7
7
  var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
- var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated"));
10
9
  var _OxyContext = require("../context/OxyContext.js");
11
10
  var _fonts = require("../styles/fonts.js");
12
11
  var _sonner = require("../../lib/sonner");
13
12
  var _useFollow = require("../hooks/useFollow.js");
14
- var _theme2 = require("@oxyhq/bloom/theme");
13
+ var _theme = require("@oxyhq/bloom/theme");
15
14
  var _jsxRuntime = require("react/jsx-runtime");
16
15
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
17
- // Create animated TouchableOpacity
18
- const AnimatedTouchableOpacity = _reactNativeReanimated.default.createAnimatedComponent(_reactNative.TouchableOpacity);
19
- /**
20
- * Inner component that handles all hooks and rendering.
21
- *
22
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
23
- * The outer wrapper handles the auth/self-follow guard and returns null
24
- * before any hooks are called. This inner component always renders
25
- * (all hooks are called unconditionally).
26
- *
27
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
28
- * not subscribe to the OxyContext. This is critical in list contexts where
29
- * N buttons would all re-render on any context change (session socket events,
30
- * token refreshes, etc.).
31
- */
32
16
  const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInner({
33
17
  userId,
34
18
  oxyServices,
@@ -39,13 +23,11 @@ const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInn
39
23
  textStyle,
40
24
  disabled = false,
41
25
  showLoadingState = true,
42
- preventParentActions = true,
43
- theme: _theme = 'light'
26
+ preventParentActions = true
44
27
  }) {
45
- const bloomTheme = (0, _theme2.useTheme)();
46
- const colors = bloomTheme.colors;
47
-
48
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
28
+ const {
29
+ colors
30
+ } = (0, _theme.useTheme)();
49
31
  const {
50
32
  isFollowing,
51
33
  isLoading,
@@ -53,102 +35,47 @@ const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInn
53
35
  setFollowStatus,
54
36
  fetchStatus
55
37
  } = (0, _useFollow.useFollowForButton)(userId, oxyServices);
56
-
57
- // Animation values
58
- const scale = (0, _reactNativeReanimated.useSharedValue)(1);
59
-
60
- // Stable press handler — depends on primitives only
61
38
  const handlePress = (0, _react.useCallback)(async event => {
62
- if (preventParentActions && event && event.preventDefault) {
39
+ if (preventParentActions && event?.preventDefault) {
63
40
  event.preventDefault();
64
41
  event.stopPropagation?.();
65
42
  }
66
43
  if (disabled || isLoading) return;
67
-
68
- // Press animation
69
- scale.value = (0, _reactNativeReanimated.withTiming)(0.95, {
70
- duration: 100
71
- }, finished => {
72
- if (finished) {
73
- scale.value = (0, _reactNativeReanimated.withSpring)(1, {
74
- damping: 15,
75
- stiffness: 200
76
- });
77
- }
78
- });
79
44
  try {
80
45
  await toggleFollow();
81
- if (onFollowChange) onFollowChange(!isFollowing);
46
+ onFollowChange?.(!isFollowing);
82
47
  } catch (err) {
83
48
  const error = err instanceof Error ? err : new Error(String(err));
84
49
  _sonner.toast.error(error.message || 'Failed to update follow status');
85
50
  }
86
- }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions, scale]);
87
-
88
- // Set initial follow status on mount if provided and not already set
51
+ }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
89
52
  (0, _react.useEffect)(() => {
90
53
  if (userId && !isFollowing && initiallyFollowing) {
91
54
  setFollowStatus(initiallyFollowing);
92
55
  }
93
- // Intentional: only run on mount with initial values
94
56
  // eslint-disable-next-line react-hooks/exhaustive-deps
95
57
  }, [userId, initiallyFollowing]);
96
-
97
- // Fetch latest follow status from backend on mount
98
58
  (0, _react.useEffect)(() => {
99
- if (userId) {
100
- fetchStatus();
101
- }
59
+ if (userId) fetchStatus();
102
60
  }, [userId, fetchStatus]);
103
-
104
- // Scale-only animated style
105
- const animatedStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({
106
- transform: [{
107
- scale: scale.value
108
- }]
109
- }));
110
-
111
- // Colors from bloom theme — follows NativeWind convention via useTheme()
112
- // Not following: bg-primary, border-primary, text white
113
- // Following: bg-background, border-border, text-foreground
114
- const buttonColorStyle = isFollowing ? {
115
- backgroundColor: colors.background,
116
- borderColor: colors.border
117
- } : {
118
- backgroundColor: colors.primary,
119
- borderColor: colors.primary
120
- };
121
- const textColor = isFollowing ? colors.text : '#FFFFFF';
122
61
  const baseButtonStyle = getBaseButtonStyle(size, style);
123
62
  const baseTextStyle = getBaseTextStyle(size, textStyle);
124
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(AnimatedTouchableOpacity, {
125
- style: [baseButtonStyle, buttonColorStyle, animatedStyle],
63
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
64
+ className: isFollowing ? 'bg-background border-border' : 'bg-primary border-primary',
65
+ style: baseButtonStyle,
126
66
  onPress: handlePress,
127
67
  disabled: disabled || isLoading,
128
68
  activeOpacity: 0.8,
129
69
  children: showLoadingState && isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
130
70
  size: "small",
131
- color: textColor
71
+ color: isFollowing ? colors.text : '#FFFFFF'
132
72
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
133
- style: [baseTextStyle, {
134
- color: textColor
135
- }],
73
+ className: isFollowing ? 'text-foreground' : 'text-primary-foreground',
74
+ style: baseTextStyle,
136
75
  children: isFollowing ? 'Following' : 'Follow'
137
76
  })
138
77
  });
139
78
  });
140
-
141
- /**
142
- * Outer wrapper that handles the "should we render?" check.
143
- *
144
- * This is the ONLY place useOxy() is called — to check authentication and
145
- * get the current user ID for the self-follow guard. The oxyServices instance
146
- * is passed down as a prop to the inner component, which avoids subscribing
147
- * to the full OxyContext.
148
- *
149
- * The early return happens BEFORE the inner component mounts, so the inner
150
- * component's hooks are never called conditionally (no Rules of Hooks violation).
151
- */
152
79
  const FollowButton = props => {
153
80
  const {
154
81
  oxyServices,
@@ -157,8 +84,6 @@ const FollowButton = props => {
157
84
  } = (0, _OxyContext.useOxy)();
158
85
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
159
86
  const targetUserId = props.userId ? String(props.userId).trim() : '';
160
-
161
- // Don't render if not authenticated or viewing own profile
162
87
  if (!isAuthenticated || !targetUserId || currentUserId && currentUserId === targetUserId) {
163
88
  return null;
164
89
  }
@@ -168,8 +93,6 @@ const FollowButton = props => {
168
93
  oxyServices: oxyServices
169
94
  });
170
95
  };
171
-
172
- // Pure helper functions (no hooks, no state) extracted outside the component
173
96
  exports.FollowButton = FollowButton;
174
97
  function getBaseButtonStyle(size, style) {
175
98
  const baseStyle = {
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_reactNativeReanimated","_OxyContext","_fonts","_sonner","_useFollow","_theme2","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","AnimatedTouchableOpacity","Animated","createAnimatedComponent","TouchableOpacity","FollowButtonInner","memo","userId","oxyServices","initiallyFollowing","size","onFollowChange","style","textStyle","disabled","showLoadingState","preventParentActions","theme","_theme","bloomTheme","useTheme","colors","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","useFollowForButton","scale","useSharedValue","handlePress","useCallback","event","preventDefault","stopPropagation","value","withTiming","duration","finished","withSpring","damping","stiffness","err","error","Error","String","toast","message","useEffect","animatedStyle","useAnimatedStyle","transform","buttonColorStyle","backgroundColor","background","borderColor","border","primary","textColor","text","baseButtonStyle","getBaseButtonStyle","baseTextStyle","getBaseTextStyle","jsx","onPress","activeOpacity","children","ActivityIndicator","color","Text","FollowButton","props","isAuthenticated","user","currentUser","useOxy","currentUserId","id","trim","targetUserId","exports","baseStyle","flexDirection","alignItems","justifyContent","borderWidth","Platform","select","web","shadowColor","shadowOffset","width","height","shadowOpacity","shadowRadius","elevation","sizeStyle","paddingVertical","paddingHorizontal","minWidth","borderRadius","fontFamily","fontFamilies","interSemiBold","fontWeight","sizeTextStyle","fontSize","_default"],"sourceRoot":"../../../../src","sources":["ui/components/FollowButton.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_OxyContext","_fonts","_sonner","_useFollow","_theme","_jsxRuntime","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","FollowButtonInner","memo","userId","oxyServices","initiallyFollowing","size","onFollowChange","style","textStyle","disabled","showLoadingState","preventParentActions","colors","useTheme","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","useFollowForButton","handlePress","useCallback","event","preventDefault","stopPropagation","err","error","Error","String","toast","message","useEffect","baseButtonStyle","getBaseButtonStyle","baseTextStyle","getBaseTextStyle","jsx","TouchableOpacity","className","onPress","activeOpacity","children","ActivityIndicator","color","text","Text","FollowButton","props","isAuthenticated","user","currentUser","useOxy","currentUserId","id","trim","targetUserId","exports","baseStyle","flexDirection","alignItems","justifyContent","borderWidth","Platform","select","web","shadowColor","shadowOffset","width","height","shadowOpacity","shadowRadius","elevation","sizeStyle","paddingVertical","paddingHorizontal","minWidth","borderRadius","fontFamily","fontFamilies","interSemiBold","fontWeight","sizeTextStyle","fontSize","_default"],"sourceRoot":"../../../../src","sources":["ui/components/FollowButton.tsx"],"mappings":"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","ignoreList":[]}
@@ -2,28 +2,12 @@
2
2
 
3
3
  import React, { useEffect, useCallback, memo } from 'react';
4
4
  import { TouchableOpacity, Text, Platform, ActivityIndicator } from 'react-native';
5
- import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming } from 'react-native-reanimated';
6
5
  import { useOxy } from "../context/OxyContext.js";
7
6
  import { fontFamilies } from "../styles/fonts.js";
8
7
  import { toast } from '../../lib/sonner';
9
8
  import { useFollowForButton } from "../hooks/useFollow.js";
10
9
  import { useTheme } from '@oxyhq/bloom/theme';
11
10
  import { jsx as _jsx } from "react/jsx-runtime";
12
- // Create animated TouchableOpacity
13
- const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);
14
- /**
15
- * Inner component that handles all hooks and rendering.
16
- *
17
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
18
- * The outer wrapper handles the auth/self-follow guard and returns null
19
- * before any hooks are called. This inner component always renders
20
- * (all hooks are called unconditionally).
21
- *
22
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
23
- * not subscribe to the OxyContext. This is critical in list contexts where
24
- * N buttons would all re-render on any context change (session socket events,
25
- * token refreshes, etc.).
26
- */
27
11
  const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
28
12
  userId,
29
13
  oxyServices,
@@ -34,13 +18,11 @@ const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
34
18
  textStyle,
35
19
  disabled = false,
36
20
  showLoadingState = true,
37
- preventParentActions = true,
38
- theme: _theme = 'light'
21
+ preventParentActions = true
39
22
  }) {
40
- const bloomTheme = useTheme();
41
- const colors = bloomTheme.colors;
42
-
43
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
23
+ const {
24
+ colors
25
+ } = useTheme();
44
26
  const {
45
27
  isFollowing,
46
28
  isLoading,
@@ -48,102 +30,47 @@ const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
48
30
  setFollowStatus,
49
31
  fetchStatus
50
32
  } = useFollowForButton(userId, oxyServices);
51
-
52
- // Animation values
53
- const scale = useSharedValue(1);
54
-
55
- // Stable press handler — depends on primitives only
56
33
  const handlePress = useCallback(async event => {
57
- if (preventParentActions && event && event.preventDefault) {
34
+ if (preventParentActions && event?.preventDefault) {
58
35
  event.preventDefault();
59
36
  event.stopPropagation?.();
60
37
  }
61
38
  if (disabled || isLoading) return;
62
-
63
- // Press animation
64
- scale.value = withTiming(0.95, {
65
- duration: 100
66
- }, finished => {
67
- if (finished) {
68
- scale.value = withSpring(1, {
69
- damping: 15,
70
- stiffness: 200
71
- });
72
- }
73
- });
74
39
  try {
75
40
  await toggleFollow();
76
- if (onFollowChange) onFollowChange(!isFollowing);
41
+ onFollowChange?.(!isFollowing);
77
42
  } catch (err) {
78
43
  const error = err instanceof Error ? err : new Error(String(err));
79
44
  toast.error(error.message || 'Failed to update follow status');
80
45
  }
81
- }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions, scale]);
82
-
83
- // Set initial follow status on mount if provided and not already set
46
+ }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
84
47
  useEffect(() => {
85
48
  if (userId && !isFollowing && initiallyFollowing) {
86
49
  setFollowStatus(initiallyFollowing);
87
50
  }
88
- // Intentional: only run on mount with initial values
89
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
90
52
  }, [userId, initiallyFollowing]);
91
-
92
- // Fetch latest follow status from backend on mount
93
53
  useEffect(() => {
94
- if (userId) {
95
- fetchStatus();
96
- }
54
+ if (userId) fetchStatus();
97
55
  }, [userId, fetchStatus]);
98
-
99
- // Scale-only animated style
100
- const animatedStyle = useAnimatedStyle(() => ({
101
- transform: [{
102
- scale: scale.value
103
- }]
104
- }));
105
-
106
- // Colors from bloom theme — follows NativeWind convention via useTheme()
107
- // Not following: bg-primary, border-primary, text white
108
- // Following: bg-background, border-border, text-foreground
109
- const buttonColorStyle = isFollowing ? {
110
- backgroundColor: colors.background,
111
- borderColor: colors.border
112
- } : {
113
- backgroundColor: colors.primary,
114
- borderColor: colors.primary
115
- };
116
- const textColor = isFollowing ? colors.text : '#FFFFFF';
117
56
  const baseButtonStyle = getBaseButtonStyle(size, style);
118
57
  const baseTextStyle = getBaseTextStyle(size, textStyle);
119
- return /*#__PURE__*/_jsx(AnimatedTouchableOpacity, {
120
- style: [baseButtonStyle, buttonColorStyle, animatedStyle],
58
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
59
+ className: isFollowing ? 'bg-background border-border' : 'bg-primary border-primary',
60
+ style: baseButtonStyle,
121
61
  onPress: handlePress,
122
62
  disabled: disabled || isLoading,
123
63
  activeOpacity: 0.8,
124
64
  children: showLoadingState && isLoading ? /*#__PURE__*/_jsx(ActivityIndicator, {
125
65
  size: "small",
126
- color: textColor
66
+ color: isFollowing ? colors.text : '#FFFFFF'
127
67
  }) : /*#__PURE__*/_jsx(Text, {
128
- style: [baseTextStyle, {
129
- color: textColor
130
- }],
68
+ className: isFollowing ? 'text-foreground' : 'text-primary-foreground',
69
+ style: baseTextStyle,
131
70
  children: isFollowing ? 'Following' : 'Follow'
132
71
  })
133
72
  });
134
73
  });
135
-
136
- /**
137
- * Outer wrapper that handles the "should we render?" check.
138
- *
139
- * This is the ONLY place useOxy() is called — to check authentication and
140
- * get the current user ID for the self-follow guard. The oxyServices instance
141
- * is passed down as a prop to the inner component, which avoids subscribing
142
- * to the full OxyContext.
143
- *
144
- * The early return happens BEFORE the inner component mounts, so the inner
145
- * component's hooks are never called conditionally (no Rules of Hooks violation).
146
- */
147
74
  const FollowButton = props => {
148
75
  const {
149
76
  oxyServices,
@@ -152,8 +79,6 @@ const FollowButton = props => {
152
79
  } = useOxy();
153
80
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
154
81
  const targetUserId = props.userId ? String(props.userId).trim() : '';
155
-
156
- // Don't render if not authenticated or viewing own profile
157
82
  if (!isAuthenticated || !targetUserId || currentUserId && currentUserId === targetUserId) {
158
83
  return null;
159
84
  }
@@ -163,8 +88,6 @@ const FollowButton = props => {
163
88
  oxyServices: oxyServices
164
89
  });
165
90
  };
166
-
167
- // Pure helper functions (no hooks, no state) extracted outside the component
168
91
  function getBaseButtonStyle(size, style) {
169
92
  const baseStyle = {
170
93
  flexDirection: 'row',
@@ -1 +1 @@
1
- {"version":3,"names":["React","useEffect","useCallback","memo","TouchableOpacity","Text","Platform","ActivityIndicator","Animated","useSharedValue","useAnimatedStyle","withSpring","withTiming","useOxy","fontFamilies","toast","useFollowForButton","useTheme","jsx","_jsx","AnimatedTouchableOpacity","createAnimatedComponent","FollowButtonInner","userId","oxyServices","initiallyFollowing","size","onFollowChange","style","textStyle","disabled","showLoadingState","preventParentActions","theme","_theme","bloomTheme","colors","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","scale","handlePress","event","preventDefault","stopPropagation","value","duration","finished","damping","stiffness","err","error","Error","String","message","animatedStyle","transform","buttonColorStyle","backgroundColor","background","borderColor","border","primary","textColor","text","baseButtonStyle","getBaseButtonStyle","baseTextStyle","getBaseTextStyle","onPress","activeOpacity","children","color","FollowButton","props","isAuthenticated","user","currentUser","currentUserId","id","trim","targetUserId","baseStyle","flexDirection","alignItems","justifyContent","borderWidth","select","web","default","shadowColor","shadowOffset","width","height","shadowOpacity","shadowRadius","elevation","sizeStyle","paddingVertical","paddingHorizontal","minWidth","borderRadius","fontFamily","interSemiBold","fontWeight","sizeTextStyle","fontSize"],"sourceRoot":"../../../../src","sources":["ui/components/FollowButton.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","useEffect","useCallback","memo","TouchableOpacity","Text","Platform","ActivityIndicator","useOxy","fontFamilies","toast","useFollowForButton","useTheme","jsx","_jsx","FollowButtonInner","userId","oxyServices","initiallyFollowing","size","onFollowChange","style","textStyle","disabled","showLoadingState","preventParentActions","colors","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","handlePress","event","preventDefault","stopPropagation","err","error","Error","String","message","baseButtonStyle","getBaseButtonStyle","baseTextStyle","getBaseTextStyle","className","onPress","activeOpacity","children","color","text","FollowButton","props","isAuthenticated","user","currentUser","currentUserId","id","trim","targetUserId","baseStyle","flexDirection","alignItems","justifyContent","borderWidth","select","web","default","shadowColor","shadowOffset","width","height","shadowOpacity","shadowRadius","elevation","sizeStyle","paddingVertical","paddingHorizontal","minWidth","borderRadius","fontFamily","interSemiBold","fontWeight","sizeTextStyle","fontSize"],"sourceRoot":"../../../../src","sources":["ui/components/FollowButton.tsx"],"mappings":"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","ignoreList":[]}
@@ -12,17 +12,6 @@ export interface FollowButtonProps {
12
12
  preventParentActions?: boolean;
13
13
  theme?: 'light' | 'dark';
14
14
  }
15
- /**
16
- * Outer wrapper that handles the "should we render?" check.
17
- *
18
- * This is the ONLY place useOxy() is called — to check authentication and
19
- * get the current user ID for the self-follow guard. The oxyServices instance
20
- * is passed down as a prop to the inner component, which avoids subscribing
21
- * to the full OxyContext.
22
- *
23
- * The early return happens BEFORE the inner component mounts, so the inner
24
- * component's hooks are never called conditionally (no Rules of Hooks violation).
25
- */
26
15
  declare const FollowButton: React.FC<FollowButtonProps>;
27
16
  export { FollowButton };
28
17
  export default FollowButton;
@@ -1 +1 @@
1
- {"version":3,"file":"FollowButton.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/FollowButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,cAAc,CAAC;AAiBtB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAwHD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkB7C,CAAC;AAmDF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"FollowButton.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/FollowButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,cAAc,CAAC;AAQtB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAkFD,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiB7C,CAAC;AAkDF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
@@ -12,17 +12,6 @@ export interface FollowButtonProps {
12
12
  preventParentActions?: boolean;
13
13
  theme?: 'light' | 'dark';
14
14
  }
15
- /**
16
- * Outer wrapper that handles the "should we render?" check.
17
- *
18
- * This is the ONLY place useOxy() is called — to check authentication and
19
- * get the current user ID for the self-follow guard. The oxyServices instance
20
- * is passed down as a prop to the inner component, which avoids subscribing
21
- * to the full OxyContext.
22
- *
23
- * The early return happens BEFORE the inner component mounts, so the inner
24
- * component's hooks are never called conditionally (no Rules of Hooks violation).
25
- */
26
15
  declare const FollowButton: React.FC<FollowButtonProps>;
27
16
  export { FollowButton };
28
17
  export default FollowButton;
@@ -1 +1 @@
1
- {"version":3,"file":"FollowButton.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/FollowButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,cAAc,CAAC;AAiBtB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAwHD;;;;;;;;;;GAUG;AACH,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAkB7C,CAAC;AAmDF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
1
+ {"version":3,"file":"FollowButton.d.ts","sourceRoot":"","sources":["../../../../../src/ui/components/FollowButton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAuC,MAAM,OAAO,CAAC;AAC5D,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,SAAS,EAGf,MAAM,cAAc,CAAC;AAQtB,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,cAAc,CAAC,EAAE,CAAC,WAAW,EAAE,OAAO,KAAK,IAAI,CAAC;IAChD,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,SAAS,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AAkFD,QAAA,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAiB7C,CAAC;AAkDF,OAAO,EAAE,YAAY,EAAE,CAAC;AACxB,eAAe,YAAY,CAAC"}
@@ -0,0 +1 @@
1
+ /// <reference types="nativewind/types" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oxyhq/services",
3
- "version": "6.9.31",
3
+ "version": "6.9.33",
4
4
  "description": "OxyHQ Expo/React Native SDK — UI components, screens, and native features",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -94,6 +94,8 @@
94
94
  "zustand": "^5.0.9"
95
95
  },
96
96
  "devDependencies": {
97
+ "nativewind": "5.0.0-preview.3",
98
+ "react-native-css": "^3.0.0",
97
99
  "@biomejs/biome": "^1.9.4",
98
100
  "@commitlint/cli": "^17.6.5",
99
101
  "@commitlint/config-conventional": "^17.6.5",
@@ -135,9 +137,13 @@
135
137
  "react-native-gesture-handler": "~2.30.0",
136
138
  "react-native-reanimated": ">=4.2.0",
137
139
  "react-native-safe-area-context": "~5.6.0",
138
- "react-native-svg": ">=13.0.0"
140
+ "react-native-svg": ">=13.0.0",
141
+ "nativewind": ">=4.0.0"
139
142
  },
140
143
  "peerDependenciesMeta": {
144
+ "nativewind": {
145
+ "optional": true
146
+ },
141
147
  "@expo/vector-icons": {
142
148
  "optional": true
143
149
  },
@@ -0,0 +1 @@
1
+ /// <reference types="nativewind/types" />
@@ -8,12 +8,6 @@ import {
8
8
  Platform,
9
9
  ActivityIndicator
10
10
  } from 'react-native';
11
- import Animated, {
12
- useSharedValue,
13
- useAnimatedStyle,
14
- withSpring,
15
- withTiming
16
- } from 'react-native-reanimated';
17
11
  import { useOxy } from '../context/OxyContext';
18
12
  import { fontFamilies } from '../styles/fonts';
19
13
  import { toast } from '../../lib/sonner';
@@ -21,9 +15,6 @@ import { useFollowForButton } from '../hooks/useFollow';
21
15
  import { useTheme } from '@oxyhq/bloom/theme';
22
16
  import type { OxyServices } from '@oxyhq/core';
23
17
 
24
- // Create animated TouchableOpacity
25
- const AnimatedTouchableOpacity = Animated.createAnimatedComponent(TouchableOpacity);
26
-
27
18
  export interface FollowButtonProps {
28
19
  userId: string;
29
20
  initiallyFollowing?: boolean;
@@ -37,19 +28,6 @@ export interface FollowButtonProps {
37
28
  theme?: 'light' | 'dark';
38
29
  }
39
30
 
40
- /**
41
- * Inner component that handles all hooks and rendering.
42
- *
43
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
44
- * The outer wrapper handles the auth/self-follow guard and returns null
45
- * before any hooks are called. This inner component always renders
46
- * (all hooks are called unconditionally).
47
- *
48
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
49
- * not subscribe to the OxyContext. This is critical in list contexts where
50
- * N buttons would all re-render on any context change (session socket events,
51
- * token refreshes, etc.).
52
- */
53
31
  const FollowButtonInner = memo(function FollowButtonInner({
54
32
  userId,
55
33
  oxyServices,
@@ -61,12 +39,9 @@ const FollowButtonInner = memo(function FollowButtonInner({
61
39
  disabled = false,
62
40
  showLoadingState = true,
63
41
  preventParentActions = true,
64
- theme: _theme = 'light',
65
42
  }: FollowButtonProps & { oxyServices: OxyServices }) {
66
- const bloomTheme = useTheme();
67
- const colors = bloomTheme.colors;
43
+ const { colors } = useTheme();
68
44
 
69
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
70
45
  const {
71
46
  isFollowing,
72
47
  isLoading,
@@ -75,68 +50,43 @@ const FollowButtonInner = memo(function FollowButtonInner({
75
50
  fetchStatus,
76
51
  } = useFollowForButton(userId, oxyServices);
77
52
 
78
- // Animation values
79
- const scale = useSharedValue(1);
80
-
81
- // Stable press handler — depends on primitives only
82
53
  const handlePress = useCallback(async (event?: { preventDefault?: () => void; stopPropagation?: () => void }) => {
83
- if (preventParentActions && event && event.preventDefault) {
54
+ if (preventParentActions && event?.preventDefault) {
84
55
  event.preventDefault();
85
56
  event.stopPropagation?.();
86
57
  }
87
58
  if (disabled || isLoading) return;
88
59
 
89
- // Press animation
90
- scale.value = withTiming(0.95, { duration: 100 }, (finished) => {
91
- if (finished) {
92
- scale.value = withSpring(1, { damping: 15, stiffness: 200 });
93
- }
94
- });
95
-
96
60
  try {
97
61
  await toggleFollow();
98
- if (onFollowChange) onFollowChange(!isFollowing);
62
+ onFollowChange?.(!isFollowing);
99
63
  } catch (err: unknown) {
100
64
  const error = err instanceof Error ? err : new Error(String(err));
101
65
  toast.error(error.message || 'Failed to update follow status');
102
66
  }
103
- }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions, scale]);
67
+ }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
104
68
 
105
- // Set initial follow status on mount if provided and not already set
106
69
  useEffect(() => {
107
70
  if (userId && !isFollowing && initiallyFollowing) {
108
71
  setFollowStatus(initiallyFollowing);
109
72
  }
110
- // Intentional: only run on mount with initial values
111
73
  // eslint-disable-next-line react-hooks/exhaustive-deps
112
74
  }, [userId, initiallyFollowing]);
113
75
 
114
- // Fetch latest follow status from backend on mount
115
76
  useEffect(() => {
116
- if (userId) {
117
- fetchStatus();
118
- }
77
+ if (userId) fetchStatus();
119
78
  }, [userId, fetchStatus]);
120
79
 
121
- // Scale-only animated style
122
- const animatedStyle = useAnimatedStyle(() => ({
123
- transform: [{ scale: scale.value }],
124
- }));
125
-
126
- // Colors from bloom theme — follows NativeWind convention via useTheme()
127
- // Not following: bg-primary, border-primary, text white
128
- // Following: bg-background, border-border, text-foreground
129
- const buttonColorStyle: ViewStyle = isFollowing
130
- ? { backgroundColor: colors.background, borderColor: colors.border }
131
- : { backgroundColor: colors.primary, borderColor: colors.primary };
132
- const textColor = isFollowing ? colors.text : '#FFFFFF';
133
-
134
80
  const baseButtonStyle = getBaseButtonStyle(size, style);
135
81
  const baseTextStyle = getBaseTextStyle(size, textStyle);
136
82
 
137
83
  return (
138
- <AnimatedTouchableOpacity
139
- style={[baseButtonStyle, buttonColorStyle, animatedStyle]}
84
+ <TouchableOpacity
85
+ className={isFollowing
86
+ ? 'bg-background border-border'
87
+ : 'bg-primary border-primary'
88
+ }
89
+ style={baseButtonStyle}
140
90
  onPress={handlePress}
141
91
  disabled={disabled || isLoading}
142
92
  activeOpacity={0.8}
@@ -144,35 +94,26 @@ const FollowButtonInner = memo(function FollowButtonInner({
144
94
  {showLoadingState && isLoading ? (
145
95
  <ActivityIndicator
146
96
  size="small"
147
- color={textColor}
97
+ color={isFollowing ? colors.text : '#FFFFFF'}
148
98
  />
149
99
  ) : (
150
- <Text style={[baseTextStyle, { color: textColor }]}>
100
+ <Text
101
+ className={isFollowing ? 'text-foreground' : 'text-primary-foreground'}
102
+ style={baseTextStyle}
103
+ >
151
104
  {isFollowing ? 'Following' : 'Follow'}
152
105
  </Text>
153
106
  )}
154
- </AnimatedTouchableOpacity>
107
+ </TouchableOpacity>
155
108
  );
156
109
  });
157
110
 
158
- /**
159
- * Outer wrapper that handles the "should we render?" check.
160
- *
161
- * This is the ONLY place useOxy() is called — to check authentication and
162
- * get the current user ID for the self-follow guard. The oxyServices instance
163
- * is passed down as a prop to the inner component, which avoids subscribing
164
- * to the full OxyContext.
165
- *
166
- * The early return happens BEFORE the inner component mounts, so the inner
167
- * component's hooks are never called conditionally (no Rules of Hooks violation).
168
- */
169
111
  const FollowButton: React.FC<FollowButtonProps> = (props) => {
170
112
  const { oxyServices, isAuthenticated, user: currentUser } = useOxy();
171
113
 
172
114
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
173
115
  const targetUserId = props.userId ? String(props.userId).trim() : '';
174
116
 
175
- // Don't render if not authenticated or viewing own profile
176
117
  if (!isAuthenticated || !targetUserId || (currentUserId && currentUserId === targetUserId)) {
177
118
  return null;
178
119
  }
@@ -186,7 +127,6 @@ const FollowButton: React.FC<FollowButtonProps> = (props) => {
186
127
  );
187
128
  };
188
129
 
189
- // Pure helper functions (no hooks, no state) extracted outside the component
190
130
  function getBaseButtonStyle(size: string, style?: StyleProp<ViewStyle>): StyleProp<ViewStyle> {
191
131
  const baseStyle: ViewStyle = {
192
132
  flexDirection: 'row',