@stevederico/skateboard-ui 2.9.5 → 2.9.7

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/App.jsx CHANGED
@@ -159,15 +159,16 @@ export function createSkateboardApp({ constants, appRoutes, defaultRoute = appRo
159
159
  <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
160
160
  <Toaster position="top-right" richColors closeButton />
161
161
  <ContextProvider constants={constants}>
162
- <AuthOverlay />
163
162
  {Wrapper ? (
164
163
  <Wrapper>
165
164
  <Router>
165
+ <AuthOverlay />
166
166
  <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} overrides={overrides} />
167
167
  </Router>
168
168
  </Wrapper>
169
169
  ) : (
170
170
  <Router>
171
+ <AuthOverlay />
171
172
  <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} overrides={overrides} />
172
173
  </Router>
173
174
  )}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # CHANGELOG
2
2
 
3
+ 2.9.7
4
+
5
+ Add useSafeNavigate hook
6
+ Fix Router context error in auth views
7
+
8
+ 2.9.6
9
+
10
+ Move AuthOverlay inside Router
11
+
3
12
  2.9.5
4
13
 
5
14
  Reuse SignInView in AuthOverlay
package/core/Utilities.js CHANGED
@@ -1,4 +1,5 @@
1
- import { useEffect, useState } from 'react';
1
+ import { useEffect, useState, useContext } from 'react';
2
+ import { UNSAFE_NavigationContext } from 'react-router-dom';
2
3
  import { getDispatch } from './Context.jsx';
3
4
 
4
5
  // Constants will be initialized by the app shell
@@ -985,3 +986,33 @@ export function setUIVisibility({ sidebar, tabBar }) {
985
986
  console.warn('setUIVisibility: Context not initialized');
986
987
  }
987
988
  }
989
+
990
+ /**
991
+ * Safe navigation hook that works with or without Router context.
992
+ *
993
+ * Uses UNSAFE_NavigationContext directly instead of useNavigate() to avoid
994
+ * throwing when rendered outside Router (e.g., in Portals or module duplication).
995
+ * Falls back to window.location.href if no Router context is available.
996
+ *
997
+ * @returns {function} Navigate function (path, options?) => void
998
+ *
999
+ * @example
1000
+ * const navigate = useSafeNavigate();
1001
+ * navigate('/app');
1002
+ * navigate('/app', { replace: true });
1003
+ */
1004
+ export function useSafeNavigate() {
1005
+ const ctx = useContext(UNSAFE_NavigationContext);
1006
+
1007
+ if (!ctx) {
1008
+ return (path) => { window.location.href = path; };
1009
+ }
1010
+
1011
+ return (path, options = {}) => {
1012
+ if (options.replace) {
1013
+ ctx.navigator.replace(path, options.state);
1014
+ } else {
1015
+ ctx.navigator.push(path, options.state);
1016
+ }
1017
+ };
1018
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stevederico/skateboard-ui",
3
3
  "private": false,
4
- "version": "2.9.5",
4
+ "version": "2.9.7",
5
5
  "type": "module",
6
6
  "exports": {
7
7
  "./Sidebar": {
@@ -6,9 +6,8 @@ import { Label } from "../shadcn/ui/label"
6
6
  import { Card, CardContent, CardHeader } from "../shadcn/ui/card"
7
7
  import { Alert, AlertDescription } from "../shadcn/ui/alert"
8
8
  import DynamicIcon from '../core/DynamicIcon';
9
- import { useNavigate } from 'react-router-dom';
10
9
  import { getState } from "../core/Context.jsx";
11
- import { getBackendURL } from '../core/Utilities'
10
+ import { getBackendURL, useSafeNavigate } from '../core/Utilities'
12
11
 
13
12
  /**
14
13
  * Sign-in form component.
@@ -43,7 +42,7 @@ export default function LoginForm({
43
42
  const [email, setEmail] = useState('');
44
43
  const [password, setPassword] = useState('');
45
44
  const [isSubmitting, setIsSubmitting] = useState(false);
46
- const navigate = useNavigate();
45
+ const navigate = useSafeNavigate();
47
46
  const emailInputRef = useRef(null);
48
47
 
49
48
  const [errorMessage, setErrorMessage] = useState('')
@@ -6,9 +6,8 @@ import { Label } from "../shadcn/ui/label"
6
6
  import { Card, CardContent, CardHeader } from "../shadcn/ui/card"
7
7
  import { Alert, AlertDescription } from "../shadcn/ui/alert"
8
8
  import DynamicIcon from '../core/DynamicIcon';
9
- import { useNavigate } from 'react-router-dom';
10
9
  import { getState } from "../core/Context.jsx";
11
- import { getBackendURL } from '../core/Utilities'
10
+ import { getBackendURL, useSafeNavigate } from '../core/Utilities'
12
11
 
13
12
  /**
14
13
  * Sign-up form component.
@@ -44,8 +43,8 @@ export default function LoginForm({
44
43
  const [email, setEmail] = useState('');
45
44
  const [password, setPassword] = useState('');
46
45
  const [name, setName] = useState('');
47
- const navigate = useNavigate();
48
- const [errorMessage, setErrorMessage] = useState('')
46
+ const [errorMessage, setErrorMessage] = useState('');
47
+ const navigate = useSafeNavigate();
49
48
  const nameInputRef = useRef(null);
50
49
 
51
50
  // Focus the first input on mount