@viibestack/ui 0.7.0 → 0.7.2

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": "@viibestack/ui",
3
- "version": "0.7.0",
3
+ "version": "0.7.2",
4
4
  "description": "Dependency-free React UI kit -- icons, core components (Button, Card, Input, Modal, etc.), gamification primitives (PointsDisplay, StreakCounter, Achievements, Leaderboard, fireReward), a real per-app data client (listRows/upsertRow/deleteRow/captureClientError), a real per-app end-user auth client (signUp/logIn/logOut/getCurrentUser/reportError), and a self-gating PoweredByBadge component -- backed by ViibeStack's own platform-managed data store.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
package/src/auth.ts CHANGED
@@ -245,7 +245,11 @@ export async function confirmPasswordReset(token: string, newPassword: string):
245
245
  // const [url, setUrl] = useState<string | null>(null);
246
246
  // useEffect(() => { googleSignInUrl().then(setUrl); }, []);
247
247
  // {url && <a href={url}>Sign in with Google</a>}
248
- const AUTH_URL = "https://sideblend-auth.sideblend.workers.dev";
248
+ // BUG FIX (2026-07-21): must match services/auth's GOOGLE_APP_REDIRECT_URI
249
+ // host -- the app-start endpoint's oauth_state cookie has to be present
250
+ // when Google's callback lands back on that exact origin, or Google login
251
+ // silently fails with "invalid_state" for every deployed app using it.
252
+ const AUTH_URL = "https://auth.viibestack.ai";
249
253
 
250
254
  export async function googleSignInUrl(): Promise<string | null> {
251
255
  const appId = await resolveAppId();
package/src/badge.tsx CHANGED
@@ -29,10 +29,18 @@ function resolveShowBadge(): Promise<boolean> {
29
29
  return showBadgePromise;
30
30
  }
31
31
 
32
+ const DISMISS_KEY = "viibestack_badge_dismissed";
33
+
32
34
  export function PoweredByBadge() {
33
35
  const [show, setShow] = useState(false);
36
+ const [dismissed, setDismissed] = useState(false);
34
37
 
35
38
  useEffect(() => {
39
+ try {
40
+ if (sessionStorage.getItem(DISMISS_KEY) === "1") setDismissed(true);
41
+ } catch {
42
+ // sessionStorage unavailable (private mode, etc.) -- badge just won't be dismissible
43
+ }
36
44
  let cancelled = false;
37
45
  resolveShowBadge().then((result) => {
38
46
  if (!cancelled) setShow(result);
@@ -42,13 +50,10 @@ export function PoweredByBadge() {
42
50
  };
43
51
  }, []);
44
52
 
45
- if (!show) return null;
53
+ if (!show || dismissed) return null;
46
54
 
47
55
  return (
48
- <a
49
- href="https://viibestack.ai?utm_source=powered_by_badge"
50
- target="_blank"
51
- rel="noopener noreferrer"
56
+ <span
52
57
  style={{
53
58
  position: "fixed",
54
59
  bottom: "1rem",
@@ -56,19 +61,58 @@ export function PoweredByBadge() {
56
61
  zIndex: 9999,
57
62
  display: "flex",
58
63
  alignItems: "center",
59
- gap: "0.375rem",
60
- padding: "0.375rem 0.75rem",
64
+ gap: "0.25rem",
65
+ padding: "0.375rem 0.5rem 0.375rem 0.75rem",
61
66
  borderRadius: "9999px",
62
67
  backgroundColor: "rgba(17, 17, 17, 0.85)",
63
- color: "#fff",
64
- fontSize: "0.75rem",
65
- fontFamily: "system-ui, -apple-system, sans-serif",
66
- fontWeight: 500,
67
- textDecoration: "none",
68
68
  boxShadow: "0 2px 8px rgba(0, 0, 0, 0.2)",
69
+ fontFamily: "system-ui, -apple-system, sans-serif",
69
70
  }}
70
71
  >
71
- Powered by ViibeStack
72
- </a>
72
+ <a
73
+ href="https://viibestack.ai?utm_source=powered_by_badge"
74
+ target="_blank"
75
+ rel="noopener noreferrer"
76
+ style={{
77
+ color: "#fff",
78
+ fontSize: "0.75rem",
79
+ fontWeight: 500,
80
+ textDecoration: "none",
81
+ }}
82
+ >
83
+ Powered by ViibeStack
84
+ </a>
85
+ <button
86
+ type="button"
87
+ aria-label="Dismiss"
88
+ title="Hide for this visit"
89
+ onClick={(e) => {
90
+ e.preventDefault();
91
+ try {
92
+ sessionStorage.setItem(DISMISS_KEY, "1");
93
+ } catch {
94
+ // ignore -- see try/catch above
95
+ }
96
+ setDismissed(true);
97
+ }}
98
+ style={{
99
+ display: "flex",
100
+ alignItems: "center",
101
+ justifyContent: "center",
102
+ width: "1rem",
103
+ height: "1rem",
104
+ padding: 0,
105
+ border: "none",
106
+ borderRadius: "9999px",
107
+ background: "rgba(255, 255, 255, 0.15)",
108
+ color: "#fff",
109
+ fontSize: "0.7rem",
110
+ lineHeight: 1,
111
+ cursor: "pointer",
112
+ }}
113
+ >
114
+ &#x2715;
115
+ </button>
116
+ </span>
73
117
  );
74
118
  }