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.
Files changed (23) hide show
  1. package/package.json +1 -1
  2. package/templates/base/apps/web/src/components/KuckitModuleRoute.tsx +47 -10
  3. package/templates/base/apps/web/src/components/dashboard/app-sidebar.tsx +120 -0
  4. package/templates/base/apps/web/src/components/dashboard/dashboard-layout.tsx +46 -0
  5. package/templates/base/apps/web/src/components/dashboard/dashboard-overview.tsx +24 -0
  6. package/templates/base/apps/web/src/components/dashboard/index.ts +2 -0
  7. package/templates/base/apps/web/src/components/dashboard/nav-user.tsx +77 -0
  8. package/templates/base/apps/web/src/components/ui/avatar.tsx +39 -0
  9. package/templates/base/apps/web/src/components/ui/breadcrumb.tsx +102 -0
  10. package/templates/base/apps/web/src/components/ui/collapsible.tsx +21 -0
  11. package/templates/base/apps/web/src/components/ui/separator.tsx +26 -0
  12. package/templates/base/apps/web/src/components/ui/sheet.tsx +130 -0
  13. package/templates/base/apps/web/src/components/ui/sidebar.tsx +694 -0
  14. package/templates/base/apps/web/src/components/ui/skeleton.tsx +13 -0
  15. package/templates/base/apps/web/src/components/ui/tooltip.tsx +55 -0
  16. package/templates/base/apps/web/src/hooks/use-mobile.ts +19 -0
  17. package/templates/base/apps/web/src/lib/utils.ts +6 -0
  18. package/templates/base/apps/web/src/modules.client.ts +1 -1
  19. package/templates/base/apps/web/src/providers/KuckitProvider.tsx +1 -25
  20. package/templates/base/apps/web/src/routes/dashboard/$.tsx +9 -0
  21. package/templates/base/apps/web/src/routes/dashboard/index.tsx +6 -0
  22. package/templates/base/apps/web/src/routes/dashboard.tsx +25 -0
  23. 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
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx'
2
+ import { twMerge } from 'tailwind-merge'
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs))
6
+ }
@@ -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,6 @@
1
+ import { createFileRoute } from '@tanstack/react-router'
2
+ import { DashboardOverview } from '@/components/dashboard/dashboard-overview'
3
+
4
+ export const Route = createFileRoute('/dashboard/')({
5
+ component: DashboardOverview,
6
+ })
@@ -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
- }