@fuma-content/studio 0.1.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 (413) hide show
  1. package/dist/bin.d.mts +1 -0
  2. package/dist/bin.mjs +90 -0
  3. package/dist/index.d.mts +13 -0
  4. package/dist/index.mjs +66 -0
  5. package/dist/mdx/actions.mjs +34 -0
  6. package/dist/mdx/client.mjs +167 -0
  7. package/dist/package.mjs +6 -0
  8. package/dist/src/components/code-editor/mdx.lazy.mjs +19 -0
  9. package/dist/src/components/code-editor/mdx.mjs +44 -0
  10. package/dist/src/components/code-editor/yaml.lazy.mjs +22 -0
  11. package/dist/src/components/code-editor/yaml.mjs +63 -0
  12. package/dist/src/components/editor/editor-base-kit.mjs +41 -0
  13. package/dist/src/components/editor/editor-kit.mjs +73 -0
  14. package/dist/src/components/editor/md.mjs +42 -0
  15. package/dist/src/components/editor/plugins/ai-kit.mjs +68 -0
  16. package/dist/src/components/editor/plugins/align-base-kit.mjs +28 -0
  17. package/dist/src/components/editor/plugins/align-kit.mjs +30 -0
  18. package/dist/src/components/editor/plugins/autoformat-kit.mjs +214 -0
  19. package/dist/src/components/editor/plugins/basic-blocks-base-kit.mjs +22 -0
  20. package/dist/src/components/editor/plugins/basic-blocks-kit.mjs +51 -0
  21. package/dist/src/components/editor/plugins/basic-marks-base-kit.mjs +20 -0
  22. package/dist/src/components/editor/plugins/basic-marks-kit.mjs +28 -0
  23. package/dist/src/components/editor/plugins/block-menu-kit.mjs +11 -0
  24. package/dist/src/components/editor/plugins/block-placeholder-kit.mjs +14 -0
  25. package/dist/src/components/editor/plugins/block-selection-kit.mjs +48 -0
  26. package/dist/src/components/editor/plugins/callout-base-kit.mjs +8 -0
  27. package/dist/src/components/editor/plugins/callout-kit.mjs +10 -0
  28. package/dist/src/components/editor/plugins/code-block-base-kit.mjs +16 -0
  29. package/dist/src/components/editor/plugins/code-block-kit.mjs +19 -0
  30. package/dist/src/components/editor/plugins/column-base-kit.mjs +8 -0
  31. package/dist/src/components/editor/plugins/column-kit.mjs +10 -0
  32. package/dist/src/components/editor/plugins/comment-base-kit.mjs +8 -0
  33. package/dist/src/components/editor/plugins/comment-kit.mjs +53 -0
  34. package/dist/src/components/editor/plugins/copilot-kit.mjs +49 -0
  35. package/dist/src/components/editor/plugins/cursor-overlay-kit.mjs +11 -0
  36. package/dist/src/components/editor/plugins/date-base-kit.mjs +8 -0
  37. package/dist/src/components/editor/plugins/date-kit.mjs +10 -0
  38. package/dist/src/components/editor/plugins/discussion-kit.mjs +94 -0
  39. package/dist/src/components/editor/plugins/dnd-kit.mjs +31 -0
  40. package/dist/src/components/editor/plugins/emoji-kit.mjs +11 -0
  41. package/dist/src/components/editor/plugins/exit-break-kit.mjs +12 -0
  42. package/dist/src/components/editor/plugins/fixed-toolbar-kit.mjs +15 -0
  43. package/dist/src/components/editor/plugins/floating-toolbar-kit.mjs +15 -0
  44. package/dist/src/components/editor/plugins/font-base-kit.mjs +14 -0
  45. package/dist/src/components/editor/plugins/font-kit.mjs +19 -0
  46. package/dist/src/components/editor/plugins/indent-base-kit.mjs +17 -0
  47. package/dist/src/components/editor/plugins/indent-kit.mjs +20 -0
  48. package/dist/src/components/editor/plugins/line-height-base-kit.mjs +20 -0
  49. package/dist/src/components/editor/plugins/line-height-kit.mjs +22 -0
  50. package/dist/src/components/editor/plugins/link-base-kit.mjs +8 -0
  51. package/dist/src/components/editor/plugins/link-kit.mjs +15 -0
  52. package/dist/src/components/editor/plugins/list-base-kit.mjs +19 -0
  53. package/dist/src/components/editor/plugins/list-kit.mjs +22 -0
  54. package/dist/src/components/editor/plugins/markdown-kit.mjs +17 -0
  55. package/dist/src/components/editor/plugins/math-base-kit.mjs +8 -0
  56. package/dist/src/components/editor/plugins/math-kit.mjs +10 -0
  57. package/dist/src/components/editor/plugins/media-base-kit.mjs +23 -0
  58. package/dist/src/components/editor/plugins/media-kit.mjs +37 -0
  59. package/dist/src/components/editor/plugins/slash-kit.mjs +11 -0
  60. package/dist/src/components/editor/plugins/suggestion-base-kit.mjs +8 -0
  61. package/dist/src/components/editor/plugins/suggestion-kit.mjs +50 -0
  62. package/dist/src/components/editor/plugins/table-base-kit.mjs +13 -0
  63. package/dist/src/components/editor/plugins/table-kit.mjs +15 -0
  64. package/dist/src/components/editor/transforms.mjs +125 -0
  65. package/dist/src/components/editor/ui/ai-chat-editor.mjs +21 -0
  66. package/dist/src/components/editor/ui/ai-menu.mjs +488 -0
  67. package/dist/src/components/editor/ui/ai-node.mjs +24 -0
  68. package/dist/src/components/editor/ui/ai-toolbar-button.mjs +23 -0
  69. package/dist/src/components/editor/ui/align-toolbar-button.mjs +71 -0
  70. package/dist/src/components/editor/ui/block-context-menu.mjs +130 -0
  71. package/dist/src/components/editor/ui/block-discussion.mjs +200 -0
  72. package/dist/src/components/editor/ui/block-draggable.mjs +265 -0
  73. package/dist/src/components/editor/ui/block-list-static.mjs +48 -0
  74. package/dist/src/components/editor/ui/block-list.mjs +47 -0
  75. package/dist/src/components/editor/ui/block-selection.mjs +28 -0
  76. package/dist/src/components/editor/ui/block-suggestion.mjs +319 -0
  77. package/dist/src/components/editor/ui/blockquote-node-static.mjs +14 -0
  78. package/dist/src/components/editor/ui/blockquote-node.mjs +16 -0
  79. package/dist/src/components/editor/ui/callout-node-static.mjs +29 -0
  80. package/dist/src/components/editor/ui/callout-node.mjs +50 -0
  81. package/dist/src/components/editor/ui/caption.mjs +39 -0
  82. package/dist/src/components/editor/ui/code-block-node-static.mjs +30 -0
  83. package/dist/src/components/editor/ui/code-block-node.mjs +121 -0
  84. package/dist/src/components/editor/ui/code-node-static.mjs +15 -0
  85. package/dist/src/components/editor/ui/code-node.mjs +17 -0
  86. package/dist/src/components/editor/ui/column-node-static.mjs +32 -0
  87. package/dist/src/components/editor/ui/column-node.mjs +229 -0
  88. package/dist/src/components/editor/ui/comment-node-static.mjs +14 -0
  89. package/dist/src/components/editor/ui/comment-node.mjs +33 -0
  90. package/dist/src/components/editor/ui/comment-toolbar-button.mjs +23 -0
  91. package/dist/src/components/editor/ui/comment.mjs +422 -0
  92. package/dist/src/components/editor/ui/cursor-overlay.mjs +36 -0
  93. package/dist/src/components/editor/ui/date-node-static.mjs +32 -0
  94. package/dist/src/components/editor/ui/date-node.mjs +60 -0
  95. package/dist/src/components/editor/ui/editor-static.mjs +31 -0
  96. package/dist/src/components/editor/ui/editor.mjs +60 -0
  97. package/dist/src/components/editor/ui/emoji-node.mjs +46 -0
  98. package/dist/src/components/editor/ui/emoji-toolbar-button.mjs +415 -0
  99. package/dist/src/components/editor/ui/equation-node-static.mjs +65 -0
  100. package/dist/src/components/editor/ui/equation-node.mjs +159 -0
  101. package/dist/src/components/editor/ui/equation-toolbar-button.mjs +23 -0
  102. package/dist/src/components/editor/ui/fixed-toolbar-buttons.mjs +109 -0
  103. package/dist/src/components/editor/ui/fixed-toolbar.mjs +16 -0
  104. package/dist/src/components/editor/ui/floating-toolbar-buttons.mjs +54 -0
  105. package/dist/src/components/editor/ui/floating-toolbar.mjs +51 -0
  106. package/dist/src/components/editor/ui/font-color-toolbar-button.mjs +637 -0
  107. package/dist/src/components/editor/ui/font-size-toolbar-button.mjs +83 -0
  108. package/dist/src/components/editor/ui/ghost-text.mjs +22 -0
  109. package/dist/src/components/editor/ui/heading-node-static.mjs +60 -0
  110. package/dist/src/components/editor/ui/heading-node.mjs +62 -0
  111. package/dist/src/components/editor/ui/highlight-node-static.mjs +15 -0
  112. package/dist/src/components/editor/ui/highlight-node.mjs +17 -0
  113. package/dist/src/components/editor/ui/history-toolbar-button.mjs +35 -0
  114. package/dist/src/components/editor/ui/hr-node-static.mjs +18 -0
  115. package/dist/src/components/editor/ui/hr-node.mjs +23 -0
  116. package/dist/src/components/editor/ui/indent-toolbar-button.mjs +29 -0
  117. package/dist/src/components/editor/ui/inline-combobox.mjs +148 -0
  118. package/dist/src/components/editor/ui/insert-toolbar-button.mjs +199 -0
  119. package/dist/src/components/editor/ui/kbd-node-static.mjs +15 -0
  120. package/dist/src/components/editor/ui/kbd-node.mjs +17 -0
  121. package/dist/src/components/editor/ui/line-height-toolbar-button.mjs +56 -0
  122. package/dist/src/components/editor/ui/link-node-static.mjs +20 -0
  123. package/dist/src/components/editor/ui/link-node.mjs +28 -0
  124. package/dist/src/components/editor/ui/link-toolbar-button.mjs +21 -0
  125. package/dist/src/components/editor/ui/link-toolbar.mjs +141 -0
  126. package/dist/src/components/editor/ui/list-toolbar-button.mjs +131 -0
  127. package/dist/src/components/editor/ui/mark-toolbar-button.mjs +20 -0
  128. package/dist/src/components/editor/ui/media-image-node-static.mjs +32 -0
  129. package/dist/src/components/editor/ui/media-image-node.mjs +64 -0
  130. package/dist/src/components/editor/ui/media-placeholder-node.mjs +184 -0
  131. package/dist/src/components/editor/ui/media-preview-dialog.mjs +113 -0
  132. package/dist/src/components/editor/ui/media-toolbar-button.mjs +156 -0
  133. package/dist/src/components/editor/ui/media-toolbar.mjs +80 -0
  134. package/dist/src/components/editor/ui/media-upload-toast.mjs +39 -0
  135. package/dist/src/components/editor/ui/media-video-node-static.mjs +27 -0
  136. package/dist/src/components/editor/ui/mode-toolbar-button.mjs +112 -0
  137. package/dist/src/components/editor/ui/paragraph-node-static.mjs +15 -0
  138. package/dist/src/components/editor/ui/paragraph-node.mjs +17 -0
  139. package/dist/src/components/editor/ui/resize-handle.mjs +43 -0
  140. package/dist/src/components/editor/ui/slash-node.mjs +228 -0
  141. package/dist/src/components/editor/ui/suggestion-node-static.mjs +24 -0
  142. package/dist/src/components/editor/ui/suggestion-node.mjs +111 -0
  143. package/dist/src/components/editor/ui/suggestion-toolbar-button.mjs +24 -0
  144. package/dist/src/components/editor/ui/table-icons.mjs +1310 -0
  145. package/dist/src/components/editor/ui/table-node-static.mjs +68 -0
  146. package/dist/src/components/editor/ui/table-node.mjs +375 -0
  147. package/dist/src/components/editor/ui/table-toolbar-button.mjs +190 -0
  148. package/dist/src/components/editor/ui/turn-into-toolbar-button.mjs +168 -0
  149. package/dist/src/components/editor/use-chat.mjs +80 -0
  150. package/dist/src/components/json-schema-editor/client.mjs +46 -0
  151. package/dist/src/components/json-schema-editor/components/inputs.mjs +438 -0
  152. package/dist/src/components/json-schema-editor/get-default-values.mjs +23 -0
  153. package/dist/src/components/json-schema-editor/schema.mjs +131 -0
  154. package/dist/src/components/json-schema-editor/utils/merge-schema.mjs +134 -0
  155. package/dist/src/components/json-schema-editor/utils/schema-to-string.mjs +53 -0
  156. package/dist/src/components/ui/alert-dialog.mjs +90 -0
  157. package/dist/src/components/ui/avatar.mjs +32 -0
  158. package/dist/src/components/ui/button.mjs +48 -0
  159. package/dist/src/components/ui/calendar.mjs +108 -0
  160. package/dist/src/components/ui/checkbox.mjs +23 -0
  161. package/dist/src/components/ui/combobox.mjs +53 -0
  162. package/dist/src/components/ui/command.mjs +42 -0
  163. package/dist/src/components/ui/context-menu.mjs +67 -0
  164. package/dist/src/components/ui/dialog.mjs +9 -0
  165. package/dist/src/components/ui/dropdown-menu.mjs +122 -0
  166. package/dist/src/components/ui/input-group.mjs +31 -0
  167. package/dist/src/components/ui/input.mjs +15 -0
  168. package/dist/src/components/ui/label.mjs +19 -0
  169. package/dist/src/components/ui/popover.mjs +37 -0
  170. package/dist/src/components/ui/select.mjs +80 -0
  171. package/dist/src/components/ui/separator.mjs +19 -0
  172. package/dist/src/components/ui/spinner.mjs +16 -0
  173. package/dist/src/components/ui/tabs.mjs +39 -0
  174. package/dist/src/components/ui/textarea.mjs +14 -0
  175. package/dist/src/components/ui/toolbar.mjs +183 -0
  176. package/dist/src/components/ui/tooltip.mjs +38 -0
  177. package/dist/src/hooks/editor/use-is-creator.mjs +19 -0
  178. package/dist/src/hooks/use-upload-file.mjs +73 -0
  179. package/dist/src/lib/config.mjs +38 -0
  180. package/dist/src/lib/data/store.d.mts +15 -0
  181. package/dist/src/lib/lowlight.mjs +7 -0
  182. package/dist/src/lib/utils/deep-equal.mjs +18 -0
  183. package/dist/src/lib/utils/remove-undefined.mjs +18 -0
  184. package/dist/src/lib/utils.mjs +10 -0
  185. package/dist/types.d.mts +50 -0
  186. package/next.config.ts +23 -0
  187. package/package.json +131 -0
  188. package/postcss.config.mjs +7 -0
  189. package/src/app/(dashboard)/collection/[name]/[...slug]/page.client.tsx +26 -0
  190. package/src/app/(dashboard)/collection/[name]/[...slug]/page.tsx +17 -0
  191. package/src/app/(dashboard)/collection/[name]/page.client.tsx +82 -0
  192. package/src/app/(dashboard)/collection/[name]/page.tsx +11 -0
  193. package/src/app/(dashboard)/layout.tsx +34 -0
  194. package/src/app/(dashboard)/page.tsx +38 -0
  195. package/src/app/api/ai/command/prompts.ts +313 -0
  196. package/src/app/api/ai/command/route.ts +203 -0
  197. package/src/app/api/ai/command/utils.ts +242 -0
  198. package/src/app/api/ai/copilot/route.ts +33 -0
  199. package/src/app/api/uploadthing/route.ts +5 -0
  200. package/src/app/codeblock/LICENSE +21 -0
  201. package/src/app/codeblock/styles.css +289 -0
  202. package/src/app/favicon.ico +0 -0
  203. package/src/app/globals.css +223 -0
  204. package/src/app/layout.client.tsx +15 -0
  205. package/src/app/layout.tsx +30 -0
  206. package/src/components/app-sidebar.tsx +162 -0
  207. package/src/components/code-editor/mdx.lazy.tsx +18 -0
  208. package/src/components/code-editor/mdx.tsx +48 -0
  209. package/src/components/code-editor/yaml.lazy.tsx +20 -0
  210. package/src/components/code-editor/yaml.tsx +71 -0
  211. package/src/components/collection/actions.tsx +41 -0
  212. package/src/components/collection/client.tsx +63 -0
  213. package/src/components/collection/context.tsx +24 -0
  214. package/src/components/collection/document/actions.tsx +83 -0
  215. package/src/components/editor/editor-base-kit.tsx +37 -0
  216. package/src/components/editor/editor-kit.tsx +87 -0
  217. package/src/components/editor/md.tsx +60 -0
  218. package/src/components/editor/plugins/ai-kit.tsx +102 -0
  219. package/src/components/editor/plugins/align-base-kit.tsx +16 -0
  220. package/src/components/editor/plugins/align-kit.tsx +18 -0
  221. package/src/components/editor/plugins/autoformat-kit.tsx +236 -0
  222. package/src/components/editor/plugins/basic-blocks-base-kit.tsx +34 -0
  223. package/src/components/editor/plugins/basic-blocks-kit.tsx +87 -0
  224. package/src/components/editor/plugins/basic-marks-base-kit.tsx +26 -0
  225. package/src/components/editor/plugins/basic-marks-kit.tsx +40 -0
  226. package/src/components/editor/plugins/basic-nodes-kit.tsx +6 -0
  227. package/src/components/editor/plugins/block-menu-kit.tsx +14 -0
  228. package/src/components/editor/plugins/block-placeholder-kit.tsx +17 -0
  229. package/src/components/editor/plugins/block-selection-kit.tsx +54 -0
  230. package/src/components/editor/plugins/callout-base-kit.tsx +5 -0
  231. package/src/components/editor/plugins/callout-kit.tsx +7 -0
  232. package/src/components/editor/plugins/code-block-base-kit.tsx +16 -0
  233. package/src/components/editor/plugins/code-block-kit.tsx +19 -0
  234. package/src/components/editor/plugins/column-base-kit.tsx +11 -0
  235. package/src/components/editor/plugins/column-kit.tsx +10 -0
  236. package/src/components/editor/plugins/comment-base-kit.tsx +5 -0
  237. package/src/components/editor/plugins/comment-kit.tsx +92 -0
  238. package/src/components/editor/plugins/copilot-kit.tsx +70 -0
  239. package/src/components/editor/plugins/cursor-overlay-kit.tsx +13 -0
  240. package/src/components/editor/plugins/date-base-kit.tsx +5 -0
  241. package/src/components/editor/plugins/date-kit.tsx +7 -0
  242. package/src/components/editor/plugins/discussion-kit.tsx +142 -0
  243. package/src/components/editor/plugins/dnd-kit.tsx +25 -0
  244. package/src/components/editor/plugins/emoji-kit.tsx +13 -0
  245. package/src/components/editor/plugins/exit-break-kit.tsx +12 -0
  246. package/src/components/editor/plugins/fixed-toolbar-kit.tsx +19 -0
  247. package/src/components/editor/plugins/floating-toolbar-kit.tsx +19 -0
  248. package/src/components/editor/plugins/font-base-kit.tsx +20 -0
  249. package/src/components/editor/plugins/font-kit.tsx +29 -0
  250. package/src/components/editor/plugins/indent-base-kit.tsx +13 -0
  251. package/src/components/editor/plugins/indent-kit.tsx +22 -0
  252. package/src/components/editor/plugins/line-height-base-kit.tsx +14 -0
  253. package/src/components/editor/plugins/line-height-kit.tsx +16 -0
  254. package/src/components/editor/plugins/link-base-kit.tsx +5 -0
  255. package/src/components/editor/plugins/link-kit.tsx +15 -0
  256. package/src/components/editor/plugins/list-base-kit.tsx +17 -0
  257. package/src/components/editor/plugins/list-kit.tsx +26 -0
  258. package/src/components/editor/plugins/markdown-kit.tsx +13 -0
  259. package/src/components/editor/plugins/math-base-kit.tsx +11 -0
  260. package/src/components/editor/plugins/math-kit.tsx +10 -0
  261. package/src/components/editor/plugins/media-base-kit.tsx +25 -0
  262. package/src/components/editor/plugins/media-kit.tsx +28 -0
  263. package/src/components/editor/plugins/slash-kit.tsx +18 -0
  264. package/src/components/editor/plugins/suggestion-base-kit.tsx +5 -0
  265. package/src/components/editor/plugins/suggestion-kit.tsx +83 -0
  266. package/src/components/editor/plugins/table-base-kit.tsx +20 -0
  267. package/src/components/editor/plugins/table-kit.tsx +22 -0
  268. package/src/components/editor/settings-dialog.tsx +418 -0
  269. package/src/components/editor/transforms.ts +193 -0
  270. package/src/components/editor/types.ts +149 -0
  271. package/src/components/editor/ui/ai-chat-editor.tsx +20 -0
  272. package/src/components/editor/ui/ai-menu.tsx +663 -0
  273. package/src/components/editor/ui/ai-node.tsx +40 -0
  274. package/src/components/editor/ui/ai-toolbar-button.tsx +23 -0
  275. package/src/components/editor/ui/align-toolbar-button.tsx +78 -0
  276. package/src/components/editor/ui/block-context-menu.tsx +154 -0
  277. package/src/components/editor/ui/block-discussion.tsx +318 -0
  278. package/src/components/editor/ui/block-draggable.tsx +464 -0
  279. package/src/components/editor/ui/block-list-static.tsx +75 -0
  280. package/src/components/editor/ui/block-list.tsx +72 -0
  281. package/src/components/editor/ui/block-selection.tsx +37 -0
  282. package/src/components/editor/ui/block-suggestion.tsx +438 -0
  283. package/src/components/editor/ui/blockquote-node-static.tsx +5 -0
  284. package/src/components/editor/ui/blockquote-node.tsx +7 -0
  285. package/src/components/editor/ui/callout-node-static.tsx +30 -0
  286. package/src/components/editor/ui/callout-node.tsx +64 -0
  287. package/src/components/editor/ui/caption.tsx +55 -0
  288. package/src/components/editor/ui/code-block-node-static.tsx +33 -0
  289. package/src/components/editor/ui/code-block-node.tsx +161 -0
  290. package/src/components/editor/ui/code-node-static.tsx +15 -0
  291. package/src/components/editor/ui/code-node.tsx +17 -0
  292. package/src/components/editor/ui/column-node-static.tsx +27 -0
  293. package/src/components/editor/ui/column-node.tsx +285 -0
  294. package/src/components/editor/ui/comment-node-static.tsx +12 -0
  295. package/src/components/editor/ui/comment-node.tsx +43 -0
  296. package/src/components/editor/ui/comment-toolbar-button.tsx +24 -0
  297. package/src/components/editor/ui/comment.tsx +577 -0
  298. package/src/components/editor/ui/cursor-overlay.tsx +66 -0
  299. package/src/components/editor/ui/date-node-static.tsx +45 -0
  300. package/src/components/editor/ui/date-node.tsx +86 -0
  301. package/src/components/editor/ui/editor-static.tsx +47 -0
  302. package/src/components/editor/ui/editor.tsx +120 -0
  303. package/src/components/editor/ui/emoji-node.tsx +65 -0
  304. package/src/components/editor/ui/emoji-toolbar-button.tsx +582 -0
  305. package/src/components/editor/ui/equation-node-static.tsx +94 -0
  306. package/src/components/editor/ui/equation-node.tsx +218 -0
  307. package/src/components/editor/ui/equation-toolbar-button.tsx +24 -0
  308. package/src/components/editor/ui/fixed-toolbar-buttons.tsx +135 -0
  309. package/src/components/editor/ui/fixed-toolbar.tsx +17 -0
  310. package/src/components/editor/ui/floating-toolbar-buttons.tsx +72 -0
  311. package/src/components/editor/ui/floating-toolbar.tsx +76 -0
  312. package/src/components/editor/ui/font-color-toolbar-button.tsx +804 -0
  313. package/src/components/editor/ui/font-size-toolbar-button.tsx +102 -0
  314. package/src/components/editor/ui/ghost-text.tsx +27 -0
  315. package/src/components/editor/ui/heading-node-static.tsx +54 -0
  316. package/src/components/editor/ui/heading-node.tsx +54 -0
  317. package/src/components/editor/ui/highlight-node-static.tsx +11 -0
  318. package/src/components/editor/ui/highlight-node.tsx +13 -0
  319. package/src/components/editor/ui/history-toolbar-button.tsx +41 -0
  320. package/src/components/editor/ui/hr-node-static.tsx +16 -0
  321. package/src/components/editor/ui/hr-node.tsx +28 -0
  322. package/src/components/editor/ui/indent-toolbar-button.tsx +27 -0
  323. package/src/components/editor/ui/inline-combobox.tsx +251 -0
  324. package/src/components/editor/ui/insert-toolbar-button.tsx +242 -0
  325. package/src/components/editor/ui/kbd-node-static.tsx +15 -0
  326. package/src/components/editor/ui/kbd-node.tsx +17 -0
  327. package/src/components/editor/ui/line-height-toolbar-button.tsx +66 -0
  328. package/src/components/editor/ui/link-node-static.tsx +21 -0
  329. package/src/components/editor/ui/link-node.tsx +37 -0
  330. package/src/components/editor/ui/link-toolbar-button.tsx +18 -0
  331. package/src/components/editor/ui/link-toolbar.tsx +196 -0
  332. package/src/components/editor/ui/list-toolbar-button.tsx +195 -0
  333. package/src/components/editor/ui/mark-toolbar-button.tsx +20 -0
  334. package/src/components/editor/ui/media-image-node-static.tsx +33 -0
  335. package/src/components/editor/ui/media-image-node.tsx +75 -0
  336. package/src/components/editor/ui/media-placeholder-node.tsx +235 -0
  337. package/src/components/editor/ui/media-preview-dialog.tsx +145 -0
  338. package/src/components/editor/ui/media-toolbar-button.tsx +202 -0
  339. package/src/components/editor/ui/media-toolbar.tsx +100 -0
  340. package/src/components/editor/ui/media-upload-toast.tsx +59 -0
  341. package/src/components/editor/ui/media-video-node-static.tsx +23 -0
  342. package/src/components/editor/ui/mode-toolbar-button.tsx +121 -0
  343. package/src/components/editor/ui/paragraph-node-static.tsx +13 -0
  344. package/src/components/editor/ui/paragraph-node.tsx +15 -0
  345. package/src/components/editor/ui/resize-handle.tsx +79 -0
  346. package/src/components/editor/ui/slash-node.tsx +274 -0
  347. package/src/components/editor/ui/suggestion-node-static.tsx +30 -0
  348. package/src/components/editor/ui/suggestion-node.tsx +157 -0
  349. package/src/components/editor/ui/suggestion-toolbar-button.tsx +25 -0
  350. package/src/components/editor/ui/table-icons.tsx +685 -0
  351. package/src/components/editor/ui/table-node-static.tsx +86 -0
  352. package/src/components/editor/ui/table-node.tsx +569 -0
  353. package/src/components/editor/ui/table-toolbar-button.tsx +260 -0
  354. package/src/components/editor/ui/turn-into-toolbar-button.tsx +176 -0
  355. package/src/components/editor/use-chat.ts +120 -0
  356. package/src/components/icons/logo.tsx +37 -0
  357. package/src/components/json-schema-editor/client.tsx +55 -0
  358. package/src/components/json-schema-editor/components/inputs.tsx +612 -0
  359. package/src/components/json-schema-editor/get-default-values.ts +29 -0
  360. package/src/components/json-schema-editor/schema.tsx +206 -0
  361. package/src/components/json-schema-editor/utils/merge-schema.ts +167 -0
  362. package/src/components/json-schema-editor/utils/schema-to-string.ts +87 -0
  363. package/src/components/nav-user.tsx +102 -0
  364. package/src/components/site-header.tsx +13 -0
  365. package/src/components/ui/alert-dialog.tsx +182 -0
  366. package/src/components/ui/avatar.tsx +96 -0
  367. package/src/components/ui/badge.tsx +46 -0
  368. package/src/components/ui/button.tsx +65 -0
  369. package/src/components/ui/calendar.tsx +186 -0
  370. package/src/components/ui/checkbox.tsx +29 -0
  371. package/src/components/ui/combobox.tsx +267 -0
  372. package/src/components/ui/command.tsx +180 -0
  373. package/src/components/ui/context-menu.tsx +161 -0
  374. package/src/components/ui/dialog.tsx +142 -0
  375. package/src/components/ui/drawer.tsx +120 -0
  376. package/src/components/ui/dropdown-menu.tsx +239 -0
  377. package/src/components/ui/field.tsx +224 -0
  378. package/src/components/ui/input-group.tsx +144 -0
  379. package/src/components/ui/input.tsx +19 -0
  380. package/src/components/ui/label.tsx +18 -0
  381. package/src/components/ui/popover.tsx +76 -0
  382. package/src/components/ui/select.tsx +182 -0
  383. package/src/components/ui/separator.tsx +28 -0
  384. package/src/components/ui/sheet.tsx +130 -0
  385. package/src/components/ui/sidebar.tsx +608 -0
  386. package/src/components/ui/sonner.tsx +45 -0
  387. package/src/components/ui/spinner.tsx +15 -0
  388. package/src/components/ui/table.tsx +89 -0
  389. package/src/components/ui/tabs.tsx +60 -0
  390. package/src/components/ui/textarea.tsx +18 -0
  391. package/src/components/ui/toggle-group.tsx +86 -0
  392. package/src/components/ui/toggle.tsx +45 -0
  393. package/src/components/ui/toolbar.tsx +365 -0
  394. package/src/components/ui/tooltip.tsx +57 -0
  395. package/src/hooks/editor/use-is-creator.ts +21 -0
  396. package/src/hooks/use-mobile.ts +19 -0
  397. package/src/hooks/use-mounted.ts +11 -0
  398. package/src/hooks/use-upload-file.ts +121 -0
  399. package/src/lib/ai/markdown-joiner-transform.ts +235 -0
  400. package/src/lib/config.ts +60 -0
  401. package/src/lib/data/actions.ts +51 -0
  402. package/src/lib/data/boundary.client.tsx +22 -0
  403. package/src/lib/data/boundary.tsx +22 -0
  404. package/src/lib/data/query.ts +9 -0
  405. package/src/lib/data/store.ts +52 -0
  406. package/src/lib/lowlight.ts +3 -0
  407. package/src/lib/uploadthing.ts +19 -0
  408. package/src/lib/utils/deep-equal.ts +37 -0
  409. package/src/lib/utils/remove-undefined.ts +21 -0
  410. package/src/lib/utils/urls.ts +6 -0
  411. package/src/lib/utils.ts +6 -0
  412. package/tsconfig.build.json +24 -0
  413. package/tsconfig.json +37 -0
@@ -0,0 +1,73 @@
1
+ import * as React$1 from "react";
2
+ import { toast } from "sonner";
3
+ import { generateReactHelpers } from "@uploadthing/react";
4
+ import { z } from "zod";
5
+
6
+ //#region src/hooks/use-upload-file.ts
7
+ function useUploadFile({ onUploadComplete, onUploadError, ...props } = {}) {
8
+ const [uploadedFile, setUploadedFile] = React$1.useState();
9
+ const [uploadingFile, setUploadingFile] = React$1.useState();
10
+ const [progress, setProgress] = React$1.useState(0);
11
+ const [isUploading, setIsUploading] = React$1.useState(false);
12
+ async function uploadThing(file) {
13
+ setIsUploading(true);
14
+ setUploadingFile(file);
15
+ try {
16
+ const res = await uploadFiles("editorUploader", {
17
+ ...props,
18
+ files: [file],
19
+ onUploadProgress: ({ progress: progress$1 }) => {
20
+ setProgress(Math.min(progress$1, 100));
21
+ }
22
+ });
23
+ setUploadedFile(res[0]);
24
+ onUploadComplete?.(res[0]);
25
+ return uploadedFile;
26
+ } catch (error) {
27
+ const errorMessage = getErrorMessage(error);
28
+ const message = errorMessage.length > 0 ? errorMessage : "Something went wrong, please try again later.";
29
+ toast.error(message);
30
+ onUploadError?.(error);
31
+ const mockUploadedFile = {
32
+ key: "mock-key-0",
33
+ appUrl: `https://mock-app-url.com/${file.name}`,
34
+ name: file.name,
35
+ size: file.size,
36
+ type: file.type,
37
+ url: URL.createObjectURL(file)
38
+ };
39
+ let progress$1 = 0;
40
+ const simulateProgress = async () => {
41
+ while (progress$1 < 100) {
42
+ await new Promise((resolve) => setTimeout(resolve, 50));
43
+ progress$1 += 2;
44
+ setProgress(Math.min(progress$1, 100));
45
+ }
46
+ };
47
+ await simulateProgress();
48
+ setUploadedFile(mockUploadedFile);
49
+ return mockUploadedFile;
50
+ } finally {
51
+ setProgress(0);
52
+ setIsUploading(false);
53
+ setUploadingFile(void 0);
54
+ }
55
+ }
56
+ return {
57
+ isUploading,
58
+ progress,
59
+ uploadedFile,
60
+ uploadFile: uploadThing,
61
+ uploadingFile
62
+ };
63
+ }
64
+ const { uploadFiles, useUploadThing } = generateReactHelpers();
65
+ function getErrorMessage(err) {
66
+ const unknownError = "Something went wrong, please try again later.";
67
+ if (err instanceof z.ZodError) return err.issues.map((issue) => issue.message).join("\n");
68
+ if (err instanceof Error) return err.message;
69
+ return unknownError;
70
+ }
71
+
72
+ //#endregion
73
+ export { useUploadFile };
@@ -0,0 +1,38 @@
1
+ import { Core } from "fuma-content";
2
+
3
+ //#region src/lib/config.ts
4
+ let core;
5
+ async function getCore() {
6
+ core ??= (async () => {
7
+ const core$1 = new Core({
8
+ outDir: ".content",
9
+ configPath: process.env.STUDIO_CONFIG,
10
+ cwd: process.env.STUDIO_PARENT_DIR
11
+ });
12
+ await core$1.init({ config: await import("virtual:content.config") });
13
+ return core$1;
14
+ })();
15
+ return core;
16
+ }
17
+ async function requireCollection(collectionId, handlers) {
18
+ const collection = (await getCore()).getCollection(collectionId);
19
+ if (!collection) throw new Error(`Missing Collection ${collectionId}`);
20
+ if (hasHandler(collection, handlers)) return collection;
21
+ throw new Error(`Missing ${handlers.join(", ")} handlers for ${collectionId}`);
22
+ }
23
+ async function requireDocument(collectionId, documentId) {
24
+ const collection = await requireCollection(collectionId, ["studio"]);
25
+ const document = await collection.handlers.studio.getDocument(documentId);
26
+ if (!document) throw new Error(`Missing Document ${documentId}`);
27
+ return {
28
+ collection,
29
+ document
30
+ };
31
+ }
32
+ function hasHandler(collection, handlers) {
33
+ for (const handler of handlers) if (collection.handlers[handler] === void 0) return false;
34
+ return true;
35
+ }
36
+
37
+ //#endregion
38
+ export { requireCollection, requireDocument };
@@ -0,0 +1,15 @@
1
+ import "@tanstack/query-db-collection";
2
+ import "@tanstack/react-db";
3
+
4
+ //#region src/lib/data/store.d.ts
5
+
6
+ interface DocumentItem {
7
+ id: string;
8
+ collectionId: string;
9
+ name: string;
10
+ permissions: {
11
+ delete: boolean;
12
+ };
13
+ }
14
+ //#endregion
15
+ export { DocumentItem };
@@ -0,0 +1,7 @@
1
+ import { all, createLowlight } from "lowlight";
2
+
3
+ //#region src/lib/lowlight.ts
4
+ const lowlight = createLowlight(all);
5
+
6
+ //#endregion
7
+ export { lowlight };
@@ -0,0 +1,18 @@
1
+ //#region src/lib/utils/deep-equal.ts
2
+ function deepEqual(a, b) {
3
+ if (a === b) return true;
4
+ if (a == null || b == null) return false;
5
+ if (typeof a !== "object" || typeof b !== "object") return false;
6
+ if (Array.isArray(a) && Array.isArray(b)) {
7
+ if (a.length !== b.length) return false;
8
+ return a.every((item, index) => deepEqual(item, b[index]));
9
+ }
10
+ if (Array.isArray(a) || Array.isArray(b)) return false;
11
+ const keysA = Object.keys(a);
12
+ const keysB = Object.keys(b);
13
+ if (keysA.length !== keysB.length) return false;
14
+ return keysA.every((key) => Object.prototype.hasOwnProperty.call(b, key) && deepEqual(a[key], b[key]));
15
+ }
16
+
17
+ //#endregion
18
+ export { deepEqual };
@@ -0,0 +1,18 @@
1
+ //#region src/lib/utils/remove-undefined.ts
2
+ function removeUndefined(value, deep = false) {
3
+ const obj = value;
4
+ for (const key in obj) {
5
+ if (obj[key] === void 0) delete obj[key];
6
+ if (!deep) continue;
7
+ const entry = obj[key];
8
+ if (typeof entry === "object" && entry !== null) {
9
+ removeUndefined(entry, deep);
10
+ continue;
11
+ }
12
+ if (Array.isArray(entry)) for (const item of entry) removeUndefined(item, deep);
13
+ }
14
+ return value;
15
+ }
16
+
17
+ //#endregion
18
+ export { removeUndefined };
@@ -0,0 +1,10 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ //#region src/lib/utils.ts
5
+ function cn(...inputs) {
6
+ return twMerge(clsx(inputs));
7
+ }
8
+
9
+ //#endregion
10
+ export { cn };
@@ -0,0 +1,50 @@
1
+ import { DocumentItem } from "./src/lib/data/store.mjs";
2
+ import { Collection } from "fuma-content/collections";
3
+ import { FC } from "react";
4
+
5
+ //#region lib/types.d.ts
6
+ type Awaitable<T> = T | Promise<T>;
7
+ interface StudioDocument {
8
+ id: string;
9
+ name: string;
10
+ }
11
+ interface MDXStudioDocument extends StudioDocument {
12
+ type: "mdx";
13
+ filePath: string;
14
+ }
15
+ interface CreateDocumentDialogContext {
16
+ collectionId: string;
17
+ useDialog: () => {
18
+ open: boolean;
19
+ setOpen: (v: boolean) => void;
20
+ onCreate: (item: DocumentItem) => void;
21
+ };
22
+ }
23
+ interface ClientContext {
24
+ dialogs?: {
25
+ createDocument?: FC<CreateDocumentDialogContext>;
26
+ };
27
+ }
28
+ interface StudioHandler<Doc extends StudioDocument> {
29
+ init?: () => Awaitable<void>;
30
+ getDocuments: () => Awaitable<Doc[]>;
31
+ getDocument: (id: string) => Awaitable<Doc | undefined>;
32
+ pages?: {
33
+ edit?: FC<{
34
+ document: Doc;
35
+ collection: Collection;
36
+ }>;
37
+ };
38
+ /**
39
+ * the properties inside should be exported from a file with "use client".
40
+ */
41
+ client?: () => Awaitable<ClientContext>;
42
+ actions?: {
43
+ deleteDocument?: (options: {
44
+ collection: Collection;
45
+ document: Doc;
46
+ }) => Awaitable<void>;
47
+ };
48
+ }
49
+ //#endregion
50
+ export { ClientContext, CreateDocumentDialogContext, MDXStudioDocument, StudioDocument, StudioHandler };
package/next.config.ts ADDED
@@ -0,0 +1,23 @@
1
+ import type { NextConfig } from "next";
2
+ import path from "node:path";
3
+
4
+ const nextConfig: NextConfig = {
5
+ reactCompiler: true,
6
+ distDir: process.env.STUDIO_DIST
7
+ ? path.relative(process.cwd(), process.env.STUDIO_DIST)
8
+ : ".studio",
9
+ typescript: {
10
+ // ignore for performance
11
+ ignoreBuildErrors: true,
12
+ tsconfigPath: "tsconfig.build.json",
13
+ },
14
+ turbopack: {
15
+ resolveAlias: {
16
+ "virtual:content.config": process.env.STUDIO_CONFIG
17
+ ? path.relative(process.cwd(), process.env.STUDIO_CONFIG)
18
+ : "content.config.ts",
19
+ },
20
+ },
21
+ };
22
+
23
+ export default nextConfig;
package/package.json ADDED
@@ -0,0 +1,131 @@
1
+ {
2
+ "name": "@fuma-content/studio",
3
+ "version": "0.1.0",
4
+ "description": "The studio integration of Fuma Content",
5
+ "keywords": [
6
+ "Contentlayer",
7
+ "Docs"
8
+ ],
9
+ "homepage": "https://fuma-content.vercel.app",
10
+ "license": "MIT",
11
+ "author": "Fuma Nama",
12
+ "repository": "github:fuma-nama/fuma-content",
13
+ "bin": {
14
+ "content-studio": "./dist/bin.mjs"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "next.config.ts",
19
+ "postcss.config.mjs",
20
+ "src",
21
+ "tsconfig.build.json",
22
+ "tsconfig.json"
23
+ ],
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.mts",
27
+ "import": "./dist/index.mjs"
28
+ }
29
+ },
30
+ "publishConfig": {
31
+ "access": "public"
32
+ },
33
+ "dependencies": {
34
+ "@ai-sdk/gateway": "^3.0.10",
35
+ "@ai-sdk/react": "3.0.21",
36
+ "@base-ui/react": "^1.0.0",
37
+ "@base-ui/utils": "^0.2.3",
38
+ "@clack/prompts": "^1.0.0-alpha.9",
39
+ "@emoji-mart/data": "1.2.1",
40
+ "@monaco-editor/react": "^4.7.0",
41
+ "@platejs/ai": "^52.0.16",
42
+ "@platejs/autoformat": "^52.0.11",
43
+ "@platejs/basic-nodes": "^52.0.11",
44
+ "@platejs/basic-styles": "^52.0.11",
45
+ "@platejs/callout": "^52.0.11",
46
+ "@platejs/caption": "^52.0.11",
47
+ "@platejs/code-block": "^52.0.11",
48
+ "@platejs/combobox": "^52.0.15",
49
+ "@platejs/comment": "^52.0.11",
50
+ "@platejs/date": "^52.0.11",
51
+ "@platejs/dnd": "^52.0.11",
52
+ "@platejs/emoji": "^52.0.15",
53
+ "@platejs/floating": "^52.0.11",
54
+ "@platejs/indent": "^52.0.11",
55
+ "@platejs/layout": "^52.0.11",
56
+ "@platejs/link": "^52.0.11",
57
+ "@platejs/list": "^52.0.11",
58
+ "@platejs/markdown": "^52.0.11",
59
+ "@platejs/math": "^52.0.11",
60
+ "@platejs/media": "^52.0.11",
61
+ "@platejs/resizable": "^52.0.11",
62
+ "@platejs/selection": "^52.0.16",
63
+ "@platejs/slash-command": "^52.0.15",
64
+ "@platejs/suggestion": "^52.0.11",
65
+ "@platejs/table": "^52.0.11",
66
+ "@standard-schema/spec": "^1.1.0",
67
+ "@tanstack/query-db-collection": "^1.0.13",
68
+ "@tanstack/react-db": "^0.1.61",
69
+ "@tanstack/react-query": "^5.90.16",
70
+ "@uploadthing/react": "7.3.3",
71
+ "ai": "6.0.21",
72
+ "ajv": "^8.17.1",
73
+ "class-variance-authority": "^0.7.1",
74
+ "clsx": "^2.1.1",
75
+ "cmdk": "^1.1.1",
76
+ "commander": "^14.0.2",
77
+ "date-fns": "^4.1.0",
78
+ "gray-matter": "^4.0.3",
79
+ "highlight.js": "^11.11.1",
80
+ "js-yaml": "^4.1.1",
81
+ "lodash.debounce": "^4.0.8",
82
+ "lowlight": "^3.3.0",
83
+ "lucide-react": "^0.562.0",
84
+ "next": "16.1.1",
85
+ "next-themes": "^0.4.6",
86
+ "open": "^11.0.0",
87
+ "platejs": "^52.0.15",
88
+ "radix-ui": "^1.4.3",
89
+ "react": "19.2.3",
90
+ "react-day-picker": "^9.13.0",
91
+ "react-dnd": "^16.0.1",
92
+ "react-dnd-html5-backend": "^16.0.1",
93
+ "react-dom": "19.2.3",
94
+ "react-hook-form": "^7.70.0",
95
+ "react-textarea-autosize": "^8.5.9",
96
+ "remark-gfm": "^4.0.1",
97
+ "remark-math": "^6.0.0",
98
+ "sonner": "^2.0.7",
99
+ "tailwind-merge": "^3.4.0",
100
+ "tinyexec": "^1.0.2",
101
+ "uploadthing": "7.7.4",
102
+ "vaul": "^1.1.2",
103
+ "zod": "^4.3.5"
104
+ },
105
+ "devDependencies": {
106
+ "@tailwindcss/postcss": "^4",
107
+ "@types/lodash.debounce": "^4.0.9",
108
+ "@types/node": "^25.0.3",
109
+ "@types/react": "^19",
110
+ "@types/react-dom": "^19",
111
+ "babel-plugin-react-compiler": "1.0.0",
112
+ "dedent": "^1.7.1",
113
+ "json-schema-typed": "^8.0.2",
114
+ "shadcn": "^3.6.3",
115
+ "tailwindcss": "^4",
116
+ "tsdown": "^0.18.3",
117
+ "tw-animate-css": "^1.4.0",
118
+ "typescript": "^5",
119
+ "fuma-content": "^1.0.3"
120
+ },
121
+ "peerDependencies": {
122
+ "fuma-content": "^1.0.3"
123
+ },
124
+ "scripts": {
125
+ "dev": "tsdown --watch",
126
+ "dev:app": "next dev",
127
+ "build": "tsdown",
128
+ "preview:app": "next build && next start",
129
+ "types:check": "tsc --noEmit"
130
+ }
131
+ }
@@ -0,0 +1,7 @@
1
+ const config = {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
6
+
7
+ export default config;
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { DocumentActionsDropdown } from "@/components/collection/document/actions";
3
+ import { SiteHeader } from "@/components/site-header";
4
+ import { documentCollection } from "@/lib/data/store";
5
+ import { eq, and, useLiveQuery } from "@tanstack/react-db";
6
+ import Link from "next/link";
7
+
8
+ export function Header({ collectionId, documentId }: { collectionId: string; documentId: string }) {
9
+ const query = useLiveQuery((q) =>
10
+ q
11
+ .from({ doc: documentCollection })
12
+ .where((b) => and(eq(b.doc.id, documentId), eq(b.doc.collectionId, collectionId)))
13
+ .findOne(),
14
+ );
15
+ const doc = query.data;
16
+ if (!doc) return;
17
+
18
+ return (
19
+ <SiteHeader>
20
+ <Link href={`/collection/${collectionId}`} className="font-mono text-sm">
21
+ {collectionId}/{documentId}
22
+ </Link>
23
+ <DocumentActionsDropdown document={doc} />
24
+ </SiteHeader>
25
+ );
26
+ }
@@ -0,0 +1,17 @@
1
+ import { notFound } from "next/navigation";
2
+ import { requireDocument } from "@/lib/config";
3
+ import { Header } from "./page.client";
4
+
5
+ export default async function Page({ params }: PageProps<"/collection/[name]/[...slug]">) {
6
+ const { name, slug } = await params;
7
+ const { collection, document } = await requireDocument(name, slug[0]).catch(() => notFound());
8
+
9
+ return (
10
+ <>
11
+ <Header collectionId={collection.name} documentId={document.id} />
12
+ <div className="flex flex-1 min-w-0 flex-col gap-2 p-2">
13
+ {await collection.handlers.studio.pages?.edit?.({ document, collection })}
14
+ </div>
15
+ </>
16
+ );
17
+ }
@@ -0,0 +1,82 @@
1
+ "use client";
2
+ import { Badge } from "@/components/ui/badge";
3
+ import Link from "next/link";
4
+ import { SiteHeader } from "@/components/site-header";
5
+ import { useLiveQuery, eq } from "@tanstack/react-db";
6
+ import { collection, documentCollection } from "@/lib/data/store";
7
+ import { useCreateDocumentDialog } from "@/components/collection/client";
8
+ import { FilePlusIcon } from "lucide-react";
9
+ import { buttonVariants } from "@/components/ui/button";
10
+ import {
11
+ DocumentActionsContext,
12
+ DocumentActionsDropdown,
13
+ } from "@/components/collection/document/actions";
14
+
15
+ export default function Client({ collectionId }: { collectionId: string }) {
16
+ const { data: info } = useLiveQuery((q) =>
17
+ q
18
+ .from({ collection })
19
+ .where((b) => eq(b.collection.id, collectionId))
20
+ .findOne(),
21
+ );
22
+ const { data: documents } = useLiveQuery((q) =>
23
+ q
24
+ .from({ documentCollection })
25
+ .where((b) => eq(b.documentCollection.collectionId, collectionId)),
26
+ );
27
+ const createDoc = useCreateDocumentDialog(collectionId);
28
+ if (!info) return null;
29
+
30
+ return (
31
+ <>
32
+ <SiteHeader>
33
+ <h1 className="font-mono text-sm">{info.name}</h1>
34
+ </SiteHeader>
35
+ <div className="flex flex-1 min-w-0 flex-col gap-2 px-2 py-6">
36
+ <h1 className="mb-2 inline-flex items-center gap-2 font-mono font-semibold text-2xl">
37
+ {info.name}
38
+ <Badge className="text-sm empty:hidden">{info.badge}</Badge>
39
+ </h1>
40
+ <div className="mb-4 flex flex-row flex-wrap items-center gap-2">
41
+ <p className="font-medium text-muted-foreground text-sm">Implements</p>
42
+ {info.handlers &&
43
+ Object.keys(info.handlers).map((handler) => (
44
+ <Badge key={handler} variant="outline">
45
+ {handler}
46
+ </Badge>
47
+ ))}
48
+ </div>
49
+ {info.handlers && "studio" in info.handlers ? (
50
+ <div className="grid grid-cols-1 border rounded-lg bg-card text-card-foreground overflow-hidden">
51
+ <div className="flex items-center gap-2 bg-secondary ps-4 pe-2 py-2">
52
+ <p className="text-sm text-muted-foreground me-auto">{documents.length} Items</p>
53
+ {createDoc && (
54
+ <createDoc.component>
55
+ <createDoc.trigger className={buttonVariants()}>
56
+ <FilePlusIcon />
57
+ Create Document
58
+ </createDoc.trigger>
59
+ </createDoc.component>
60
+ )}
61
+ </div>
62
+
63
+ {documents.map((doc) => (
64
+ <DocumentActionsContext key={doc.id} document={doc}>
65
+ <div className="flex text-sm font-medium hover:bg-accent hover:text-accent-foreground data-popup-open:bg-accent data-popup-open:text-accent-foreground">
66
+ <Link href={`/collection/${info.name}/${doc.id}`} className="px-4 py-2 flex-1">
67
+ {doc.name}
68
+ </Link>
69
+ <DocumentActionsDropdown document={doc} />
70
+ </div>
71
+ </DocumentActionsContext>
72
+ ))}
73
+ </div>
74
+ ) : (
75
+ <div className="bg-muted text-sm text-muted-foreground p-4 rounded-lg border text-center">
76
+ This collection doesn't have studio integration.
77
+ </div>
78
+ )}
79
+ </div>
80
+ </>
81
+ );
82
+ }
@@ -0,0 +1,11 @@
1
+ import { notFound } from "next/navigation";
2
+ import { getCore } from "@/lib/config";
3
+ import Client from "./page.client";
4
+
5
+ export default async function Page({ params }: PageProps<"/collection/[name]">) {
6
+ const core = await getCore();
7
+ const collection = core.getCollection((await params).name);
8
+ if (!collection) notFound();
9
+
10
+ return <Client collectionId={collection.name} />;
11
+ }
@@ -0,0 +1,34 @@
1
+ import { AppSidebar } from "@/components/app-sidebar";
2
+ import { ClientContextProvider } from "@/components/collection/context";
3
+ import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar";
4
+ import { Toaster } from "@/components/ui/sonner";
5
+ import { getCore } from "@/lib/config";
6
+ import { DataBoundary } from "@/lib/data/boundary";
7
+ import { ClientContext } from "lib";
8
+ import type { ReactNode } from "react";
9
+
10
+ export default async function Layout({ children }: { children: ReactNode }) {
11
+ const core = await getCore();
12
+ const collections = core.getCollections(true);
13
+ const clientContexts = new Map<string, ClientContext>();
14
+ for (const collection of collections) {
15
+ const { studio } = collection.handlers;
16
+ if (studio && studio.client) {
17
+ clientContexts.set(collection.name, await studio.client());
18
+ }
19
+ }
20
+
21
+ return (
22
+ <ClientContextProvider contexts={clientContexts}>
23
+ <DataBoundary>
24
+ <SidebarProvider>
25
+ <AppSidebar />
26
+ <SidebarInset>
27
+ {children}
28
+ <Toaster />
29
+ </SidebarInset>
30
+ </SidebarProvider>
31
+ </DataBoundary>
32
+ </ClientContextProvider>
33
+ );
34
+ }
@@ -0,0 +1,38 @@
1
+ "use client";
2
+ import { CollectionActionsContext } from "@/components/collection/actions";
3
+ import { SiteHeader } from "@/components/site-header";
4
+ import { collection } from "@/lib/data/store";
5
+ import { useLiveQuery } from "@tanstack/react-db";
6
+ import { AppWindowIcon } from "lucide-react";
7
+ import Link from "next/link";
8
+
9
+ export default function Page() {
10
+ const query = useLiveQuery((q) => q.from({ collection }));
11
+ return (
12
+ <>
13
+ <SiteHeader />
14
+ <div className="flex-1 px-2 py-6">
15
+ <h1 className="inline-flex items-center gap-2 text-xl font-semibold mb-6">
16
+ <AppWindowIcon />
17
+ Collections
18
+ </h1>
19
+ <div className="grid grid-cols-1 border rounded-lg bg-card text-card-foreground overflow-hidden">
20
+ <div className="flex items-center gap-2 bg-secondary ps-4 pe-2 py-2">
21
+ <p className="text-sm text-muted-foreground">Collections</p>
22
+ </div>
23
+
24
+ {query.data.map((collection) => (
25
+ <CollectionActionsContext key={collection.id} collection={collection}>
26
+ <Link
27
+ href={`/collection/${collection.id}`}
28
+ className="text-sm font-medium px-4 py-2 hover:bg-accent hover:text-accent-foreground data-popup-open:bg-accent data-popup-open:text-accent-foreground"
29
+ >
30
+ {collection.name}
31
+ </Link>
32
+ </CollectionActionsContext>
33
+ ))}
34
+ </div>
35
+ </div>
36
+ </>
37
+ );
38
+ }