@teriusu/rich-editor 0.4.1

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 (90) hide show
  1. package/README.md +178 -0
  2. package/dist/components/BubbleToolbar.svelte +299 -0
  3. package/dist/components/BubbleToolbar.svelte.d.ts +9 -0
  4. package/dist/components/BubbleToolbar.svelte.d.ts.map +1 -0
  5. package/dist/components/FixedToolbar.svelte +892 -0
  6. package/dist/components/FixedToolbar.svelte.d.ts +11 -0
  7. package/dist/components/FixedToolbar.svelte.d.ts.map +1 -0
  8. package/dist/components/InputModal.svelte +102 -0
  9. package/dist/components/InputModal.svelte.d.ts +11 -0
  10. package/dist/components/InputModal.svelte.d.ts.map +1 -0
  11. package/dist/components/PdfViewer.svelte +152 -0
  12. package/dist/components/PdfViewer.svelte.d.ts +8 -0
  13. package/dist/components/PdfViewer.svelte.d.ts.map +1 -0
  14. package/dist/components/SlashCommandMenu.svelte +315 -0
  15. package/dist/components/SlashCommandMenu.svelte.d.ts +14 -0
  16. package/dist/components/SlashCommandMenu.svelte.d.ts.map +1 -0
  17. package/dist/components/TableBubbleMenu.svelte +472 -0
  18. package/dist/components/TableBubbleMenu.svelte.d.ts +8 -0
  19. package/dist/components/TableBubbleMenu.svelte.d.ts.map +1 -0
  20. package/dist/components/TipTapEditor.svelte +649 -0
  21. package/dist/components/TipTapEditor.svelte.d.ts +17 -0
  22. package/dist/components/TipTapEditor.svelte.d.ts.map +1 -0
  23. package/dist/extensions/Column.d.ts +3 -0
  24. package/dist/extensions/Column.d.ts.map +1 -0
  25. package/dist/extensions/Column.js +20 -0
  26. package/dist/extensions/Columns.d.ts +11 -0
  27. package/dist/extensions/Columns.d.ts.map +1 -0
  28. package/dist/extensions/Columns.js +103 -0
  29. package/dist/extensions/Columns.test.d.ts +2 -0
  30. package/dist/extensions/Columns.test.d.ts.map +1 -0
  31. package/dist/extensions/Columns.test.js +62 -0
  32. package/dist/extensions/FileAttachment.d.ts +24 -0
  33. package/dist/extensions/FileAttachment.d.ts.map +1 -0
  34. package/dist/extensions/FileAttachment.js +190 -0
  35. package/dist/extensions/FileAttachment.test.d.ts +2 -0
  36. package/dist/extensions/FileAttachment.test.d.ts.map +1 -0
  37. package/dist/extensions/FileAttachment.test.js +63 -0
  38. package/dist/extensions/FixedDetails.d.ts +2 -0
  39. package/dist/extensions/FixedDetails.d.ts.map +1 -0
  40. package/dist/extensions/FixedDetails.js +100 -0
  41. package/dist/extensions/FixedDetails.test.d.ts +2 -0
  42. package/dist/extensions/FixedDetails.test.d.ts.map +1 -0
  43. package/dist/extensions/FixedDetails.test.js +40 -0
  44. package/dist/extensions/Indent.d.ts +11 -0
  45. package/dist/extensions/Indent.d.ts.map +1 -0
  46. package/dist/extensions/Indent.js +87 -0
  47. package/dist/extensions/Indent.test.d.ts +2 -0
  48. package/dist/extensions/Indent.test.d.ts.map +1 -0
  49. package/dist/extensions/Indent.test.js +78 -0
  50. package/dist/extensions/PdfBlock.d.ts +3 -0
  51. package/dist/extensions/PdfBlock.d.ts.map +1 -0
  52. package/dist/extensions/PdfBlock.js +301 -0
  53. package/dist/extensions/PdfBlock.test.d.ts +2 -0
  54. package/dist/extensions/PdfBlock.test.d.ts.map +1 -0
  55. package/dist/extensions/PdfBlock.test.js +51 -0
  56. package/dist/extensions/VideoBlock.d.ts +16 -0
  57. package/dist/extensions/VideoBlock.d.ts.map +1 -0
  58. package/dist/extensions/VideoBlock.js +87 -0
  59. package/dist/extensions/VideoBlock.test.d.ts +2 -0
  60. package/dist/extensions/VideoBlock.test.d.ts.map +1 -0
  61. package/dist/extensions/VideoBlock.test.js +54 -0
  62. package/dist/index.d.ts +20 -0
  63. package/dist/index.d.ts.map +1 -0
  64. package/dist/index.js +20 -0
  65. package/dist/styles/editor.css +698 -0
  66. package/dist/types.d.ts +44 -0
  67. package/dist/types.d.ts.map +1 -0
  68. package/dist/types.js +1 -0
  69. package/dist/utils/cn.d.ts +3 -0
  70. package/dist/utils/cn.d.ts.map +1 -0
  71. package/dist/utils/cn.js +5 -0
  72. package/dist/utils/cn.test.d.ts +2 -0
  73. package/dist/utils/cn.test.d.ts.map +1 -0
  74. package/dist/utils/cn.test.js +28 -0
  75. package/dist/utils/escape-html.d.ts +2 -0
  76. package/dist/utils/escape-html.d.ts.map +1 -0
  77. package/dist/utils/escape-html.js +7 -0
  78. package/dist/utils/escape-html.test.d.ts +2 -0
  79. package/dist/utils/escape-html.test.d.ts.map +1 -0
  80. package/dist/utils/escape-html.test.js +25 -0
  81. package/dist/utils/pdf.d.ts +9 -0
  82. package/dist/utils/pdf.d.ts.map +1 -0
  83. package/dist/utils/pdf.js +33 -0
  84. package/dist/utils/sanitize.d.ts +9 -0
  85. package/dist/utils/sanitize.d.ts.map +1 -0
  86. package/dist/utils/sanitize.js +115 -0
  87. package/dist/utils/sanitize.test.d.ts +2 -0
  88. package/dist/utils/sanitize.test.d.ts.map +1 -0
  89. package/dist/utils/sanitize.test.js +206 -0
  90. package/package.json +76 -0
package/README.md ADDED
@@ -0,0 +1,178 @@
1
+ # @teriusu/rich-editor
2
+
3
+ TipTap v3 기반 리치 텍스트 에디터. Svelte 5 컴포넌트 라이브러리.
4
+
5
+ ## 설치
6
+
7
+ ```bash
8
+ npm install @teriusu/rich-editor
9
+ ```
10
+
11
+ Tailwind CSS v4 사용 시 `@source` 추가:
12
+ ```css
13
+ @import "@teriusu/rich-editor/styles";
14
+ @source "../node_modules/@teriusu/rich-editor/dist";
15
+ ```
16
+
17
+ ## 기본 사용법
18
+
19
+ ```svelte
20
+ <script>
21
+ import { TipTapEditor } from '@teriusu/rich-editor';
22
+ import '@teriusu/rich-editor/styles';
23
+
24
+ let html = $state('');
25
+ </script>
26
+
27
+ <TipTapEditor
28
+ content={html}
29
+ onChange={(h) => html = h}
30
+ onUploadFile={async (file) => {
31
+ const form = new FormData();
32
+ form.append('file', file);
33
+ const res = await fetch('/api/upload', { method: 'POST', body: form });
34
+ const { url } = await res.json();
35
+ return url;
36
+ }}
37
+ />
38
+ ```
39
+
40
+ ## Props
41
+
42
+ | Prop | 타입 | 기본값 | 설명 |
43
+ |------|------|--------|------|
44
+ | `content` | `string` | `""` | HTML 콘텐츠 |
45
+ | `onChange` | `(html: string) => void` | 필수 | 콘텐츠 변경 콜백 |
46
+ | `placeholder` | `string` | `"'/'를 눌러..."` | 플레이스홀더 |
47
+ | `onUploadFile` | `(file: File) => Promise<string>` | - | 파일 업로드 핸들러 (URL 반환) |
48
+ | `onResolveFile` | `(fileId: string) => Promise<{src, name?, size?}>` | - | 파일 ID → URL 변환 |
49
+ | `extensions` | `AnyExtension[]` | `[]` | 추가 TipTap 확장 주입 |
50
+ | `editable` | `boolean` | `true` | 읽기 전용 모드 |
51
+
52
+ ## 파일 저장 방식
53
+
54
+ ### URL 직접 (기본)
55
+
56
+ `onUploadFile`만 제공하면 파일 URL이 HTML에 직접 저장됩니다.
57
+
58
+ ```html
59
+ <div data-file-src="/files/report.pdf" data-file-name="report.pdf" data-file-size="204800"></div>
60
+ ```
61
+
62
+ ### ID 기반 (하이브리드)
63
+
64
+ `onResolveFile`을 추가하면 파일 ID + 캐시 URL이 함께 저장됩니다.
65
+
66
+ ```svelte
67
+ <TipTapEditor
68
+ content={html}
69
+ onChange={(h) => html = h}
70
+ onUploadFile={async (file) => {
71
+ const res = await fetch('/api/upload', { method: 'POST', body: file });
72
+ return await res.json(); // { id, url, name, size }
73
+ }}
74
+ onResolveFile={async (fileId) => {
75
+ const res = await fetch(`/api/files/${fileId}`);
76
+ return await res.json(); // { src, name, size }
77
+ }}
78
+ />
79
+ ```
80
+
81
+ ```html
82
+ <div data-file-id="abc123" data-file-src="/files/report.pdf" data-file-name="report.pdf"></div>
83
+ ```
84
+
85
+ ID 기반은 URL이 변경되어도 대응 가능하고, 권한 제어(signed URL)에 활용할 수 있습니다.
86
+
87
+ ## 기능
88
+
89
+ ### 텍스트 서식
90
+ Bold, Italic, Underline, Strikethrough, Highlight, Superscript, Subscript, 텍스트 색상
91
+
92
+ ### 구조
93
+ 제목 (H1~H3), 글머리/번호 목록, 체크리스트, 인용문, 구분선, 접기/펼치기 (Details), 들여쓰기 (Tab/Shift-Tab)
94
+
95
+ ### 미디어
96
+ 이미지, PDF (PDF.js 캔버스 렌더링), 영상 파일 (mp4/webm), YouTube, 파일 첨부, 드래그 앤 드롭 업로드
97
+
98
+ ### 레이아웃
99
+ 2단/3단 컬럼, 텍스트 정렬 (좌/중/우)
100
+
101
+ ### 테이블
102
+ 삽입, 행/열 추가/삭제, 헤더 토글, 셀 병합/분할, 셀 배경색, 열 리사이즈
103
+
104
+ ### 입력
105
+ `/` 슬래시 커맨드, 고정 툴바, 테이블 버블 메뉴, Undo/Redo
106
+
107
+ ## 레거시 HTML 호환
108
+
109
+ TipTap v2 커스텀 태그를 자동 변환합니다. 에디터 로드 시 `transformLegacyHtml`이 자동 호출됩니다.
110
+
111
+ | 레거시 태그 | 변환 결과 |
112
+ |---|---|
113
+ | `<tiptap-file id="X">` | `<div data-file-id="X">` |
114
+ | `<tiptap-midibus id="X">` | iframe (play.mbus.tv) |
115
+ | `<tiptap-collapsable title="X">` | `<details><summary>` |
116
+ | `<lite-youtube videoid="X">` | YouTube iframe |
117
+ | `<embed type="application/pdf">` | `<div data-pdf-src>` |
118
+ | `<div class="tiptap-columns">` | `<div data-type="columns">` |
119
+ | `margin-left: 40px` | indent level 1 (em 출력) |
120
+
121
+ 게시물 조회 페이지(읽기 전용)에서도 적용:
122
+
123
+ ```js
124
+ import { transformLegacyHtml } from '@teriusu/rich-editor';
125
+
126
+ const html = transformLegacyHtml(post.content);
127
+ ```
128
+
129
+ ## 커스텀 확장 주입
130
+
131
+ `extensions` prop으로 호스트 앱 전용 확장을 주입할 수 있습니다.
132
+
133
+ ```svelte
134
+ <script>
135
+ import { TipTapEditor } from '@teriusu/rich-editor';
136
+ import { Node } from '@tiptap/core';
137
+
138
+ const MyExtension = Node.create({ /* ... */ });
139
+ </script>
140
+
141
+ <TipTapEditor
142
+ content={html}
143
+ onChange={handleChange}
144
+ extensions={[MyExtension]}
145
+ />
146
+ ```
147
+
148
+ ## Exports
149
+
150
+ ### 컴포넌트
151
+ `TipTapEditor`, `FixedToolbar`, `BubbleToolbar`, `SlashCommandMenu`, `TableBubbleMenu`, `InputModal`, `PdfViewer`
152
+
153
+ ### 확장
154
+ `PdfBlock`, `FileAttachment`, `VideoBlock`, `Columns`, `Column`, `Indent`, `FixedDetails`
155
+
156
+ ### 유틸리티
157
+ `transformLegacyHtml`, `sanitizeHtml`, `stripHtmlToExcerpt`, `configurePdfJs`, `getPdfJs`, `cn`
158
+
159
+ ### 타입
160
+ `UploadHandler`, `FileResolver`, `FileResolveResult`, `TipTapEditorProps`, `SlashMenuItem`
161
+
162
+ ## 빌드
163
+
164
+ ```bash
165
+ npm run build # svelte-package → dist/
166
+ npm version patch # 버전 올리기
167
+ ```
168
+
169
+ ## 기술 스택
170
+
171
+ | 구분 | 기술 |
172
+ |------|------|
173
+ | 에디터 엔진 | TipTap v3 |
174
+ | UI | Svelte 5 (runes) |
175
+ | 언어 | TypeScript |
176
+ | 빌드 | svelte-package |
177
+ | 아이콘 | lucide-svelte |
178
+ | 스타일 | Tailwind CSS + CSS 변수 |
@@ -0,0 +1,299 @@
1
+ <script lang="ts">
2
+ import type { Editor } from "@tiptap/core";
3
+ import { BubbleMenuPlugin } from "@tiptap/extension-bubble-menu";
4
+ import { PluginKey } from "@tiptap/pm/state";
5
+ import { onMount } from "svelte";
6
+
7
+ const bubbleToolbarKey = new PluginKey("bubbleToolbar");
8
+ import {
9
+ Bold,
10
+ Italic,
11
+ Underline as UnderlineIcon,
12
+ Strikethrough,
13
+ Highlighter,
14
+ LinkIcon,
15
+ AlignLeft,
16
+ AlignCenter,
17
+ AlignRight,
18
+ Heading1,
19
+ Heading2,
20
+ Heading3,
21
+ Type,
22
+ Code,
23
+ } from "lucide-svelte";
24
+ import { cn } from "../utils/cn";
25
+
26
+ let { editor, minimal = false }: { editor: Editor; minimal?: boolean } = $props();
27
+
28
+ let showHeadings = $state(false);
29
+ let menuEl: HTMLDivElement | undefined = $state();
30
+ const iconSize = 14;
31
+
32
+ function getCurrentBlockLabel(): string {
33
+ if (editor.isActive("heading", { level: 1 })) return "제목 1";
34
+ if (editor.isActive("heading", { level: 2 })) return "제목 2";
35
+ if (editor.isActive("heading", { level: 3 })) return "제목 3";
36
+ return "본문";
37
+ }
38
+
39
+ function addLink() {
40
+ const previousUrl = editor.getAttributes("link").href || "";
41
+ const url = window.prompt("링크 URL을 입력하세요", previousUrl);
42
+ if (url === null) return;
43
+ if (url === "") {
44
+ editor.chain().focus().extendMarkRange("link").unsetLink().run();
45
+ } else {
46
+ editor
47
+ .chain()
48
+ .focus()
49
+ .extendMarkRange("link")
50
+ .setLink({ href: url })
51
+ .run();
52
+ }
53
+ }
54
+
55
+ onMount(() => {
56
+ if (!menuEl) return;
57
+
58
+ const plugin = BubbleMenuPlugin({
59
+ pluginKey: bubbleToolbarKey,
60
+ editor,
61
+ element: menuEl,
62
+ shouldShow: ({ editor: e, state }) => {
63
+ const { from, to } = state.selection;
64
+ if (from === to) return false;
65
+ if (e.isActive("codeBlock")) return false;
66
+ if (e.isActive("image")) return false;
67
+ return true;
68
+ },
69
+ tippyOptions: {
70
+ placement: "top",
71
+ },
72
+ });
73
+
74
+ editor.registerPlugin(plugin);
75
+
76
+ return () => {
77
+ editor.unregisterPlugin(bubbleToolbarKey);
78
+ };
79
+ });
80
+ </script>
81
+
82
+ <div bind:this={menuEl} class="bubble-toolbar-container" style="visibility: hidden">
83
+ <div class="flex items-center gap-0.5 px-1.5 py-1 bg-foreground rounded-lg shadow-xl">
84
+ {#if !minimal}
85
+ <!-- Block type selector -->
86
+ <div class="relative">
87
+ <button
88
+ type="button"
89
+ onclick={() => (showHeadings = !showHeadings)}
90
+ class="flex items-center gap-1 px-2 py-1.5 rounded-md text-xs font-medium text-white/80 hover:text-white hover:bg-white/10 transition-colors"
91
+ >
92
+ <Type size={12} />
93
+ {getCurrentBlockLabel()}
94
+ </button>
95
+ {#if showHeadings}
96
+ <div
97
+ class="absolute bottom-full left-0 mb-1 bg-foreground rounded-lg shadow-xl border border-white/10 py-1"
98
+ style="min-width: 120px"
99
+ >
100
+ <button
101
+ type="button"
102
+ class={cn(
103
+ "w-full flex items-center gap-2 px-3 py-1.5 text-xs transition-colors",
104
+ !editor.isActive("heading")
105
+ ? "text-white bg-white/10"
106
+ : "text-white/70 hover:text-white hover:bg-white/10",
107
+ )}
108
+ onclick={() => {
109
+ editor.chain().focus().setParagraph().run();
110
+ showHeadings = false;
111
+ }}
112
+ >
113
+ <Type size={12} /> 본문
114
+ </button>
115
+ {#each [1, 2, 3] as level}
116
+ {@const Icon = level === 1 ? Heading1 : level === 2 ? Heading2 : Heading3}
117
+ <button
118
+ type="button"
119
+ class={cn(
120
+ "w-full flex items-center gap-2 px-3 py-1.5 text-xs transition-colors",
121
+ editor.isActive("heading", { level })
122
+ ? "text-white bg-white/10"
123
+ : "text-white/70 hover:text-white hover:bg-white/10",
124
+ )}
125
+ onclick={() => {
126
+ editor
127
+ .chain()
128
+ .focus()
129
+ .toggleHeading({ level: level as 1 | 2 | 3 })
130
+ .run();
131
+ showHeadings = false;
132
+ }}
133
+ >
134
+ <Icon size={12} /> 제목 {level}
135
+ </button>
136
+ {/each}
137
+ </div>
138
+ {/if}
139
+ </div>
140
+
141
+ <div class="w-px h-5 bg-white/20 mx-0.5"></div>
142
+ {/if}
143
+
144
+ <!-- Format buttons -->
145
+ <button
146
+ type="button"
147
+ onclick={() => editor.chain().focus().toggleBold().run()}
148
+ title="굵게"
149
+ aria-label="굵게"
150
+ class={cn(
151
+ "p-1.5 rounded-md transition-colors",
152
+ editor.isActive("bold")
153
+ ? "bg-white/20 text-white"
154
+ : "text-white/70 hover:text-white hover:bg-white/10",
155
+ )}
156
+ >
157
+ <Bold size={iconSize} />
158
+ </button>
159
+ <button
160
+ type="button"
161
+ onclick={() => editor.chain().focus().toggleItalic().run()}
162
+ title="기울임"
163
+ aria-label="기울임"
164
+ class={cn(
165
+ "p-1.5 rounded-md transition-colors",
166
+ editor.isActive("italic")
167
+ ? "bg-white/20 text-white"
168
+ : "text-white/70 hover:text-white hover:bg-white/10",
169
+ )}
170
+ >
171
+ <Italic size={iconSize} />
172
+ </button>
173
+ {#if !minimal}
174
+ <button
175
+ type="button"
176
+ onclick={() => editor.chain().focus().toggleUnderline().run()}
177
+ title="밑줄"
178
+ aria-label="밑줄"
179
+ class={cn(
180
+ "p-1.5 rounded-md transition-colors",
181
+ editor.isActive("underline")
182
+ ? "bg-white/20 text-white"
183
+ : "text-white/70 hover:text-white hover:bg-white/10",
184
+ )}
185
+ >
186
+ <UnderlineIcon size={iconSize} />
187
+ </button>
188
+ {/if}
189
+ <button
190
+ type="button"
191
+ onclick={() => editor.chain().focus().toggleStrike().run()}
192
+ title="취소선"
193
+ aria-label="취소선"
194
+ class={cn(
195
+ "p-1.5 rounded-md transition-colors",
196
+ editor.isActive("strike")
197
+ ? "bg-white/20 text-white"
198
+ : "text-white/70 hover:text-white hover:bg-white/10",
199
+ )}
200
+ >
201
+ <Strikethrough size={iconSize} />
202
+ </button>
203
+ {#if !minimal}
204
+ <button
205
+ type="button"
206
+ onclick={() => editor.chain().focus().toggleHighlight().run()}
207
+ title="하이라이트"
208
+ aria-label="하이라이트"
209
+ class={cn(
210
+ "p-1.5 rounded-md transition-colors",
211
+ editor.isActive("highlight")
212
+ ? "bg-white/20 text-white"
213
+ : "text-white/70 hover:text-white hover:bg-white/10",
214
+ )}
215
+ >
216
+ <Highlighter size={iconSize} />
217
+ </button>
218
+ {/if}
219
+ <button
220
+ type="button"
221
+ onclick={() => editor.chain().focus().toggleCode().run()}
222
+ title="코드"
223
+ aria-label="코드"
224
+ class={cn(
225
+ "p-1.5 rounded-md transition-colors",
226
+ editor.isActive("code")
227
+ ? "bg-white/20 text-white"
228
+ : "text-white/70 hover:text-white hover:bg-white/10",
229
+ )}
230
+ >
231
+ <Code size={iconSize} />
232
+ </button>
233
+
234
+ <div class="w-px h-5 bg-white/20 mx-0.5"></div>
235
+
236
+ <button
237
+ type="button"
238
+ onclick={addLink}
239
+ title="링크"
240
+ aria-label="링크"
241
+ class={cn(
242
+ "p-1.5 rounded-md transition-colors",
243
+ editor.isActive("link")
244
+ ? "bg-white/20 text-white"
245
+ : "text-white/70 hover:text-white hover:bg-white/10",
246
+ )}
247
+ >
248
+ <LinkIcon size={iconSize} />
249
+ </button>
250
+
251
+ {#if !minimal}
252
+ <div class="w-px h-5 bg-white/20 mx-0.5"></div>
253
+
254
+ <!-- Alignment -->
255
+ <button
256
+ type="button"
257
+ onclick={() => editor.chain().focus().setTextAlign("left").run()}
258
+ title="왼쪽 정렬"
259
+ aria-label="왼쪽 정렬"
260
+ class={cn(
261
+ "p-1.5 rounded-md transition-colors",
262
+ editor.isActive({ textAlign: "left" })
263
+ ? "bg-white/20 text-white"
264
+ : "text-white/70 hover:text-white hover:bg-white/10",
265
+ )}
266
+ >
267
+ <AlignLeft size={iconSize} />
268
+ </button>
269
+ <button
270
+ type="button"
271
+ onclick={() => editor.chain().focus().setTextAlign("center").run()}
272
+ title="가운데 정렬"
273
+ aria-label="가운데 정렬"
274
+ class={cn(
275
+ "p-1.5 rounded-md transition-colors",
276
+ editor.isActive({ textAlign: "center" })
277
+ ? "bg-white/20 text-white"
278
+ : "text-white/70 hover:text-white hover:bg-white/10",
279
+ )}
280
+ >
281
+ <AlignCenter size={iconSize} />
282
+ </button>
283
+ <button
284
+ type="button"
285
+ onclick={() => editor.chain().focus().setTextAlign("right").run()}
286
+ title="오른쪽 정렬"
287
+ aria-label="오른쪽 정렬"
288
+ class={cn(
289
+ "p-1.5 rounded-md transition-colors",
290
+ editor.isActive({ textAlign: "right" })
291
+ ? "bg-white/20 text-white"
292
+ : "text-white/70 hover:text-white hover:bg-white/10",
293
+ )}
294
+ >
295
+ <AlignRight size={iconSize} />
296
+ </button>
297
+ {/if}
298
+ </div>
299
+ </div>
@@ -0,0 +1,9 @@
1
+ import type { Editor } from "@tiptap/core";
2
+ type $$ComponentProps = {
3
+ editor: Editor;
4
+ minimal?: boolean;
5
+ };
6
+ declare const BubbleToolbar: import("svelte").Component<$$ComponentProps, {}, "">;
7
+ type BubbleToolbar = ReturnType<typeof BubbleToolbar>;
8
+ export default BubbleToolbar;
9
+ //# sourceMappingURL=BubbleToolbar.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BubbleToolbar.svelte.d.ts","sourceRoot":"","sources":["../../src/components/BubbleToolbar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAsB1C,KAAK,gBAAgB,GAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAqNhE,QAAA,MAAM,aAAa,sDAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}