@stevederico/skateboard-ui 2.0.0 → 2.2.0

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.
Files changed (47) hide show
  1. package/.claude/settings.local.json +10 -0
  2. package/App.jsx +54 -27
  3. package/CHANGELOG.md +30 -0
  4. package/MIGRATION.md +230 -0
  5. package/README.md +861 -125
  6. package/components/AuthOverlay.jsx +273 -0
  7. package/{ErrorBoundary.jsx → components/ErrorBoundary.jsx} +28 -25
  8. package/{ProtectedRoute.jsx → components/ProtectedRoute.jsx} +7 -2
  9. package/{Sheet.jsx → components/Sheet.jsx} +5 -8
  10. package/{ThemeToggle.jsx → components/ThemeToggle.jsx} +13 -33
  11. package/components/UpgradeSheet.jsx +127 -0
  12. package/components.json +1 -1
  13. package/core/DynamicIcon.jsx +48 -0
  14. package/{Utilities.js → core/Utilities.js} +1 -1
  15. package/{useAuthGate.js → hooks/useAuthGate.js} +1 -1
  16. package/index.js +2 -2
  17. package/layout/Header.jsx +50 -0
  18. package/layout/Layout.jsx +49 -0
  19. package/layout/Sidebar.jsx +221 -0
  20. package/layout/TabBar.jsx +70 -0
  21. package/package.json +46 -58
  22. package/views/LandingView.jsx +161 -0
  23. package/views/NotFound.jsx +27 -0
  24. package/{PaymentView.jsx → views/PaymentView.jsx} +9 -9
  25. package/views/SettingsView.jsx +175 -0
  26. package/views/SignInView.jsx +151 -0
  27. package/{SignOutView.jsx → views/SignOutView.jsx} +6 -7
  28. package/views/SignUpView.jsx +190 -0
  29. package/{TextView.jsx → views/TextView.jsx} +14 -6
  30. package/AppSidebar.jsx +0 -167
  31. package/AuthOverlay.jsx +0 -277
  32. package/DynamicIcon.jsx +0 -30
  33. package/Header.jsx +0 -47
  34. package/LandingView.jsx +0 -324
  35. package/Layout.jsx +0 -85
  36. package/NotFound.jsx +0 -22
  37. package/SettingsView.jsx +0 -180
  38. package/SignInView.jsx +0 -140
  39. package/SignUpView.jsx +0 -186
  40. package/SkeletonLoader.jsx +0 -91
  41. package/TabBar.jsx +0 -68
  42. package/Toast.jsx +0 -30
  43. package/USAGE.md +0 -266
  44. package/UpgradeSheet.jsx +0 -118
  45. package/docs/AUTHENTICATION.md +0 -555
  46. package/styles/globals.css +0 -124
  47. /package/{Context.jsx → core/Context.jsx} +0 -0
@@ -0,0 +1,10 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(ls:*)",
5
+ "Bash(git mv:*)",
6
+ "Bash(git rm:*)",
7
+ "Bash(python3:*)"
8
+ ]
9
+ }
10
+ }
package/App.jsx CHANGED
@@ -8,23 +8,23 @@ import {
8
8
  } from 'react-router-dom';
9
9
  import { useEffect } from 'react';
10
10
  import { ThemeProvider } from 'next-themes';
11
- import Layout from './Layout.jsx';
12
- import LandingView from './LandingView.jsx';
13
- import TextView from './TextView.jsx';
14
- import SignUpView from './SignUpView.jsx';
15
- import SignInView from './SignInView.jsx';
16
- import SignOutView from './SignOutView.jsx';
17
- import PaymentView from './PaymentView.jsx';
18
- import SettingsView from './SettingsView.jsx';
19
- import NotFound from './NotFound.jsx';
20
- import ProtectedRoute from './ProtectedRoute.jsx';
21
- import ErrorBoundary from './ErrorBoundary.jsx';
22
- import { useAppSetup, initializeUtilities, validateConstants } from './Utilities.js';
23
- import { ContextProvider } from './Context.jsx';
24
- import Toast from './Toast.jsx';
25
- import AuthOverlay from './AuthOverlay.jsx';
11
+ import Layout from './layout/Layout.jsx';
12
+ import LandingView from './views/LandingView.jsx';
13
+ import TextView from './views/TextView.jsx';
14
+ import SignUpView from './views/SignUpView.jsx';
15
+ import SignInView from './views/SignInView.jsx';
16
+ import SignOutView from './views/SignOutView.jsx';
17
+ import PaymentView from './views/PaymentView.jsx';
18
+ import SettingsView from './views/SettingsView.jsx';
19
+ import NotFound from './views/NotFound.jsx';
20
+ import ProtectedRoute from './components/ProtectedRoute.jsx';
21
+ import ErrorBoundary from './components/ErrorBoundary.jsx';
22
+ import { useAppSetup, initializeUtilities, validateConstants } from './core/Utilities.js';
23
+ import { ContextProvider } from './core/Context.jsx';
24
+ import { Toaster } from './shadcn/ui/sonner.jsx';
25
+ import AuthOverlay from './components/AuthOverlay.jsx';
26
26
 
27
- function App({ constants, appRoutes, defaultRoute, landingPage }) {
27
+ function App({ constants, appRoutes, defaultRoute, landingPage, overrides = {} }) {
28
28
  const location = useLocation();
29
29
 
30
30
  useEffect(() => {
@@ -33,28 +33,36 @@ function App({ constants, appRoutes, defaultRoute, landingPage }) {
33
33
 
34
34
  useAppSetup(location);
35
35
 
36
+ const LayoutComponent = overrides.layout || Layout;
37
+ const SettingsComponent = overrides.settings || SettingsView;
38
+ const PaymentComponent = overrides.payment || PaymentView;
39
+ const SignInComponent = overrides.signIn || SignInView;
40
+ const SignUpComponent = overrides.signUp || SignUpView;
41
+ const SignOutComponent = overrides.signOut || SignOutView;
42
+ const NotFoundComponent = overrides.notFound || NotFound;
43
+
36
44
  return (
37
45
  <Routes>
38
- <Route element={<Layout />}>
46
+ <Route element={<LayoutComponent />}>
39
47
  <Route path="/console" element={<Navigate to="/app" replace />} />
40
48
  <Route path="/app" element={<ProtectedRoute />}>
41
49
  <Route index element={<Navigate to={defaultRoute} replace />} />
42
50
  {appRoutes.map(({ path, element }) => (
43
51
  <Route key={path} path={path} element={element} />
44
52
  ))}
45
- <Route path="settings" element={<SettingsView />} />
46
- <Route path="payment" element={<PaymentView />} />
53
+ <Route path="settings" element={<SettingsComponent />} />
54
+ <Route path="payment" element={<PaymentComponent />} />
47
55
  </Route>
48
56
  </Route>
49
57
  <Route path="/" element={landingPage || <LandingView />} />
50
- <Route path="/signin" element={<SignInView />} />
51
- <Route path="/signup" element={<SignUpView />} />
52
- <Route path="/signout" element={<SignOutView />} />
58
+ <Route path="/signin" element={<SignInComponent />} />
59
+ <Route path="/signup" element={<SignUpComponent />} />
60
+ <Route path="/signout" element={<SignOutComponent />} />
53
61
  <Route path="/terms" element={<TextView details={constants.termsOfService} />} />
54
62
  <Route path="/privacy" element={<TextView details={constants.privacyPolicy} />} />
55
63
  <Route path="/eula" element={<TextView details={constants.EULA} />} />
56
64
  <Route path="/subs" element={<TextView details={constants.subscriptionDetails} />} />
57
- <Route path="*" element={<NotFound />} />
65
+ <Route path="*" element={<NotFoundComponent />} />
58
66
  </Routes>
59
67
  );
60
68
  }
@@ -71,6 +79,14 @@ function App({ constants, appRoutes, defaultRoute, landingPage }) {
71
79
  * @param {string} [config.defaultRoute] - Default route path under /app (defaults to first route)
72
80
  * @param {JSX.Element} [config.landingPage] - Custom landing page for "/". Defaults to LandingView.
73
81
  * @param {React.ComponentType} [config.wrapper] - Optional wrapper component around the router
82
+ * @param {Object} [config.overrides] - Override built-in view components
83
+ * @param {React.ComponentType} [config.overrides.layout] - Replace Layout
84
+ * @param {React.ComponentType} [config.overrides.settings] - Replace SettingsView
85
+ * @param {React.ComponentType} [config.overrides.payment] - Replace PaymentView
86
+ * @param {React.ComponentType} [config.overrides.signIn] - Replace SignInView
87
+ * @param {React.ComponentType} [config.overrides.signUp] - Replace SignUpView
88
+ * @param {React.ComponentType} [config.overrides.signOut] - Replace SignOutView
89
+ * @param {React.ComponentType} [config.overrides.notFound] - Replace NotFound
74
90
  *
75
91
  * @example
76
92
  * import { createSkateboardApp } from '@stevederico/skateboard-ui/App';
@@ -80,8 +96,19 @@ function App({ constants, appRoutes, defaultRoute, landingPage }) {
80
96
  * constants,
81
97
  * appRoutes: [{ path: 'home', element: <HomeView /> }]
82
98
  * });
99
+ *
100
+ * @example
101
+ * // Override built-in views
102
+ * createSkateboardApp({
103
+ * constants,
104
+ * appRoutes: [{ path: 'home', element: <HomeView /> }],
105
+ * overrides: {
106
+ * settings: MySettingsView,
107
+ * signIn: MySignInView,
108
+ * }
109
+ * });
83
110
  */
84
- export function createSkateboardApp({ constants, appRoutes, defaultRoute = appRoutes[0]?.path || 'home', landingPage, wrapper: Wrapper }) {
111
+ export function createSkateboardApp({ constants, appRoutes, defaultRoute = appRoutes[0]?.path || 'home', landingPage, wrapper: Wrapper, overrides }) {
85
112
  // Validate constants before initialization
86
113
  validateConstants(constants);
87
114
 
@@ -94,18 +121,18 @@ export function createSkateboardApp({ constants, appRoutes, defaultRoute = appRo
94
121
  root.render(
95
122
  <ErrorBoundary>
96
123
  <ThemeProvider attribute="class" defaultTheme="system" enableSystem>
97
- <Toast />
124
+ <Toaster position="top-right" richColors closeButton />
98
125
  <ContextProvider constants={constants}>
99
126
  <AuthOverlay />
100
127
  {Wrapper ? (
101
128
  <Wrapper>
102
129
  <Router>
103
- <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} />
130
+ <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} overrides={overrides} />
104
131
  </Router>
105
132
  </Wrapper>
106
133
  ) : (
107
134
  <Router>
108
- <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} />
135
+ <App constants={constants} appRoutes={appRoutes} defaultRoute={defaultRoute} landingPage={landingPage} overrides={overrides} />
109
136
  </Router>
110
137
  )}
111
138
  </ContextProvider>
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # CHANGELOG
2
2
 
3
+ 2.2.0
4
+
5
+ Reorganize into folders
6
+ Add migration guide
7
+ Remove AppSidebar dead code
8
+ Remove LandingViewSimple export
9
+ Add view overrides
10
+
11
+ 2.1.0
12
+
13
+ Rename AppSidebar to Sidebar
14
+ Simplify LandingView layout
15
+ Add form Labels to views
16
+ Add AuthOverlay dialog header
17
+ Update SettingsView card layout
18
+ Add DynamicIcon className support
19
+ Remove Layout theme logic
20
+ Add sidebar Settings button
21
+ Consolidate docs into README
22
+ Remove USAGE.md
23
+ Remove AUTHENTICATION.md
24
+
25
+ 2.0.1
26
+
27
+ Add shadcn sidebar primitives
28
+ Add NavUser dropdown footer
29
+ Add SidebarInset layout
30
+ Fix ProtectedRoute loading state
31
+ Update sidebar width CSS var
32
+
3
33
  2.0.0
4
34
 
5
35
  Add gradient Button variant
package/MIGRATION.md ADDED
@@ -0,0 +1,230 @@
1
+ # Migration Guide
2
+
3
+ ## Upgrading from 1.4.x to 2.0.x
4
+
5
+ ### Breaking Changes
6
+
7
+ #### 1. `noProtectedRoutes` renamed to `authOverlay`
8
+
9
+ ```diff
10
+ const constants = {
11
+ - noProtectedRoutes: true,
12
+ + authOverlay: true,
13
+ };
14
+ ```
15
+
16
+ If you were using `noProtectedRoutes` to allow unauthenticated access to `/app` routes, rename it to `authOverlay`.
17
+
18
+ #### 2. `Toast` replaced by Sonner `Toaster`
19
+
20
+ If you imported `Toast` directly:
21
+
22
+ ```diff
23
+ - import Toast from '@stevederico/skateboard-ui/Toast';
24
+ ```
25
+
26
+ Remove it. `createSkateboardApp` now renders `<Toaster />` from [sonner](https://sonner.emilkowal.dev/) automatically. Use `toast()` from sonner directly:
27
+
28
+ ```javascript
29
+ import { toast } from 'sonner';
30
+
31
+ toast.success('Saved!');
32
+ toast.error('Something went wrong');
33
+ ```
34
+
35
+ #### 3. `SkeletonLoader` removed
36
+
37
+ ```diff
38
+ - import SkeletonLoader from '@stevederico/skateboard-ui/SkeletonLoader';
39
+ ```
40
+
41
+ Use the shadcn `Skeleton` component instead:
42
+
43
+ ```javascript
44
+ import { Skeleton } from '@stevederico/skateboard-ui/shadcn/ui/skeleton';
45
+
46
+ <Skeleton className="h-4 w-[200px]" />
47
+ ```
48
+
49
+ #### 4. `AppSidebar` renamed to `Sidebar`
50
+
51
+ ```diff
52
+ - import AppSidebar from '@stevederico/skateboard-ui/AppSidebar';
53
+ + import Sidebar from '@stevederico/skateboard-ui/Sidebar';
54
+ ```
55
+
56
+ Most apps don't import this directly (Layout handles it), but update if you do.
57
+
58
+ #### 5. `LandingViewSimple` removed
59
+
60
+ ```diff
61
+ - import LandingViewSimple from '@stevederico/skateboard-ui/LandingViewSimple';
62
+ ```
63
+
64
+ Use the `landingPage` parameter on `createSkateboardApp` to provide a custom landing page instead:
65
+
66
+ ```javascript
67
+ createSkateboardApp({
68
+ constants,
69
+ appRoutes,
70
+ landingPage: <MyCustomLanding />,
71
+ });
72
+ ```
73
+
74
+ ### New Features
75
+
76
+ #### AuthOverlay and useAuthGate (1.5.0+)
77
+
78
+ Gate actions behind authentication without redirecting:
79
+
80
+ ```javascript
81
+ import { useAuthGate } from '@stevederico/skateboard-ui/useAuthGate';
82
+
83
+ function SaveButton() {
84
+ const requireAuth = useAuthGate();
85
+
86
+ return (
87
+ <button onClick={() => requireAuth(() => saveThing())}>
88
+ Save
89
+ </button>
90
+ );
91
+ }
92
+ ```
93
+
94
+ Enable by setting `authOverlay: true` in constants. The overlay renders automatically.
95
+
96
+ #### Custom Landing Page (1.4.1+)
97
+
98
+ ```javascript
99
+ createSkateboardApp({
100
+ constants,
101
+ appRoutes,
102
+ landingPage: <MyLandingPage />,
103
+ });
104
+ ```
105
+
106
+ #### Sidebar Visibility Control (1.2.5+)
107
+
108
+ ```javascript
109
+ import { hideSidebar, showSidebar, hideTabBar, showTabBar } from '@stevederico/skateboard-ui/Utilities';
110
+
111
+ hideSidebar();
112
+ showTabBar();
113
+ ```
114
+
115
+ Or via constants:
116
+
117
+ ```javascript
118
+ const constants = {
119
+ hideSidebar: true,
120
+ hideTabBar: true,
121
+ };
122
+ ```
123
+
124
+ ### Full Upgrade Steps
125
+
126
+ 1. Update the package:
127
+ ```bash
128
+ deno install npm:@stevederico/skateboard-ui@latest
129
+ ```
130
+
131
+ 2. Search your codebase for removed imports:
132
+ ```
133
+ Toast, SkeletonLoader, AppSidebar, LandingViewSimple, noProtectedRoutes
134
+ ```
135
+
136
+ 3. Replace any direct `Toast` usage with `sonner`:
137
+ ```javascript
138
+ import { toast } from 'sonner';
139
+ ```
140
+
141
+ 4. Replace `SkeletonLoader` with shadcn `Skeleton`.
142
+
143
+ 5. Rename `noProtectedRoutes` to `authOverlay` in your constants.
144
+
145
+ 6. Run the app and verify routing, auth, sidebar, and toasts.
146
+
147
+ ---
148
+
149
+ ## Upgrading from 2.0.x to 2.1.x+
150
+
151
+ ### No Breaking Changes
152
+
153
+ All consumer import paths are unchanged. This release reorganized the internal file structure but the `exports` map in `package.json` keeps every public import stable:
154
+
155
+ ```javascript
156
+ // These all still work exactly the same
157
+ import { createSkateboardApp } from '@stevederico/skateboard-ui/App';
158
+ import { getState } from '@stevederico/skateboard-ui/Context';
159
+ import { apiRequest } from '@stevederico/skateboard-ui/Utilities';
160
+ import Layout from '@stevederico/skateboard-ui/Layout';
161
+ import Sidebar from '@stevederico/skateboard-ui/Sidebar';
162
+ import { Button } from '@stevederico/skateboard-ui/shadcn/ui/button';
163
+ ```
164
+
165
+ ### What Changed Internally
166
+
167
+ Files were reorganized into folders:
168
+
169
+ | Before (2.0.x) | After (2.1.x+) |
170
+ |-----------------|-----------------|
171
+ | `Context.jsx` | `core/Context.jsx` |
172
+ | `Utilities.js` | `core/Utilities.js` |
173
+ | `DynamicIcon.jsx` | `core/DynamicIcon.jsx` |
174
+ | `Layout.jsx` | `layout/Layout.jsx` |
175
+ | `Sidebar.jsx` | `layout/Sidebar.jsx` |
176
+ | `TabBar.jsx` | `layout/TabBar.jsx` |
177
+ | `Header.jsx` | `layout/Header.jsx` |
178
+ | `LandingView.jsx` | `views/LandingView.jsx` |
179
+ | `SignInView.jsx` | `views/SignInView.jsx` |
180
+ | `SignUpView.jsx` | `views/SignUpView.jsx` |
181
+ | `SignOutView.jsx` | `views/SignOutView.jsx` |
182
+ | `SettingsView.jsx` | `views/SettingsView.jsx` |
183
+ | `PaymentView.jsx` | `views/PaymentView.jsx` |
184
+ | `TextView.jsx` | `views/TextView.jsx` |
185
+ | `NotFound.jsx` | `views/NotFound.jsx` |
186
+ | `ThemeToggle.jsx` | `components/ThemeToggle.jsx` |
187
+ | `Sheet.jsx` | `components/Sheet.jsx` |
188
+ | `UpgradeSheet.jsx` | `components/UpgradeSheet.jsx` |
189
+ | `ErrorBoundary.jsx` | `components/ErrorBoundary.jsx` |
190
+ | `AuthOverlay.jsx` | `components/AuthOverlay.jsx` |
191
+ | `ProtectedRoute.jsx` | `components/ProtectedRoute.jsx` |
192
+ | `useAuthGate.js` | `hooks/useAuthGate.js` |
193
+
194
+ ### Cleanup
195
+
196
+ - `AppSidebar.jsx` deleted (was dead code since 2.1.0)
197
+ - `LandingViewSimple` export removed (file never existed on disk)
198
+
199
+ ### New: View Overrides (2.1.x+)
200
+
201
+ Override built-in views without forking:
202
+
203
+ ```javascript
204
+ createSkateboardApp({
205
+ constants,
206
+ appRoutes,
207
+ overrides: {
208
+ settings: MySettingsView,
209
+ signIn: MySignInView,
210
+ signUp: MySignUpView,
211
+ signOut: MySignOutView,
212
+ payment: MyPaymentView,
213
+ notFound: MyNotFoundView,
214
+ layout: MyLayout,
215
+ },
216
+ });
217
+ ```
218
+
219
+ ### Upgrade Steps
220
+
221
+ 1. Update the package:
222
+ ```bash
223
+ deno install npm:@stevederico/skateboard-ui@latest
224
+ ```
225
+
226
+ 2. No code changes required. All imports resolve the same way.
227
+
228
+ 3. If you were importing `LandingViewSimple`, it was already broken (file didn't exist). Remove the import.
229
+
230
+ 4. Run the app and confirm everything works.