doclific 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 (231) hide show
  1. package/.gitattributes +2 -0
  2. package/.prettierignore +5 -0
  3. package/.prettierrc +9 -0
  4. package/.vscode/settings.json +13 -0
  5. package/dist/bin/doclific.d.ts +3 -0
  6. package/dist/bin/doclific.d.ts.map +1 -0
  7. package/dist/bin/doclific.js +11 -0
  8. package/dist/core/codebase.js +31 -0
  9. package/dist/core/docs.js +75 -0
  10. package/dist/core/git.js +47 -0
  11. package/dist/server/index.d.ts +2 -0
  12. package/dist/server/index.d.ts.map +1 -0
  13. package/dist/server/index.js +46 -0
  14. package/dist/server/router.d.ts +9 -0
  15. package/dist/server/router.d.ts.map +1 -0
  16. package/dist/server/router.js +55 -0
  17. package/frontend/README.md +73 -0
  18. package/frontend/components.json +24 -0
  19. package/frontend/eslint.config.js +23 -0
  20. package/frontend/index.html +25 -0
  21. package/frontend/package-lock.json +15754 -0
  22. package/frontend/package.json +122 -0
  23. package/frontend/public/logo.svg +1 -0
  24. package/frontend/src/App.tsx +21 -0
  25. package/frontend/src/components/app-sidebar.tsx +393 -0
  26. package/frontend/src/components/editor/editor-base-kit.tsx +43 -0
  27. package/frontend/src/components/editor/editor-kit.tsx +93 -0
  28. package/frontend/src/components/editor/plugins/align-base-kit.tsx +16 -0
  29. package/frontend/src/components/editor/plugins/align-kit.tsx +18 -0
  30. package/frontend/src/components/editor/plugins/autoformat-kit.tsx +236 -0
  31. package/frontend/src/components/editor/plugins/basic-blocks-base-kit.tsx +35 -0
  32. package/frontend/src/components/editor/plugins/basic-blocks-kit.tsx +88 -0
  33. package/frontend/src/components/editor/plugins/basic-marks-base-kit.tsx +27 -0
  34. package/frontend/src/components/editor/plugins/basic-marks-kit.tsx +41 -0
  35. package/frontend/src/components/editor/plugins/basic-nodes-kit.tsx +6 -0
  36. package/frontend/src/components/editor/plugins/block-menu-kit.tsx +14 -0
  37. package/frontend/src/components/editor/plugins/block-placeholder-kit.tsx +17 -0
  38. package/frontend/src/components/editor/plugins/block-selection-kit.tsx +32 -0
  39. package/frontend/src/components/editor/plugins/callout-base-kit.tsx +7 -0
  40. package/frontend/src/components/editor/plugins/callout-kit.tsx +7 -0
  41. package/frontend/src/components/editor/plugins/code-block-base-kit.tsx +23 -0
  42. package/frontend/src/components/editor/plugins/code-block-kit.tsx +26 -0
  43. package/frontend/src/components/editor/plugins/codebase-kit.tsx +23 -0
  44. package/frontend/src/components/editor/plugins/column-base-kit.tsx +11 -0
  45. package/frontend/src/components/editor/plugins/column-kit.tsx +10 -0
  46. package/frontend/src/components/editor/plugins/comment-base-kit.tsx +7 -0
  47. package/frontend/src/components/editor/plugins/comment-kit.tsx +97 -0
  48. package/frontend/src/components/editor/plugins/cursor-overlay-kit.tsx +13 -0
  49. package/frontend/src/components/editor/plugins/date-base-kit.tsx +5 -0
  50. package/frontend/src/components/editor/plugins/date-kit.tsx +7 -0
  51. package/frontend/src/components/editor/plugins/discussion-kit.tsx +148 -0
  52. package/frontend/src/components/editor/plugins/dnd-kit.tsx +28 -0
  53. package/frontend/src/components/editor/plugins/docx-kit.tsx +6 -0
  54. package/frontend/src/components/editor/plugins/emoji-kit.tsx +13 -0
  55. package/frontend/src/components/editor/plugins/excalidraw-kit.tsx +9 -0
  56. package/frontend/src/components/editor/plugins/exit-break-kit.tsx +12 -0
  57. package/frontend/src/components/editor/plugins/floating-toolbar-kit.tsx +19 -0
  58. package/frontend/src/components/editor/plugins/font-base-kit.tsx +20 -0
  59. package/frontend/src/components/editor/plugins/font-kit.tsx +29 -0
  60. package/frontend/src/components/editor/plugins/indent-base-kit.tsx +19 -0
  61. package/frontend/src/components/editor/plugins/indent-kit.tsx +22 -0
  62. package/frontend/src/components/editor/plugins/line-height-base-kit.tsx +14 -0
  63. package/frontend/src/components/editor/plugins/line-height-kit.tsx +16 -0
  64. package/frontend/src/components/editor/plugins/link-base-kit.tsx +5 -0
  65. package/frontend/src/components/editor/plugins/link-kit.tsx +15 -0
  66. package/frontend/src/components/editor/plugins/list-base-kit.tsx +23 -0
  67. package/frontend/src/components/editor/plugins/list-kit.tsx +26 -0
  68. package/frontend/src/components/editor/plugins/markdown-kit.tsx +46 -0
  69. package/frontend/src/components/editor/plugins/math-base-kit.tsx +11 -0
  70. package/frontend/src/components/editor/plugins/math-kit.tsx +13 -0
  71. package/frontend/src/components/editor/plugins/media-base-kit.tsx +31 -0
  72. package/frontend/src/components/editor/plugins/media-kit.tsx +43 -0
  73. package/frontend/src/components/editor/plugins/mention-base-kit.tsx +7 -0
  74. package/frontend/src/components/editor/plugins/mention-kit.tsx +15 -0
  75. package/frontend/src/components/editor/plugins/slash-kit.tsx +18 -0
  76. package/frontend/src/components/editor/plugins/suggestion-base-kit.tsx +7 -0
  77. package/frontend/src/components/editor/plugins/suggestion-kit.tsx +90 -0
  78. package/frontend/src/components/editor/plugins/table-base-kit.tsx +20 -0
  79. package/frontend/src/components/editor/plugins/table-kit.tsx +22 -0
  80. package/frontend/src/components/editor/plugins/toc-base-kit.tsx +5 -0
  81. package/frontend/src/components/editor/plugins/toc-kit.tsx +14 -0
  82. package/frontend/src/components/editor/plugins/toggle-base-kit.tsx +7 -0
  83. package/frontend/src/components/editor/plugins/toggle-kit.tsx +11 -0
  84. package/frontend/src/components/editor/transforms.ts +194 -0
  85. package/frontend/src/components/markdown-to-slate-demo.tsx +50 -0
  86. package/frontend/src/components/mode-toggle.tsx +15 -0
  87. package/frontend/src/components/theme-provider.tsx +73 -0
  88. package/frontend/src/components/ui/alert-dialog.tsx +155 -0
  89. package/frontend/src/components/ui/align-toolbar-button.tsx +84 -0
  90. package/frontend/src/components/ui/avatar.tsx +51 -0
  91. package/frontend/src/components/ui/block-context-menu.tsx +199 -0
  92. package/frontend/src/components/ui/block-discussion.tsx +365 -0
  93. package/frontend/src/components/ui/block-draggable.tsx +512 -0
  94. package/frontend/src/components/ui/block-list-static.tsx +80 -0
  95. package/frontend/src/components/ui/block-list.tsx +87 -0
  96. package/frontend/src/components/ui/block-selection.tsx +42 -0
  97. package/frontend/src/components/ui/block-suggestion.tsx +473 -0
  98. package/frontend/src/components/ui/blockquote-node-static.tsx +11 -0
  99. package/frontend/src/components/ui/blockquote-node.tsx +13 -0
  100. package/frontend/src/components/ui/button.tsx +62 -0
  101. package/frontend/src/components/ui/calendar.tsx +218 -0
  102. package/frontend/src/components/ui/callout-node-static.tsx +36 -0
  103. package/frontend/src/components/ui/callout-node.tsx +63 -0
  104. package/frontend/src/components/ui/caption.tsx +63 -0
  105. package/frontend/src/components/ui/checkbox.tsx +30 -0
  106. package/frontend/src/components/ui/code-block-node-static.tsx +35 -0
  107. package/frontend/src/components/ui/code-block-node.tsx +287 -0
  108. package/frontend/src/components/ui/code-node-static.tsx +15 -0
  109. package/frontend/src/components/ui/code-node.tsx +17 -0
  110. package/frontend/src/components/ui/codebase-snippet-node.tsx +237 -0
  111. package/frontend/src/components/ui/column-node-static.tsx +29 -0
  112. package/frontend/src/components/ui/column-node.tsx +317 -0
  113. package/frontend/src/components/ui/command.tsx +182 -0
  114. package/frontend/src/components/ui/comment-node-static.tsx +15 -0
  115. package/frontend/src/components/ui/comment-node.tsx +45 -0
  116. package/frontend/src/components/ui/comment-toolbar-button.tsx +24 -0
  117. package/frontend/src/components/ui/comment.tsx +618 -0
  118. package/frontend/src/components/ui/context-menu.tsx +250 -0
  119. package/frontend/src/components/ui/cursor-overlay.tsx +66 -0
  120. package/frontend/src/components/ui/date-node-static.tsx +45 -0
  121. package/frontend/src/components/ui/date-node.tsx +93 -0
  122. package/frontend/src/components/ui/dialog.tsx +143 -0
  123. package/frontend/src/components/ui/dropdown-menu.tsx +255 -0
  124. package/frontend/src/components/ui/dynamic-icon.tsx +12 -0
  125. package/frontend/src/components/ui/editor-static.tsx +53 -0
  126. package/frontend/src/components/ui/editor.tsx +130 -0
  127. package/frontend/src/components/ui/emoji-node.tsx +69 -0
  128. package/frontend/src/components/ui/emoji-toolbar-button.tsx +628 -0
  129. package/frontend/src/components/ui/equation-node-static.tsx +98 -0
  130. package/frontend/src/components/ui/equation-node.tsx +235 -0
  131. package/frontend/src/components/ui/equation-toolbar-button.tsx +25 -0
  132. package/frontend/src/components/ui/excalidraw-node.tsx +36 -0
  133. package/frontend/src/components/ui/export-toolbar-button.tsx +174 -0
  134. package/frontend/src/components/ui/file-selector.tsx +339 -0
  135. package/frontend/src/components/ui/floating-toolbar-buttons.tsx +73 -0
  136. package/frontend/src/components/ui/floating-toolbar.tsx +85 -0
  137. package/frontend/src/components/ui/font-color-toolbar-button.tsx +831 -0
  138. package/frontend/src/components/ui/font-size-toolbar-button.tsx +152 -0
  139. package/frontend/src/components/ui/heading-node-static.tsx +68 -0
  140. package/frontend/src/components/ui/heading-node.tsx +58 -0
  141. package/frontend/src/components/ui/highlight-node-static.tsx +11 -0
  142. package/frontend/src/components/ui/highlight-node.tsx +13 -0
  143. package/frontend/src/components/ui/history-toolbar-button.tsx +50 -0
  144. package/frontend/src/components/ui/hr-node-static.tsx +20 -0
  145. package/frontend/src/components/ui/hr-node.tsx +33 -0
  146. package/frontend/src/components/ui/import-toolbar-button.tsx +97 -0
  147. package/frontend/src/components/ui/indent-toolbar-button.tsx +30 -0
  148. package/frontend/src/components/ui/inline-combobox.tsx +414 -0
  149. package/frontend/src/components/ui/input.tsx +21 -0
  150. package/frontend/src/components/ui/insert-toolbar-button.tsx +254 -0
  151. package/frontend/src/components/ui/kbd-node-static.tsx +15 -0
  152. package/frontend/src/components/ui/kbd-node.tsx +17 -0
  153. package/frontend/src/components/ui/layout-header.tsx +35 -0
  154. package/frontend/src/components/ui/line-height-toolbar-button.tsx +68 -0
  155. package/frontend/src/components/ui/link-node-static.tsx +21 -0
  156. package/frontend/src/components/ui/link-node.tsx +39 -0
  157. package/frontend/src/components/ui/link-toolbar-button.tsx +22 -0
  158. package/frontend/src/components/ui/link-toolbar.tsx +206 -0
  159. package/frontend/src/components/ui/list-toolbar-button.tsx +204 -0
  160. package/frontend/src/components/ui/mark-toolbar-button.tsx +19 -0
  161. package/frontend/src/components/ui/media-audio-node-static.tsx +17 -0
  162. package/frontend/src/components/ui/media-audio-node.tsx +39 -0
  163. package/frontend/src/components/ui/media-embed-node.tsx +136 -0
  164. package/frontend/src/components/ui/media-file-node-static.tsx +29 -0
  165. package/frontend/src/components/ui/media-file-node.tsx +47 -0
  166. package/frontend/src/components/ui/media-image-node-static.tsx +39 -0
  167. package/frontend/src/components/ui/media-image-node.tsx +80 -0
  168. package/frontend/src/components/ui/media-placeholder-node.tsx +249 -0
  169. package/frontend/src/components/ui/media-preview-dialog.tsx +152 -0
  170. package/frontend/src/components/ui/media-toolbar-button.tsx +225 -0
  171. package/frontend/src/components/ui/media-toolbar.tsx +115 -0
  172. package/frontend/src/components/ui/media-upload-toast.tsx +66 -0
  173. package/frontend/src/components/ui/media-video-node-static.tsx +30 -0
  174. package/frontend/src/components/ui/media-video-node.tsx +121 -0
  175. package/frontend/src/components/ui/mention-node-static.tsx +36 -0
  176. package/frontend/src/components/ui/mention-node.tsx +194 -0
  177. package/frontend/src/components/ui/mode-toolbar-button.tsx +123 -0
  178. package/frontend/src/components/ui/more-toolbar-button.tsx +80 -0
  179. package/frontend/src/components/ui/paragraph-node-static.tsx +13 -0
  180. package/frontend/src/components/ui/paragraph-node.tsx +15 -0
  181. package/frontend/src/components/ui/popover.tsx +46 -0
  182. package/frontend/src/components/ui/resize-handle.tsx +87 -0
  183. package/frontend/src/components/ui/separator.tsx +28 -0
  184. package/frontend/src/components/ui/sheet.tsx +139 -0
  185. package/frontend/src/components/ui/sidebar.tsx +726 -0
  186. package/frontend/src/components/ui/skeleton.tsx +13 -0
  187. package/frontend/src/components/ui/slash-node.tsx +233 -0
  188. package/frontend/src/components/ui/sonner.tsx +38 -0
  189. package/frontend/src/components/ui/suggestion-node-static.tsx +35 -0
  190. package/frontend/src/components/ui/suggestion-node.tsx +162 -0
  191. package/frontend/src/components/ui/suggestion-toolbar-button.tsx +25 -0
  192. package/frontend/src/components/ui/table-icons.tsx +862 -0
  193. package/frontend/src/components/ui/table-node-static.tsx +98 -0
  194. package/frontend/src/components/ui/table-node.tsx +656 -0
  195. package/frontend/src/components/ui/table-toolbar-button.tsx +264 -0
  196. package/frontend/src/components/ui/toc-node-static.tsx +92 -0
  197. package/frontend/src/components/ui/toc-node.tsx +55 -0
  198. package/frontend/src/components/ui/toggle-node-static.tsx +18 -0
  199. package/frontend/src/components/ui/toggle-node.tsx +36 -0
  200. package/frontend/src/components/ui/toggle-toolbar-button.tsx +22 -0
  201. package/frontend/src/components/ui/toolbar.tsx +387 -0
  202. package/frontend/src/components/ui/tooltip.tsx +59 -0
  203. package/frontend/src/components/ui/turn-into-toolbar-button.tsx +188 -0
  204. package/frontend/src/hooks/use-debounce.ts +18 -0
  205. package/frontend/src/hooks/use-is-touch-device.ts +24 -0
  206. package/frontend/src/hooks/use-mobile.ts +19 -0
  207. package/frontend/src/hooks/use-mounted.ts +11 -0
  208. package/frontend/src/hooks/use-upload-file.ts +128 -0
  209. package/frontend/src/index.css +128 -0
  210. package/frontend/src/layout.tsx +42 -0
  211. package/frontend/src/lib/markdown-joiner-transform.ts +239 -0
  212. package/frontend/src/lib/orpc.ts +13 -0
  213. package/frontend/src/lib/uploadthing.ts +19 -0
  214. package/frontend/src/lib/utils.ts +6 -0
  215. package/frontend/src/main.tsx +13 -0
  216. package/frontend/src/pages/editor.tsx +44 -0
  217. package/frontend/src/types/docs.d.ts +6 -0
  218. package/frontend/src/types/global.d.ts +9 -0
  219. package/frontend/src/types/router.d.ts +4 -0
  220. package/frontend/tsconfig.app.json +33 -0
  221. package/frontend/tsconfig.json +10 -0
  222. package/frontend/tsconfig.node.json +26 -0
  223. package/frontend/vite.config.ts +14 -0
  224. package/package.json +30 -0
  225. package/src/bin/doclific.ts +17 -0
  226. package/src/core/codebase.ts +39 -0
  227. package/src/core/docs.ts +90 -0
  228. package/src/core/git.ts +48 -0
  229. package/src/server/index.ts +55 -0
  230. package/src/server/router.ts +65 -0
  231. package/tsconfig.json +15 -0
@@ -0,0 +1,317 @@
1
+ import React from 'react';
2
+
3
+ import type { TColumnElement } from 'platejs';
4
+ import type { PlateElementProps } from 'platejs/react';
5
+
6
+ import { useDraggable, useDropLine } from '@platejs/dnd';
7
+ import { setColumns } from '@platejs/layout';
8
+ import { ResizableProvider } from '@platejs/resizable';
9
+ import { BlockSelectionPlugin } from '@platejs/selection/react';
10
+ import { useComposedRef } from '@udecode/cn';
11
+ import { type LucideProps, Trash2Icon } from 'lucide-react';
12
+ import { GripHorizontal } from 'lucide-react';
13
+ import { PathApi } from 'platejs';
14
+ import {
15
+ PlateElement,
16
+ useEditorRef,
17
+ useEditorSelector,
18
+ useElement,
19
+ useFocusedLast,
20
+ usePluginOption,
21
+ useReadOnly,
22
+ useRemoveNodeButton,
23
+ useSelected,
24
+ withHOC,
25
+ } from 'platejs/react';
26
+
27
+ import { Button } from '@/components/ui/button';
28
+ import {
29
+ Popover,
30
+ PopoverAnchor,
31
+ PopoverContent,
32
+ } from '@/components/ui/popover';
33
+ import { Separator } from '@/components/ui/separator';
34
+ import {
35
+ Tooltip,
36
+ TooltipContent,
37
+ TooltipProvider,
38
+ TooltipTrigger,
39
+ } from '@/components/ui/tooltip';
40
+ import { cn } from '@/lib/utils';
41
+
42
+ export const ColumnElement = withHOC(
43
+ ResizableProvider,
44
+ function ColumnElement(props: PlateElementProps<TColumnElement>) {
45
+ const { width } = props.element;
46
+ const readOnly = useReadOnly();
47
+ const isSelectionAreaVisible = usePluginOption(
48
+ BlockSelectionPlugin,
49
+ 'isSelectionAreaVisible'
50
+ );
51
+
52
+ const { isDragging, previewRef, handleRef } = useDraggable({
53
+ element: props.element,
54
+ orientation: 'horizontal',
55
+ type: 'column',
56
+ canDropNode: ({ dragEntry, dropEntry }) =>
57
+ PathApi.equals(
58
+ PathApi.parent(dragEntry[1]),
59
+ PathApi.parent(dropEntry[1])
60
+ ),
61
+ });
62
+
63
+ return (
64
+ <div className="group/column relative" style={{ width: width ?? '100%' }}>
65
+ {!readOnly && !isSelectionAreaVisible && (
66
+ <div
67
+ ref={handleRef}
68
+ className={cn(
69
+ '-translate-x-1/2 -translate-y-1/2 absolute top-2 left-1/2 z-50',
70
+ 'pointer-events-auto flex items-center',
71
+ 'opacity-0 transition-opacity group-hover/column:opacity-100'
72
+ )}
73
+ >
74
+ <ColumnDragHandle />
75
+ </div>
76
+ )}
77
+
78
+ <PlateElement
79
+ {...props}
80
+ ref={useComposedRef(props.ref, previewRef)}
81
+ className="h-full px-2 pt-2 group-first/column:pl-0 group-last/column:pr-0"
82
+ >
83
+ <div
84
+ className={cn(
85
+ 'relative h-full border border-transparent p-1.5',
86
+ !readOnly && 'rounded-lg border-border border-dashed',
87
+ isDragging && 'opacity-50'
88
+ )}
89
+ >
90
+ {props.children}
91
+
92
+ {!readOnly && !isSelectionAreaVisible && <DropLine />}
93
+ </div>
94
+ </PlateElement>
95
+ </div>
96
+ );
97
+ }
98
+ );
99
+
100
+ const ColumnDragHandle = React.memo(function ColumnDragHandle() {
101
+ return (
102
+ <TooltipProvider>
103
+ <Tooltip>
104
+ <TooltipTrigger asChild>
105
+ <Button variant="ghost" className="!px-1 h-5">
106
+ <GripHorizontal
107
+ className="text-muted-foreground"
108
+ onClick={(event) => {
109
+ event.stopPropagation();
110
+ event.preventDefault();
111
+ }}
112
+ />
113
+ </Button>
114
+ </TooltipTrigger>
115
+
116
+ <TooltipContent>Drag to move column</TooltipContent>
117
+ </Tooltip>
118
+ </TooltipProvider>
119
+ );
120
+ });
121
+
122
+ function DropLine() {
123
+ const { dropLine } = useDropLine({ orientation: 'horizontal' });
124
+
125
+ if (!dropLine) return null;
126
+
127
+ return (
128
+ <div
129
+ className={cn(
130
+ 'slate-dropLine',
131
+ 'absolute bg-brand/50',
132
+ dropLine === 'left' &&
133
+ 'group-first/column:-left-1 inset-y-0 left-[-10.5px] w-1',
134
+ dropLine === 'right' &&
135
+ 'group-last/column:-right-1 inset-y-0 right-[-11px] w-1'
136
+ )}
137
+ />
138
+ );
139
+ }
140
+
141
+ export function ColumnGroupElement(props: PlateElementProps) {
142
+ return (
143
+ <PlateElement className="mb-2" {...props}>
144
+ <ColumnFloatingToolbar>
145
+ <div className="flex size-full rounded">{props.children}</div>
146
+ </ColumnFloatingToolbar>
147
+ </PlateElement>
148
+ );
149
+ }
150
+
151
+ function ColumnFloatingToolbar({ children }: React.PropsWithChildren) {
152
+ const editor = useEditorRef();
153
+ const readOnly = useReadOnly();
154
+ const element = useElement<TColumnElement>();
155
+ const { props: buttonProps } = useRemoveNodeButton({ element });
156
+ const selected = useSelected();
157
+ const isCollapsed = useEditorSelector(
158
+ (editor) => editor.api.isCollapsed(),
159
+ []
160
+ );
161
+ const isFocusedLast = useFocusedLast();
162
+
163
+ const open = isFocusedLast && !readOnly && selected && isCollapsed;
164
+
165
+ const onColumnChange = (widths: string[]) => {
166
+ setColumns(editor, {
167
+ at: element,
168
+ widths,
169
+ });
170
+ };
171
+
172
+ return (
173
+ <Popover open={open} modal={false}>
174
+ <PopoverAnchor>{children}</PopoverAnchor>
175
+ <PopoverContent
176
+ className="w-auto p-1"
177
+ onOpenAutoFocus={(e) => e.preventDefault()}
178
+ align="center"
179
+ side="top"
180
+ sideOffset={10}
181
+ >
182
+ <div className="box-content flex h-8 items-center">
183
+ <Button
184
+ variant="ghost"
185
+ className="size-8"
186
+ onClick={() => onColumnChange(['50%', '50%'])}
187
+ >
188
+ <DoubleColumnOutlined />
189
+ </Button>
190
+ <Button
191
+ variant="ghost"
192
+ className="size-8"
193
+ onClick={() => onColumnChange(['33%', '33%', '33%'])}
194
+ >
195
+ <ThreeColumnOutlined />
196
+ </Button>
197
+ <Button
198
+ variant="ghost"
199
+ className="size-8"
200
+ onClick={() => onColumnChange(['70%', '30%'])}
201
+ >
202
+ <RightSideDoubleColumnOutlined />
203
+ </Button>
204
+ <Button
205
+ variant="ghost"
206
+ className="size-8"
207
+ onClick={() => onColumnChange(['30%', '70%'])}
208
+ >
209
+ <LeftSideDoubleColumnOutlined />
210
+ </Button>
211
+ <Button
212
+ variant="ghost"
213
+ className="size-8"
214
+ onClick={() => onColumnChange(['25%', '50%', '25%'])}
215
+ >
216
+ <DoubleSideDoubleColumnOutlined />
217
+ </Button>
218
+
219
+ <Separator orientation="vertical" className="mx-1 h-6" />
220
+ <Button variant="ghost" className="size-8" {...buttonProps}>
221
+ <Trash2Icon />
222
+ </Button>
223
+ </div>
224
+ </PopoverContent>
225
+ </Popover>
226
+ );
227
+ }
228
+
229
+ const DoubleColumnOutlined = (props: LucideProps) => (
230
+ <svg
231
+ fill="none"
232
+ height="16"
233
+ viewBox="0 0 16 16"
234
+ width="16"
235
+ xmlns="http://www.w3.org/2000/svg"
236
+ {...props}
237
+ >
238
+ <path
239
+ clipRule="evenodd"
240
+ d="M8.5 3H13V13H8.5V3ZM7.5 2H8.5H13C13.5523 2 14 2.44772 14 3V13C14 13.5523 13.5523 14 13 14H8.5H7.5H3C2.44772 14 2 13.5523 2 13V3C2 2.44772 2.44772 2 3 2H7.5ZM7.5 13H3L3 3H7.5V13Z"
241
+ fill="currentColor"
242
+ fillRule="evenodd"
243
+ />
244
+ </svg>
245
+ );
246
+
247
+ const ThreeColumnOutlined = (props: LucideProps) => (
248
+ <svg
249
+ fill="none"
250
+ height="16"
251
+ viewBox="0 0 16 16"
252
+ width="16"
253
+ xmlns="http://www.w3.org/2000/svg"
254
+ {...props}
255
+ >
256
+ <path
257
+ clipRule="evenodd"
258
+ d="M9.25 3H6.75V13H9.25V3ZM9.25 2H6.75H5.75H3C2.44772 2 2 2.44772 2 3V13C2 13.5523 2.44772 14 3 14H5.75H6.75H9.25H10.25H13C13.5523 14 14 13.5523 14 13V3C14 2.44772 13.5523 2 13 2H10.25H9.25ZM10.25 3V13H13V3H10.25ZM3 13H5.75V3H3L3 13Z"
259
+ fill="currentColor"
260
+ fillRule="evenodd"
261
+ />
262
+ </svg>
263
+ );
264
+
265
+ const RightSideDoubleColumnOutlined = (props: LucideProps) => (
266
+ <svg
267
+ fill="none"
268
+ height="16"
269
+ viewBox="0 0 16 16"
270
+ width="16"
271
+ xmlns="http://www.w3.org/2000/svg"
272
+ {...props}
273
+ >
274
+ <path
275
+ clipRule="evenodd"
276
+ d="M11.25 3H13V13H11.25V3ZM10.25 2H11.25H13C13.5523 2 14 2.44772 14 3V13C14 13.5523 13.5523 14 13 14H11.25H10.25H3C2.44772 14 2 13.5523 2 13V3C2 2.44772 2.44772 2 3 2H10.25ZM10.25 13H3L3 3H10.25V13Z"
277
+ fill="currentColor"
278
+ fillRule="evenodd"
279
+ />
280
+ </svg>
281
+ );
282
+
283
+ const LeftSideDoubleColumnOutlined = (props: LucideProps) => (
284
+ <svg
285
+ fill="none"
286
+ height="16"
287
+ viewBox="0 0 16 16"
288
+ width="16"
289
+ xmlns="http://www.w3.org/2000/svg"
290
+ {...props}
291
+ >
292
+ <path
293
+ clipRule="evenodd"
294
+ d="M5.75 3H13V13H5.75V3ZM4.75 2H5.75H13C13.5523 2 14 2.44772 14 3V13C14 13.5523 13.5523 14 13 14H5.75H4.75H3C2.44772 14 2 13.5523 2 13V3C2 2.44772 2.44772 2 3 2H4.75ZM4.75 13H3L3 3H4.75V13Z"
295
+ fill="currentColor"
296
+ fillRule="evenodd"
297
+ />
298
+ </svg>
299
+ );
300
+
301
+ const DoubleSideDoubleColumnOutlined = (props: LucideProps) => (
302
+ <svg
303
+ fill="none"
304
+ height="16"
305
+ viewBox="0 0 16 16"
306
+ width="16"
307
+ xmlns="http://www.w3.org/2000/svg"
308
+ {...props}
309
+ >
310
+ <path
311
+ clipRule="evenodd"
312
+ d="M10.25 3H5.75V13H10.25V3ZM10.25 2H5.75H4.75H3C2.44772 2 2 2.44772 2 3V13C2 13.5523 2.44772 14 3 14H4.75H5.75H10.25H11.25H13C13.5523 14 14 13.5523 14 13V3C14 2.44772 13.5523 2 13 2H11.25H10.25ZM11.25 3V13H13V3H11.25ZM3 13H4.75V3H3L3 13Z"
313
+ fill="currentColor"
314
+ fillRule="evenodd"
315
+ />
316
+ </svg>
317
+ );
@@ -0,0 +1,182 @@
1
+ import * as React from "react"
2
+ import { Command as CommandPrimitive } from "cmdk"
3
+ import { SearchIcon } from "lucide-react"
4
+
5
+ import { cn } from "@/lib/utils"
6
+ import {
7
+ Dialog,
8
+ DialogContent,
9
+ DialogDescription,
10
+ DialogHeader,
11
+ DialogTitle,
12
+ } from "@/components/ui/dialog"
13
+
14
+ function Command({
15
+ className,
16
+ ...props
17
+ }: React.ComponentProps<typeof CommandPrimitive>) {
18
+ return (
19
+ <CommandPrimitive
20
+ data-slot="command"
21
+ className={cn(
22
+ "bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
23
+ className
24
+ )}
25
+ {...props}
26
+ />
27
+ )
28
+ }
29
+
30
+ function CommandDialog({
31
+ title = "Command Palette",
32
+ description = "Search for a command to run...",
33
+ children,
34
+ className,
35
+ showCloseButton = true,
36
+ ...props
37
+ }: React.ComponentProps<typeof Dialog> & {
38
+ title?: string
39
+ description?: string
40
+ className?: string
41
+ showCloseButton?: boolean
42
+ }) {
43
+ return (
44
+ <Dialog {...props}>
45
+ <DialogHeader className="sr-only">
46
+ <DialogTitle>{title}</DialogTitle>
47
+ <DialogDescription>{description}</DialogDescription>
48
+ </DialogHeader>
49
+ <DialogContent
50
+ className={cn("overflow-hidden p-0", className)}
51
+ showCloseButton={showCloseButton}
52
+ >
53
+ <Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
54
+ {children}
55
+ </Command>
56
+ </DialogContent>
57
+ </Dialog>
58
+ )
59
+ }
60
+
61
+ function CommandInput({
62
+ className,
63
+ ...props
64
+ }: React.ComponentProps<typeof CommandPrimitive.Input>) {
65
+ return (
66
+ <div
67
+ data-slot="command-input-wrapper"
68
+ className="flex h-9 items-center gap-2 border-b px-3"
69
+ >
70
+ <SearchIcon className="size-4 shrink-0 opacity-50" />
71
+ <CommandPrimitive.Input
72
+ data-slot="command-input"
73
+ className={cn(
74
+ "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
75
+ className
76
+ )}
77
+ {...props}
78
+ />
79
+ </div>
80
+ )
81
+ }
82
+
83
+ function CommandList({
84
+ className,
85
+ ...props
86
+ }: React.ComponentProps<typeof CommandPrimitive.List>) {
87
+ return (
88
+ <CommandPrimitive.List
89
+ data-slot="command-list"
90
+ className={cn(
91
+ "max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
92
+ className
93
+ )}
94
+ {...props}
95
+ />
96
+ )
97
+ }
98
+
99
+ function CommandEmpty({
100
+ ...props
101
+ }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
102
+ return (
103
+ <CommandPrimitive.Empty
104
+ data-slot="command-empty"
105
+ className="py-6 text-center text-sm"
106
+ {...props}
107
+ />
108
+ )
109
+ }
110
+
111
+ function CommandGroup({
112
+ className,
113
+ ...props
114
+ }: React.ComponentProps<typeof CommandPrimitive.Group>) {
115
+ return (
116
+ <CommandPrimitive.Group
117
+ data-slot="command-group"
118
+ className={cn(
119
+ "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
120
+ className
121
+ )}
122
+ {...props}
123
+ />
124
+ )
125
+ }
126
+
127
+ function CommandSeparator({
128
+ className,
129
+ ...props
130
+ }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
131
+ return (
132
+ <CommandPrimitive.Separator
133
+ data-slot="command-separator"
134
+ className={cn("bg-border -mx-1 h-px", className)}
135
+ {...props}
136
+ />
137
+ )
138
+ }
139
+
140
+ function CommandItem({
141
+ className,
142
+ ...props
143
+ }: React.ComponentProps<typeof CommandPrimitive.Item>) {
144
+ return (
145
+ <CommandPrimitive.Item
146
+ data-slot="command-item"
147
+ className={cn(
148
+ "data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
149
+ className
150
+ )}
151
+ {...props}
152
+ />
153
+ )
154
+ }
155
+
156
+ function CommandShortcut({
157
+ className,
158
+ ...props
159
+ }: React.ComponentProps<"span">) {
160
+ return (
161
+ <span
162
+ data-slot="command-shortcut"
163
+ className={cn(
164
+ "text-muted-foreground ml-auto text-xs tracking-widest",
165
+ className
166
+ )}
167
+ {...props}
168
+ />
169
+ )
170
+ }
171
+
172
+ export {
173
+ Command,
174
+ CommandDialog,
175
+ CommandInput,
176
+ CommandList,
177
+ CommandEmpty,
178
+ CommandGroup,
179
+ CommandItem,
180
+ CommandShortcut,
181
+ CommandSeparator,
182
+ }
@@ -0,0 +1,15 @@
1
+ import type { TCommentText } from 'platejs';
2
+ import type { SlateLeafProps } from 'platejs/static';
3
+
4
+ import { SlateLeaf } from 'platejs/static';
5
+
6
+ export function CommentLeafStatic(props: SlateLeafProps<TCommentText>) {
7
+ return (
8
+ <SlateLeaf
9
+ {...props}
10
+ className="border-b-2 border-b-highlight/35 bg-highlight/15"
11
+ >
12
+ {props.children}
13
+ </SlateLeaf>
14
+ );
15
+ }
@@ -0,0 +1,45 @@
1
+
2
+
3
+ import type { TCommentText } from 'platejs';
4
+ import type { PlateLeafProps } from 'platejs/react';
5
+
6
+ import { getCommentCount } from '@platejs/comment';
7
+ import { PlateLeaf, useEditorPlugin, usePluginOption } from 'platejs/react';
8
+
9
+ import { cn } from '@/lib/utils';
10
+ import { commentPlugin } from '@/components/editor/plugins/comment-kit';
11
+
12
+ export function CommentLeaf(props: PlateLeafProps<TCommentText>) {
13
+ const { children, leaf } = props;
14
+
15
+ const { api, setOption } = useEditorPlugin(commentPlugin);
16
+ const hoverId = usePluginOption(commentPlugin, 'hoverId');
17
+ const activeId = usePluginOption(commentPlugin, 'activeId');
18
+
19
+ const isOverlapping = getCommentCount(leaf) > 1;
20
+ const currentId = api.comment.nodeId(leaf);
21
+ const isActive = activeId === currentId;
22
+ const isHover = hoverId === currentId;
23
+
24
+ return (
25
+ <PlateLeaf
26
+ {...props}
27
+ className={cn(
28
+ 'border-b-2 border-b-highlight/[.36] bg-highlight/[.13] transition-colors duration-200',
29
+ (isHover || isActive) && 'border-b-highlight bg-highlight/25',
30
+ isOverlapping && 'border-b-2 border-b-highlight/[.7] bg-highlight/25',
31
+ (isHover || isActive) &&
32
+ isOverlapping &&
33
+ 'border-b-highlight bg-highlight/45'
34
+ )}
35
+ attributes={{
36
+ ...props.attributes,
37
+ onClick: () => setOption('activeId', currentId ?? null),
38
+ onMouseEnter: () => setOption('hoverId', currentId ?? null),
39
+ onMouseLeave: () => setOption('hoverId', null),
40
+ }}
41
+ >
42
+ {children}
43
+ </PlateLeaf>
44
+ );
45
+ }
@@ -0,0 +1,24 @@
1
+
2
+
3
+ import { MessageSquareTextIcon } from 'lucide-react';
4
+ import { useEditorRef } from 'platejs/react';
5
+
6
+ import { commentPlugin } from '@/components/editor/plugins/comment-kit';
7
+
8
+ import { ToolbarButton } from './toolbar';
9
+
10
+ export function CommentToolbarButton() {
11
+ const editor = useEditorRef();
12
+
13
+ return (
14
+ <ToolbarButton
15
+ onClick={() => {
16
+ editor.getTransforms(commentPlugin).comment.setDraft();
17
+ }}
18
+ data-plate-prevent-overlay
19
+ tooltip="Comment"
20
+ >
21
+ <MessageSquareTextIcon />
22
+ </ToolbarButton>
23
+ );
24
+ }