@oxyhq/services 6.9.32 → 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.
@@ -10,22 +10,9 @@ var _OxyContext = require("../context/OxyContext.js");
10
10
  var _fonts = require("../styles/fonts.js");
11
11
  var _sonner = require("../../lib/sonner");
12
12
  var _useFollow = require("../hooks/useFollow.js");
13
- var _theme2 = require("@oxyhq/bloom/theme");
13
+ var _theme = require("@oxyhq/bloom/theme");
14
14
  var _jsxRuntime = require("react/jsx-runtime");
15
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); }
16
- /**
17
- * Inner component that handles all hooks and rendering.
18
- *
19
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
20
- * The outer wrapper handles the auth/self-follow guard and returns null
21
- * before any hooks are called. This inner component always renders
22
- * (all hooks are called unconditionally).
23
- *
24
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
25
- * not subscribe to the OxyContext. This is critical in list contexts where
26
- * N buttons would all re-render on any context change (session socket events,
27
- * token refreshes, etc.).
28
- */
29
16
  const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInner({
30
17
  userId,
31
18
  oxyServices,
@@ -36,13 +23,11 @@ const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInn
36
23
  textStyle,
37
24
  disabled = false,
38
25
  showLoadingState = true,
39
- preventParentActions = true,
40
- theme: _theme = 'light'
26
+ preventParentActions = true
41
27
  }) {
42
- const bloomTheme = (0, _theme2.useTheme)();
43
- const colors = bloomTheme.colors;
44
-
45
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
28
+ const {
29
+ colors
30
+ } = (0, _theme.useTheme)();
46
31
  const {
47
32
  isFollowing,
48
33
  isLoading,
@@ -50,80 +35,47 @@ const FollowButtonInner = /*#__PURE__*/(0, _react.memo)(function FollowButtonInn
50
35
  setFollowStatus,
51
36
  fetchStatus
52
37
  } = (0, _useFollow.useFollowForButton)(userId, oxyServices);
53
-
54
- // Stable press handler — depends on primitives only
55
38
  const handlePress = (0, _react.useCallback)(async event => {
56
- if (preventParentActions && event && event.preventDefault) {
39
+ if (preventParentActions && event?.preventDefault) {
57
40
  event.preventDefault();
58
41
  event.stopPropagation?.();
59
42
  }
60
43
  if (disabled || isLoading) return;
61
44
  try {
62
45
  await toggleFollow();
63
- if (onFollowChange) onFollowChange(!isFollowing);
46
+ onFollowChange?.(!isFollowing);
64
47
  } catch (err) {
65
48
  const error = err instanceof Error ? err : new Error(String(err));
66
49
  _sonner.toast.error(error.message || 'Failed to update follow status');
67
50
  }
68
51
  }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
69
-
70
- // Set initial follow status on mount if provided and not already set
71
52
  (0, _react.useEffect)(() => {
72
53
  if (userId && !isFollowing && initiallyFollowing) {
73
54
  setFollowStatus(initiallyFollowing);
74
55
  }
75
- // Intentional: only run on mount with initial values
76
56
  // eslint-disable-next-line react-hooks/exhaustive-deps
77
57
  }, [userId, initiallyFollowing]);
78
-
79
- // Fetch latest follow status from backend on mount
80
58
  (0, _react.useEffect)(() => {
81
- if (userId) {
82
- fetchStatus();
83
- }
59
+ if (userId) fetchStatus();
84
60
  }, [userId, fetchStatus]);
85
-
86
- // Colors from bloom theme — follows NativeWind convention via useTheme()
87
- // Not following: bg-primary, border-primary, text white
88
- // Following: bg-background, border-border, text-foreground
89
- const buttonColorStyle = isFollowing ? {
90
- backgroundColor: colors.background,
91
- borderColor: colors.border
92
- } : {
93
- backgroundColor: colors.primary,
94
- borderColor: colors.primary
95
- };
96
- const textColor = isFollowing ? colors.text : '#FFFFFF';
97
61
  const baseButtonStyle = getBaseButtonStyle(size, style);
98
62
  const baseTextStyle = getBaseTextStyle(size, textStyle);
99
63
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
100
- style: [baseButtonStyle, buttonColorStyle],
64
+ className: isFollowing ? 'bg-background border-border' : 'bg-primary border-primary',
65
+ style: baseButtonStyle,
101
66
  onPress: handlePress,
102
67
  disabled: disabled || isLoading,
103
68
  activeOpacity: 0.8,
104
69
  children: showLoadingState && isLoading ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {
105
70
  size: "small",
106
- color: textColor
71
+ color: isFollowing ? colors.text : '#FFFFFF'
107
72
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
108
- style: [baseTextStyle, {
109
- color: textColor
110
- }],
73
+ className: isFollowing ? 'text-foreground' : 'text-primary-foreground',
74
+ style: baseTextStyle,
111
75
  children: isFollowing ? 'Following' : 'Follow'
112
76
  })
113
77
  });
114
78
  });
115
-
116
- /**
117
- * Outer wrapper that handles the "should we render?" check.
118
- *
119
- * This is the ONLY place useOxy() is called — to check authentication and
120
- * get the current user ID for the self-follow guard. The oxyServices instance
121
- * is passed down as a prop to the inner component, which avoids subscribing
122
- * to the full OxyContext.
123
- *
124
- * The early return happens BEFORE the inner component mounts, so the inner
125
- * component's hooks are never called conditionally (no Rules of Hooks violation).
126
- */
127
79
  const FollowButton = props => {
128
80
  const {
129
81
  oxyServices,
@@ -132,8 +84,6 @@ const FollowButton = props => {
132
84
  } = (0, _OxyContext.useOxy)();
133
85
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
134
86
  const targetUserId = props.userId ? String(props.userId).trim() : '';
135
-
136
- // Don't render if not authenticated or viewing own profile
137
87
  if (!isAuthenticated || !targetUserId || currentUserId && currentUserId === targetUserId) {
138
88
  return null;
139
89
  }
@@ -143,8 +93,6 @@ const FollowButton = props => {
143
93
  oxyServices: oxyServices
144
94
  });
145
95
  };
146
-
147
- // Pure helper functions (no hooks, no state) extracted outside the component
148
96
  exports.FollowButton = FollowButton;
149
97
  function getBaseButtonStyle(size, style) {
150
98
  const baseStyle = {
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","_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","FollowButtonInner","memo","userId","oxyServices","initiallyFollowing","size","onFollowChange","style","textStyle","disabled","showLoadingState","preventParentActions","theme","_theme","bloomTheme","useTheme","colors","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","useFollowForButton","handlePress","useCallback","event","preventDefault","stopPropagation","err","error","Error","String","toast","message","useEffect","buttonColorStyle","backgroundColor","background","borderColor","border","primary","textColor","text","baseButtonStyle","getBaseButtonStyle","baseTextStyle","getBaseTextStyle","jsx","TouchableOpacity","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":[]}
@@ -8,19 +8,6 @@ import { toast } from '../../lib/sonner';
8
8
  import { useFollowForButton } from "../hooks/useFollow.js";
9
9
  import { useTheme } from '@oxyhq/bloom/theme';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
- /**
12
- * Inner component that handles all hooks and rendering.
13
- *
14
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
15
- * The outer wrapper handles the auth/self-follow guard and returns null
16
- * before any hooks are called. This inner component always renders
17
- * (all hooks are called unconditionally).
18
- *
19
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
20
- * not subscribe to the OxyContext. This is critical in list contexts where
21
- * N buttons would all re-render on any context change (session socket events,
22
- * token refreshes, etc.).
23
- */
24
11
  const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
25
12
  userId,
26
13
  oxyServices,
@@ -31,13 +18,11 @@ const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
31
18
  textStyle,
32
19
  disabled = false,
33
20
  showLoadingState = true,
34
- preventParentActions = true,
35
- theme: _theme = 'light'
21
+ preventParentActions = true
36
22
  }) {
37
- const bloomTheme = useTheme();
38
- const colors = bloomTheme.colors;
39
-
40
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
23
+ const {
24
+ colors
25
+ } = useTheme();
41
26
  const {
42
27
  isFollowing,
43
28
  isLoading,
@@ -45,80 +30,47 @@ const FollowButtonInner = /*#__PURE__*/memo(function FollowButtonInner({
45
30
  setFollowStatus,
46
31
  fetchStatus
47
32
  } = useFollowForButton(userId, oxyServices);
48
-
49
- // Stable press handler — depends on primitives only
50
33
  const handlePress = useCallback(async event => {
51
- if (preventParentActions && event && event.preventDefault) {
34
+ if (preventParentActions && event?.preventDefault) {
52
35
  event.preventDefault();
53
36
  event.stopPropagation?.();
54
37
  }
55
38
  if (disabled || isLoading) return;
56
39
  try {
57
40
  await toggleFollow();
58
- if (onFollowChange) onFollowChange(!isFollowing);
41
+ onFollowChange?.(!isFollowing);
59
42
  } catch (err) {
60
43
  const error = err instanceof Error ? err : new Error(String(err));
61
44
  toast.error(error.message || 'Failed to update follow status');
62
45
  }
63
46
  }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
64
-
65
- // Set initial follow status on mount if provided and not already set
66
47
  useEffect(() => {
67
48
  if (userId && !isFollowing && initiallyFollowing) {
68
49
  setFollowStatus(initiallyFollowing);
69
50
  }
70
- // Intentional: only run on mount with initial values
71
51
  // eslint-disable-next-line react-hooks/exhaustive-deps
72
52
  }, [userId, initiallyFollowing]);
73
-
74
- // Fetch latest follow status from backend on mount
75
53
  useEffect(() => {
76
- if (userId) {
77
- fetchStatus();
78
- }
54
+ if (userId) fetchStatus();
79
55
  }, [userId, fetchStatus]);
80
-
81
- // Colors from bloom theme — follows NativeWind convention via useTheme()
82
- // Not following: bg-primary, border-primary, text white
83
- // Following: bg-background, border-border, text-foreground
84
- const buttonColorStyle = isFollowing ? {
85
- backgroundColor: colors.background,
86
- borderColor: colors.border
87
- } : {
88
- backgroundColor: colors.primary,
89
- borderColor: colors.primary
90
- };
91
- const textColor = isFollowing ? colors.text : '#FFFFFF';
92
56
  const baseButtonStyle = getBaseButtonStyle(size, style);
93
57
  const baseTextStyle = getBaseTextStyle(size, textStyle);
94
58
  return /*#__PURE__*/_jsx(TouchableOpacity, {
95
- style: [baseButtonStyle, buttonColorStyle],
59
+ className: isFollowing ? 'bg-background border-border' : 'bg-primary border-primary',
60
+ style: baseButtonStyle,
96
61
  onPress: handlePress,
97
62
  disabled: disabled || isLoading,
98
63
  activeOpacity: 0.8,
99
64
  children: showLoadingState && isLoading ? /*#__PURE__*/_jsx(ActivityIndicator, {
100
65
  size: "small",
101
- color: textColor
66
+ color: isFollowing ? colors.text : '#FFFFFF'
102
67
  }) : /*#__PURE__*/_jsx(Text, {
103
- style: [baseTextStyle, {
104
- color: textColor
105
- }],
68
+ className: isFollowing ? 'text-foreground' : 'text-primary-foreground',
69
+ style: baseTextStyle,
106
70
  children: isFollowing ? 'Following' : 'Follow'
107
71
  })
108
72
  });
109
73
  });
110
-
111
- /**
112
- * Outer wrapper that handles the "should we render?" check.
113
- *
114
- * This is the ONLY place useOxy() is called — to check authentication and
115
- * get the current user ID for the self-follow guard. The oxyServices instance
116
- * is passed down as a prop to the inner component, which avoids subscribing
117
- * to the full OxyContext.
118
- *
119
- * The early return happens BEFORE the inner component mounts, so the inner
120
- * component's hooks are never called conditionally (no Rules of Hooks violation).
121
- */
122
74
  const FollowButton = props => {
123
75
  const {
124
76
  oxyServices,
@@ -127,8 +79,6 @@ const FollowButton = props => {
127
79
  } = useOxy();
128
80
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
129
81
  const targetUserId = props.userId ? String(props.userId).trim() : '';
130
-
131
- // Don't render if not authenticated or viewing own profile
132
82
  if (!isAuthenticated || !targetUserId || currentUserId && currentUserId === targetUserId) {
133
83
  return null;
134
84
  }
@@ -138,8 +88,6 @@ const FollowButton = props => {
138
88
  oxyServices: oxyServices
139
89
  });
140
90
  };
141
-
142
- // Pure helper functions (no hooks, no state) extracted outside the component
143
91
  function getBaseButtonStyle(size, style) {
144
92
  const baseStyle = {
145
93
  flexDirection: 'row',
@@ -1 +1 @@
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","theme","_theme","bloomTheme","colors","isFollowing","isLoading","toggleFollow","setFollowStatus","fetchStatus","handlePress","event","preventDefault","stopPropagation","err","error","Error","String","message","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;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;AAyGD;;;;;;;;;;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;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;AAyGD;;;;;;;;;;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.32",
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" />
@@ -28,19 +28,6 @@ export interface FollowButtonProps {
28
28
  theme?: 'light' | 'dark';
29
29
  }
30
30
 
31
- /**
32
- * Inner component that handles all hooks and rendering.
33
- *
34
- * Separated from the outer wrapper to avoid a Rules of Hooks violation.
35
- * The outer wrapper handles the auth/self-follow guard and returns null
36
- * before any hooks are called. This inner component always renders
37
- * (all hooks are called unconditionally).
38
- *
39
- * Receives oxyServices as a prop instead of calling useOxy(), so it does
40
- * not subscribe to the OxyContext. This is critical in list contexts where
41
- * N buttons would all re-render on any context change (session socket events,
42
- * token refreshes, etc.).
43
- */
44
31
  const FollowButtonInner = memo(function FollowButtonInner({
45
32
  userId,
46
33
  oxyServices,
@@ -52,12 +39,9 @@ const FollowButtonInner = memo(function FollowButtonInner({
52
39
  disabled = false,
53
40
  showLoadingState = true,
54
41
  preventParentActions = true,
55
- theme: _theme = 'light',
56
42
  }: FollowButtonProps & { oxyServices: OxyServices }) {
57
- const bloomTheme = useTheme();
58
- const colors = bloomTheme.colors;
43
+ const { colors } = useTheme();
59
44
 
60
- // Uses granular Zustand selectors — only re-renders when THIS user's data changes
61
45
  const {
62
46
  isFollowing,
63
47
  isLoading,
@@ -66,9 +50,8 @@ const FollowButtonInner = memo(function FollowButtonInner({
66
50
  fetchStatus,
67
51
  } = useFollowForButton(userId, oxyServices);
68
52
 
69
- // Stable press handler — depends on primitives only
70
53
  const handlePress = useCallback(async (event?: { preventDefault?: () => void; stopPropagation?: () => void }) => {
71
- if (preventParentActions && event && event.preventDefault) {
54
+ if (preventParentActions && event?.preventDefault) {
72
55
  event.preventDefault();
73
56
  event.stopPropagation?.();
74
57
  }
@@ -76,43 +59,34 @@ const FollowButtonInner = memo(function FollowButtonInner({
76
59
 
77
60
  try {
78
61
  await toggleFollow();
79
- if (onFollowChange) onFollowChange(!isFollowing);
62
+ onFollowChange?.(!isFollowing);
80
63
  } catch (err: unknown) {
81
64
  const error = err instanceof Error ? err : new Error(String(err));
82
65
  toast.error(error.message || 'Failed to update follow status');
83
66
  }
84
67
  }, [disabled, isLoading, toggleFollow, onFollowChange, isFollowing, preventParentActions]);
85
68
 
86
- // Set initial follow status on mount if provided and not already set
87
69
  useEffect(() => {
88
70
  if (userId && !isFollowing && initiallyFollowing) {
89
71
  setFollowStatus(initiallyFollowing);
90
72
  }
91
- // Intentional: only run on mount with initial values
92
73
  // eslint-disable-next-line react-hooks/exhaustive-deps
93
74
  }, [userId, initiallyFollowing]);
94
75
 
95
- // Fetch latest follow status from backend on mount
96
76
  useEffect(() => {
97
- if (userId) {
98
- fetchStatus();
99
- }
77
+ if (userId) fetchStatus();
100
78
  }, [userId, fetchStatus]);
101
79
 
102
- // Colors from bloom theme — follows NativeWind convention via useTheme()
103
- // Not following: bg-primary, border-primary, text white
104
- // Following: bg-background, border-border, text-foreground
105
- const buttonColorStyle: ViewStyle = isFollowing
106
- ? { backgroundColor: colors.background, borderColor: colors.border }
107
- : { backgroundColor: colors.primary, borderColor: colors.primary };
108
- const textColor = isFollowing ? colors.text : '#FFFFFF';
109
-
110
80
  const baseButtonStyle = getBaseButtonStyle(size, style);
111
81
  const baseTextStyle = getBaseTextStyle(size, textStyle);
112
82
 
113
83
  return (
114
84
  <TouchableOpacity
115
- style={[baseButtonStyle, buttonColorStyle]}
85
+ className={isFollowing
86
+ ? 'bg-background border-border'
87
+ : 'bg-primary border-primary'
88
+ }
89
+ style={baseButtonStyle}
116
90
  onPress={handlePress}
117
91
  disabled={disabled || isLoading}
118
92
  activeOpacity={0.8}
@@ -120,10 +94,13 @@ const FollowButtonInner = memo(function FollowButtonInner({
120
94
  {showLoadingState && isLoading ? (
121
95
  <ActivityIndicator
122
96
  size="small"
123
- color={textColor}
97
+ color={isFollowing ? colors.text : '#FFFFFF'}
124
98
  />
125
99
  ) : (
126
- <Text style={[baseTextStyle, { color: textColor }]}>
100
+ <Text
101
+ className={isFollowing ? 'text-foreground' : 'text-primary-foreground'}
102
+ style={baseTextStyle}
103
+ >
127
104
  {isFollowing ? 'Following' : 'Follow'}
128
105
  </Text>
129
106
  )}
@@ -131,24 +108,12 @@ const FollowButtonInner = memo(function FollowButtonInner({
131
108
  );
132
109
  });
133
110
 
134
- /**
135
- * Outer wrapper that handles the "should we render?" check.
136
- *
137
- * This is the ONLY place useOxy() is called — to check authentication and
138
- * get the current user ID for the self-follow guard. The oxyServices instance
139
- * is passed down as a prop to the inner component, which avoids subscribing
140
- * to the full OxyContext.
141
- *
142
- * The early return happens BEFORE the inner component mounts, so the inner
143
- * component's hooks are never called conditionally (no Rules of Hooks violation).
144
- */
145
111
  const FollowButton: React.FC<FollowButtonProps> = (props) => {
146
112
  const { oxyServices, isAuthenticated, user: currentUser } = useOxy();
147
113
 
148
114
  const currentUserId = currentUser?.id ? String(currentUser.id).trim() : '';
149
115
  const targetUserId = props.userId ? String(props.userId).trim() : '';
150
116
 
151
- // Don't render if not authenticated or viewing own profile
152
117
  if (!isAuthenticated || !targetUserId || (currentUserId && currentUserId === targetUserId)) {
153
118
  return null;
154
119
  }
@@ -162,7 +127,6 @@ const FollowButton: React.FC<FollowButtonProps> = (props) => {
162
127
  );
163
128
  };
164
129
 
165
- // Pure helper functions (no hooks, no state) extracted outside the component
166
130
  function getBaseButtonStyle(size: string, style?: StyleProp<ViewStyle>): StyleProp<ViewStyle> {
167
131
  const baseStyle: ViewStyle = {
168
132
  flexDirection: 'row',