@placeholderco/placeholder-ui 1.0.12 → 2.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 (278) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +134 -130
  3. package/dist/app.css +178 -0
  4. package/dist/bootstrap.min.css +3600 -0
  5. package/dist/cards/GitCard.svelte +115 -0
  6. package/dist/cards/GitCard.svelte.d.ts +22 -0
  7. package/dist/display/Avatar.svelte +29 -17
  8. package/dist/display/Avatar.svelte.d.ts +12 -2
  9. package/dist/display/LinkCollection.svelte +40 -18
  10. package/dist/display/LinkCollection.svelte.d.ts +9 -2
  11. package/dist/display/Paper.svelte +31 -19
  12. package/dist/display/Paper.svelte.d.ts +12 -3
  13. package/dist/display/alert/Alert.svelte +129 -0
  14. package/dist/display/alert/Alert.svelte.d.ts +15 -0
  15. package/dist/display/alert/AlertVariant.d.ts +1 -0
  16. package/dist/display/alert/AlertVariant.js +1 -0
  17. package/dist/display/filetree/FileTree.svelte +259 -0
  18. package/dist/display/filetree/FileTree.svelte.d.ts +76 -0
  19. package/dist/display/filetree/FileTreeItem.svelte +396 -0
  20. package/dist/display/filetree/FileTreeItem.svelte.d.ts +40 -0
  21. package/dist/display/filetree/FileTreeNode.d.ts +46 -0
  22. package/dist/display/filetree/FileTreeNode.js +115 -0
  23. package/dist/display/filetree/index.d.ts +5 -0
  24. package/dist/display/filetree/index.js +3 -0
  25. package/dist/editors/CodeMirror.svelte +306 -0
  26. package/dist/editors/CodeMirror.svelte.d.ts +31 -0
  27. package/dist/editors/tiptap/LinkActionMenu.svelte +307 -0
  28. package/dist/editors/tiptap/LinkActionMenu.svelte.d.ts +8 -0
  29. package/dist/editors/tiptap/TipTap.svelte +856 -0
  30. package/dist/editors/tiptap/TipTap.svelte.d.ts +54 -0
  31. package/dist/editors/tiptap/TipTapBubble.svelte +790 -0
  32. package/dist/editors/tiptap/TipTapBubble.svelte.d.ts +44 -0
  33. package/dist/editors/tiptap/collaboration.d.ts +55 -0
  34. package/dist/editors/tiptap/collaboration.js +1 -0
  35. package/dist/editors/tiptap/extensions/Alert.d.ts +18 -0
  36. package/dist/editors/tiptap/extensions/Alert.js +72 -0
  37. package/dist/editors/tiptap/extensions/CodeBlockEditor.d.ts +21 -0
  38. package/dist/editors/tiptap/extensions/CodeBlockEditor.js +326 -0
  39. package/dist/editors/tiptap/extensions/Div.d.ts +19 -0
  40. package/dist/editors/tiptap/extensions/Div.js +89 -0
  41. package/dist/editors/tiptap/extensions/Span.d.ts +5 -0
  42. package/dist/editors/tiptap/extensions/Span.js +56 -0
  43. package/dist/editors/tiptap/extensions/codeBlockEditor.css +236 -0
  44. package/dist/editors/tiptap/extensions/codeBlockLanguages.d.ts +17 -0
  45. package/dist/editors/tiptap/extensions/codeBlockLanguages.js +124 -0
  46. package/dist/editors/tiptap/extensions/index.d.ts +7 -0
  47. package/dist/editors/tiptap/extensions/index.js +5 -0
  48. package/dist/editors/tiptap/toolbar/AlertButton.svelte +261 -0
  49. package/dist/editors/tiptap/toolbar/AlertButton.svelte.d.ts +7 -0
  50. package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte +18 -0
  51. package/dist/editors/tiptap/toolbar/AlignCenterButton.svelte.d.ts +7 -0
  52. package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte +18 -0
  53. package/dist/editors/tiptap/toolbar/AlignJustifyButton.svelte.d.ts +7 -0
  54. package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte +18 -0
  55. package/dist/editors/tiptap/toolbar/AlignLeftButton.svelte.d.ts +7 -0
  56. package/dist/editors/tiptap/toolbar/AlignRightButton.svelte +18 -0
  57. package/dist/editors/tiptap/toolbar/AlignRightButton.svelte.d.ts +7 -0
  58. package/dist/editors/tiptap/toolbar/BoldButton.svelte +18 -0
  59. package/dist/editors/tiptap/toolbar/BoldButton.svelte.d.ts +7 -0
  60. package/dist/editors/tiptap/toolbar/BulletListButton.svelte +18 -0
  61. package/dist/editors/tiptap/toolbar/BulletListButton.svelte.d.ts +7 -0
  62. package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte +18 -0
  63. package/dist/editors/tiptap/toolbar/CodeBlockButton.svelte.d.ts +7 -0
  64. package/dist/editors/tiptap/toolbar/CodeButton.svelte +18 -0
  65. package/dist/editors/tiptap/toolbar/CodeButton.svelte.d.ts +7 -0
  66. package/dist/editors/tiptap/toolbar/ColorButton.svelte +299 -0
  67. package/dist/editors/tiptap/toolbar/ColorButton.svelte.d.ts +20 -0
  68. package/dist/editors/tiptap/toolbar/DocumentButton.svelte +58 -0
  69. package/dist/editors/tiptap/toolbar/DocumentButton.svelte.d.ts +9 -0
  70. package/dist/editors/tiptap/toolbar/HeadingButton.svelte +30 -0
  71. package/dist/editors/tiptap/toolbar/HeadingButton.svelte.d.ts +8 -0
  72. package/dist/editors/tiptap/toolbar/HtmlButton.svelte +68 -0
  73. package/dist/editors/tiptap/toolbar/HtmlButton.svelte.d.ts +7 -0
  74. package/dist/editors/tiptap/toolbar/ImageButton.svelte +54 -0
  75. package/dist/editors/tiptap/toolbar/ImageButton.svelte.d.ts +8 -0
  76. package/dist/editors/tiptap/toolbar/ItalicButton.svelte +18 -0
  77. package/dist/editors/tiptap/toolbar/ItalicButton.svelte.d.ts +7 -0
  78. package/dist/editors/tiptap/toolbar/LinkButton.svelte +257 -0
  79. package/dist/editors/tiptap/toolbar/LinkButton.svelte.d.ts +7 -0
  80. package/dist/editors/tiptap/toolbar/OrderedListButton.svelte +18 -0
  81. package/dist/editors/tiptap/toolbar/OrderedListButton.svelte.d.ts +7 -0
  82. package/dist/editors/tiptap/toolbar/RedoButton.svelte +18 -0
  83. package/dist/editors/tiptap/toolbar/RedoButton.svelte.d.ts +7 -0
  84. package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte +18 -0
  85. package/dist/editors/tiptap/toolbar/StrikethroughButton.svelte.d.ts +7 -0
  86. package/dist/editors/tiptap/toolbar/SubscriptButton.svelte +18 -0
  87. package/dist/editors/tiptap/toolbar/SubscriptButton.svelte.d.ts +7 -0
  88. package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte +18 -0
  89. package/dist/editors/tiptap/toolbar/SuperscriptButton.svelte.d.ts +7 -0
  90. package/dist/editors/tiptap/toolbar/TableButton.svelte +258 -0
  91. package/dist/editors/tiptap/toolbar/TableButton.svelte.d.ts +7 -0
  92. package/dist/editors/tiptap/toolbar/ToolbarButton.svelte +84 -0
  93. package/dist/editors/tiptap/toolbar/ToolbarButton.svelte.d.ts +10 -0
  94. package/dist/editors/tiptap/toolbar/UnderlineButton.svelte +18 -0
  95. package/dist/editors/tiptap/toolbar/UnderlineButton.svelte.d.ts +7 -0
  96. package/dist/editors/tiptap/toolbar/UndoButton.svelte +18 -0
  97. package/dist/editors/tiptap/toolbar/UndoButton.svelte.d.ts +7 -0
  98. package/dist/form/Autocomplete.svelte +86 -135
  99. package/dist/form/Autocomplete.svelte.d.ts +6 -8
  100. package/dist/form/AutocompleteMulti.svelte +385 -227
  101. package/dist/form/AutocompleteMulti.svelte.d.ts +59 -10
  102. package/dist/form/Checkbox.svelte +59 -54
  103. package/dist/form/Checkbox.svelte.d.ts +14 -5
  104. package/dist/form/Chips.svelte +29 -13
  105. package/dist/form/Chips.svelte.d.ts +16 -2
  106. package/dist/form/ColorPicker.svelte +957 -0
  107. package/dist/form/ColorPicker.svelte.d.ts +78 -0
  108. package/dist/form/ComboBox.svelte +30 -20
  109. package/dist/form/ComboBox.svelte.d.ts +1 -1
  110. package/dist/form/ComboBoxItemBuilder.svelte +161 -188
  111. package/dist/form/ComboBoxItemBuilder.svelte.d.ts +19 -2
  112. package/dist/form/ComboBoxMulti.svelte +38 -24
  113. package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
  114. package/dist/form/CronBuilder.svelte +84 -67
  115. package/dist/form/CronBuilder.svelte.d.ts +16 -3
  116. package/dist/form/DatePicker.svelte +148 -195
  117. package/dist/form/DateRangePicker.svelte +101 -98
  118. package/dist/form/DateTimePicker.svelte +167 -208
  119. package/dist/form/DateTimePicker.svelte.d.ts +10 -2
  120. package/dist/form/FormGroup.svelte +33 -10
  121. package/dist/form/FormGroup.svelte.d.ts +12 -2
  122. package/dist/form/Number.svelte +70 -47
  123. package/dist/form/Number.svelte.d.ts +36 -6
  124. package/dist/form/Radio.svelte +18 -18
  125. package/dist/form/RadioGroup.svelte +23 -12
  126. package/dist/form/RadioGroup.svelte.d.ts +13 -2
  127. package/dist/form/SegmentedControl.svelte +76 -56
  128. package/dist/form/SegmentedControl.svelte.d.ts +9 -4
  129. package/dist/form/Select.svelte +150 -233
  130. package/dist/form/Select.svelte.d.ts +29 -5
  131. package/dist/form/SelectMulti.svelte +163 -277
  132. package/dist/form/SelectMulti.svelte.d.ts +36 -7
  133. package/dist/form/Slider.svelte +183 -269
  134. package/dist/form/Slider.svelte.d.ts +32 -17
  135. package/dist/form/StringArrayBuilder.svelte +249 -0
  136. package/dist/form/StringArrayBuilder.svelte.d.ts +15 -0
  137. package/dist/form/Switch.svelte +164 -106
  138. package/dist/form/Switch.svelte.d.ts +22 -3
  139. package/dist/form/TextArea.svelte +49 -29
  140. package/dist/form/TextArea.svelte.d.ts +23 -3
  141. package/dist/form/Textbox.svelte +69 -68
  142. package/dist/form/Textbox.svelte.d.ts +32 -4
  143. package/dist/form/TimePicker.svelte +42 -47
  144. package/dist/form/TimePicker.svelte.d.ts +12 -2
  145. package/dist/form/comboBoxCore.svelte.d.ts +99 -0
  146. package/dist/form/comboBoxCore.svelte.js +243 -0
  147. package/dist/icon/Icon.svelte +8 -3
  148. package/dist/icon/Icon.svelte.d.ts +8 -3
  149. package/dist/icon/file-type-bmp.svg +1 -0
  150. package/dist/icon/file-type-csv.svg +1 -0
  151. package/dist/icon/file-type-doc.svg +1 -0
  152. package/dist/icon/file-type-docx.svg +1 -0
  153. package/dist/icon/file-type-jpg.svg +1 -0
  154. package/dist/icon/file-type-pdf.svg +1 -0
  155. package/dist/icon/file-type-png.svg +1 -0
  156. package/dist/icon/file-type-ppt.svg +1 -0
  157. package/dist/icon/file-type-svg.svg +1 -0
  158. package/dist/icon/file-type-txt.svg +1 -0
  159. package/dist/icon/file-type-xls.svg +1 -0
  160. package/dist/icon/file-type-zip.svg +1 -0
  161. package/dist/icon/index.d.ts +166 -151
  162. package/dist/icon/index.js +166 -152
  163. package/dist/icon/logo-placeholder.svg +6 -0
  164. package/dist/icon/source-code.svg +1 -0
  165. package/dist/icon/sun-moon.svg +1 -0
  166. package/dist/icon/table.svg +6 -0
  167. package/dist/index.d.ts +146 -82
  168. package/dist/index.js +77 -78
  169. package/dist/layout/AppShell.svelte +12 -162
  170. package/dist/layout/AppShell.svelte.d.ts +6 -27
  171. package/dist/layout/CustomNavbar.svelte +9 -7
  172. package/dist/layout/CustomNavbar.svelte.d.ts +4 -2
  173. package/dist/layout/Navbar.svelte +161 -129
  174. package/dist/layout/Navbar.svelte.d.ts +29 -15
  175. package/dist/layout/NavbarItemDisplay.svelte +2 -2
  176. package/dist/layout/NavbarItemView.svelte +182 -0
  177. package/dist/layout/NavbarItemView.svelte.d.ts +10 -0
  178. package/dist/layout/Sidenav.svelte +280 -341
  179. package/dist/layout/Sidenav.svelte.d.ts +36 -4
  180. package/dist/models/ComboBoxItem.d.ts +2 -0
  181. package/dist/models/Employee.d.ts +53 -0
  182. package/dist/models/Employee.js +23 -0
  183. package/dist/models/Hyperlink.d.ts +3 -1
  184. package/dist/models/LinkCollectionItem.d.ts +3 -1
  185. package/dist/models/NavbarItem.d.ts +6 -2
  186. package/dist/theme.svelte.d.ts +0 -1
  187. package/dist/theme.svelte.js +46 -58
  188. package/dist/ui/Accordion.svelte +81 -242
  189. package/dist/ui/Accordion.svelte.d.ts +37 -14
  190. package/dist/ui/AccordionItem.svelte +303 -0
  191. package/dist/ui/AccordionItem.svelte.d.ts +21 -0
  192. package/dist/ui/ActionIcon.svelte +25 -21
  193. package/dist/ui/ActionIcon.svelte.d.ts +15 -2
  194. package/dist/ui/Badge.svelte +163 -171
  195. package/dist/ui/Badge.svelte.d.ts +13 -5
  196. package/dist/ui/Button.svelte +178 -205
  197. package/dist/ui/Button.svelte.d.ts +19 -2
  198. package/dist/ui/ButtonVariant.d.ts +15 -1
  199. package/dist/ui/ContextMenu.svelte +146 -0
  200. package/dist/ui/ContextMenu.svelte.d.ts +37 -0
  201. package/dist/ui/ContextMenuList.svelte +188 -0
  202. package/dist/ui/ContextMenuList.svelte.d.ts +12 -0
  203. package/dist/ui/Dialog.svelte +183 -111
  204. package/dist/ui/Dialog.svelte.d.ts +21 -4
  205. package/dist/ui/Drawer.svelte +237 -184
  206. package/dist/ui/Drawer.svelte.d.ts +20 -2
  207. package/dist/ui/Dropdown.svelte +24 -14
  208. package/dist/ui/Dropdown.svelte.d.ts +11 -2
  209. package/dist/ui/Dropzone.svelte +159 -57
  210. package/dist/ui/Dropzone.svelte.d.ts +29 -2
  211. package/dist/ui/Link.svelte +12 -4
  212. package/dist/ui/Link.svelte.d.ts +8 -2
  213. package/dist/ui/Loader.svelte +23 -18
  214. package/dist/ui/Loader.svelte.d.ts +5 -2
  215. package/dist/ui/Logo.svelte +37 -0
  216. package/dist/ui/Logo.svelte.d.ts +16 -0
  217. package/dist/ui/MultiSortable.svelte +287 -0
  218. package/dist/ui/MultiSortable.svelte.d.ts +50 -0
  219. package/dist/ui/Pagination.svelte +15 -9
  220. package/dist/ui/Pagination.svelte.d.ts +6 -2
  221. package/dist/ui/Popover.svelte +43 -65
  222. package/dist/ui/Popover.svelte.d.ts +14 -5
  223. package/dist/ui/ProgressBar.svelte +28 -30
  224. package/dist/ui/ProgressBarVariant.d.ts +7 -1
  225. package/dist/ui/SegmentedControl.svelte +0 -0
  226. package/dist/ui/SegmentedControl.svelte.d.ts +26 -0
  227. package/dist/ui/Sortable.svelte +163 -0
  228. package/dist/ui/Sortable.svelte.d.ts +47 -0
  229. package/dist/ui/Table.svelte +383 -80
  230. package/dist/ui/Table.svelte.d.ts +43 -2
  231. package/dist/ui/Tabs.svelte +22 -18
  232. package/dist/ui/Tabs.svelte.d.ts +6 -2
  233. package/dist/ui/ThemeSwitcher.svelte +26 -7
  234. package/dist/ui/ThemeSwitcher.svelte.d.ts +4 -2
  235. package/dist/ui/Tooltip.svelte +312 -180
  236. package/dist/ui/Tooltip.svelte.d.ts +4 -3
  237. package/dist/uiTheme.svelte.d.ts +86 -0
  238. package/dist/uiTheme.svelte.js +214 -0
  239. package/dist/util/DateFunctions.js +1 -1
  240. package/dist/util/DragDrop.d.ts +50 -0
  241. package/dist/util/DragDrop.js +154 -0
  242. package/dist/util/NavigateTo.js +2 -2
  243. package/dist/util/dayjs.d.ts +4 -0
  244. package/dist/util/dayjs.js +15 -0
  245. package/package.json +66 -26
  246. package/dist/display/Alert.svelte +0 -179
  247. package/dist/display/Alert.svelte.d.ts +0 -13
  248. package/dist/form/FileInput.svelte +0 -235
  249. package/dist/form/FileInput.svelte.d.ts +0 -23
  250. package/dist/form/PasswordInput.svelte +0 -253
  251. package/dist/form/PasswordInput.svelte.d.ts +0 -34
  252. package/dist/form/Rating.svelte +0 -235
  253. package/dist/form/Rating.svelte.d.ts +0 -21
  254. package/dist/styles/components.css +0 -199
  255. package/dist/styles/dark.css +0 -146
  256. package/dist/styles/index.css +0 -116
  257. package/dist/styles/reset.css +0 -110
  258. package/dist/styles/semantic.css +0 -86
  259. package/dist/styles/tokens.css +0 -203
  260. package/dist/styles/utilities.css +0 -523
  261. package/dist/ui/Breadcrumbs.svelte +0 -131
  262. package/dist/ui/Breadcrumbs.svelte.d.ts +0 -16
  263. package/dist/ui/LoadingOverlay.svelte +0 -53
  264. package/dist/ui/LoadingOverlay.svelte.d.ts +0 -11
  265. package/dist/ui/Progress.svelte +0 -191
  266. package/dist/ui/Progress.svelte.d.ts +0 -15
  267. package/dist/ui/RingProgress.svelte +0 -141
  268. package/dist/ui/RingProgress.svelte.d.ts +0 -18
  269. package/dist/ui/Skeleton.svelte +0 -85
  270. package/dist/ui/Skeleton.svelte.d.ts +0 -12
  271. package/dist/ui/Stepper.svelte +0 -355
  272. package/dist/ui/Stepper.svelte.d.ts +0 -24
  273. package/dist/ui/Timeline.svelte +0 -225
  274. package/dist/ui/Timeline.svelte.d.ts +0 -23
  275. /package/dist/{actions → util}/ClickOutside.d.ts +0 -0
  276. /package/dist/{actions → util}/ClickOutside.js +0 -0
  277. /package/dist/{transitions → util}/Transitions.d.ts +0 -0
  278. /package/dist/{transitions → util}/Transitions.js +0 -0
@@ -0,0 +1,44 @@
1
+ import { type AnyExtension } from '@tiptap/core';
2
+ import { type CodeBlocksOptions } from './extensions/index.js';
3
+ import type { CollaborationConfig } from './collaboration.js';
4
+ export interface TipTapBubbleProps {
5
+ /** HTML content value (bindable). Ignored when collaboration is enabled. */
6
+ value?: string;
7
+ /** Label text displayed above the editor */
8
+ label?: string;
9
+ /** Mark field as required (shows asterisk) */
10
+ required?: boolean;
11
+ /** CSS classes for the FormGroup wrapper */
12
+ groupClass?: string;
13
+ /** Tooltip text on hover */
14
+ tooltipText?: string;
15
+ /** Position of the tooltip */
16
+ tooltipLocation?: 'top' | 'bottom' | 'left' | 'right';
17
+ /** Enable editing mode */
18
+ editable?: boolean;
19
+ /** Placeholder text when editor is empty */
20
+ placeholder?: string;
21
+ /** Additional CSS classes */
22
+ class?: string;
23
+ /** Async handler for image uploads, returns URL or null */
24
+ onImageUpload?: (file: File) => Promise<string | null>;
25
+ /** Callback when content changes */
26
+ onUpdate?: (html: string) => void;
27
+ /** Opt-in real-time collaboration config. When provided, content syncs via Yjs. */
28
+ collaboration?: CollaborationConfig;
29
+ /** Opt-in rich code blocks: CodeMirror-powered editing with syntax highlighting,
30
+ * autocompletion and a per-block language picker. Pass true for all languages
31
+ * or a config to narrow the offered languages and set the default. */
32
+ codeBlocks?: boolean | CodeBlocksOptions;
33
+ /** Additional TipTap extensions to register with the editor */
34
+ extensions?: AnyExtension[];
35
+ }
36
+ declare const TipTapBubble: import("svelte").Component<TipTapBubbleProps, {
37
+ getHTML: () => string;
38
+ getJSON: () => object;
39
+ setContent: (html: string) => void;
40
+ clear: () => void;
41
+ focus: () => void;
42
+ }, "value">;
43
+ type TipTapBubble = ReturnType<typeof TipTapBubble>;
44
+ export default TipTapBubble;
@@ -0,0 +1,55 @@
1
+ import type { XmlFragment } from 'yjs';
2
+ /** User identity shown on remote collaboration cursors. */
3
+ export interface CollaborationUser {
4
+ /** Display name shown on the cursor label */
5
+ name: string;
6
+ /** 6-digit hex color for the cursor and selection highlight (e.g. `'#f59e0b'`). Must be hex format — HSL, RGB, and named colors are not supported. */
7
+ color: `#${string}`;
8
+ }
9
+ /**
10
+ * Configuration for real-time collaborative editing.
11
+ *
12
+ * **Required peer dependencies** (install in your app):
13
+ * - `yjs` — CRDT document model
14
+ * - A Yjs network provider such as `y-websocket`, `y-webrtc`, or `@hocuspocus/provider`
15
+ *
16
+ * **Usage:**
17
+ * ```ts
18
+ * import * as Y from 'yjs';
19
+ * import { WebsocketProvider } from 'y-websocket';
20
+ *
21
+ * const ydoc = new Y.Doc();
22
+ * const provider = new WebsocketProvider('wss://your-server.com', 'room-id', ydoc);
23
+ *
24
+ * const collaboration = {
25
+ * fragment: ydoc.getXmlFragment('content'),
26
+ * provider,
27
+ * user: { name: 'Alice', color: '#f59e0b' }
28
+ * };
29
+ * ```
30
+ *
31
+ * **Notes:**
32
+ * - When collaboration is enabled, the `value` prop is ignored — Yjs is the source of truth.
33
+ * - The built-in undo/redo is replaced by Yjs collaborative history.
34
+ * - Your app is responsible for managing the provider lifecycle (connect/disconnect).
35
+ */
36
+ export interface CollaborationConfig {
37
+ /**
38
+ * A Yjs XML fragment to sync editor content.
39
+ *
40
+ * Create with `ydoc.getXmlFragment('content')`. All clients sharing
41
+ * the same Y.Doc and fragment name will see each other's edits.
42
+ */
43
+ fragment: XmlFragment;
44
+ /**
45
+ * A Yjs provider instance that handles network transport.
46
+ *
47
+ * Common choices:
48
+ * - `WebsocketProvider` from `y-websocket` (requires a WebSocket server)
49
+ * - `WebrtcProvider` from `y-webrtc` (peer-to-peer, no server)
50
+ * - `HocuspocusProvider` from `@hocuspocus/provider` (TipTap's managed solution)
51
+ */
52
+ provider: any;
53
+ /** Current user info displayed on remote cursors */
54
+ user: CollaborationUser;
55
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import { Node } from '@tiptap/core';
2
+ export interface AlertOptions {
3
+ HTMLAttributes: Record<string, any>;
4
+ }
5
+ declare module '@tiptap/core' {
6
+ interface Commands<ReturnType> {
7
+ alert: {
8
+ /**
9
+ * Insert an alert block
10
+ */
11
+ setAlert: (attributes?: {
12
+ variant?: string;
13
+ title?: string;
14
+ }) => ReturnType;
15
+ };
16
+ }
17
+ }
18
+ export declare const Alert: Node<AlertOptions, any>;
@@ -0,0 +1,72 @@
1
+ import { Node, mergeAttributes } from '@tiptap/core';
2
+ export const Alert = Node.create({
3
+ name: 'alert',
4
+ group: 'block',
5
+ content: 'block+',
6
+ defining: true,
7
+ addAttributes() {
8
+ return {
9
+ variant: {
10
+ default: 'default',
11
+ parseHTML: (element) => element.getAttribute('data-variant'),
12
+ renderHTML: (attributes) => {
13
+ return {
14
+ 'data-variant': attributes.variant,
15
+ };
16
+ },
17
+ },
18
+ title: {
19
+ default: 'Alert',
20
+ parseHTML: (element) => element.getAttribute('data-title'),
21
+ renderHTML: (attributes) => {
22
+ return {
23
+ 'data-title': attributes.title,
24
+ };
25
+ },
26
+ },
27
+ };
28
+ },
29
+ parseHTML() {
30
+ return [
31
+ {
32
+ tag: 'div[data-type="alert"]',
33
+ },
34
+ ];
35
+ },
36
+ renderHTML({ HTMLAttributes }) {
37
+ return [
38
+ 'div',
39
+ mergeAttributes(HTMLAttributes, {
40
+ 'data-type': 'alert',
41
+ class: `alert alert-${HTMLAttributes['data-variant'] || 'default'}`,
42
+ }),
43
+ [
44
+ 'div',
45
+ { class: 'alert-title', 'data-title-element': 'true' },
46
+ HTMLAttributes['data-title'] || 'Alert',
47
+ ],
48
+ ['div', { class: 'alert-content' }, 0],
49
+ ];
50
+ },
51
+ addCommands() {
52
+ return {
53
+ setAlert: (attributes) => ({ commands }) => {
54
+ return commands.insertContent({
55
+ type: this.name,
56
+ attrs: attributes,
57
+ content: [
58
+ {
59
+ type: 'paragraph',
60
+ content: [
61
+ {
62
+ type: 'text',
63
+ text: 'Enter your alert message here...',
64
+ },
65
+ ],
66
+ },
67
+ ],
68
+ });
69
+ },
70
+ };
71
+ },
72
+ });
@@ -0,0 +1,21 @@
1
+ import { type CodeBlockOptions } from '@tiptap/extension-code-block';
2
+ import { type CodeBlockLanguageId } from './codeBlockLanguages.js';
3
+ import './codeBlockEditor.css';
4
+ /** Configuration accepted by the `codeBlocks` prop on TipTap / TipTapBubble */
5
+ export interface CodeBlocksOptions {
6
+ /** Languages offered in the code block language picker (default: all registered) */
7
+ languages?: CodeBlockLanguageId[];
8
+ /** Language applied to newly inserted code blocks (default 'javascript') */
9
+ defaultLanguage?: CodeBlockLanguageId;
10
+ }
11
+ export interface CodeBlockEditorOptions extends CodeBlockOptions {
12
+ /** Language ids offered in the picker; null offers every registered language */
13
+ languages: CodeBlockLanguageId[] | null;
14
+ }
15
+ /**
16
+ * CodeBlock extension whose blocks are full CodeMirror editors: syntax
17
+ * highlighting, autocompletion, bracket matching and smart indentation, with a
18
+ * per-block language picker. Serializes to standard
19
+ * `<pre><code class="language-...">` HTML, so content round-trips unchanged.
20
+ */
21
+ export declare const CodeBlockEditor: import("@tiptap/core").Node<CodeBlockEditorOptions, any>;
@@ -0,0 +1,326 @@
1
+ import { CodeBlock } from '@tiptap/extension-code-block';
2
+ import { Selection, TextSelection } from '@tiptap/pm/state';
3
+ import { exitCode } from '@tiptap/pm/commands';
4
+ import { EditorView as CodeMirrorView, drawSelection, keymap } from '@codemirror/view';
5
+ import { Compartment, EditorState as CodeMirrorState } from '@codemirror/state';
6
+ import { defaultKeymap, indentWithTab } from '@codemirror/commands';
7
+ import { autocompletion, closeBrackets, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
8
+ import { bracketMatching, indentOnInput, syntaxHighlighting } from '@codemirror/language';
9
+ import { classHighlighter } from '@lezer/highlight';
10
+ import { codeBlockLanguages, resolveCodeBlockLanguage } from './codeBlockLanguages.js';
11
+ import './codeBlockEditor.css';
12
+ /**
13
+ * Renders each code block as an embedded CodeMirror editor, following the
14
+ * ProseMirror codemirror node view pattern: CodeMirror owns the block's text and
15
+ * selection while focused, and every change is forwarded to ProseMirror so the
16
+ * document (and collaboration/undo) stay authoritative.
17
+ */
18
+ class CodeBlockView {
19
+ dom;
20
+ node;
21
+ editor;
22
+ getPos;
23
+ cm;
24
+ select;
25
+ languageCompartment = new Compartment();
26
+ updating = false;
27
+ constructor(node, editor, getPos, languages) {
28
+ this.node = node;
29
+ this.editor = editor;
30
+ this.getPos = getPos;
31
+ const editable = editor.isEditable;
32
+ this.cm = new CodeMirrorView({
33
+ doc: node.textContent,
34
+ extensions: [
35
+ keymap.of([
36
+ ...closeBracketsKeymap,
37
+ ...completionKeymap,
38
+ ...this.codeMirrorKeymap(),
39
+ ...defaultKeymap,
40
+ indentWithTab
41
+ ]),
42
+ drawSelection(),
43
+ syntaxHighlighting(classHighlighter),
44
+ bracketMatching(),
45
+ closeBrackets(),
46
+ autocompletion(),
47
+ indentOnInput(),
48
+ CodeMirrorView.lineWrapping,
49
+ this.languageCompartment.of(this.languageExtension()),
50
+ CodeMirrorView.editable.of(editable),
51
+ CodeMirrorState.readOnly.of(!editable),
52
+ CodeMirrorView.updateListener.of((update) => this.forwardUpdate(update))
53
+ ]
54
+ });
55
+ this.select = this.buildLanguageSelect(languages, editable);
56
+ this.dom = document.createElement('div');
57
+ this.dom.className = 'code-block-editor';
58
+ this.dom.appendChild(this.select);
59
+ this.dom.appendChild(this.cm.dom);
60
+ }
61
+ // The ProseMirror view is looked up lazily because node views are constructed
62
+ // while the outer view itself is still being created.
63
+ get view() {
64
+ return this.editor.view;
65
+ }
66
+ languageExtension() {
67
+ return resolveCodeBlockLanguage(this.node.attrs.language)?.load() ?? [];
68
+ }
69
+ buildLanguageSelect(languages, editable) {
70
+ const select = document.createElement('select');
71
+ select.className = 'code-block-language';
72
+ select.setAttribute('aria-label', 'Code language');
73
+ select.contentEditable = 'false';
74
+ for (const def of languages) {
75
+ const option = document.createElement('option');
76
+ option.value = def.id;
77
+ option.textContent = def.label;
78
+ select.appendChild(option);
79
+ }
80
+ select.disabled = !editable;
81
+ this.syncSelect(select);
82
+ select.addEventListener('change', () => {
83
+ const pos = this.getPos();
84
+ if (pos === undefined)
85
+ return;
86
+ this.view.dispatch(this.view.state.tr.setNodeMarkup(pos, undefined, {
87
+ ...this.node.attrs,
88
+ language: select.value
89
+ }));
90
+ this.cm.focus();
91
+ });
92
+ return select;
93
+ }
94
+ // Reflect the node's language in the picker, adding a fallback option for
95
+ // languages present in parsed content but missing from the configured list.
96
+ syncSelect(select = this.select) {
97
+ const raw = this.node.attrs.language;
98
+ const current = resolveCodeBlockLanguage(raw)?.id ?? raw ?? 'plaintext';
99
+ if (![...select.options].some((option) => option.value === current)) {
100
+ const option = document.createElement('option');
101
+ option.value = current;
102
+ option.textContent = current;
103
+ select.appendChild(option);
104
+ }
105
+ select.value = current;
106
+ }
107
+ // Map CodeMirror document/selection changes onto the ProseMirror document.
108
+ forwardUpdate(update) {
109
+ if (this.updating || !this.cm.hasFocus)
110
+ return;
111
+ const pos = this.getPos();
112
+ if (pos === undefined)
113
+ return;
114
+ let offset = pos + 1;
115
+ const { main } = update.state.selection;
116
+ const selFrom = offset + main.from;
117
+ const selTo = offset + main.to;
118
+ const pmSelection = this.view.state.selection;
119
+ if (update.docChanged || pmSelection.from !== selFrom || pmSelection.to !== selTo) {
120
+ const tr = this.view.state.tr;
121
+ update.changes.iterChanges((fromA, toA, fromB, toB, text) => {
122
+ if (text.length) {
123
+ tr.replaceWith(offset + fromA, offset + toA, this.view.state.schema.text(text.toString()));
124
+ }
125
+ else {
126
+ tr.delete(offset + fromA, offset + toA);
127
+ }
128
+ offset += toB - fromB - (toA - fromA);
129
+ });
130
+ tr.setSelection(TextSelection.create(tr.doc, selFrom, selTo));
131
+ this.view.dispatch(tr);
132
+ }
133
+ }
134
+ codeMirrorKeymap() {
135
+ return [
136
+ { key: 'ArrowUp', run: () => this.maybeEscape('line', -1) },
137
+ { key: 'ArrowLeft', run: () => this.maybeEscape('char', -1) },
138
+ { key: 'ArrowDown', run: () => this.maybeEscape('line', 1) },
139
+ { key: 'ArrowRight', run: () => this.maybeEscape('char', 1) },
140
+ { key: 'Escape', run: () => this.escape() },
141
+ {
142
+ key: 'Mod-Enter',
143
+ run: () => {
144
+ if (!exitCode(this.view.state, this.view.dispatch))
145
+ return false;
146
+ this.view.focus();
147
+ return true;
148
+ }
149
+ },
150
+ { key: 'Backspace', run: () => this.removeWhenEmpty() },
151
+ { key: 'Mod-z', run: () => this.editor.commands.undo() },
152
+ { key: 'Mod-y', run: () => this.editor.commands.redo() },
153
+ { key: 'Shift-Mod-z', run: () => this.editor.commands.redo() }
154
+ ];
155
+ }
156
+ // Move the selection out of the block when an arrow key is pressed at its edge.
157
+ maybeEscape(unit, dir) {
158
+ const { state } = this.cm;
159
+ const { main } = state.selection;
160
+ if (!main.empty)
161
+ return false;
162
+ if (unit === 'line') {
163
+ const line = state.doc.lineAt(main.head);
164
+ if (dir < 0 ? line.from > 0 : line.to < state.doc.length)
165
+ return false;
166
+ }
167
+ else if (dir < 0 ? main.from > 0 : main.to < state.doc.length) {
168
+ return false;
169
+ }
170
+ const pos = this.getPos();
171
+ if (pos === undefined)
172
+ return false;
173
+ const after = pos + this.node.nodeSize;
174
+ // Arrowing down out of a trailing code block: create a paragraph to land in.
175
+ if (dir > 0 && unit === 'line' && after >= this.view.state.doc.content.size) {
176
+ const paragraph = this.view.state.schema.nodes.paragraph.createAndFill();
177
+ if (!paragraph)
178
+ return false;
179
+ const tr = this.view.state.tr.insert(after, paragraph);
180
+ tr.setSelection(TextSelection.create(tr.doc, after + 1));
181
+ this.view.dispatch(tr.scrollIntoView());
182
+ this.view.focus();
183
+ return true;
184
+ }
185
+ const selection = Selection.near(this.view.state.doc.resolve(dir < 0 ? pos : after), dir);
186
+ this.view.dispatch(this.view.state.tr.setSelection(selection).scrollIntoView());
187
+ this.view.focus();
188
+ return true;
189
+ }
190
+ escape() {
191
+ const pos = this.getPos();
192
+ if (pos === undefined)
193
+ return false;
194
+ const selection = Selection.near(this.view.state.doc.resolve(pos + this.node.nodeSize), 1);
195
+ this.view.dispatch(this.view.state.tr.setSelection(selection).scrollIntoView());
196
+ this.view.focus();
197
+ return true;
198
+ }
199
+ // Backspace in an empty block converts it back to a paragraph.
200
+ removeWhenEmpty() {
201
+ if (this.cm.state.doc.length > 0)
202
+ return false;
203
+ const pos = this.getPos();
204
+ if (pos === undefined)
205
+ return false;
206
+ const paragraph = this.view.state.schema.nodes.paragraph.createAndFill();
207
+ if (!paragraph)
208
+ return false;
209
+ const tr = this.view.state.tr.replaceWith(pos, pos + this.node.nodeSize, paragraph);
210
+ tr.setSelection(TextSelection.create(tr.doc, pos + 1));
211
+ this.view.dispatch(tr);
212
+ this.view.focus();
213
+ return true;
214
+ }
215
+ // Apply external changes (undo, collaboration, setContent) to CodeMirror.
216
+ update(node) {
217
+ if (node.type !== this.node.type)
218
+ return false;
219
+ const previousLanguage = this.node.attrs.language;
220
+ this.node = node;
221
+ if (node.attrs.language !== previousLanguage) {
222
+ this.syncSelect();
223
+ this.cm.dispatch({
224
+ effects: this.languageCompartment.reconfigure(this.languageExtension())
225
+ });
226
+ }
227
+ const newText = node.textContent;
228
+ const currentText = this.cm.state.doc.toString();
229
+ if (newText !== currentText) {
230
+ let start = 0;
231
+ let currentEnd = currentText.length;
232
+ let newEnd = newText.length;
233
+ while (start < currentEnd &&
234
+ start < newEnd &&
235
+ currentText.charCodeAt(start) === newText.charCodeAt(start)) {
236
+ start++;
237
+ }
238
+ while (currentEnd > start &&
239
+ newEnd > start &&
240
+ currentText.charCodeAt(currentEnd - 1) === newText.charCodeAt(newEnd - 1)) {
241
+ currentEnd--;
242
+ newEnd--;
243
+ }
244
+ this.updating = true;
245
+ this.cm.dispatch({
246
+ changes: { from: start, to: currentEnd, insert: newText.slice(start, newEnd) }
247
+ });
248
+ this.updating = false;
249
+ }
250
+ return true;
251
+ }
252
+ setSelection(anchor, head) {
253
+ this.cm.focus();
254
+ this.updating = true;
255
+ this.cm.dispatch({ selection: { anchor, head } });
256
+ this.updating = false;
257
+ }
258
+ selectNode() {
259
+ this.cm.focus();
260
+ }
261
+ stopEvent() {
262
+ return true;
263
+ }
264
+ ignoreMutation() {
265
+ return true;
266
+ }
267
+ destroy() {
268
+ this.cm.destroy();
269
+ }
270
+ }
271
+ // Let arrow keys move the cursor from an adjacent textblock into a code block;
272
+ // ProseMirror can't do this itself because the block's content lives in CodeMirror.
273
+ function arrowIntoCodeBlock(direction) {
274
+ return ({ editor }) => {
275
+ const { state, view } = editor;
276
+ if (!state.selection.empty || !view.endOfTextblock(direction))
277
+ return false;
278
+ const side = direction === 'left' || direction === 'up' ? -1 : 1;
279
+ const { $head } = state.selection;
280
+ try {
281
+ const nextPos = Selection.near(state.doc.resolve(side > 0 ? $head.after() : $head.before()), side);
282
+ if (nextPos.$head && nextPos.$head.parent.type.name === 'codeBlock') {
283
+ view.dispatch(state.tr.setSelection(nextPos));
284
+ return true;
285
+ }
286
+ }
287
+ catch {
288
+ // selection sits at the document boundary — nothing to move into
289
+ }
290
+ return false;
291
+ };
292
+ }
293
+ /**
294
+ * CodeBlock extension whose blocks are full CodeMirror editors: syntax
295
+ * highlighting, autocompletion, bracket matching and smart indentation, with a
296
+ * per-block language picker. Serializes to standard
297
+ * `<pre><code class="language-...">` HTML, so content round-trips unchanged.
298
+ */
299
+ export const CodeBlockEditor = CodeBlock.extend({
300
+ addOptions() {
301
+ const parent = this.parent?.() ?? {};
302
+ return {
303
+ ...parent,
304
+ defaultLanguage: 'javascript',
305
+ languages: null
306
+ };
307
+ },
308
+ addKeyboardShortcuts() {
309
+ return {
310
+ ...this.parent?.(),
311
+ ArrowLeft: arrowIntoCodeBlock('left'),
312
+ ArrowRight: arrowIntoCodeBlock('right'),
313
+ ArrowUp: arrowIntoCodeBlock('up'),
314
+ ArrowDown: arrowIntoCodeBlock('down')
315
+ };
316
+ },
317
+ addNodeView() {
318
+ const configured = this.options.languages;
319
+ const languages = configured
320
+ ? configured
321
+ .map((id) => resolveCodeBlockLanguage(id))
322
+ .filter((def) => Boolean(def))
323
+ : codeBlockLanguages;
324
+ return ({ node, editor, getPos }) => new CodeBlockView(node, editor, getPos, languages);
325
+ }
326
+ });
@@ -0,0 +1,19 @@
1
+ import { Node } from '@tiptap/core';
2
+ export interface DivOptions {
3
+ HTMLAttributes: Record<string, any>;
4
+ }
5
+ declare module '@tiptap/core' {
6
+ interface Commands<ReturnType> {
7
+ div: {
8
+ /**
9
+ * Set the current node as a div
10
+ */
11
+ setDiv: () => ReturnType;
12
+ /**
13
+ * Toggle between div and paragraph
14
+ */
15
+ toggleDiv: () => ReturnType;
16
+ };
17
+ }
18
+ }
19
+ export declare const Div: Node<DivOptions, any>;
@@ -0,0 +1,89 @@
1
+ import { Node, mergeAttributes } from '@tiptap/core';
2
+ export const Div = Node.create({
3
+ name: 'div',
4
+ group: 'block',
5
+ content: 'block*',
6
+ isolating: false,
7
+ defining: false,
8
+ addOptions() {
9
+ return {
10
+ HTMLAttributes: {},
11
+ };
12
+ },
13
+ parseHTML() {
14
+ return [
15
+ {
16
+ tag: 'div',
17
+ // Preserve all attributes
18
+ getAttrs: (node) => {
19
+ if (typeof node === 'string')
20
+ return false;
21
+ const element = node;
22
+ // Skip if it's an alert or other custom node with data-type
23
+ if (element.getAttribute('data-type'))
24
+ return false;
25
+ // Preserve all attributes
26
+ const attrs = {};
27
+ Array.from(element.attributes).forEach(attr => {
28
+ attrs[attr.name] = attr.value;
29
+ });
30
+ return attrs;
31
+ },
32
+ },
33
+ ];
34
+ },
35
+ renderHTML({ HTMLAttributes }) {
36
+ return ['div', mergeAttributes(this.options.HTMLAttributes, HTMLAttributes), 0];
37
+ },
38
+ addCommands() {
39
+ return {
40
+ setDiv: () => ({ commands }) => {
41
+ return commands.setNode(this.name);
42
+ },
43
+ toggleDiv: () => ({ commands }) => {
44
+ return commands.toggleNode(this.name, 'paragraph');
45
+ },
46
+ };
47
+ },
48
+ addAttributes() {
49
+ return {
50
+ // Preserve all HTML attributes
51
+ class: {
52
+ default: null,
53
+ parseHTML: element => element.getAttribute('class'),
54
+ renderHTML: attributes => {
55
+ if (!attributes.class)
56
+ return {};
57
+ return { class: attributes.class };
58
+ },
59
+ },
60
+ style: {
61
+ default: null,
62
+ parseHTML: element => element.getAttribute('style'),
63
+ renderHTML: attributes => {
64
+ if (!attributes.style)
65
+ return {};
66
+ return { style: attributes.style };
67
+ },
68
+ },
69
+ id: {
70
+ default: null,
71
+ parseHTML: element => element.getAttribute('id'),
72
+ renderHTML: attributes => {
73
+ if (!attributes.id)
74
+ return {};
75
+ return { id: attributes.id };
76
+ },
77
+ },
78
+ 'data-type': {
79
+ default: null,
80
+ parseHTML: element => element.getAttribute('data-type'),
81
+ renderHTML: attributes => {
82
+ if (!attributes['data-type'])
83
+ return {};
84
+ return { 'data-type': attributes['data-type'] };
85
+ },
86
+ },
87
+ };
88
+ },
89
+ });
@@ -0,0 +1,5 @@
1
+ import { Node } from '@tiptap/core';
2
+ export interface SpanOptions {
3
+ HTMLAttributes: Record<string, any>;
4
+ }
5
+ export declare const Span: Node<SpanOptions, any>;