@teriusu/rich-editor 0.6.0 → 0.6.2

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.
package/README.md CHANGED
@@ -195,7 +195,7 @@ npm test # vitest
195
195
 
196
196
  publish 성공 시 `repository_dispatch` (`rich-editor-published`) 이벤트가 다음 repo로 전송되고, 각 repo의 `update-*` 워크플로우가 `package.json`을 새 버전으로 업데이트 + 커밋:
197
197
  - `teriusu-ko/hancomac` → `@teriusu/rich-editor`
198
- - `HancomAC/arcturus-next` → `apps/jungol`, `apps/codepass`의 `@teriusu/rich-editor`
198
+ - `HancomAC/trinity` → `apps/jungol`, `apps/codepass`의 `@teriusu/rich-editor`
199
199
 
200
200
  `teriusu-ko/teriusu`는 현재 수동 업데이트 (hook 미설정 — `GH_PAT` secret 추가 시 연결 가능).
201
201
 
@@ -5,6 +5,9 @@
5
5
 
6
6
  let { src, fileName }: { src: string; fileName?: string } = $props();
7
7
 
8
+ const cleanName = (raw?: string) =>
9
+ (raw || "").replace(/[?#].*$/, "").trim() || "PDF 문서";
10
+
8
11
  let canvasEl: HTMLCanvasElement | undefined = $state();
9
12
  let containerEl: HTMLDivElement | undefined = $state();
10
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -21,7 +24,7 @@
21
24
  try {
22
25
  const pageObj = await pdf.getPage(page);
23
26
  const unscaledViewport = pageObj.getViewport({ scale: 1 });
24
- const availableWidth = containerEl.clientWidth - 32;
27
+ const availableWidth = containerEl.clientWidth;
25
28
  if (availableWidth <= 0) return;
26
29
  const scale = availableWidth / unscaledViewport.width;
27
30
  const viewport = pageObj.getViewport({ scale });
@@ -102,12 +105,12 @@
102
105
  <p class="text-sm text-muted-foreground animate-pulse">PDF 로딩 중...</p>
103
106
  </div>
104
107
  {:else}
105
- <div class="border border-border rounded-lg overflow-hidden bg-muted/30 my-4">
108
+ <div class="border border-border rounded-lg overflow-hidden my-4">
106
109
  <div
107
- class="flex items-center justify-between px-4 py-2 border-b border-border bg-background"
110
+ class="flex items-center justify-between px-4 py-2 border-b border-border bg-muted"
108
111
  >
109
112
  <span class="text-xs text-muted-foreground truncate">
110
- {fileName || "PDF 문서"}
113
+ {cleanName(fileName)}
111
114
  </span>
112
115
  <span class="text-xs text-muted-foreground tabular-nums">
113
116
  {page} / {total}
@@ -116,14 +119,14 @@
116
119
 
117
120
  <div
118
121
  bind:this={containerEl}
119
- class="flex items-center justify-center p-4 bg-neutral-100 dark:bg-neutral-900"
122
+ class="flex items-center justify-center"
120
123
  >
121
124
  <canvas bind:this={canvasEl} class="shadow-sm"></canvas>
122
125
  </div>
123
126
 
124
127
  {#if total > 1}
125
128
  <div
126
- class="flex items-center justify-center gap-4 px-4 py-2 border-t border-border bg-background"
129
+ class="flex items-center justify-center gap-4 px-4 py-2 border-t border-border bg-muted"
127
130
  >
128
131
  <button
129
132
  type="button"
@@ -1 +1 @@
1
- {"version":3,"file":"PdfViewer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/PdfViewer.svelte.ts"],"names":[],"mappings":"AAOC,KAAK,gBAAgB,GAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAoI7D,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
1
+ {"version":3,"file":"PdfViewer.svelte.d.ts","sourceRoot":"","sources":["../../src/components/PdfViewer.svelte.ts"],"names":[],"mappings":"AAOC,KAAK,gBAAgB,GAAI;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAuI7D,QAAA,MAAM,SAAS,sDAAwC,CAAC;AACxD,KAAK,SAAS,GAAG,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9C,eAAe,SAAS,CAAC"}
@@ -28,6 +28,9 @@
28
28
 
29
29
  /** 각 feature가 속하는 섹션 라벨 */
30
30
  const SECTION_MAP: Record<string, string> = {
31
+ "code-block": "자주 쓰는",
32
+ file: "자주 쓰는",
33
+ pdf: "자주 쓰는",
31
34
  h1: "기본",
32
35
  h2: "기본",
33
36
  h3: "기본",
@@ -37,18 +40,15 @@
37
40
  toggle: "리스트",
38
41
  blockquote: "블록",
39
42
  "horizontal-rule": "블록",
40
- "code-block": "블록",
41
43
  table: "레이아웃",
42
44
  "columns-2": "레이아웃",
43
45
  "columns-3": "레이아웃",
44
46
  link: "미디어",
45
47
  image: "미디어",
46
48
  youtube: "미디어",
47
- pdf: "미디어",
48
49
  video: "미디어",
49
- file: "미디어",
50
50
  };
51
- const SECTION_ORDER = ["기본", "리스트", "블록", "레이아웃", "미디어"];
51
+ const SECTION_ORDER = ["자주 쓰는", "기본", "리스트", "블록", "레이아웃", "미디어"];
52
52
 
53
53
  const SLASH_MENU_ITEMS_DATA: {
54
54
  feature: ToolbarFeature;
@@ -118,20 +118,12 @@
118
118
  },
119
119
  {
120
120
  feature: "code-block",
121
- label: "C++ 코드",
122
- keywords: "code cpp c++ 코드 블록",
121
+ label: "코드",
122
+ keywords: "code 코드 블록 cpp c++ python 파이썬",
123
123
  icon: Code2,
124
124
  command: (editor) =>
125
125
  editor.chain().focus().setCodeBlock({ language: "cpp" }).run(),
126
126
  },
127
- {
128
- feature: "code-block",
129
- label: "Python 코드",
130
- keywords: "code python 파이썬 코드 블록",
131
- icon: Code2,
132
- command: (editor) =>
133
- editor.chain().focus().setCodeBlock({ language: "python" }).run(),
134
- },
135
127
  {
136
128
  feature: "toggle",
137
129
  label: "토글",
@@ -251,6 +243,15 @@
251
243
 
252
244
  const allItems = $derived.by(() => {
253
245
  const items = SLASH_MENU_ITEMS_DATA.filter((item) => features.has(item.feature));
246
+ if (onFileUpload) {
247
+ items.push({
248
+ feature: "file" as ToolbarFeature,
249
+ label: "파일 첨부",
250
+ keywords: "file attach 파일 첨부",
251
+ icon: Paperclip,
252
+ command: () => onFileUpload!(),
253
+ });
254
+ }
254
255
  if (onPdfUpload) {
255
256
  items.push({
256
257
  feature: "pdf" as ToolbarFeature,
@@ -269,15 +270,6 @@
269
270
  command: () => onVideoUpload!(),
270
271
  });
271
272
  }
272
- if (onFileUpload) {
273
- items.push({
274
- feature: "file" as ToolbarFeature,
275
- label: "파일 첨부",
276
- keywords: "file attach 파일 첨부",
277
- icon: Paperclip,
278
- command: () => onFileUpload!(),
279
- });
280
- }
281
273
  return items;
282
274
  });
283
275
 
@@ -306,6 +298,16 @@
306
298
  }
307
299
  });
308
300
 
301
+ $effect(() => {
302
+ function handleMouseDown(e: MouseEvent) {
303
+ if (menuEl && !menuEl.contains(e.target as Node)) {
304
+ onClose();
305
+ }
306
+ }
307
+ document.addEventListener("mousedown", handleMouseDown, true);
308
+ return () => document.removeEventListener("mousedown", handleMouseDown, true);
309
+ });
310
+
309
311
  $effect(() => {
310
312
  function handleKeyDown(e: KeyboardEvent) {
311
313
  if (e.key === "ArrowDown") {
@@ -1 +1 @@
1
- {"version":3,"file":"SlashCommandMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/components/SlashCommandMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAsB3C,OAAO,KAAK,EAAiB,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEvC,KAAK,gBAAgB,GAAI;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AA4VJ,QAAA,MAAM,gBAAgB,qCAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
1
+ {"version":3,"file":"SlashCommandMenu.svelte.d.ts","sourceRoot":"","sources":["../../src/components/SlashCommandMenu.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAsB3C,OAAO,KAAK,EAAiB,cAAc,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AAEvC,KAAK,gBAAgB,GAAI;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,GAAG,CAAC,cAAc,CAAC,CAAC;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B,CAAC;AA8VJ,QAAA,MAAM,gBAAgB,qCAAwC,CAAC;AAC/D,KAAK,gBAAgB,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAC5D,eAAe,gBAAgB,CAAC"}
@@ -149,7 +149,7 @@
149
149
  let slashMenuPos = $state({ top: 0, left: 0 });
150
150
  let slashQuery = $state("");
151
151
  let slashStartPos: number | null = null;
152
- const MENU_HEIGHT = 200;
152
+ const MENU_HEIGHT = 320;
153
153
 
154
154
  function updateSlashMenuPosition() {
155
155
  if (!editor || slashStartPos === null) return;
@@ -1 +1 @@
1
- {"version":3,"file":"FileAttachment.d.ts","sourceRoot":"","sources":["../../src/extensions/FileAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE1E,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,cAAc,EAAE;YACd,iBAAiB,EAAE,CAAC,KAAK,EAAE;gBACzB,GAAG,CAAC,EAAE,MAAM,CAAC;gBACb,MAAM,CAAC,EAAE,MAAM,CAAC;gBAChB,IAAI,EAAE,MAAM,CAAC;gBACb,IAAI,CAAC,EAAE,MAAM,CAAC;aACf,KAAK,UAAU,CAAC;SAClB,CAAC;KACH;CACF;AAkCD,eAAO,MAAM,cAAc,kCAmNzB,CAAC"}
1
+ {"version":3,"file":"FileAttachment.d.ts","sourceRoot":"","sources":["../../src/extensions/FileAttachment.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,cAAc,CAAC;AAErD,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAED,MAAM,MAAM,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAC9E,MAAM,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE1E,OAAO,QAAQ,cAAc,CAAC;IAC5B,UAAU,QAAQ,CAAC,UAAU;QAC3B,cAAc,EAAE;YACd,iBAAiB,EAAE,CAAC,KAAK,EAAE;gBACzB,GAAG,CAAC,EAAE,MAAM,CAAC;gBACb,MAAM,CAAC,EAAE,MAAM,CAAC;gBAChB,IAAI,EAAE,MAAM,CAAC;gBACb,IAAI,CAAC,EAAE,MAAM,CAAC;aACf,KAAK,UAAU,CAAC;SAClB,CAAC;KACH;CACF;AAkCD,eAAO,MAAM,cAAc,kCAqNzB,CAAC"}
@@ -108,16 +108,15 @@ export const FileAttachment = Node.create({
108
108
  return ({ node, editor }) => {
109
109
  const dom = document.createElement("div");
110
110
  dom.style.cssText =
111
- "display:flex;align-items:center;gap:10px;padding:10px 14px;margin:8px 0;border:1px solid var(--border, #e2e8f0);border-radius:10px;background:var(--muted, #f7fafc);cursor:default;max-width:400px;";
111
+ "display:flex;align-items:center;gap:10px;padding:8px 14px;margin:8px 0;border:1px solid var(--border, #e2e8f0);border-radius:8px;background:var(--muted, #f7fafc);cursor:default;max-width:400px;";
112
112
  const icon = document.createElement("span");
113
- icon.style.cssText = "font-size:24px;flex-shrink:0;line-height:1;";
113
+ icon.style.cssText = "font-size:22px;flex-shrink:0;line-height:1;";
114
114
  icon.textContent = getFileIcon(node.attrs.name);
115
- const info = document.createElement("div");
116
- info.style.cssText = "flex:1;min-width:0;";
117
- const nameEl = document.createElement("a");
115
+ const nameEl = document.createElement("button");
116
+ nameEl.type = "button";
118
117
  nameEl.textContent = node.attrs.name;
119
118
  nameEl.style.cssText =
120
- "display:block;font-size:13px;font-weight:600;color:var(--primary, #4A7DAC);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;";
119
+ "flex:1;min-width:0;font-size:15px;font-weight:600;color:var(--primary, #4A7DAC);text-decoration:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer;background:none;border:0;padding:0;text-align:left;font-family:inherit;";
121
120
  let resolvedSrc = null;
122
121
  let resolvedName = node.attrs.name;
123
122
  function getProxyUrl() {
@@ -127,8 +126,12 @@ export const FileAttachment = Node.create({
127
126
  const baseUrl = editor.storage.fileAttachment?.downloadBaseUrl || "/api/upload";
128
127
  return `${baseUrl}/${fileId}/download`;
129
128
  }
129
+ let downloadInProgress = false;
130
130
  function handleClick(e) {
131
131
  e.preventDefault();
132
+ e.stopPropagation();
133
+ if (downloadInProgress)
134
+ return;
132
135
  const proxyUrl = getProxyUrl();
133
136
  const targetUrl = proxyUrl || resolvedSrc;
134
137
  if (!targetUrl)
@@ -137,6 +140,7 @@ export const FileAttachment = Node.create({
137
140
  window.open(targetUrl, "_blank");
138
141
  }
139
142
  else {
143
+ downloadInProgress = true;
140
144
  fetch(targetUrl)
141
145
  .then((res) => res.blob())
142
146
  .then((blob) => {
@@ -146,32 +150,33 @@ export const FileAttachment = Node.create({
146
150
  a.download = resolvedName;
147
151
  a.click();
148
152
  URL.revokeObjectURL(url);
153
+ })
154
+ .finally(() => {
155
+ downloadInProgress = false;
149
156
  });
150
157
  }
151
158
  }
152
159
  nameEl.addEventListener("click", handleClick);
160
+ nameEl.addEventListener("mousedown", (e) => e.stopPropagation());
153
161
  const sizeEl = document.createElement("span");
154
162
  sizeEl.style.cssText =
155
- "font-size:11px;color:var(--muted-foreground, #718096);";
163
+ "flex-shrink:0;font-size:12px;color:var(--muted-foreground, #718096);white-space:nowrap;";
156
164
  // URL이 있으면 바로 표시
157
165
  if (node.attrs.src) {
158
166
  resolvedSrc = node.attrs.src;
159
- nameEl.href = node.attrs.src;
160
167
  if (node.attrs.size)
161
168
  sizeEl.textContent = formatFileSize(node.attrs.size);
162
169
  }
163
170
  else if (node.attrs.fileId) {
164
171
  // ID만 있으면 resolver로 해결 시도
165
- nameEl.href = "#";
166
- nameEl.style.pointerEvents = "none";
172
+ nameEl.disabled = true;
167
173
  sizeEl.textContent = "loading...";
168
174
  const resolver = editor.storage.fileAttachment?.resolver;
169
175
  if (resolver) {
170
176
  resolver(node.attrs.fileId)
171
177
  .then((result) => {
172
178
  resolvedSrc = result.src;
173
- nameEl.href = result.src;
174
- nameEl.style.pointerEvents = "";
179
+ nameEl.disabled = false;
175
180
  if (result.name) {
176
181
  resolvedName = result.name;
177
182
  nameEl.textContent = result.name;
@@ -187,16 +192,15 @@ export const FileAttachment = Node.create({
187
192
  sizeEl.textContent = `ID: ${node.attrs.fileId}`;
188
193
  }
189
194
  }
190
- info.appendChild(nameEl);
191
- info.appendChild(sizeEl);
192
195
  dom.appendChild(icon);
193
- dom.appendChild(info);
196
+ dom.appendChild(nameEl);
197
+ dom.appendChild(sizeEl);
194
198
  if (editor.isEditable) {
195
199
  const del = document.createElement("button");
196
200
  del.type = "button";
197
201
  del.textContent = "\u00D7";
198
202
  del.style.cssText =
199
- "flex-shrink:0;width:22px;height:22px;border:none;background:transparent;color:var(--muted-foreground, #718096);font-size:16px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center;";
203
+ "flex-shrink:0;width:20px;height:20px;border:none;background:transparent;color:var(--muted-foreground, #718096);font-size:14px;cursor:pointer;border-radius:4px;display:flex;align-items:center;justify-content:center;";
200
204
  del.addEventListener("mouseenter", () => {
201
205
  del.style.background = "var(--destructive, #FF6B6B)";
202
206
  del.style.color = "#fff";
@@ -1 +1 @@
1
- {"version":3,"file":"PdfBlock.d.ts","sourceRoot":"","sources":["../../src/extensions/PdfBlock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAmB,MAAM,cAAc,CAAC;AAInE,eAAO,MAAM,QAAQ,sBA8TnB,CAAC"}
1
+ {"version":3,"file":"PdfBlock.d.ts","sourceRoot":"","sources":["../../src/extensions/PdfBlock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,IAAI,UAAU,EAAmB,MAAM,cAAc,CAAC;AAInE,eAAO,MAAM,QAAQ,sBAoZnB,CAAC"}
@@ -9,6 +9,7 @@ export const PdfBlock = TiptapNode.create({
9
9
  src: { default: null },
10
10
  fileId: { default: null },
11
11
  name: { default: "PDF" },
12
+ width: { default: null },
12
13
  };
13
14
  },
14
15
  parseHTML() {
@@ -20,6 +21,7 @@ export const PdfBlock = TiptapNode.create({
20
21
  fileId: dom.getAttribute("data-pdf-id"),
21
22
  src: dom.getAttribute("data-pdf-src") || null,
22
23
  name: dom.getAttribute("data-pdf-name") || "PDF",
24
+ width: dom.getAttribute("data-pdf-width") || dom.style?.width || null,
23
25
  }),
24
26
  },
25
27
  // URL 직접 방식
@@ -29,6 +31,7 @@ export const PdfBlock = TiptapNode.create({
29
31
  src: dom.getAttribute("data-pdf-src"),
30
32
  fileId: null,
31
33
  name: dom.getAttribute("data-pdf-name") || "PDF",
34
+ width: dom.getAttribute("data-pdf-width") || dom.style?.width || null,
32
35
  }),
33
36
  },
34
37
  // 레거시: <embed type="application/pdf">
@@ -36,8 +39,8 @@ export const PdfBlock = TiptapNode.create({
36
39
  tag: 'embed[type="application/pdf"]',
37
40
  getAttrs: (dom) => {
38
41
  const src = dom.getAttribute("src") || "";
39
- const name = src.split("/").pop()?.replace(/\?.*$/, "") || "PDF";
40
- return { src, fileId: null, name };
42
+ const name = src.split("/").pop()?.replace(/[?#].*$/, "") || "PDF";
43
+ return { src, fileId: null, name, width: null };
41
44
  },
42
45
  },
43
46
  ];
@@ -49,6 +52,10 @@ export const PdfBlock = TiptapNode.create({
49
52
  if (HTMLAttributes.src)
50
53
  attrs["data-pdf-src"] = HTMLAttributes.src;
51
54
  attrs["data-pdf-name"] = HTMLAttributes.name || "PDF";
55
+ if (HTMLAttributes.width) {
56
+ attrs["data-pdf-width"] = HTMLAttributes.width;
57
+ attrs["style"] = `width: ${HTMLAttributes.width}`;
58
+ }
52
59
  return [
53
60
  "div",
54
61
  mergeAttributes(attrs),
@@ -76,20 +83,95 @@ export const PdfBlock = TiptapNode.create({
76
83
  dom.classList.add("my-4");
77
84
  dom.contentEditable = "false";
78
85
  dom.setAttribute("data-drag-handle", "");
86
+ dom.setAttribute("data-node-view-wrapper", "");
87
+ dom.style.position = "relative";
88
+ dom.style.boxSizing = "border-box";
89
+ dom.style.maxWidth = "100%";
90
+ if (node.attrs.width)
91
+ dom.style.width = node.attrs.width;
79
92
  const wrapper = document.createElement("div");
80
93
  wrapper.className =
81
94
  "border rounded-lg overflow-hidden bg-muted/30 transition-shadow";
82
95
  wrapper.style.borderColor = "var(--border)";
83
96
  dom.appendChild(wrapper);
97
+ // 리사이즈 핸들 (편집 가능 모드에서만)
98
+ if (editor.isEditable) {
99
+ const resizeHandle = document.createElement("button");
100
+ resizeHandle.type = "button";
101
+ resizeHandle.contentEditable = "false";
102
+ resizeHandle.setAttribute("aria-label", "PDF 너비 조절");
103
+ resizeHandle.style.cssText =
104
+ "position:absolute;right:-12px;top:0;bottom:0;width:14px;padding:0;margin:0;border:0;background:transparent;cursor:ew-resize;z-index:2;display:flex;align-items:center;justify-content:center;";
105
+ const bar = document.createElement("span");
106
+ bar.style.cssText =
107
+ "display:block;width:3px;height:48px;background:var(--border, #d1d5db);border-radius:2px;transition:background 0.15s;pointer-events:none;";
108
+ resizeHandle.appendChild(bar);
109
+ resizeHandle.addEventListener("mouseenter", () => {
110
+ bar.style.background = "var(--primary, #3382f2)";
111
+ });
112
+ resizeHandle.addEventListener("mouseleave", () => {
113
+ if (!resizing)
114
+ bar.style.background = "var(--border, #d1d5db)";
115
+ });
116
+ const MIN_W = 240;
117
+ const MAX_W = 1600;
118
+ let resizing = false;
119
+ let startX = 0;
120
+ let startWidth = 0;
121
+ resizeHandle.addEventListener("pointerdown", (e) => {
122
+ e.preventDefault();
123
+ e.stopPropagation();
124
+ resizing = true;
125
+ startX = e.clientX;
126
+ startWidth = dom.getBoundingClientRect().width;
127
+ bar.style.background = "var(--primary, #3382f2)";
128
+ resizeHandle.setPointerCapture(e.pointerId);
129
+ });
130
+ resizeHandle.addEventListener("pointermove", (e) => {
131
+ if (!resizing)
132
+ return;
133
+ const delta = e.clientX - startX;
134
+ const next = Math.max(MIN_W, Math.min(MAX_W, startWidth + delta));
135
+ dom.style.width = `${next}px`;
136
+ });
137
+ const endResize = (e) => {
138
+ if (!resizing)
139
+ return;
140
+ resizing = false;
141
+ bar.style.background = "var(--border, #d1d5db)";
142
+ try {
143
+ resizeHandle.releasePointerCapture(e.pointerId);
144
+ }
145
+ catch {
146
+ // ignore release errors (handle may have lost capture already)
147
+ }
148
+ const finalWidth = dom.style.width;
149
+ if (!finalWidth)
150
+ return;
151
+ const pos = getPos();
152
+ if (pos == null)
153
+ return;
154
+ editor.view.dispatch(editor.view.state.tr.setNodeMarkup(pos, undefined, {
155
+ ...node.attrs,
156
+ width: finalWidth,
157
+ }));
158
+ };
159
+ resizeHandle.addEventListener("pointerup", endResize);
160
+ resizeHandle.addEventListener("pointercancel", endResize);
161
+ dom.appendChild(resizeHandle);
162
+ }
84
163
  // Header
85
164
  const header = document.createElement("div");
86
165
  header.className =
87
- "flex items-center justify-between px-4 py-2 border-b border-border bg-background";
166
+ "flex items-center justify-between px-4 py-2 border-b border-border";
167
+ header.style.background = "var(--muted)";
88
168
  wrapper.appendChild(header);
169
+ const cleanName = (raw) => (raw || "").replace(/[?#].*$/, "").trim() || "PDF";
89
170
  const nameSpan = document.createElement("span");
90
- nameSpan.className = "text-xs text-muted-foreground truncate";
171
+ nameSpan.className = "text-xs text-muted-foreground truncate select-none";
91
172
  nameSpan.style.maxWidth = "200px";
92
- nameSpan.textContent = node.attrs.name || "PDF";
173
+ nameSpan.style.userSelect = "none";
174
+ nameSpan.textContent = cleanName(node.attrs.name);
93
175
  header.appendChild(nameSpan);
94
176
  const btnGroup = document.createElement("div");
95
177
  btnGroup.className = "flex items-center gap-1";
@@ -122,8 +204,7 @@ export const PdfBlock = TiptapNode.create({
122
204
  btnGroup.appendChild(deleteBtn);
123
205
  // Content area
124
206
  const contentArea = document.createElement("div");
125
- contentArea.className =
126
- "flex items-center justify-center p-4 bg-neutral-100 dark:bg-neutral-900";
207
+ contentArea.className = "flex items-center justify-center";
127
208
  wrapper.appendChild(contentArea);
128
209
  const canvas = document.createElement("canvas");
129
210
  canvas.className = "shadow-sm";
@@ -149,7 +230,7 @@ export const PdfBlock = TiptapNode.create({
149
230
  if (destroyed)
150
231
  return;
151
232
  const unscaledViewport = pageObj.getViewport({ scale: 1 });
152
- const availableWidth = contentArea.clientWidth - 32;
233
+ const availableWidth = contentArea.clientWidth;
153
234
  if (availableWidth <= 0) {
154
235
  rendering = false;
155
236
  return;
@@ -195,11 +276,12 @@ export const PdfBlock = TiptapNode.create({
195
276
  if (totalPages > 1) {
196
277
  navDiv = document.createElement("div");
197
278
  navDiv.className =
198
- "flex items-center justify-center gap-4 px-4 py-2 border-t border-border bg-background";
279
+ "flex items-center justify-center gap-4 px-4 py-2 border-t border-border";
280
+ navDiv.style.background = "var(--muted)";
199
281
  const prevBtn = document.createElement("button");
200
282
  prevBtn.type = "button";
201
283
  prevBtn.className =
202
- "p-1.5 rounded hover:bg-muted transition-colors disabled:opacity-30";
284
+ "p-1.5 rounded hover:bg-muted transition-colors disabled:opacity-30 text-foreground";
203
285
  prevBtn.innerHTML =
204
286
  '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>';
205
287
  prevBtn.addEventListener("click", () => {
@@ -212,13 +294,14 @@ export const PdfBlock = TiptapNode.create({
212
294
  });
213
295
  navDiv.appendChild(prevBtn);
214
296
  const pageSpan = document.createElement("span");
215
- pageSpan.className = "text-sm tabular-nums page-counter";
297
+ pageSpan.className = "text-sm tabular-nums page-counter select-none";
298
+ pageSpan.style.userSelect = "none";
216
299
  pageSpan.textContent = `1 / ${totalPages}`;
217
300
  navDiv.appendChild(pageSpan);
218
301
  const nextBtn = document.createElement("button");
219
302
  nextBtn.type = "button";
220
303
  nextBtn.className =
221
- "p-1.5 rounded hover:bg-muted transition-colors disabled:opacity-30";
304
+ "p-1.5 rounded hover:bg-muted transition-colors disabled:opacity-30 text-foreground";
222
305
  nextBtn.innerHTML =
223
306
  '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>';
224
307
  nextBtn.addEventListener("click", () => {
@@ -281,17 +364,14 @@ export const PdfBlock = TiptapNode.create({
281
364
  update: (updatedNode) => {
282
365
  if (updatedNode.type.name !== "pdfBlock")
283
366
  return false;
367
+ const newWidth = updatedNode.attrs.width;
368
+ if (newWidth !== node.attrs.width) {
369
+ dom.style.width = newWidth || "";
370
+ }
284
371
  return true;
285
372
  },
286
- selectNode: () => {
287
- wrapper.style.borderColor = "var(--primary)";
288
- wrapper.style.boxShadow =
289
- "0 0 0 3px color-mix(in srgb, var(--primary) 25%, transparent)";
290
- },
291
- deselectNode: () => {
292
- wrapper.style.borderColor = "var(--border)";
293
- wrapper.style.boxShadow = "none";
294
- },
373
+ selectNode: () => { },
374
+ deselectNode: () => { },
295
375
  destroy: () => {
296
376
  destroyed = true;
297
377
  clearTimeout(resizeTimeout);
@@ -1 +1 @@
1
- .pointer-events-none{pointer-events:none}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.top-full{top:100%}.z-30{z-index:30}.z-50{z-index:50}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-4{height:1rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-px{height:1px}.w-4{width:1rem}.w-\[360px\]{width:360px}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-\[90vw\]{max-width:90vw}.flex-shrink{flex-shrink:1}.-translate-x-1\/2{--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.columns-2{-moz-columns:2;column-count:2}.columns-3{-moz-columns:3;column-count:3}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:var(--radius-md,4px)}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius-xl,8px)}.rounded-md{border-radius:var(--radius-md,6px)}.rounded-xl{border-radius:var(--radius-2xl,12px)}.rounded-t-xl{border-top-left-radius:var(--radius-2xl,12px);border-top-right-radius:var(--radius-2xl,12px)}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-border{border-color:var(--border)}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.bg-background{background-color:var(--background)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-border{background-color:var(--border)}.bg-foreground{background-color:var(--foreground)}.bg-neutral-100{--tw-bg-opacity:1;background-color:rgb(245 245 245/var(--tw-bg-opacity,1))}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.text-destructive{color:var(--destructive)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/60{color:hsla(0,0%,100%,.6)}.text-white\/70{color:hsla(0,0%,100%,.7)}.text-white\/80{color:hsla(0,0%,100%,.8)}.underline{text-decoration-line:underline}.opacity-30{opacity:.3}.shadow-lg{--tw-shadow:var(--shadow-dropdown,0 10px 15px -3px rgba(0,0,0,.1));--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:var(--shadow-dropdown,0 1px 2px 0 rgba(0,0,0,.05));--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:var(--shadow-popup,0 20px 25px -5px rgba(0,0,0,.1));--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hce-editor-wrapper{overflow:visible!important}.bubble-toolbar-container button,.hce-editor-wrapper button,.slash-menu button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;cursor:pointer;box-sizing:border-box}.bubble-toolbar-container button:disabled,.hce-editor-wrapper button:disabled,.slash-menu button:disabled{cursor:default}.tiptap{font-size:1.0625rem;line-height:1.8;color:var(--foreground);padding:1.5rem 1rem 1.5rem 0}.tiptap>*+*{margin-top:.5em}.tiptap>*{margin-left:1.5rem;margin-right:1.5rem}.tiptap p{margin:.25em 0}.tiptap p:empty,.tiptap p:has(>br:only-child){min-height:1.8em}.tiptap h1,.tiptap h2,.tiptap h3,.tiptap li,.tiptap p{white-space:pre-wrap}.tiptap h1{font-size:2rem;font-weight:700;margin:1.5em 0 .5em;line-height:1.25}.tiptap h2{font-size:1.5rem;font-weight:600;margin:1.2em 0 .4em;line-height:1.3}.tiptap h3{font-size:1.25rem;font-weight:600;margin:1em 0 .3em;line-height:1.35}.tiptap ul{list-style:disc}.tiptap ol,.tiptap ul{padding-left:1.5em;margin:.5em 0}.tiptap ol{list-style:decimal}.tiptap ul ul{list-style:circle}.tiptap ul ul ul{list-style:square}.tiptap ol ol{list-style:lower-alpha}.tiptap ol ol ol{list-style:lower-roman}.tiptap li{margin:.25em 0}.tiptap ul[data-type=taskList]{list-style:none;padding-left:0}.tiptap ul[data-type=taskList] li{display:flex;align-items:baseline;gap:.5rem;margin:.1em 0;list-style:none;list-style-type:none}.tiptap ul[data-type=taskList] li>label{flex-shrink:0;display:flex;align-items:center;height:1.5em}.tiptap ul[data-type=taskList] li>label input[type=checkbox]{accent-color:var(--primary);width:1.1em;height:1.1em;cursor:pointer;margin:0}.tiptap ul[data-type=taskList] li>div{flex:1}.tiptap ul[data-type=taskList] li[data-checked=true]>div{text-decoration:line-through;opacity:.6}.tiptap blockquote{border-left:3px solid var(--border);padding:.5rem 1rem;margin:.75em 0;color:var(--muted-foreground);font-style:italic}.tiptap hr{border:none;border-top:2px solid color-mix(in srgb,var(--foreground) 38%,transparent);margin:1.5em 0}.tiptap code{background:var(--muted);border-radius:4px;padding:.15em .35em;font-size:.9em}.tiptap pre{background:#282c34;color:#abb2bf;border-radius:8px;padding:1em;margin:.75em 0;overflow-x:auto;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.9em;line-height:1.6}.tiptap pre code{background:none;padding:0;border-radius:0;color:#abb2bf;font-size:inherit}.tiptap pre code .hljs-keyword,.tiptap pre code .hljs-operator{color:#c678dd}.tiptap pre code .hljs-addition,.tiptap pre code .hljs-doctag,.tiptap pre code .hljs-regexp,.tiptap pre code .hljs-string{color:#98c379}.tiptap pre code .hljs-attr,.tiptap pre code .hljs-number,.tiptap pre code .hljs-selector-class,.tiptap pre code .hljs-template-variable,.tiptap pre code .hljs-type,.tiptap pre code .hljs-variable{color:#d19a66}.tiptap pre code .hljs-function,.tiptap pre code .hljs-section,.tiptap pre code .hljs-title,.tiptap pre code .hljs-title.class_{color:#61aeee}.tiptap pre code .hljs-params,.tiptap pre code .hljs-punctuation{color:#abb2bf}.tiptap pre code .hljs-comment,.tiptap pre code .hljs-quote{color:#5c6370;font-style:italic}.tiptap pre code .hljs-built_in,.tiptap pre code .hljs-formula{color:#e6c07b}.tiptap pre code .hljs-meta,.tiptap pre code .hljs-meta .hljs-keyword{color:#61aeee}.tiptap pre code .hljs-meta .hljs-string{color:#98c379}.tiptap pre code .hljs-attribute,.tiptap pre code .hljs-deletion,.tiptap pre code .hljs-name,.tiptap pre code .hljs-property,.tiptap pre code .hljs-selector-tag,.tiptap pre code .hljs-subst,.tiptap pre code .hljs-tag{color:#e06c75}.tiptap pre code .hljs-literal{color:#56b6c2}.tiptap pre code .hljs-selector-attr,.tiptap pre code .hljs-selector-id,.tiptap pre code .hljs-selector-pseudo{color:#61aeee}.tiptap pre code .hljs-link{color:#61aeee;text-decoration:underline}.tiptap pre code .hljs-bullet,.tiptap pre code .hljs-symbol{color:#61aeee}.tiptap pre code .hljs-emphasis{font-style:italic}.tiptap pre code .hljs-strong{font-weight:700}.tiptap img{max-width:100%;height:auto;border-radius:8px;margin:.75em 0;cursor:pointer;transition:box-shadow .15s}.tiptap [data-type=pdfBlock].ProseMirror-selectednode>div,.tiptap div[data-youtube-video].ProseMirror-selectednode iframe,.tiptap img.ProseMirror-selectednode{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 25%,transparent)}.tiptap [data-type=pdfBlock].ProseMirror-selectednode>div{border-radius:8px}.tiptap a{color:var(--primary);text-decoration:underline;text-underline-offset:2px}.tiptap a:hover{opacity:.8}.tiptap mark{background-color:#fef08a;border-radius:2px;padding:.05em .1em}.tiptap [data-type=details]{border:none;border-radius:0;padding:.25em 0;margin:.5em 0;background:transparent;display:flex;align-items:flex-start;gap:.25em}.tiptap [data-type=details]>button{background:none;border:none;cursor:pointer;padding:0;width:1.4em;height:1.4em;display:inline-flex;align-items:center;justify-content:center;color:var(--muted-foreground);border-radius:4px;transition:transform .15s,background .15s;flex-shrink:0;margin-top:.25em}.tiptap [data-type=details]>button:after{content:"";display:block;width:0;height:0;border-left:5px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;margin-left:2px}.tiptap [data-type=details]>button:hover{background:var(--muted);color:var(--foreground)}.tiptap [data-type=details].is-open>button{transform:rotate(90deg)}.tiptap [data-type=details]>div{flex:1;min-width:0}.tiptap [data-type=details] summary{font-weight:600;cursor:text;padding:.25em 0;display:block}.tiptap [data-type=detailsContent]{margin-top:.5em;padding-left:.5em;border-left:2px solid var(--border)}.tiptap [data-type=detailsContent][hidden]{display:none}.tiptap details{border:1px solid var(--border);border-radius:8px;padding:.5em 1em;margin:.75em 0;background:var(--background)}.tiptap details summary{font-weight:600;cursor:pointer;padding:.25em 0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tiptap details summary::marker{color:var(--muted-foreground)}.tiptap details[open]>:not(summary){margin-top:.5em}.tiptap div[data-youtube-video]{margin:1em 0}.tiptap div[data-youtube-video] iframe{width:100%;aspect-ratio:16/9;border-radius:8px;border:none}.tiptap table{border-collapse:collapse;margin:1em 0;table-layout:fixed;border:2px solid var(--border);max-width:100%}.tiptap .tableWrapper{overflow-x:auto;max-width:100%}.tiptap td,.tiptap th{border:1px solid var(--border);padding:.6em .8em;min-width:60px;vertical-align:middle;position:relative;box-sizing:border-box;overflow:hidden;word-break:break-word;line-height:1.5}.tiptap th{background:var(--muted);font-weight:600;text-align:left}.tiptap td{background:var(--background)}.tiptap .selectedCell:after{content:"";position:absolute;inset:0;background:var(--primary);opacity:.12;pointer-events:none;z-index:1}.tiptap .column-resize-handle{position:absolute;right:-3px;top:0;bottom:0;width:6px;background:var(--primary);opacity:0;cursor:col-resize;z-index:20;border-radius:2px;transition:opacity .15s}.tiptap table:hover .column-resize-handle{opacity:.4}.tiptap .column-resize-handle:hover{opacity:1}.tiptap.resize-cursor{cursor:col-resize}.tableWrapper{overflow-x:auto;overflow-y:hidden;margin:1em 0;max-width:100%;padding-right:4px}.tiptap table .grip-column,.tiptap table .grip-row,.tiptap table .grip-table{display:none!important}.tiptap .is-empty:before{content:attr(data-placeholder);float:left;color:var(--muted-foreground);opacity:.5;pointer-events:none;height:0}.tiptap h1.is-empty:before{font-size:2rem;font-weight:700}.tiptap h2.is-empty:before{font-size:1.5rem;font-weight:600}.tiptap h3.is-empty:before{font-size:1.25rem;font-weight:600}.ProseMirror-gapcursor{display:none;pointer-events:none;position:relative}.ProseMirror-gapcursor:after{content:"";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid var(--foreground);animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}.ProseMirror-focused .ProseMirror-gapcursor{display:block}.ProseMirror-dropcursor{border-top:2px solid var(--primary);margin:-1px 0}.tiptap ::-moz-selection{background-color:color-mix(in srgb,var(--primary) 15%,transparent)}.tiptap ::selection{background-color:color-mix(in srgb,var(--primary) 15%,transparent)}.ProseMirror-noderangeselection ::-moz-selection{background:transparent}.ProseMirror-noderangeselection ::selection{background:transparent}.ProseMirror-noderangeselection *{caret-color:transparent}.ProseMirror-selectednode,.ProseMirror-selectednoderange{position:relative}.ProseMirror-selectednode:not(img):not([data-youtube-video]):not([data-type=pdfBlock]):before,.ProseMirror-selectednoderange:before{content:"";position:absolute;inset:-.25rem;background-color:color-mix(in srgb,var(--primary) 10%,transparent);border:2px solid color-mix(in srgb,var(--primary) 30%,transparent);border-radius:.5rem;pointer-events:none;z-index:-1}.bubble-toolbar-container{z-index:50}.hce-floating-plus{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;border:1px solid var(--border);background:var(--background);color:var(--muted-foreground);cursor:pointer;transition:all .15s}.hce-floating-plus:hover{color:var(--foreground);border-color:var(--foreground);background:var(--muted)}.hce-drag-handle{display:flex;align-items:center;gap:2px}.hce-drag-handle__plus{display:flex;align-items:center;justify-content:center;padding:4px;border-radius:4px;border:none;background:transparent;color:var(--muted-foreground);opacity:.5;cursor:pointer;transition:opacity .15s,background-color .15s}.hce-drag-handle__plus:hover{opacity:1;background:var(--muted)}.hce-drag-handle__grip{display:flex;align-items:center;justify-content:center;padding:2px;border-radius:4px;color:var(--muted-foreground);opacity:.5;cursor:grab;transition:opacity .15s,background-color .15s}.hce-drag-handle__grip:hover{opacity:1;background:var(--muted)}.hce-drag-handle__grip:active{cursor:grabbing}.tiptap div[data-type=columns]{display:grid;gap:24px;margin:1em 0}.tiptap div[data-type=columns][data-columns="2"]{grid-template-columns:1fr 1fr}.tiptap div[data-type=columns][data-columns="3"]{grid-template-columns:1fr 1fr 1fr}.tiptap div[data-type=column]{min-width:0;padding:4px 8px;border:1px dashed var(--border);border-radius:8px}.tiptap div[data-type=column]:focus-within{border-color:var(--primary);border-style:solid}.tiptap div[data-type=columns].ProseMirror-selectednode{outline:2px solid color-mix(in srgb,var(--primary) 30%,transparent);border-radius:8px}@media (max-width:640px){.tiptap div[data-type=columns]{grid-template-columns:1fr!important}}.hce-editor-wrapper button[data-tooltip]{position:relative}.hce-editor-wrapper button[data-tooltip]:hover:after{content:attr(data-tooltip);position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:6px;padding:4px 8px;font-size:11px;line-height:1.2;white-space:nowrap;color:#fff;background:#1e293b;border-radius:6px;pointer-events:none;z-index:60}.hce-table-btn-wrap{position:relative;display:inline-flex}.hce-table-btn-tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);margin-bottom:6px;padding:4px 8px;font-size:11px;line-height:1.2;white-space:nowrap;color:#fff;background:#1e293b;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .15s;z-index:60}.hce-table-btn-wrap:hover .hce-table-btn-tooltip{opacity:1}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:text-destructive:hover{color:var(--destructive)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.focus\:border-primary:focus{border-color:var(--primary)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\:opacity-30:disabled{opacity:.3}@media (prefers-color-scheme:dark){.dark\:bg-neutral-900{--tw-bg-opacity:1;background-color:rgb(23 23 23/var(--tw-bg-opacity,1))}}
1
+ .pointer-events-none{pointer-events:none}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{inset:0}.bottom-0{bottom:0}.bottom-full{bottom:100%}.left-0{left:0}.left-1\/2{left:50%}.top-full{top:100%}.z-30{z-index:30}.z-50{z-index:50}.mx-0\.5{margin-left:.125rem;margin-right:.125rem}.mx-auto{margin-left:auto;margin-right:auto}.my-1{margin-top:.25rem;margin-bottom:.25rem}.my-4{margin-top:1rem;margin-bottom:1rem}.mb-1{margin-bottom:.25rem}.mb-1\.5{margin-bottom:.375rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mt-1{margin-top:.25rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.table{display:table}.grid{display:grid}.hidden{display:none}.h-4{height:1rem}.h-5{height:1.25rem}.h-7{height:1.75rem}.h-9{height:2.25rem}.h-px{height:1px}.w-4{width:1rem}.w-\[360px\]{width:360px}.w-fit{width:-moz-fit-content;width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-\[90vw\]{max-width:90vw}.flex-shrink{flex-shrink:1}.-translate-x-1\/2{--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.columns-2{-moz-columns:2;column-count:2}.columns-3{-moz-columns:3;column-count:3}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-4{gap:1rem}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:var(--radius-md,4px)}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:var(--radius-xl,8px)}.rounded-md{border-radius:var(--radius-md,6px)}.rounded-xl{border-radius:var(--radius-2xl,12px)}.rounded-t-xl{border-top-left-radius:var(--radius-2xl,12px);border-top-right-radius:var(--radius-2xl,12px)}.border{border-width:1px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-border{border-color:var(--border)}.border-white\/10{border-color:hsla(0,0%,100%,.1)}.border-white\/20{border-color:hsla(0,0%,100%,.2)}.bg-background{background-color:var(--background)}.bg-black\/30{background-color:rgba(0,0,0,.3)}.bg-black\/40{background-color:rgba(0,0,0,.4)}.bg-border{background-color:var(--border)}.bg-foreground{background-color:var(--foreground)}.bg-muted{background-color:var(--muted)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.bg-white\/10{background-color:hsla(0,0%,100%,.1)}.bg-white\/20{background-color:hsla(0,0%,100%,.2)}.p-1{padding:.25rem}.p-1\.5{padding:.375rem}.p-2{padding:.5rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.italic{font-style:italic}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.text-white\/60{color:hsla(0,0%,100%,.6)}.text-white\/70{color:hsla(0,0%,100%,.7)}.text-white\/80{color:hsla(0,0%,100%,.8)}.underline{text-decoration-line:underline}.opacity-30{opacity:.3}.shadow-lg{--tw-shadow:var(--shadow-dropdown,0 10px 15px -3px rgba(0,0,0,.1));--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color)}.shadow-lg,.shadow-sm{box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:var(--shadow-dropdown,0 1px 2px 0 rgba(0,0,0,.05));--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color)}.shadow-xl{--tw-shadow:var(--shadow-popup,0 20px 25px -5px rgba(0,0,0,.1));--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline-none{outline:2px solid transparent;outline-offset:2px}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-opacity{transition-property:opacity;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-shadow{transition-property:box-shadow;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.hce-editor-wrapper{overflow:visible!important}.bubble-toolbar-container button,.hce-editor-wrapper button,.slash-menu button{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:0;cursor:pointer;box-sizing:border-box}.bubble-toolbar-container button:disabled,.hce-editor-wrapper button:disabled,.slash-menu button:disabled{cursor:default}.tiptap{font-size:1.0625rem;line-height:1.8;color:var(--foreground);padding:1.5rem}.tiptap>*+*{margin-top:.5em}.tiptap p{margin:.25em 0}.tiptap p:empty,.tiptap p:has(>br:only-child){min-height:1.8em}.tiptap h1,.tiptap h2,.tiptap h3,.tiptap li,.tiptap p{white-space:pre-wrap}.tiptap h1{font-size:2rem;font-weight:700;margin:1.5em 0 .5em;line-height:1.25}.tiptap h2{font-size:1.5rem;font-weight:600;margin:1.2em 0 .4em;line-height:1.3}.tiptap h3{font-size:1.25rem;font-weight:600;margin:1em 0 .3em;line-height:1.35}.tiptap ul{list-style:disc}.tiptap ol,.tiptap ul{padding-left:1.5em;margin:.5em 0}.tiptap ol{list-style:decimal}.tiptap ul ul{list-style:circle}.tiptap ul ul ul{list-style:square}.tiptap ol ol{list-style:lower-alpha}.tiptap ol ol ol{list-style:lower-roman}.tiptap li{margin:.25em 0}.tiptap ul[data-type=taskList]{list-style:none;padding-left:0}.tiptap ul[data-type=taskList] li{display:flex;align-items:baseline;gap:.5rem;margin:.1em 0;list-style:none;list-style-type:none}.tiptap ul[data-type=taskList] li>label{flex-shrink:0;display:flex;align-items:center;height:1.5em}.tiptap ul[data-type=taskList] li>label input[type=checkbox]{accent-color:var(--primary);width:1.1em;height:1.1em;cursor:pointer;margin:0}.tiptap ul[data-type=taskList] li>div{flex:1}.tiptap ul[data-type=taskList] li[data-checked=true]>div{text-decoration:line-through;opacity:.6}.tiptap blockquote{border-left:3px solid var(--border);padding:.5rem 1rem;margin:.75em 0;color:var(--muted-foreground);font-style:italic}.tiptap hr{border:none;border-top:2px solid color-mix(in srgb,var(--foreground) 38%,transparent);margin:1.5em 0}.tiptap code{background:var(--muted);border-radius:4px;padding:.15em .35em;font-size:.9em}.tiptap pre{background:#282c34;color:#abb2bf;border-radius:8px;padding:1em;margin:.75em 0;overflow-x:auto;font-family:JetBrains Mono,Fira Code,Consolas,monospace;font-size:.9em;line-height:1.6}.tiptap pre code{background:none;padding:0;border-radius:0;color:#abb2bf;font-size:inherit}.tiptap pre code .hljs-keyword,.tiptap pre code .hljs-operator{color:#c678dd}.tiptap pre code .hljs-addition,.tiptap pre code .hljs-doctag,.tiptap pre code .hljs-regexp,.tiptap pre code .hljs-string{color:#98c379}.tiptap pre code .hljs-attr,.tiptap pre code .hljs-number,.tiptap pre code .hljs-selector-class,.tiptap pre code .hljs-template-variable,.tiptap pre code .hljs-type,.tiptap pre code .hljs-variable{color:#d19a66}.tiptap pre code .hljs-function,.tiptap pre code .hljs-section,.tiptap pre code .hljs-title,.tiptap pre code .hljs-title.class_{color:#61aeee}.tiptap pre code .hljs-params,.tiptap pre code .hljs-punctuation{color:#abb2bf}.tiptap pre code .hljs-comment,.tiptap pre code .hljs-quote{color:#5c6370;font-style:italic}.tiptap pre code .hljs-built_in,.tiptap pre code .hljs-formula{color:#e6c07b}.tiptap pre code .hljs-meta,.tiptap pre code .hljs-meta .hljs-keyword{color:#61aeee}.tiptap pre code .hljs-meta .hljs-string{color:#98c379}.tiptap pre code .hljs-attribute,.tiptap pre code .hljs-deletion,.tiptap pre code .hljs-name,.tiptap pre code .hljs-property,.tiptap pre code .hljs-selector-tag,.tiptap pre code .hljs-subst,.tiptap pre code .hljs-tag{color:#e06c75}.tiptap pre code .hljs-literal{color:#56b6c2}.tiptap pre code .hljs-selector-attr,.tiptap pre code .hljs-selector-id,.tiptap pre code .hljs-selector-pseudo{color:#61aeee}.tiptap pre code .hljs-link{color:#61aeee;text-decoration:underline}.tiptap pre code .hljs-bullet,.tiptap pre code .hljs-symbol{color:#61aeee}.tiptap pre code .hljs-emphasis{font-style:italic}.tiptap pre code .hljs-strong{font-weight:700}.tiptap img{max-width:100%;height:auto;border-radius:8px;margin:.75em 0;cursor:pointer;transition:box-shadow .15s}.tiptap div[data-youtube-video].ProseMirror-selectednode iframe,.tiptap img.ProseMirror-selectednode{box-shadow:0 0 0 3px color-mix(in srgb,var(--primary) 25%,transparent)}.tiptap [data-type=pdfBlock].ProseMirror-selectednode>div{border-radius:8px}.tiptap a{color:var(--primary);text-decoration:underline;text-underline-offset:2px}.tiptap a:hover{opacity:.8}.tiptap mark{background-color:#fef08a;border-radius:2px;padding:.05em .1em}.tiptap [data-type=details]{border:none;border-radius:0;padding:.25em 0;margin:.5em 0;background:transparent;display:flex;align-items:flex-start;gap:.25em}.tiptap [data-type=details]>button{background:none;border:none;cursor:pointer;padding:0;width:1.4em;height:1.4em;display:inline-flex;align-items:center;justify-content:center;color:var(--muted-foreground);border-radius:4px;transition:transform .15s,background .15s;flex-shrink:0;margin-top:.25em}.tiptap [data-type=details]>button:after{content:"";display:block;width:0;height:0;border-left:5px solid;border-top:4px solid transparent;border-bottom:4px solid transparent;margin-left:2px}.tiptap [data-type=details]>button:hover{background:var(--muted);color:var(--foreground)}.tiptap [data-type=details].is-open>button{transform:rotate(90deg)}.tiptap [data-type=details]>div{flex:1;min-width:0}.tiptap [data-type=details] summary{font-weight:600;cursor:text;padding:.25em 0;display:block}.tiptap [data-type=detailsContent]{margin-top:.5em;padding-left:.5em;border-left:2px solid var(--border)}.tiptap [data-type=detailsContent][hidden]{display:none}.tiptap details{border:1px solid var(--border);border-radius:8px;padding:.5em 1em;margin:.75em 0;background:var(--background)}.tiptap details summary{font-weight:600;cursor:pointer;padding:.25em 0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.tiptap details summary::marker{color:var(--muted-foreground)}.tiptap details[open]>:not(summary){margin-top:.5em}.tiptap div[data-youtube-video]{margin:1em 0}.tiptap div[data-youtube-video] iframe{width:100%;aspect-ratio:16/9;border-radius:8px;border:none}.tiptap table{border-collapse:collapse;margin:1em 0;table-layout:fixed;border:2px solid var(--border);max-width:100%}.tiptap .tableWrapper{overflow-x:auto;max-width:100%}.tiptap td,.tiptap th{border:1px solid var(--border);padding:.6em .8em;min-width:60px;vertical-align:middle;position:relative;box-sizing:border-box;overflow:hidden;word-break:break-word;line-height:1.5}.tiptap th{background:var(--muted);font-weight:600;text-align:left}.tiptap td{background:var(--background)}.tiptap .selectedCell:after{content:"";position:absolute;inset:0;background:var(--primary);opacity:.12;pointer-events:none;z-index:1}.tiptap .column-resize-handle{position:absolute;right:-3px;top:0;bottom:0;width:6px;background:var(--primary);opacity:0;cursor:col-resize;z-index:20;border-radius:2px;transition:opacity .15s}.tiptap table:hover .column-resize-handle{opacity:.4}.tiptap .column-resize-handle:hover{opacity:1}.tiptap.resize-cursor{cursor:col-resize}.tableWrapper{overflow-x:auto;overflow-y:hidden;margin:1em 0;max-width:100%;padding-right:4px}.tiptap table .grip-column,.tiptap table .grip-row,.tiptap table .grip-table{display:none!important}.tiptap .is-empty:before{content:attr(data-placeholder);float:left;color:var(--muted-foreground);opacity:.5;pointer-events:none;height:0}.tiptap h1.is-empty:before{font-size:2rem;font-weight:700}.tiptap h2.is-empty:before{font-size:1.5rem;font-weight:600}.tiptap h3.is-empty:before{font-size:1.25rem;font-weight:600}.ProseMirror-gapcursor{display:none;pointer-events:none;position:relative}.ProseMirror-gapcursor:after{content:"";display:block;position:absolute;top:-2px;width:20px;border-top:1px solid var(--foreground);animation:ProseMirror-cursor-blink 1.1s steps(2,start) infinite}@keyframes ProseMirror-cursor-blink{to{visibility:hidden}}.ProseMirror-focused .ProseMirror-gapcursor{display:block}.ProseMirror-dropcursor{border-top:2px solid var(--primary);margin:-1px 0}.tiptap ::-moz-selection{background-color:color-mix(in srgb,var(--primary) 15%,transparent)}.tiptap ::selection{background-color:color-mix(in srgb,var(--primary) 15%,transparent)}.ProseMirror-noderangeselection ::-moz-selection{background:transparent}.ProseMirror-noderangeselection ::selection{background:transparent}.ProseMirror-noderangeselection *{caret-color:transparent}.ProseMirror-selectednode,.ProseMirror-selectednoderange{position:relative}.ProseMirror-selectednode:not(img):not([data-youtube-video]):not([data-type=pdfBlock]):before,.ProseMirror-selectednoderange:before{content:"";position:absolute;inset:-.25rem;background-color:color-mix(in srgb,var(--primary) 10%,transparent);border:2px solid color-mix(in srgb,var(--primary) 30%,transparent);border-radius:.5rem;pointer-events:none;z-index:-1}.bubble-toolbar-container{z-index:50}.hce-floating-plus{display:flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:6px;border:1px solid var(--border);background:var(--background);color:var(--muted-foreground);cursor:pointer;transition:all .15s}.hce-floating-plus:hover{color:var(--foreground);border-color:var(--foreground);background:var(--muted)}.hce-drag-handle{display:flex;align-items:center;gap:2px}.hce-drag-handle__plus{display:flex;align-items:center;justify-content:center;padding:4px;border-radius:4px;border:none;background:transparent;color:var(--muted-foreground);opacity:.5;cursor:pointer;transition:opacity .15s,background-color .15s}.hce-drag-handle__plus:hover{opacity:1;background:var(--muted)}.hce-drag-handle__grip{display:flex;align-items:center;justify-content:center;padding:2px;border-radius:4px;color:var(--muted-foreground);opacity:.5;cursor:grab;transition:opacity .15s,background-color .15s}.hce-drag-handle__grip:hover{opacity:1;background:var(--muted)}.hce-drag-handle__grip:active{cursor:grabbing}.tiptap div[data-type=columns]{display:grid;gap:24px;margin:1em 0}.tiptap div[data-type=columns][data-columns="2"]{grid-template-columns:1fr 1fr}.tiptap div[data-type=columns][data-columns="3"]{grid-template-columns:1fr 1fr 1fr}.tiptap div[data-type=column]{min-width:0;padding:4px 8px;border:1px dashed var(--border);border-radius:8px}.tiptap div[data-type=column]:focus-within{border-color:var(--primary);border-style:solid}.tiptap div[data-type=columns].ProseMirror-selectednode{outline:2px solid color-mix(in srgb,var(--primary) 30%,transparent);border-radius:8px}@media (max-width:640px){.tiptap div[data-type=columns]{grid-template-columns:1fr!important}}.hce-editor-wrapper button[data-tooltip]{position:relative}.hce-editor-wrapper button[data-tooltip]:hover:after{content:attr(data-tooltip);position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:6px;padding:4px 8px;font-size:11px;line-height:1.2;white-space:nowrap;color:#fff;background:#1e293b;border-radius:6px;pointer-events:none;z-index:60}.hce-table-btn-wrap{position:relative;display:inline-flex}.hce-table-btn-tooltip{position:absolute;bottom:100%;left:50%;transform:translateX(-50%);margin-bottom:6px;padding:4px 8px;font-size:11px;line-height:1.2;white-space:nowrap;color:#fff;background:#1e293b;border-radius:6px;pointer-events:none;opacity:0;transition:opacity .15s;z-index:60}.hce-table-btn-wrap:hover .hce-table-btn-tooltip{opacity:1}.hover\:scale-105:hover{--tw-scale-x:1.05;--tw-scale-y:1.05}.hover\:scale-105:hover,.hover\:scale-110:hover{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1}.hover\:bg-muted:hover{background-color:var(--muted)}.hover\:bg-white\/10:hover{background-color:hsla(0,0%,100%,.1)}.hover\:text-destructive:hover{color:var(--destructive)}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-red-300:hover{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:underline:hover{text-decoration-line:underline}.hover\:opacity-90:hover{opacity:.9}.focus\:border-primary:focus{border-color:var(--primary)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.disabled\:opacity-30:disabled{opacity:.3}
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,+BAA+B;AAC/B,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE7E,YAAY;AACZ,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE1D,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAEvB,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GACxD,aAAa,GAAG,WAAW,GAAG,MAAM,GAEpC,YAAY,GAAG,cAAc,GAAG,aAAa,GAE7C,IAAI,GAAG,IAAI,GAAG,IAAI,GAElB,aAAa,GAAG,cAAc,GAAG,WAAW,GAC5C,YAAY,GAAG,iBAAiB,GAAG,QAAQ,GAE3C,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAEvD,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,GAElD,MAAM,GAAG,MAAM,GAEf,eAAe,GAAG,gBAAgB,GAAG,YAAY,GACjD,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEvD,yBAAyB;AACzB,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,cAAc,EAAE,CA4BjE,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,eAAe,CAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,cAAc,EAAE,GACzB,GAAG,CAAC,cAAc,CAAC,CAErB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,uCAAuC;IACvC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,yFAAyF;IACzF,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,2CAA2C;IAC3C,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,+BAA+B;AAC/B,MAAM,MAAM,aAAa,GAAG,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;AAE5D;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;AAE7E,YAAY;AACZ,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAE1D,kBAAkB;AAClB,MAAM,MAAM,cAAc,GAEvB,MAAM,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GACxD,aAAa,GAAG,WAAW,GAAG,MAAM,GAEpC,YAAY,GAAG,cAAc,GAAG,aAAa,GAE7C,IAAI,GAAG,IAAI,GAAG,IAAI,GAElB,aAAa,GAAG,cAAc,GAAG,WAAW,GAC5C,YAAY,GAAG,iBAAiB,GAAG,QAAQ,GAE3C,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAEvD,WAAW,GAAG,WAAW,GAAG,OAAO,GAAG,YAAY,GAElD,MAAM,GAAG,MAAM,GAEf,eAAe,GAAG,gBAAgB,GAAG,YAAY,GACjD,YAAY,GAAG,iBAAiB,GAAG,gBAAgB,CAAC;AAEvD,yBAAyB;AACzB,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,cAAc,EAAE,CA+BjE,CAAC;AAEF,mEAAmE;AACnE,wBAAgB,eAAe,CAC9B,OAAO,EAAE,WAAW,EACpB,QAAQ,CAAC,EAAE,cAAc,EAAE,GACzB,GAAG,CAAC,cAAc,CAAC,CAErB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,uCAAuC;IACvC,aAAa,CAAC,EAAE,YAAY,CAAC;IAC7B,yFAAyF;IACzF,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,2CAA2C;IAC3C,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,0DAA0D;IAC1D,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,SAAS,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC"}
package/dist/types.js CHANGED
@@ -24,7 +24,10 @@ export const TOOLBAR_PRESETS = {
24
24
  ],
25
25
  minimal: [
26
26
  'bold', 'italic', 'strike', 'code',
27
- 'link',
27
+ 'h2', 'h3',
28
+ 'bullet-list', 'ordered-list', 'checklist',
29
+ 'blockquote', 'code-block',
30
+ 'link', 'image', 'file', 'pdf',
28
31
  'bubble-toolbar', 'slash-menu'
29
32
  ]
30
33
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@teriusu/rich-editor",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "TipTap 기반 Notion-style 리치 텍스트 에디터 (Svelte)",
5
5
  "type": "module",
6
6
  "svelte": "./dist/index.js",