@interactive-inc/docs-client 0.0.1

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 (91) hide show
  1. package/.tanstack/tmp/router-generator-Eq20Yx/50b11a0f488e61cf92364a7e585c1448 +123 -0
  2. package/.tanstack/tmp/router-generator-KQIYSa/aecb094e4891f9475b91de590abc8809 +117 -0
  3. package/.tanstack/tmp/router-generator-ekW2pI/aecb094e4891f9475b91de590abc8809 +117 -0
  4. package/app/components/archived-file-list-view.tsx +99 -0
  5. package/app/components/directory-file-list-view.tsx +32 -0
  6. package/app/components/directory-file-tree-node.tsx +96 -0
  7. package/app/components/directory-layout-sidebar.tsx +181 -0
  8. package/app/components/directory-page-view.tsx +208 -0
  9. package/app/components/directory-table-view.tsx +383 -0
  10. package/app/components/editable-table-cell/boolean-editable-cell.tsx +44 -0
  11. package/app/components/editable-table-cell/multi-boolean-editable-cell.tsx +59 -0
  12. package/app/components/editable-table-cell/multi-number-editable-cell.tsx +62 -0
  13. package/app/components/editable-table-cell/multi-relation-editable-cell.tsx +19 -0
  14. package/app/components/editable-table-cell/multi-select-number-editable-cell.tsx +82 -0
  15. package/app/components/editable-table-cell/multi-select-text-editable-cell.tsx +82 -0
  16. package/app/components/editable-table-cell/multi-text-editable-cell.tsx +62 -0
  17. package/app/components/editable-table-cell/number-editable-cell.tsx +54 -0
  18. package/app/components/editable-table-cell/relation-editable-cell.tsx +20 -0
  19. package/app/components/editable-table-cell/select-number-editable-cell.tsx +43 -0
  20. package/app/components/editable-table-cell/select-text-editable-cell.tsx +33 -0
  21. package/app/components/editable-table-cell/string-editable-cell.tsx +42 -0
  22. package/app/components/editable-table-cell.tsx +129 -0
  23. package/app/components/file-card.tsx +120 -0
  24. package/app/components/file-tree-icon.tsx +26 -0
  25. package/app/components/file-view/archive-restore-banner.tsx +86 -0
  26. package/app/components/file-view/csv-file-view.tsx +50 -0
  27. package/app/components/file-view/default-file-view.tsx +11 -0
  28. package/app/components/file-view/editable-csv-cell.tsx +37 -0
  29. package/app/components/file-view/editable-front-matter-view.tsx +105 -0
  30. package/app/components/file-view/file-csv-columns-view.tsx +181 -0
  31. package/app/components/file-view/file-csv-table.tsx +142 -0
  32. package/app/components/file-view/file-header.tsx +115 -0
  33. package/app/components/file-view/file-page-view.tsx +165 -0
  34. package/app/components/file-view/front-matter-input-field.tsx +157 -0
  35. package/app/components/file-view/front-matter-view.tsx +30 -0
  36. package/app/components/file-view/json-file-editor.tsx +38 -0
  37. package/app/components/file-view/markdown-file-view.tsx +71 -0
  38. package/app/components/file-view/multi-relation-select.tsx +129 -0
  39. package/app/components/file-view/render-front-matter-value.tsx +57 -0
  40. package/app/components/file-view/single-relation-select.tsx +41 -0
  41. package/app/components/file-view/sortable-csv-row.tsx +57 -0
  42. package/app/components/file-view/sortable-header.tsx +30 -0
  43. package/app/components/file-view/utils.ts +8 -0
  44. package/app/components/milestones-editor.tsx +95 -0
  45. package/app/components/page-header.tsx +20 -0
  46. package/app/components/project-view/feature-item.tsx +139 -0
  47. package/app/components/project-view/project-page-group.tsx +125 -0
  48. package/app/components/project-view/project-view.tsx +230 -0
  49. package/app/components/project-view/unlinked-features-section.tsx +73 -0
  50. package/app/components/providers.tsx +21 -0
  51. package/app/components/reload-button.tsx +25 -0
  52. package/app/components/sidebar-button.tsx +13 -0
  53. package/app/components/ui/alert.tsx +66 -0
  54. package/app/components/ui/badge.tsx +46 -0
  55. package/app/components/ui/button.tsx +59 -0
  56. package/app/components/ui/card.tsx +92 -0
  57. package/app/components/ui/dialog.tsx +133 -0
  58. package/app/components/ui/emoji-picker.tsx +133 -0
  59. package/app/components/ui/icons.tsx +3 -0
  60. package/app/components/ui/input.tsx +21 -0
  61. package/app/components/ui/select.tsx +183 -0
  62. package/app/components/ui/separator.tsx +26 -0
  63. package/app/components/ui/sheet.tsx +137 -0
  64. package/app/components/ui/sidebar.tsx +724 -0
  65. package/app/components/ui/simple-sidebar.tsx +50 -0
  66. package/app/components/ui/skeleton.tsx +13 -0
  67. package/app/components/ui/sonner.tsx +23 -0
  68. package/app/components/ui/table.tsx +114 -0
  69. package/app/components/ui/tabs.tsx +53 -0
  70. package/app/components/ui/textarea.tsx +18 -0
  71. package/app/components/ui/tooltip.tsx +59 -0
  72. package/app/components/vscode-button.tsx +23 -0
  73. package/app/hooks/use-directory-query.ts +22 -0
  74. package/app/hooks/use-file-properties-mutation.ts +38 -0
  75. package/app/hooks/use-file-query.ts +21 -0
  76. package/app/hooks/use-mobile.ts +19 -0
  77. package/app/main.css +122 -0
  78. package/app/main.tsx +38 -0
  79. package/app/routes/$.index.tsx +25 -0
  80. package/app/routes/$.tsx +20 -0
  81. package/app/routes/__root.tsx +20 -0
  82. package/app/routes/_index.tsx +17 -0
  83. package/app/routes/apps.client.$.tsx +21 -0
  84. package/build/assets/index.css +1 -0
  85. package/build/assets/index.js +298 -0
  86. package/build/index.d.ts +2 -0
  87. package/build/index.d.ts.map +1 -0
  88. package/build/index.js +23 -0
  89. package/components.json +21 -0
  90. package/package.json +54 -0
  91. package/tsconfig.index.json +17 -0
@@ -0,0 +1,50 @@
1
+ import type { ReactNode } from "react"
2
+ import { Button } from "@/components/ui/button"
3
+
4
+ type Props = {
5
+ title: string
6
+ children: ReactNode
7
+ isOpen: boolean
8
+ onClose: () => void
9
+ onOpen: () => void
10
+ footer: ReactNode
11
+ }
12
+
13
+ export function SimpleSidebar(props: Props) {
14
+ return (
15
+ <>
16
+ <div
17
+ className={`border-r transition-all duration-200 ${
18
+ props.isOpen ? "w-64" : "w-0 overflow-hidden"
19
+ }`}
20
+ >
21
+ <div className="flex h-full flex-col">
22
+ <div className="flex items-center justify-between border-b p-4">
23
+ <h2 className="font-semibold">{props.title}</h2>
24
+ <Button
25
+ variant="ghost"
26
+ size="sm"
27
+ onClick={props.onClose}
28
+ className="h-8 w-8 p-0"
29
+ >
30
+ {"<"}
31
+ </Button>
32
+ </div>
33
+ <div className="flex-1 overflow-auto p-4">{props.children}</div>
34
+ <div className="border-t p-4">{props.footer}</div>
35
+ </div>
36
+ </div>
37
+
38
+ {!props.isOpen && (
39
+ <Button
40
+ variant="ghost"
41
+ size="sm"
42
+ onClick={props.onOpen}
43
+ className="absolute top-16 left-4 h-8 w-8 p-0"
44
+ >
45
+ {">"}
46
+ </Button>
47
+ )}
48
+ </>
49
+ )
50
+ }
@@ -0,0 +1,13 @@
1
+ import { cn } from "@/lib/utils"
2
+
3
+ function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
4
+ return (
5
+ <div
6
+ data-slot="skeleton"
7
+ className={cn("animate-pulse rounded-md bg-accent", className)}
8
+ {...props}
9
+ />
10
+ )
11
+ }
12
+
13
+ export { Skeleton }
@@ -0,0 +1,23 @@
1
+ import { useTheme } from "next-themes"
2
+ import { Toaster as Sonner, type ToasterProps } from "sonner"
3
+
4
+ const Toaster = ({ ...props }: ToasterProps) => {
5
+ const { theme = "system" } = useTheme()
6
+
7
+ return (
8
+ <Sonner
9
+ theme={theme as ToasterProps["theme"]}
10
+ className="toaster group"
11
+ style={
12
+ {
13
+ "--normal-bg": "var(--popover)",
14
+ "--normal-text": "var(--popover-foreground)",
15
+ "--normal-border": "var(--border)",
16
+ } as React.CSSProperties
17
+ }
18
+ {...props}
19
+ />
20
+ )
21
+ }
22
+
23
+ export { Toaster }
@@ -0,0 +1,114 @@
1
+ import type * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
6
+ return (
7
+ <div
8
+ data-slot="table-container"
9
+ className="relative w-full overflow-x-auto"
10
+ >
11
+ <table
12
+ data-slot="table"
13
+ className={cn("w-full caption-bottom text-sm", className)}
14
+ {...props}
15
+ />
16
+ </div>
17
+ )
18
+ }
19
+
20
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
21
+ return (
22
+ <thead
23
+ data-slot="table-header"
24
+ className={cn("[&_tr]:border-b", className)}
25
+ {...props}
26
+ />
27
+ )
28
+ }
29
+
30
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
31
+ return (
32
+ <tbody
33
+ data-slot="table-body"
34
+ className={cn("[&_tr:last-child]:border-0", className)}
35
+ {...props}
36
+ />
37
+ )
38
+ }
39
+
40
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
41
+ return (
42
+ <tfoot
43
+ data-slot="table-footer"
44
+ className={cn(
45
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ )
51
+ }
52
+
53
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
54
+ return (
55
+ <tr
56
+ data-slot="table-row"
57
+ className={cn(
58
+ "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
59
+ className,
60
+ )}
61
+ {...props}
62
+ />
63
+ )
64
+ }
65
+
66
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
67
+ return (
68
+ <th
69
+ data-slot="table-head"
70
+ className={cn(
71
+ "h-10 whitespace-nowrap px-2 text-left align-middle font-medium text-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
72
+ className,
73
+ )}
74
+ {...props}
75
+ />
76
+ )
77
+ }
78
+
79
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
80
+ return (
81
+ <td
82
+ data-slot="table-cell"
83
+ className={cn(
84
+ "whitespace-nowrap p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
85
+ className,
86
+ )}
87
+ {...props}
88
+ />
89
+ )
90
+ }
91
+
92
+ function TableCaption({
93
+ className,
94
+ ...props
95
+ }: React.ComponentProps<"caption">) {
96
+ return (
97
+ <caption
98
+ data-slot="table-caption"
99
+ className={cn("mt-4 text-muted-foreground text-sm", className)}
100
+ {...props}
101
+ />
102
+ )
103
+ }
104
+
105
+ export {
106
+ Table,
107
+ TableHeader,
108
+ TableBody,
109
+ TableFooter,
110
+ TableHead,
111
+ TableRow,
112
+ TableCell,
113
+ TableCaption,
114
+ }
@@ -0,0 +1,53 @@
1
+ import { Tabs as TabsPrimitive } from "radix-ui"
2
+ import * as React from "react"
3
+
4
+ import { cn } from "@/lib/utils"
5
+
6
+ const Tabs = TabsPrimitive.Root
7
+
8
+ const TabsList = React.forwardRef<
9
+ React.ElementRef<typeof TabsPrimitive.List>,
10
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
11
+ >(({ className, ...props }, ref) => (
12
+ <TabsPrimitive.List
13
+ ref={ref}
14
+ className={cn(
15
+ "inline-flex h-10 items-center justify-center rounded-md bg-muted p-1 text-muted-foreground",
16
+ className,
17
+ )}
18
+ {...props}
19
+ />
20
+ ))
21
+ TabsList.displayName = TabsPrimitive.List.displayName
22
+
23
+ const TabsTrigger = React.forwardRef<
24
+ React.ElementRef<typeof TabsPrimitive.Trigger>,
25
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
26
+ >(({ className, ...props }, ref) => (
27
+ <TabsPrimitive.Trigger
28
+ ref={ref}
29
+ className={cn(
30
+ "inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 font-medium text-sm ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
31
+ className,
32
+ )}
33
+ {...props}
34
+ />
35
+ ))
36
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
37
+
38
+ const TabsContent = React.forwardRef<
39
+ React.ElementRef<typeof TabsPrimitive.Content>,
40
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
41
+ >(({ className, ...props }, ref) => (
42
+ <TabsPrimitive.Content
43
+ ref={ref}
44
+ className={cn(
45
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
46
+ className,
47
+ )}
48
+ {...props}
49
+ />
50
+ ))
51
+ TabsContent.displayName = TabsPrimitive.Content.displayName
52
+
53
+ export { Tabs, TabsList, TabsTrigger, TabsContent }
@@ -0,0 +1,18 @@
1
+ import type * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
6
+ return (
7
+ <textarea
8
+ data-slot="textarea"
9
+ className={cn(
10
+ "field-sizing-content flex min-h-16 w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs outline-none transition-[color,box-shadow] placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
11
+ className,
12
+ )}
13
+ {...props}
14
+ />
15
+ )
16
+ }
17
+
18
+ export { Textarea }
@@ -0,0 +1,59 @@
1
+ import { Tooltip as TooltipPrimitive } from "radix-ui"
2
+ import type * as React from "react"
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({
20
+ ...props
21
+ }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
22
+ return (
23
+ <TooltipProvider>
24
+ <TooltipPrimitive.Root data-slot="tooltip" {...props} />
25
+ </TooltipProvider>
26
+ )
27
+ }
28
+
29
+ function TooltipTrigger({
30
+ ...props
31
+ }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
32
+ return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
33
+ }
34
+
35
+ function TooltipContent({
36
+ className,
37
+ sideOffset = 0,
38
+ children,
39
+ ...props
40
+ }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
41
+ return (
42
+ <TooltipPrimitive.Portal>
43
+ <TooltipPrimitive.Content
44
+ data-slot="tooltip-content"
45
+ sideOffset={sideOffset}
46
+ className={cn(
47
+ "fade-in-0 zoom-in-95 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) animate-in text-balance rounded-md bg-primary px-3 py-1.5 text-primary-foreground text-xs data-[state=closed]:animate-out",
48
+ className,
49
+ )}
50
+ {...props}
51
+ >
52
+ {children}
53
+ <TooltipPrimitive.Arrow className="z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary" />
54
+ </TooltipPrimitive.Content>
55
+ </TooltipPrimitive.Portal>
56
+ )
57
+ }
58
+
59
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
@@ -0,0 +1,23 @@
1
+ import { ExternalLink } from "lucide-react"
2
+ import { getVSCodeFileLink } from "@/lib/get-vscode-link"
3
+ import { Button } from "./ui/button"
4
+
5
+ type Props = {
6
+ cwd: string
7
+ filePath: string
8
+ size?: "sm" | "default" | "lg" | "icon"
9
+ variant?: "default" | "secondary" | "ghost" | "outline"
10
+ }
11
+
12
+ export function VscodeButton(props: Props) {
13
+ // filePathは既に絶対パスとして渡されることを期待
14
+ const href = getVSCodeFileLink(props.filePath)
15
+
16
+ return (
17
+ <a href={href} className="block">
18
+ <Button size={props.size || "sm"} variant={props.variant || "secondary"}>
19
+ <ExternalLink />
20
+ </Button>
21
+ </a>
22
+ )
23
+ }
@@ -0,0 +1,22 @@
1
+ import { useSuspenseQuery } from "@tanstack/react-query"
2
+ import { apiClient } from "@/lib/api-client"
3
+ import { getDirectoryPath } from "@/lib/open-csv/get-directory-path"
4
+
5
+ const endpoint = apiClient.api.directories[":path{.+}"]
6
+
7
+ export function useDirectoryQuery(filePath: string) {
8
+ const directoryPath = getDirectoryPath(filePath)
9
+
10
+ const path = directoryPath.startsWith("/")
11
+ ? directoryPath.substring(1)
12
+ : directoryPath
13
+
14
+ return useSuspenseQuery({
15
+ queryKey: [endpoint.$url({ param: { path } })],
16
+ async queryFn() {
17
+ const resp = await endpoint.$get({ param: { path } })
18
+
19
+ return resp.json()
20
+ },
21
+ })
22
+ }
@@ -0,0 +1,38 @@
1
+ import { useMutation } from "@tanstack/react-query"
2
+ import { apiClient } from "@/lib/api-client"
3
+ import { normalizePath } from "@/lib/path-utils"
4
+
5
+ type Params = {
6
+ path: string
7
+ field?: string
8
+ value?: unknown
9
+ }
10
+
11
+ const endpoint = apiClient.api.files[":path{.+}"]
12
+
13
+ export function useFilePropertiesMutation() {
14
+ return useMutation({
15
+ async mutationFn(params: Params) {
16
+ const normalizedPath = normalizePath(params.path)
17
+
18
+ const path = normalizedPath.startsWith("/")
19
+ ? normalizedPath.substring(1)
20
+ : normalizedPath
21
+
22
+ const properties = params.field ? { [params.field]: params.value } : {}
23
+
24
+ const response = await endpoint.$put({
25
+ param: { path },
26
+ json: {
27
+ properties,
28
+ content: null,
29
+ title: null,
30
+ description: null,
31
+ isArchived: null,
32
+ },
33
+ })
34
+
35
+ return response.json()
36
+ },
37
+ })
38
+ }
@@ -0,0 +1,21 @@
1
+ import { useSuspenseQuery } from "@tanstack/react-query"
2
+ import { apiClient } from "@/lib/api-client"
3
+
4
+ const endpoint = apiClient.api.files[":path{.+}"]
5
+
6
+ export function useFileQuery(currentPath: string) {
7
+ const normalizedPath = currentPath.replace(/^docs\//, "")
8
+
9
+ const path = normalizedPath.startsWith("/")
10
+ ? normalizedPath.substring(1)
11
+ : normalizedPath
12
+
13
+ return useSuspenseQuery({
14
+ queryKey: [endpoint.$url({ param: { path } })],
15
+ async queryFn() {
16
+ const resp = await endpoint.$get({ param: { path } })
17
+
18
+ return resp.json()
19
+ },
20
+ })
21
+ }
@@ -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
+ }
package/app/main.css ADDED
@@ -0,0 +1,122 @@
1
+ @import "tailwindcss";
2
+ @plugin "tailwindcss-animate";
3
+
4
+ @custom-variant dark (&:is(.dark *));
5
+
6
+ :root {
7
+ --radius: 0.65rem;
8
+ --background: oklch(1 0 0);
9
+ --foreground: oklch(0.145 0 0);
10
+ --card: oklch(1 0 0);
11
+ --card-foreground: oklch(0.145 0 0);
12
+ --popover: oklch(1 0 0);
13
+ --popover-foreground: oklch(0.145 0 0);
14
+ --primary: oklch(0.205 0 0);
15
+ --primary-foreground: oklch(0.985 0 0);
16
+ --secondary: oklch(0.97 0 0);
17
+ --secondary-foreground: oklch(0.205 0 0);
18
+ --muted: oklch(0.97 0 0);
19
+ --muted-foreground: oklch(0.556 0 0);
20
+ --accent: oklch(0.97 0 0);
21
+ --accent-foreground: oklch(0.205 0 0);
22
+ --destructive: oklch(0.577 0.245 27.325);
23
+ --border: oklch(0.922 0 0);
24
+ --input: oklch(0.922 0 0);
25
+ --ring: oklch(0.708 0 0);
26
+ --chart-1: oklch(0.646 0.222 41.116);
27
+ --chart-2: oklch(0.6 0.118 184.704);
28
+ --chart-3: oklch(0.398 0.07 227.392);
29
+ --chart-4: oklch(0.828 0.189 84.429);
30
+ --chart-5: oklch(0.769 0.188 70.08);
31
+ --radius: 0.625rem;
32
+ --sidebar: oklch(0.985 0 0);
33
+ --sidebar-foreground: oklch(0.145 0 0);
34
+ --sidebar-primary: oklch(0.205 0 0);
35
+ --sidebar-primary-foreground: oklch(0.985 0 0);
36
+ --sidebar-accent: oklch(0.97 0 0);
37
+ --sidebar-accent-foreground: oklch(0.205 0 0);
38
+ --sidebar-border: oklch(0.922 0 0);
39
+ --sidebar-ring: oklch(0.708 0 0);
40
+ }
41
+
42
+ .dark {
43
+ --background: oklch(0.145 0 0);
44
+ --foreground: oklch(0.985 0 0);
45
+ --card: oklch(0.205 0 0);
46
+ --card-foreground: oklch(0.985 0 0);
47
+ --popover: oklch(0.205 0 0);
48
+ --popover-foreground: oklch(0.985 0 0);
49
+ --primary: oklch(0.922 0 0);
50
+ --primary-foreground: oklch(0.205 0 0);
51
+ --secondary: oklch(0.269 0 0);
52
+ --secondary-foreground: oklch(0.985 0 0);
53
+ --muted: oklch(0.269 0 0);
54
+ --muted-foreground: oklch(0.708 0 0);
55
+ --accent: oklch(0.269 0 0);
56
+ --accent-foreground: oklch(0.985 0 0);
57
+ --destructive: oklch(0.704 0.191 22.216);
58
+ --border: oklch(1 0 0 / 10%);
59
+ --input: oklch(1 0 0 / 15%);
60
+ --ring: oklch(0.556 0 0);
61
+ --chart-1: oklch(0.488 0.243 264.376);
62
+ --chart-2: oklch(0.696 0.17 162.48);
63
+ --chart-3: oklch(0.769 0.188 70.08);
64
+ --chart-4: oklch(0.627 0.265 303.9);
65
+ --chart-5: oklch(0.645 0.246 16.439);
66
+ --sidebar: oklch(0.205 0 0);
67
+ --sidebar-foreground: oklch(0.985 0 0);
68
+ --sidebar-primary: oklch(0.488 0.243 264.376);
69
+ --sidebar-primary-foreground: oklch(0.985 0 0);
70
+ --sidebar-accent: oklch(0.269 0 0);
71
+ --sidebar-accent-foreground: oklch(0.985 0 0);
72
+ --sidebar-border: oklch(1 0 0 / 10%);
73
+ --sidebar-ring: oklch(0.556 0 0);
74
+ }
75
+
76
+ @theme inline {
77
+ --color-background: var(--background);
78
+ --color-foreground: var(--foreground);
79
+ --color-card: var(--card);
80
+ --color-card-foreground: var(--card-foreground);
81
+ --color-popover: var(--popover);
82
+ --color-popover-foreground: var(--popover-foreground);
83
+ --color-primary: var(--primary);
84
+ --color-primary-foreground: var(--primary-foreground);
85
+ --color-secondary: var(--secondary);
86
+ --color-secondary-foreground: var(--secondary-foreground);
87
+ --color-muted: var(--muted);
88
+ --color-muted-foreground: var(--muted-foreground);
89
+ --color-accent: var(--accent);
90
+ --color-accent-foreground: var(--accent-foreground);
91
+ --color-destructive: var(--destructive);
92
+ --color-destructive-foreground: var(--destructive-foreground);
93
+ --color-border: var(--border);
94
+ --color-input: var(--input);
95
+ --color-ring: var(--ring);
96
+ --color-chart-1: var(--chart-1);
97
+ --color-chart-2: var(--chart-2);
98
+ --color-chart-3: var(--chart-3);
99
+ --color-chart-4: var(--chart-4);
100
+ --color-chart-5: var(--chart-5);
101
+ --radius-sm: calc(var(--radius) - 4px);
102
+ --radius-md: calc(var(--radius) - 2px);
103
+ --radius-lg: var(--radius);
104
+ --radius-xl: calc(var(--radius) + 4px);
105
+ --color-sidebar-ring: var(--sidebar-ring);
106
+ --color-sidebar-border: var(--sidebar-border);
107
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
108
+ --color-sidebar-accent: var(--sidebar-accent);
109
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
110
+ --color-sidebar-primary: var(--sidebar-primary);
111
+ --color-sidebar-foreground: var(--sidebar-foreground);
112
+ --color-sidebar: var(--sidebar);
113
+ }
114
+
115
+ @layer base {
116
+ * {
117
+ @apply border-border outline-ring/50;
118
+ }
119
+ body {
120
+ @apply bg-background text-foreground;
121
+ }
122
+ }
package/app/main.tsx ADDED
@@ -0,0 +1,38 @@
1
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query"
2
+ import { createRouter, RouterProvider } from "@tanstack/react-router"
3
+ import { Suspense } from "react"
4
+ import { createRoot } from "react-dom/client"
5
+ import { Toaster } from "@/components/ui/sonner"
6
+ import { routeTree } from "@/lib/route-tree.gen"
7
+
8
+ import "@/main.css"
9
+
10
+ const router = createRouter({
11
+ routeTree,
12
+ defaultPreload: "intent",
13
+ })
14
+
15
+ declare module "@tanstack/react-router" {
16
+ interface Register {
17
+ router: typeof router
18
+ }
19
+ }
20
+
21
+ const container = document.getElementById("app")
22
+
23
+ if (container === null) {
24
+ throw new Error("No container found")
25
+ }
26
+
27
+ const root = createRoot(container)
28
+
29
+ const queryClient = new QueryClient()
30
+
31
+ root.render(
32
+ <QueryClientProvider client={queryClient}>
33
+ <Suspense fallback={null}>
34
+ <RouterProvider router={router} />
35
+ <Toaster />
36
+ </Suspense>
37
+ </QueryClientProvider>,
38
+ )
@@ -0,0 +1,25 @@
1
+ import { createFileRoute, useLocation } from "@tanstack/react-router"
2
+ import { DirectoryPageView } from "@/components/directory-page-view"
3
+ import { FilePageView } from "@/components/file-view/file-page-view"
4
+
5
+ export const Route = createFileRoute("/$/")({
6
+ component: Component,
7
+ })
8
+
9
+ function Component() {
10
+ const pathname = useLocation({ select: (location) => location.pathname })
11
+
12
+ const supportedExtensions = [".md", ".csv", ".json", ".mermaid"]
13
+
14
+ const isFile = supportedExtensions.some((ext) => pathname.endsWith(ext))
15
+
16
+ if (pathname.startsWith("/apps")) {
17
+ return null
18
+ }
19
+
20
+ if (isFile) {
21
+ return <FilePageView filePath={pathname} />
22
+ }
23
+
24
+ return <DirectoryPageView key={pathname} currentPath={pathname} />
25
+ }
@@ -0,0 +1,20 @@
1
+ import { createFileRoute, Outlet, useLocation } from "@tanstack/react-router"
2
+ import { Suspense } from "react"
3
+
4
+ export const Route = createFileRoute("/$")({
5
+ component: Component,
6
+ })
7
+
8
+ function Component() {
9
+ return (
10
+ <Suspense
11
+ fallback={
12
+ <div className="flex h-[50vh] items-center justify-center">
13
+ <div className="text-muted-foreground">読み込み中...</div>
14
+ </div>
15
+ }
16
+ >
17
+ <Outlet />
18
+ </Suspense>
19
+ )
20
+ }