@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,612 @@
1
+ "use client";
2
+ import { type ComponentProps, type HTMLAttributes, type ReactNode, useState } from "react";
3
+ import { ChevronDown, Plus, Trash2, X } from "lucide-react";
4
+ import { useController, useFieldArray, useFormContext } from "react-hook-form";
5
+ import {
6
+ Select,
7
+ SelectContent,
8
+ SelectItem,
9
+ SelectTrigger,
10
+ SelectValue,
11
+ } from "@/components/ui/select";
12
+ import { Input } from "@/components/ui/input";
13
+ import { labelVariants } from "@/components/ui/label";
14
+ import { getDefaultValue } from "../get-default-values";
15
+ import { cn } from "@/lib/utils";
16
+ import { buttonVariants } from "@/components/ui/button";
17
+ import { FormatFlags, schemaToString } from "../utils/schema-to-string";
18
+ import { anyFields, useFieldInfo, useResolvedSchema, useSchema } from "../schema";
19
+ import type { JSONSchema } from "json-schema-typed/draft-2020-12";
20
+ import { Textarea } from "@/components/ui/textarea";
21
+
22
+ function FieldLabel(props: ComponentProps<"label">) {
23
+ return (
24
+ <label {...props} className={cn("w-full inline-flex items-center gap-0.5", props.className)}>
25
+ {props.children}
26
+ </label>
27
+ );
28
+ }
29
+
30
+ function FieldLabelName({
31
+ required = false,
32
+ className,
33
+ children,
34
+ ...props
35
+ }: ComponentProps<"span"> & { required?: boolean }) {
36
+ return (
37
+ <span {...props} className={cn(labelVariants(), "me-auto", className)}>
38
+ {children}
39
+ {required && <span className="text-destructive mx-1">*</span>}
40
+ </span>
41
+ );
42
+ }
43
+
44
+ function FieldLabelType(props: ComponentProps<"code">) {
45
+ return (
46
+ <code {...props} className={cn("text-xs text-muted-foreground", props.className)}>
47
+ {props.children}
48
+ </code>
49
+ );
50
+ }
51
+
52
+ export function ObjectInput({
53
+ field: _field,
54
+ fieldName,
55
+ ...props
56
+ }: {
57
+ field: Exclude<JSONSchema, boolean>;
58
+ fieldName: string;
59
+ } & ComponentProps<"div">) {
60
+ const field = useResolvedSchema(_field);
61
+
62
+ return (
63
+ <div {...props} className={cn("flex flex-col gap-4", props.className)}>
64
+ {Object.entries(field.properties ?? {}).map(([key, child]) => (
65
+ <FieldSet
66
+ key={key}
67
+ name={key}
68
+ field={child}
69
+ fieldName={`${fieldName}.${key}`}
70
+ isRequired={field.required?.includes(key)}
71
+ />
72
+ ))}
73
+ {(field.additionalProperties || field.patternProperties) && (
74
+ <DynamicProperties
75
+ fieldName={fieldName}
76
+ filterKey={(v) => !field.properties || !Object.keys(field.properties).includes(v)}
77
+ getType={(key) => {
78
+ for (const pattern in field.patternProperties) {
79
+ if (key.match(RegExp(pattern))) {
80
+ return field.patternProperties[pattern];
81
+ }
82
+ }
83
+
84
+ if (field.additionalProperties) return field.additionalProperties;
85
+
86
+ return anyFields;
87
+ }}
88
+ />
89
+ )}
90
+ </div>
91
+ );
92
+ }
93
+
94
+ function DynamicProperties({
95
+ fieldName,
96
+ filterKey = () => true,
97
+ getType = () => anyFields,
98
+ }: {
99
+ fieldName: string;
100
+ filterKey?: (key: string) => boolean;
101
+ getType: (key: string) => JSONSchema;
102
+ }) {
103
+ const { control, setValue, getValues } = useFormContext();
104
+ const [nextName, setNextName] = useState("");
105
+ const [properties, setProperties] = useState<string[]>(() => {
106
+ const value = getValues(fieldName);
107
+ if (value) return Object.keys(value).filter(filterKey);
108
+
109
+ return [];
110
+ });
111
+
112
+ const onAppend = () => {
113
+ const name = nextName.trim();
114
+ if (name.length === 0) return;
115
+
116
+ setProperties((p) => {
117
+ if (p.includes(name) || !filterKey(name)) return p;
118
+ const type = getType(name);
119
+
120
+ setValue(`${fieldName}.${name}`, getDefaultValue(type));
121
+ setNextName("");
122
+ return [...p, name];
123
+ });
124
+ };
125
+
126
+ return (
127
+ <>
128
+ {properties.map((item) => {
129
+ const type = getType(item);
130
+
131
+ return (
132
+ <FieldSet
133
+ key={item}
134
+ name={item}
135
+ field={type}
136
+ fieldName={`${fieldName}.${item}`}
137
+ toolbar={
138
+ <button
139
+ type="button"
140
+ aria-label="Remove Item"
141
+ className={cn(
142
+ buttonVariants({
143
+ variant: "outline",
144
+ size: "icon-xs",
145
+ }),
146
+ )}
147
+ onClick={() => {
148
+ setProperties((p) => p.filter((prop) => prop !== item));
149
+ control.unregister(`${fieldName}.${item}`);
150
+ }}
151
+ >
152
+ <Trash2 />
153
+ </button>
154
+ }
155
+ />
156
+ );
157
+ })}
158
+ <div className="flex gap-2 col-span-full">
159
+ <Input
160
+ value={nextName}
161
+ placeholder="Enter Property Name"
162
+ onChange={(e) => setNextName(e.target.value)}
163
+ onKeyDown={(e) => {
164
+ if (e.key === "Enter") {
165
+ onAppend();
166
+ e.preventDefault();
167
+ }
168
+ }}
169
+ />
170
+ <button
171
+ type="button"
172
+ className={cn(buttonVariants({ variant: "secondary", size: "sm" }), "px-4")}
173
+ onClick={onAppend}
174
+ >
175
+ New
176
+ </button>
177
+ </div>
178
+ </>
179
+ );
180
+ }
181
+
182
+ export function FieldInput({
183
+ field,
184
+ fieldName,
185
+ isRequired,
186
+ ...props
187
+ }: HTMLAttributes<HTMLElement> & {
188
+ field: Exclude<JSONSchema, boolean>;
189
+ isRequired?: boolean;
190
+ fieldName: string;
191
+ }) {
192
+ const form = useFormContext();
193
+ const {
194
+ field: { value, onChange, ...restField },
195
+ fieldState,
196
+ } = useController({
197
+ control: form.control,
198
+ name: fieldName,
199
+ });
200
+
201
+ if (field.type === "null") return;
202
+
203
+ if (field.enum) {
204
+ return (
205
+ <Select
206
+ value={field.enum.indexOf(value).toString()}
207
+ onValueChange={(value) => {
208
+ onChange(value === "-1" ? undefined : value);
209
+ }}
210
+ disabled={restField.disabled}
211
+ >
212
+ <SelectTrigger id={fieldName} className={props.className} {...restField}>
213
+ <SelectValue />
214
+ </SelectTrigger>
215
+ <SelectContent>
216
+ {field.enum.map((item, i) => (
217
+ <SelectItem key={i} value={i.toString()}>
218
+ {JSON.stringify(item)}
219
+ </SelectItem>
220
+ ))}
221
+ {!isRequired && <SelectItem value="-1">Unset</SelectItem>}
222
+ </SelectContent>
223
+ </Select>
224
+ );
225
+ }
226
+
227
+ if (field.type === "boolean") {
228
+ return (
229
+ <Select
230
+ value={String(value)}
231
+ onValueChange={(value) => onChange(value === "undefined" ? undefined : value === "true")}
232
+ disabled={restField.disabled}
233
+ >
234
+ <SelectTrigger id={fieldName} className={props.className} {...restField}>
235
+ <SelectValue />
236
+ </SelectTrigger>
237
+ <SelectContent>
238
+ <SelectItem value="true">True</SelectItem>
239
+ <SelectItem value="false">False</SelectItem>
240
+ {!isRequired && <SelectItem value="undefined">Unset</SelectItem>}
241
+ </SelectContent>
242
+ </Select>
243
+ );
244
+ }
245
+
246
+ const resetBn = fieldState.isDirty && (
247
+ <button
248
+ type="button"
249
+ // TODO: `react-hook-form` doesn't support setting a value to `undefined` (aka remove the value), if there's a default value defined.
250
+ // the default value is kept by `react-hook-form` internally, we cannot manipulate it.
251
+ // hence, we can only support resetting to the default value.
252
+ // perhaps when we migrate to Tanstack Form, we can reconsider this.
253
+ onClick={() => form.resetField(fieldName)}
254
+ className="text-muted-foreground"
255
+ >
256
+ <X className="size-4" />
257
+ </button>
258
+ );
259
+
260
+ if (field.type === "string") {
261
+ if (field.format === "binary") {
262
+ return (
263
+ <div {...props}>
264
+ <label
265
+ htmlFor={fieldName}
266
+ className={cn(
267
+ buttonVariants({
268
+ variant: "secondary",
269
+ className: "w-full h-9 gap-2 truncate",
270
+ }),
271
+ )}
272
+ >
273
+ {value instanceof File ? (
274
+ <>
275
+ <span className="text-muted-foreground text-xs">Selected</span>
276
+ <span className="truncate w-0 flex-1 text-end">{value.name}</span>
277
+ </>
278
+ ) : (
279
+ <span className="text-muted-foreground">Upload</span>
280
+ )}
281
+ </label>
282
+ <input
283
+ id={fieldName}
284
+ type="file"
285
+ multiple={false}
286
+ onChange={(e) => {
287
+ if (!e.target.files) return;
288
+ onChange(e.target.files.item(0));
289
+ }}
290
+ hidden
291
+ {...restField}
292
+ />
293
+ </div>
294
+ );
295
+ }
296
+ if (field.format === "datetime" || field.format === "time" || field.format === "date")
297
+ return (
298
+ <div {...props} className={cn("flex flex-row gap-2", props.className)}>
299
+ <Input
300
+ id={fieldName}
301
+ type={field.format}
302
+ placeholder="Enter value"
303
+ value={value ?? ""}
304
+ onChange={(e) => onChange(e.target.value)}
305
+ {...restField}
306
+ />
307
+ {resetBn}
308
+ </div>
309
+ );
310
+
311
+ return (
312
+ <div {...props} className={cn("flex flex-row gap-2", props.className)}>
313
+ <Textarea
314
+ id={fieldName}
315
+ placeholder="Enter value"
316
+ value={value ?? ""}
317
+ onChange={(e) => onChange(e.target.value)}
318
+ {...restField}
319
+ />
320
+ {resetBn}
321
+ </div>
322
+ );
323
+ }
324
+
325
+ if (field.type === "integer" || field.type === "number") {
326
+ return (
327
+ <div {...props} className={cn("flex flex-row gap-2", props.className)}>
328
+ <Input
329
+ id={fieldName}
330
+ placeholder="Enter value"
331
+ type="number"
332
+ step={field.type === "integer" ? 1 : undefined}
333
+ value={value ?? ""}
334
+ onChange={(e) => {
335
+ if (!Number.isNaN(e.target.valueAsNumber)) {
336
+ onChange(e.target.valueAsNumber);
337
+ }
338
+ }}
339
+ {...restField}
340
+ />
341
+ {resetBn}
342
+ </div>
343
+ );
344
+ }
345
+ }
346
+
347
+ export function FieldSet({
348
+ field: _field,
349
+ fieldName,
350
+ toolbar,
351
+ name,
352
+ isRequired,
353
+ depth = 0,
354
+ slotType,
355
+ collapsible = true,
356
+ ...props
357
+ }: HTMLAttributes<HTMLElement> & {
358
+ isRequired?: boolean;
359
+ name?: ReactNode;
360
+ field: JSONSchema;
361
+ fieldName: string;
362
+ depth?: number;
363
+
364
+ slotType?: ReactNode;
365
+ toolbar?: ReactNode;
366
+ collapsible?: boolean;
367
+ }) {
368
+ const schemaContext = useSchema();
369
+ const field = useResolvedSchema(_field);
370
+ const [show, setShow] = useState(!collapsible);
371
+ const { info, updateInfo } = useFieldInfo(fieldName, field, depth);
372
+
373
+ if (_field === false) return;
374
+ if (field.readOnly && !schemaContext.readOnly) return;
375
+ if (field.writeOnly && !schemaContext.writeOnly) return;
376
+
377
+ if (info.unionField) {
378
+ const union = field[info.unionField]!;
379
+ const showSelect = union.length > 1;
380
+
381
+ return (
382
+ <FieldSet
383
+ {...props}
384
+ name={name}
385
+ fieldName={fieldName}
386
+ isRequired={isRequired}
387
+ field={union[info.oneOf]}
388
+ depth={depth + 1}
389
+ slotType={showSelect ? false : slotType}
390
+ toolbar={
391
+ <>
392
+ {showSelect && (
393
+ <select
394
+ className="text-xs font-mono"
395
+ value={info.oneOf}
396
+ onChange={(e) => {
397
+ updateInfo({
398
+ oneOf: Number(e.target.value),
399
+ });
400
+ }}
401
+ >
402
+ {union.map((item, i) => (
403
+ <option key={i} value={i} className="bg-popover text-popover-foreground">
404
+ {schemaToString(item, schemaContext, FormatFlags.UseAlias)}
405
+ </option>
406
+ ))}
407
+ </select>
408
+ )}
409
+ {toolbar}
410
+ </>
411
+ }
412
+ />
413
+ );
414
+ }
415
+
416
+ if (Array.isArray(field.type)) {
417
+ const showSelect = field.type.length > 1;
418
+
419
+ return (
420
+ <FieldSet
421
+ {...props}
422
+ name={name}
423
+ fieldName={fieldName}
424
+ isRequired={isRequired}
425
+ field={{
426
+ ...field,
427
+ type: info.selectedType,
428
+ }}
429
+ depth={depth + 1}
430
+ slotType={showSelect ? false : slotType}
431
+ toolbar={
432
+ <>
433
+ {showSelect && (
434
+ <select
435
+ className="text-xs font-mono"
436
+ value={info.selectedType}
437
+ onChange={(e) => {
438
+ updateInfo({
439
+ selectedType: e.target.value,
440
+ });
441
+ }}
442
+ >
443
+ {field.type.map((item) => (
444
+ <option key={item} value={item} className="bg-popover text-popover-foreground">
445
+ {item}
446
+ </option>
447
+ ))}
448
+ </select>
449
+ )}
450
+ {toolbar}
451
+ </>
452
+ }
453
+ />
454
+ );
455
+ }
456
+
457
+ const showBn = collapsible && (
458
+ <button
459
+ type="button"
460
+ onClick={() => setShow((prev) => !prev)}
461
+ className={cn(
462
+ buttonVariants({
463
+ size: "icon-xs",
464
+ variant: "ghost",
465
+ className: "text-muted-foreground -ms-1",
466
+ }),
467
+ )}
468
+ >
469
+ <ChevronDown className={cn(show && "rotate-180")} />
470
+ </button>
471
+ );
472
+
473
+ if (field.type === "object" || info.intersection) {
474
+ return (
475
+ <fieldset
476
+ {...props}
477
+ className={cn("flex flex-col gap-1.5 col-span-full @container", props.className)}
478
+ >
479
+ <FieldLabel htmlFor={fieldName}>
480
+ {showBn}
481
+ <FieldLabelName required={isRequired}>{name}</FieldLabelName>
482
+ {slotType ?? <FieldLabelType>{schemaToString(field, schemaContext)}</FieldLabelType>}
483
+ {toolbar}
484
+ </FieldLabel>
485
+ {show && (
486
+ <ObjectInput
487
+ field={info.intersection?.merged ?? field}
488
+ fieldName={fieldName}
489
+ {...props}
490
+ className={cn(
491
+ "rounded-lg border bg-card text-card-foreground p-3 shadow-sm",
492
+ props.className,
493
+ )}
494
+ />
495
+ )}
496
+ </fieldset>
497
+ );
498
+ }
499
+
500
+ if (field.type === "array") {
501
+ return (
502
+ <fieldset {...props} className={cn("flex flex-col gap-1.5 col-span-full", props.className)}>
503
+ <FieldLabel htmlFor={fieldName}>
504
+ {showBn}
505
+ <FieldLabelName required={isRequired}>{name}</FieldLabelName>
506
+ {slotType ?? <FieldLabelType>{schemaToString(field, schemaContext)}</FieldLabelType>}
507
+ {toolbar}
508
+ </FieldLabel>
509
+ {show && (
510
+ <ArrayInput
511
+ fieldName={fieldName}
512
+ items={field.items ?? anyFields}
513
+ {...props}
514
+ className={cn(
515
+ "rounded-lg border bg-card text-card-foreground p-3 shadow-sm",
516
+ props.className,
517
+ )}
518
+ />
519
+ )}
520
+ </fieldset>
521
+ );
522
+ }
523
+
524
+ if (!field.type) {
525
+ return (
526
+ <FieldSet
527
+ {...props}
528
+ name={name}
529
+ fieldName={fieldName}
530
+ isRequired={isRequired}
531
+ field={anyFields}
532
+ depth={depth + 1}
533
+ slotType={slotType}
534
+ toolbar={toolbar}
535
+ />
536
+ );
537
+ }
538
+
539
+ return (
540
+ <fieldset {...props} className={cn("flex flex-col gap-1.5", props.className)}>
541
+ <FieldLabel htmlFor={fieldName}>
542
+ <FieldLabelName required={isRequired}>{name}</FieldLabelName>
543
+ {slotType ?? <FieldLabelType>{schemaToString(field, schemaContext)}</FieldLabelType>}
544
+ {toolbar}
545
+ </FieldLabel>
546
+ <FieldInput field={field} fieldName={fieldName} isRequired={isRequired} />
547
+ </fieldset>
548
+ );
549
+ }
550
+
551
+ function ArrayInput({
552
+ fieldName,
553
+ items,
554
+ ...props
555
+ }: {
556
+ fieldName: string;
557
+ items: JSONSchema;
558
+ } & ComponentProps<"div">) {
559
+ const name = fieldName.split(".").at(-1) ?? "";
560
+ const { fields, append, remove } = useFieldArray({
561
+ name: fieldName,
562
+ });
563
+
564
+ return (
565
+ <div {...props} className={cn("flex flex-col gap-2", props.className)}>
566
+ {fields.map((item, index) => (
567
+ <FieldSet
568
+ key={item.id}
569
+ name={
570
+ <span className="text-muted-foreground">
571
+ {name}[{index}]
572
+ </span>
573
+ }
574
+ field={items}
575
+ isRequired
576
+ fieldName={`${fieldName}.${index}`}
577
+ toolbar={
578
+ <button
579
+ type="button"
580
+ aria-label="Remove Item"
581
+ className={cn(
582
+ buttonVariants({
583
+ variant: "outline",
584
+ size: "icon-xs",
585
+ }),
586
+ )}
587
+ onClick={() => remove(index)}
588
+ >
589
+ <Trash2 />
590
+ </button>
591
+ }
592
+ />
593
+ ))}
594
+ <button
595
+ type="button"
596
+ className={cn(
597
+ buttonVariants({
598
+ variant: "secondary",
599
+ className: "gap-1.5 py-2",
600
+ size: "sm",
601
+ }),
602
+ )}
603
+ onClick={() => {
604
+ append(getDefaultValue(items));
605
+ }}
606
+ >
607
+ <Plus className="size-4" />
608
+ New Item
609
+ </button>
610
+ </div>
611
+ );
612
+ }
@@ -0,0 +1,29 @@
1
+ import type { JSONSchema } from "json-schema-typed/draft-2020-12";
2
+
3
+ export function getDefaultValue(schema: JSONSchema): unknown {
4
+ if (typeof schema === "boolean") return null;
5
+
6
+ const type = schema.type;
7
+ if (Array.isArray(type))
8
+ return getDefaultValue({
9
+ ...schema,
10
+ type: type[0],
11
+ });
12
+
13
+ if (type === "object" && typeof schema === "object")
14
+ return Object.fromEntries(
15
+ Object.entries(schema.properties ?? {}).map(([key, prop]) => {
16
+ return [key, getDefaultValue(prop)];
17
+ }),
18
+ );
19
+
20
+ if (type === "array") return [];
21
+ if (type === "null") return null;
22
+ if (type === "string") {
23
+ if (typeof schema === "object" && schema.format === "binary") return undefined;
24
+
25
+ return "";
26
+ }
27
+ if (type === "number" || type === "integer") return 0;
28
+ if (type === "boolean") return false;
29
+ }