create-kuckit-app 0.2.1 → 0.3.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.
- package/package.json +1 -1
- package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +47 -10
- package/templates/base/apps/web/src/components/dashboard/app-sidebar.tsx +120 -0
- package/templates/base/apps/web/src/components/dashboard/dashboard-layout.tsx +46 -0
- package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +24 -0
- package/templates/base/apps/web/src/components/dashboard/index.ts +2 -0
- package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +77 -0
- package/templates/base/apps/web/src/components/ui/avatar.tsx +39 -0
- package/templates/base/apps/web/src/components/ui/breadcrumb.tsx +102 -0
- package/templates/base/apps/web/src/components/ui/collapsible.tsx +21 -0
- package/templates/base/apps/web/src/components/ui/separator.tsx +26 -0
- package/templates/base/apps/web/src/components/ui/sheet.tsx +130 -0
- package/templates/base/apps/web/src/components/ui/sidebar.tsx +694 -0
- package/templates/base/apps/web/src/components/ui/skeleton.tsx +13 -0
- package/templates/base/apps/web/src/components/ui/tooltip.tsx +55 -0
- package/templates/base/apps/web/src/hooks/use-mobile.ts +19 -0
- package/templates/base/apps/web/src/lib/utils.ts +6 -0
- package/templates/base/apps/web/src/modules.client.ts +1 -1
- package/templates/base/apps/web/src/providers/KuckitProvider.tsx +1 -25
- package/templates/base/apps/web/src/routes/dashboard/$.tsx +9 -0
- package/templates/base/apps/web/src/routes/dashboard/index.tsx +6 -0
- package/templates/base/apps/web/src/routes/dashboard.tsx +25 -0
- package/templates/base/apps/web/src/lib/kuckit-router.ts +0 -42
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
|
3
|
+
|
|
4
|
+
import { cn } from '@/lib/utils'
|
|
5
|
+
|
|
6
|
+
function TooltipProvider({
|
|
7
|
+
delayDuration = 0,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
|
10
|
+
return (
|
|
11
|
+
<TooltipPrimitive.Provider
|
|
12
|
+
data-slot="tooltip-provider"
|
|
13
|
+
delayDuration={delayDuration}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
|
20
|
+
return (
|
|
21
|
+
<TooltipProvider>
|
|
22
|
+
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
|
23
|
+
</TooltipProvider>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
|
28
|
+
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function TooltipContent({
|
|
32
|
+
className,
|
|
33
|
+
sideOffset = 0,
|
|
34
|
+
children,
|
|
35
|
+
...props
|
|
36
|
+
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
|
37
|
+
return (
|
|
38
|
+
<TooltipPrimitive.Portal>
|
|
39
|
+
<TooltipPrimitive.Content
|
|
40
|
+
data-slot="tooltip-content"
|
|
41
|
+
sideOffset={sideOffset}
|
|
42
|
+
className={cn(
|
|
43
|
+
'bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance',
|
|
44
|
+
className
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
<TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" />
|
|
50
|
+
</TooltipPrimitive.Content>
|
|
51
|
+
</TooltipPrimitive.Portal>
|
|
52
|
+
)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react'
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
+
}
|
|
13
|
+
mql.addEventListener('change', onChange)
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
+
return () => mql.removeEventListener('change', onChange)
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return !!isMobile
|
|
19
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ClientModuleSpec } from '@kuckit/sdk-react'
|
|
2
|
-
import { kuckitClientModule as itemsClientModule } from '@__APP_NAME_KEBAB__/items-module/client'
|
|
2
|
+
import { kuckitClientModule as itemsClientModule } from '@__APP_NAME_KEBAB__/items-module/src/client-module'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Client modules configuration
|
|
@@ -1,10 +1,5 @@
|
|
|
1
1
|
import { createContext, useContext, useEffect, useState, useMemo, type ReactNode } from 'react'
|
|
2
|
-
import {
|
|
3
|
-
RouterProvider,
|
|
4
|
-
createRouter,
|
|
5
|
-
createRoute,
|
|
6
|
-
type RouteComponent,
|
|
7
|
-
} from '@tanstack/react-router'
|
|
2
|
+
import { RouterProvider, createRouter } from '@tanstack/react-router'
|
|
8
3
|
import {
|
|
9
4
|
loadKuckitClientModules,
|
|
10
5
|
KuckitNavProvider,
|
|
@@ -16,7 +11,6 @@ import {
|
|
|
16
11
|
type SlotRegistry,
|
|
17
12
|
} from '@kuckit/sdk-react'
|
|
18
13
|
import { routeTree } from '../routeTree.gen'
|
|
19
|
-
import { Route as rootRoute } from '../routes/__root'
|
|
20
14
|
import { useServices } from './ServicesProvider'
|
|
21
15
|
import { getClientModuleSpecs } from '../modules.client'
|
|
22
16
|
|
|
@@ -81,26 +75,8 @@ export function KuckitProvider({ children }: KuckitProviderProps) {
|
|
|
81
75
|
}
|
|
82
76
|
}, [orpc, queryClient])
|
|
83
77
|
|
|
84
|
-
// Build router with module routes
|
|
85
78
|
const router = useMemo(() => {
|
|
86
79
|
if (!loadResult) return null
|
|
87
|
-
|
|
88
|
-
const moduleRouteDefs = loadResult.routeRegistry.getAll()
|
|
89
|
-
const moduleRoutes = moduleRouteDefs.map((routeDef) =>
|
|
90
|
-
createRoute({
|
|
91
|
-
getParentRoute: () => rootRoute,
|
|
92
|
-
path: routeDef.path,
|
|
93
|
-
component: routeDef.component as RouteComponent,
|
|
94
|
-
})
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
if (moduleRoutes.length > 0) {
|
|
98
|
-
console.log(
|
|
99
|
-
`Loaded ${moduleRoutes.length} module routes:`,
|
|
100
|
-
moduleRouteDefs.map((r) => r.path)
|
|
101
|
-
)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
80
|
return createRouter({
|
|
105
81
|
routeTree,
|
|
106
82
|
defaultPreload: 'intent',
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router'
|
|
2
|
+
import { KuckitModuleRoute } from '@/components/KuckitModuleRoute'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Catch-all route for KuckitModule routes under /dashboard.
|
|
6
|
+
*/
|
|
7
|
+
export const Route = createFileRoute('/dashboard/$')({
|
|
8
|
+
component: KuckitModuleRoute,
|
|
9
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createFileRoute, Outlet, redirect } from '@tanstack/react-router'
|
|
2
|
+
import { DashboardLayout } from '@/components/dashboard/dashboard-layout'
|
|
3
|
+
import { createAuthClientService } from '../services/auth-client'
|
|
4
|
+
|
|
5
|
+
export const Route = createFileRoute('/dashboard')({
|
|
6
|
+
beforeLoad: async () => {
|
|
7
|
+
const authClient = createAuthClientService()
|
|
8
|
+
const session = await authClient.getSession()
|
|
9
|
+
if (!session.data) {
|
|
10
|
+
throw redirect({
|
|
11
|
+
to: '/login',
|
|
12
|
+
})
|
|
13
|
+
}
|
|
14
|
+
return { session }
|
|
15
|
+
},
|
|
16
|
+
component: DashboardLayoutRoute,
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
function DashboardLayoutRoute() {
|
|
20
|
+
return (
|
|
21
|
+
<DashboardLayout>
|
|
22
|
+
<Outlet />
|
|
23
|
+
</DashboardLayout>
|
|
24
|
+
)
|
|
25
|
+
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { createRoute, type AnyRoute, type RouteComponent } from '@tanstack/react-router'
|
|
2
|
-
import type { QueryClient } from '@tanstack/react-query'
|
|
3
|
-
import type { RouteRegistry, RouteDefinition } from '@kuckit/sdk-react'
|
|
4
|
-
import type { ORPCUtils } from '../services/types'
|
|
5
|
-
|
|
6
|
-
export interface KuckitRouterContext {
|
|
7
|
-
orpc: ORPCUtils
|
|
8
|
-
queryClient: QueryClient
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Build TanStack Router routes from a RouteRegistry
|
|
13
|
-
*/
|
|
14
|
-
export function buildModuleRoutes(routeRegistry: RouteRegistry, rootRoute: AnyRoute): AnyRoute[] {
|
|
15
|
-
const routes = routeRegistry.getAll()
|
|
16
|
-
const routeMap = new Map<string, AnyRoute>()
|
|
17
|
-
|
|
18
|
-
for (const routeDef of routes) {
|
|
19
|
-
const route = createModuleRoute(routeDef, rootRoute)
|
|
20
|
-
routeMap.set(routeDef.id, route)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const topLevelRoutes = routes
|
|
24
|
-
.filter((r) => !r.parentRouteId || r.parentRouteId === '__root__')
|
|
25
|
-
.map((r) => routeMap.get(r.id)!)
|
|
26
|
-
.filter(Boolean)
|
|
27
|
-
|
|
28
|
-
return topLevelRoutes
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createModuleRoute(routeDef: RouteDefinition, parentRoute: AnyRoute): AnyRoute {
|
|
32
|
-
return createRoute({
|
|
33
|
-
getParentRoute: () => parentRoute,
|
|
34
|
-
path: routeDef.path,
|
|
35
|
-
component: routeDef.component as RouteComponent,
|
|
36
|
-
...(routeDef.meta?.title && {
|
|
37
|
-
head: () => ({
|
|
38
|
-
meta: [{ title: routeDef.meta!.title }],
|
|
39
|
-
}),
|
|
40
|
-
}),
|
|
41
|
-
})
|
|
42
|
-
}
|