@interactive-inc/docs-client 0.0.1 → 0.0.3

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 (93) hide show
  1. package/bin/docs.js +3 -0
  2. package/build/assets/index.css +1 -1
  3. package/build/assets/index.js +53 -53
  4. package/build/index.html +13 -0
  5. package/build/index.js +24057 -16
  6. package/package.json +13 -6
  7. package/.tanstack/tmp/router-generator-Eq20Yx/50b11a0f488e61cf92364a7e585c1448 +0 -123
  8. package/.tanstack/tmp/router-generator-KQIYSa/aecb094e4891f9475b91de590abc8809 +0 -117
  9. package/.tanstack/tmp/router-generator-ekW2pI/aecb094e4891f9475b91de590abc8809 +0 -117
  10. package/app/components/archived-file-list-view.tsx +0 -99
  11. package/app/components/directory-file-list-view.tsx +0 -32
  12. package/app/components/directory-file-tree-node.tsx +0 -96
  13. package/app/components/directory-layout-sidebar.tsx +0 -181
  14. package/app/components/directory-page-view.tsx +0 -208
  15. package/app/components/directory-table-view.tsx +0 -383
  16. package/app/components/editable-table-cell/boolean-editable-cell.tsx +0 -44
  17. package/app/components/editable-table-cell/multi-boolean-editable-cell.tsx +0 -59
  18. package/app/components/editable-table-cell/multi-number-editable-cell.tsx +0 -62
  19. package/app/components/editable-table-cell/multi-relation-editable-cell.tsx +0 -19
  20. package/app/components/editable-table-cell/multi-select-number-editable-cell.tsx +0 -82
  21. package/app/components/editable-table-cell/multi-select-text-editable-cell.tsx +0 -82
  22. package/app/components/editable-table-cell/multi-text-editable-cell.tsx +0 -62
  23. package/app/components/editable-table-cell/number-editable-cell.tsx +0 -54
  24. package/app/components/editable-table-cell/relation-editable-cell.tsx +0 -20
  25. package/app/components/editable-table-cell/select-number-editable-cell.tsx +0 -43
  26. package/app/components/editable-table-cell/select-text-editable-cell.tsx +0 -33
  27. package/app/components/editable-table-cell/string-editable-cell.tsx +0 -42
  28. package/app/components/editable-table-cell.tsx +0 -129
  29. package/app/components/file-card.tsx +0 -120
  30. package/app/components/file-tree-icon.tsx +0 -26
  31. package/app/components/file-view/archive-restore-banner.tsx +0 -86
  32. package/app/components/file-view/csv-file-view.tsx +0 -50
  33. package/app/components/file-view/default-file-view.tsx +0 -11
  34. package/app/components/file-view/editable-csv-cell.tsx +0 -37
  35. package/app/components/file-view/editable-front-matter-view.tsx +0 -105
  36. package/app/components/file-view/file-csv-columns-view.tsx +0 -181
  37. package/app/components/file-view/file-csv-table.tsx +0 -142
  38. package/app/components/file-view/file-header.tsx +0 -115
  39. package/app/components/file-view/file-page-view.tsx +0 -165
  40. package/app/components/file-view/front-matter-input-field.tsx +0 -157
  41. package/app/components/file-view/front-matter-view.tsx +0 -30
  42. package/app/components/file-view/json-file-editor.tsx +0 -38
  43. package/app/components/file-view/markdown-file-view.tsx +0 -71
  44. package/app/components/file-view/multi-relation-select.tsx +0 -129
  45. package/app/components/file-view/render-front-matter-value.tsx +0 -57
  46. package/app/components/file-view/single-relation-select.tsx +0 -41
  47. package/app/components/file-view/sortable-csv-row.tsx +0 -57
  48. package/app/components/file-view/sortable-header.tsx +0 -30
  49. package/app/components/file-view/utils.ts +0 -8
  50. package/app/components/milestones-editor.tsx +0 -95
  51. package/app/components/page-header.tsx +0 -20
  52. package/app/components/project-view/feature-item.tsx +0 -139
  53. package/app/components/project-view/project-page-group.tsx +0 -125
  54. package/app/components/project-view/project-view.tsx +0 -230
  55. package/app/components/project-view/unlinked-features-section.tsx +0 -73
  56. package/app/components/providers.tsx +0 -21
  57. package/app/components/reload-button.tsx +0 -25
  58. package/app/components/sidebar-button.tsx +0 -13
  59. package/app/components/ui/alert.tsx +0 -66
  60. package/app/components/ui/badge.tsx +0 -46
  61. package/app/components/ui/button.tsx +0 -59
  62. package/app/components/ui/card.tsx +0 -92
  63. package/app/components/ui/dialog.tsx +0 -133
  64. package/app/components/ui/emoji-picker.tsx +0 -133
  65. package/app/components/ui/icons.tsx +0 -3
  66. package/app/components/ui/input.tsx +0 -21
  67. package/app/components/ui/select.tsx +0 -183
  68. package/app/components/ui/separator.tsx +0 -26
  69. package/app/components/ui/sheet.tsx +0 -137
  70. package/app/components/ui/sidebar.tsx +0 -724
  71. package/app/components/ui/simple-sidebar.tsx +0 -50
  72. package/app/components/ui/skeleton.tsx +0 -13
  73. package/app/components/ui/sonner.tsx +0 -23
  74. package/app/components/ui/table.tsx +0 -114
  75. package/app/components/ui/tabs.tsx +0 -53
  76. package/app/components/ui/textarea.tsx +0 -18
  77. package/app/components/ui/tooltip.tsx +0 -59
  78. package/app/components/vscode-button.tsx +0 -23
  79. package/app/hooks/use-directory-query.ts +0 -22
  80. package/app/hooks/use-file-properties-mutation.ts +0 -38
  81. package/app/hooks/use-file-query.ts +0 -21
  82. package/app/hooks/use-mobile.ts +0 -19
  83. package/app/main.css +0 -122
  84. package/app/main.tsx +0 -38
  85. package/app/routes/$.index.tsx +0 -25
  86. package/app/routes/$.tsx +0 -20
  87. package/app/routes/__root.tsx +0 -20
  88. package/app/routes/_index.tsx +0 -17
  89. package/app/routes/apps.client.$.tsx +0 -21
  90. package/build/index.d.ts +0 -2
  91. package/build/index.d.ts.map +0 -1
  92. package/components.json +0 -21
  93. package/tsconfig.index.json +0 -17
@@ -1,181 +0,0 @@
1
- import { useSuspenseQuery } from "@tanstack/react-query"
2
- import {
3
- Link,
4
- useLocation,
5
- useNavigate,
6
- useRouter,
7
- } from "@tanstack/react-router"
8
- import { useEffect, useState } from "react"
9
- import { DirectoryFileTreeNode } from "@/components/directory-file-tree-node"
10
- import { Button } from "@/components/ui/button"
11
- import {
12
- Sidebar,
13
- SidebarContent,
14
- SidebarFooter,
15
- SidebarGroup,
16
- SidebarGroupContent,
17
- SidebarGroupLabel,
18
- SidebarInset,
19
- SidebarMenu,
20
- SidebarMenuItem,
21
- SidebarProvider,
22
- } from "@/components/ui/sidebar"
23
- import { apiClient } from "@/lib/api-client"
24
- import { normalizePath } from "@/lib/path-utils"
25
- import type { DocFileNode } from "@/lib/types"
26
-
27
- type FileNode = {
28
- type: 'file' | 'directory'
29
- name: string
30
- path: string
31
- icon?: string
32
- title?: string
33
- children?: unknown[]
34
- }
35
-
36
- function isFileNode(node: unknown): node is FileNode {
37
- return (
38
- typeof node === 'object' &&
39
- node !== null &&
40
- 'type' in node &&
41
- 'name' in node &&
42
- 'path' in node
43
- )
44
- }
45
-
46
- type Props = {
47
- children: React.ReactNode
48
- }
49
-
50
- export function DirectoryLayoutSidebar(props: Props) {
51
- const [openPaths, setOpenPaths] = useState<Set<string>>(new Set())
52
-
53
- const [selectedDirectory, setSelectedDirectory] = useState<string>("")
54
-
55
- const _router = useRouter()
56
-
57
- const navigate = useNavigate()
58
-
59
- const path = useLocation({ select: (location) => location.pathname })
60
-
61
- const query = useSuspenseQuery({
62
- queryKey: ["file-tree"],
63
- queryFn: async () => {
64
- const response = await apiClient.api.directories.tree.$get()
65
- return response.json()
66
- },
67
- })
68
-
69
- const files = query.data
70
-
71
- function getCurrentPath(path: string) {
72
- const dirPath = path
73
-
74
- const pathSegments = dirPath.split("/").filter(Boolean)
75
-
76
- if (pathSegments.length > 0) {
77
- const lastSegment = pathSegments[pathSegments.length - 1]
78
- if (lastSegment === undefined) {
79
- throw new Error("Last segment is undefined")
80
- }
81
- const isFile = lastSegment.includes(".")
82
-
83
- if (isFile) {
84
- pathSegments.pop()
85
- return `/${pathSegments.join("/")}`
86
- }
87
- }
88
-
89
- return dirPath
90
- }
91
-
92
- getCurrentPath(path)
93
-
94
- useEffect(() => {
95
- const collectAllDirectoryPaths = (nodes: unknown[]): string[] => {
96
- const paths: string[] = []
97
- for (const node of nodes) {
98
- if (isFileNode(node) && node.type === "directory") {
99
- const nodePath = normalizePath(node.path)
100
- paths.push(nodePath)
101
- if (node.children) {
102
- paths.push(...collectAllDirectoryPaths(node.children))
103
- }
104
- }
105
- }
106
- return paths
107
- }
108
-
109
- const allPaths = collectAllDirectoryPaths(files)
110
- setOpenPaths(new Set(allPaths))
111
- }, [files])
112
-
113
- useEffect(() => {
114
- const getCurrentDirectoryFromPath = (pathname: string) => {
115
- const dirPath = pathname
116
- const pathSegments = dirPath.split("/").filter(Boolean)
117
-
118
- if (pathSegments.length > 0) {
119
- const lastSegment = pathSegments[pathSegments.length - 1]
120
- if (lastSegment?.includes(".")) {
121
- pathSegments.pop()
122
- return `/${pathSegments.join("/")}`
123
- }
124
- }
125
- return dirPath
126
- }
127
-
128
- const currentDir = getCurrentDirectoryFromPath(path)
129
- const cleanDir = currentDir.startsWith("/")
130
- ? currentDir.substring(1)
131
- : currentDir
132
- setSelectedDirectory(cleanDir)
133
- }, [path])
134
-
135
- const handleSelectDirectory = (path: string) => {
136
- setSelectedDirectory(path)
137
- navigate({ to: `/${path}` })
138
- }
139
-
140
- const handleToggleOpen = (path: string) => {
141
- const newOpenPaths = new Set(openPaths)
142
- if (newOpenPaths.has(path)) {
143
- newOpenPaths.delete(path)
144
- } else {
145
- newOpenPaths.add(path)
146
- }
147
- setOpenPaths(newOpenPaths)
148
- }
149
-
150
- const renderAllDirectories = (nodes: unknown[], currentDepth = 0) => {
151
- return nodes.filter(isFileNode).map((node) => (
152
- <DirectoryFileTreeNode
153
- key={node.path || `file-${node.name}`}
154
- node={node}
155
- depth={currentDepth}
156
- currentPath={window.location.pathname.match(/\/(.*)$/)?.[1] || ""}
157
- onSelectDirectory={handleSelectDirectory}
158
- openPaths={openPaths}
159
- onToggleOpen={handleToggleOpen}
160
- selectedDirectory={selectedDirectory}
161
- />
162
- ))
163
- }
164
-
165
- return (
166
- <SidebarProvider>
167
- <Sidebar collapsible={"offcanvas"} variant={"inset"}>
168
- <SidebarContent>
169
- <SidebarGroup>
170
- <SidebarGroupLabel>{"ファイル"}</SidebarGroupLabel>
171
- <SidebarGroupContent>
172
- <SidebarMenu>{renderAllDirectories(files)}</SidebarMenu>
173
- </SidebarGroupContent>
174
- </SidebarGroup>
175
- </SidebarContent>
176
- <SidebarFooter />
177
- </Sidebar>
178
- <SidebarInset className="overflow-hidden">{props.children}</SidebarInset>
179
- </SidebarProvider>
180
- )
181
- }
@@ -1,208 +0,0 @@
1
- import { useEffect, useState } from "react"
2
- import { DirectoryFileListView } from "@/components/directory-file-list-view"
3
- import { DirectoryTableView } from "@/components/directory-table-view"
4
- import { SidebarButton } from "@/components/sidebar-button"
5
- import { EmojiPicker } from "@/components/ui/emoji-picker"
6
- import { Input } from "@/components/ui/input"
7
- import { Textarea } from "@/components/ui/textarea"
8
- import { VscodeButton } from "@/components/vscode-button"
9
- import { useDirectoryQuery } from "@/hooks/use-directory-query"
10
- import { apiClient } from "@/lib/api-client"
11
- import type { DocFile, DocFileMd, DocFileUnknown, DocSchemaFieldType } from "@/lib/types"
12
-
13
- /**
14
- * テーブルカラムの型定義
15
- */
16
- type DocTableColumn = {
17
- key: string
18
- label: string
19
- type: DocSchemaFieldType
20
- path: string
21
- options: string[] | number[]
22
- }
23
-
24
- function isDocFileMd(file: DocFile): file is DocFileMd {
25
- return file.type === 'markdown'
26
- }
27
-
28
- function isDocFileUnknown(file: DocFile): file is DocFileUnknown {
29
- return file.type === 'unknown'
30
- }
31
-
32
- function hasIsArchived(file: DocFile): file is (DocFileMd | DocFileUnknown) {
33
- return file.type === 'markdown' || file.type === 'unknown'
34
- }
35
-
36
- type Props = {
37
- currentPath: string
38
- }
39
-
40
- export function DirectoryPageView(props: Props) {
41
- const query = useDirectoryQuery(props.currentPath)
42
-
43
- const directoryData = query.data
44
-
45
- // アーカイブファイルの表示状態
46
- const [showArchived, setShowArchived] = useState(false)
47
-
48
- // ファイルをタイプ別にフィルタリング
49
- const allMdFiles = directoryData.files.filter((file: DocFile) => isDocFileMd(file))
50
-
51
- const activeMdFiles = allMdFiles.filter((file: DocFile) => {
52
- return !hasIsArchived(file) || !file.isArchived
53
- })
54
-
55
- const archivedMdFiles = allMdFiles.filter((file: DocFile) => {
56
- return hasIsArchived(file) && file.isArchived
57
- })
58
-
59
-
60
- // 表示するファイルを決定
61
- const mdFiles = showArchived ? allMdFiles : activeMdFiles
62
-
63
- const otherFiles = directoryData.files.filter((file: DocFile) => {
64
- return isDocFileUnknown(file) && (hasIsArchived(file) ? !file.isArchived : true)
65
- })
66
-
67
- const [title, setTitle] = useState("")
68
- const [description, setDescription] = useState("")
69
- const [icon, setIcon] = useState("📁")
70
-
71
- useEffect(() => {
72
- if (directoryData?.indexFile) {
73
- setTitle(directoryData.indexFile.content.title || "")
74
- setDescription(directoryData.indexFile.content.description || "")
75
- setIcon(directoryData.indexFile.content.frontMatter?.icon || "📁")
76
- }
77
- }, [directoryData])
78
-
79
- const handleTitleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
80
- setTitle(e.target.value)
81
- }
82
-
83
- const handleTitleBlur = async () => {
84
- await apiClient.api.directories[":path{.+}"].$put({
85
- param: {
86
- path: props.currentPath.startsWith("/") ? props.currentPath.substring(1) : props.currentPath,
87
- },
88
- json: {
89
- title: title,
90
- description: null,
91
- icon: null,
92
- schema: null,
93
- },
94
- })
95
- }
96
-
97
- const handleDescriptionChange = (
98
- e: React.ChangeEvent<HTMLTextAreaElement>,
99
- ) => {
100
- setDescription(e.target.value)
101
- }
102
-
103
- const handleDescriptionBlur = async () => {
104
- await apiClient.api.directories[":path{.+}"].$put({
105
- param: {
106
- path: props.currentPath.startsWith("/") ? props.currentPath.substring(1) : props.currentPath,
107
- },
108
- json: {
109
- title: null,
110
- description: description,
111
- icon: null,
112
- schema: null,
113
- },
114
- })
115
- }
116
-
117
- const handleIconSelect = async (newIcon: string) => {
118
- console.log("Selected icon:", newIcon)
119
- console.log("Current path:", props.currentPath)
120
- setIcon(newIcon)
121
- try {
122
- const response = await apiClient.api.directories[":path{.+}"].$put({
123
- param: {
124
- path: props.currentPath.startsWith("/") ? props.currentPath.substring(1) : props.currentPath,
125
- },
126
- json: {
127
- title: null,
128
- description: null,
129
- icon: newIcon,
130
- schema: null,
131
- },
132
- })
133
- const result = await response.json()
134
- console.log("API response:", result)
135
- // キャッシュを更新して最新データを取得
136
- await query.refetch()
137
- } catch (error) {
138
- console.error("Error updating icon:", error)
139
- }
140
- }
141
-
142
- return (
143
- <div className="h-full overflow-x-hidden">
144
- <div className="space-y-2 p-2">
145
- <div className="flex items-center gap-2">
146
- <SidebarButton />
147
- {directoryData.indexFile && (
148
- <VscodeButton
149
- cwd={directoryData.cwd}
150
- filePath={directoryData.indexFile.path.fullPath}
151
- size="icon"
152
- variant="outline"
153
- />
154
- )}
155
- <EmojiPicker currentIcon={icon} onIconSelect={handleIconSelect} />
156
- <Input
157
- value={title}
158
- onChange={handleTitleChange}
159
- onBlur={handleTitleBlur}
160
- placeholder="タイトルを入力"
161
- className="flex-1"
162
- />
163
- </div>
164
- <Textarea
165
- value={description}
166
- onChange={handleDescriptionChange}
167
- onBlur={handleDescriptionBlur}
168
- placeholder="説明を入力"
169
- rows={2}
170
- />
171
- <DirectoryTableView
172
- files={mdFiles}
173
- columns={(() => {
174
- const schema = directoryData.indexFile?.content.frontMatter?.schema
175
- if (!schema) return []
176
-
177
- const columns = Object.entries(schema).map(([key, fieldValue]) => {
178
- // fieldValueが正しいオブジェクトであることを確認
179
- if (!fieldValue || typeof fieldValue !== 'object' || !('type' in fieldValue)) {
180
- return null
181
- }
182
-
183
- const value = fieldValue as Record<string, unknown>
184
- return {
185
- key,
186
- label: typeof value.title === 'string' ? value.title : key,
187
- type: String(value.type) as DocTableColumn['type'],
188
- path: (value.type === 'relation' || value.type === 'multi-relation') && typeof value.path === 'string' ? value.path : "",
189
- options: Array.isArray(value.options) ? value.options : []
190
- }
191
- }).filter((col): col is NonNullable<typeof col> => col !== null)
192
- return columns
193
- })()}
194
- directoryPath={props.currentPath}
195
- relations={directoryData.relations}
196
- onDataChanged={() => query.refetch()}
197
- archivedCount={archivedMdFiles.length}
198
- showArchived={showArchived}
199
- onToggleArchived={() => setShowArchived(!showArchived)}
200
- />
201
- <DirectoryFileListView
202
- files={otherFiles}
203
- onDataChanged={() => query.refetch()}
204
- />
205
- </div>
206
- </div>
207
- )
208
- }