@moda-editor/core 0.1.2 → 0.1.5

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 (247) hide show
  1. package/dist/collab.d.ts +61 -0
  2. package/dist/collab.d.ts.map +1 -0
  3. package/dist/collab.js +67 -0
  4. package/dist/collab.js.map +1 -0
  5. package/dist/commands.d.ts +11 -0
  6. package/dist/commands.d.ts.map +1 -1
  7. package/dist/commands.js +48 -4
  8. package/dist/commands.js.map +1 -1
  9. package/dist/conformance/editor-base.d.ts +7 -0
  10. package/dist/conformance/editor-base.d.ts.map +1 -0
  11. package/dist/conformance/editor-base.js +280 -0
  12. package/dist/conformance/editor-base.js.map +1 -0
  13. package/dist/conformance/editor-codeblock.d.ts +8 -0
  14. package/dist/conformance/editor-codeblock.d.ts.map +1 -0
  15. package/dist/conformance/editor-codeblock.js +402 -0
  16. package/dist/conformance/editor-codeblock.js.map +1 -0
  17. package/dist/conformance/editor-ime.d.ts +7 -0
  18. package/dist/conformance/editor-ime.d.ts.map +1 -0
  19. package/dist/conformance/editor-ime.js +166 -0
  20. package/dist/conformance/editor-ime.js.map +1 -0
  21. package/dist/conformance/editor-input.d.ts +8 -0
  22. package/dist/conformance/editor-input.d.ts.map +1 -0
  23. package/dist/conformance/editor-input.js +676 -0
  24. package/dist/conformance/editor-input.js.map +1 -0
  25. package/dist/conformance/editor-nodeview.d.ts +7 -0
  26. package/dist/conformance/editor-nodeview.d.ts.map +1 -0
  27. package/dist/conformance/editor-nodeview.js +120 -0
  28. package/dist/conformance/editor-nodeview.js.map +1 -0
  29. package/dist/conformance/editor-overlay.d.ts +8 -0
  30. package/dist/conformance/editor-overlay.d.ts.map +1 -0
  31. package/dist/conformance/editor-overlay.js +323 -0
  32. package/dist/conformance/editor-overlay.js.map +1 -0
  33. package/dist/conformance/fixtures.d.ts +4 -0
  34. package/dist/conformance/fixtures.d.ts.map +1 -0
  35. package/dist/conformance/fixtures.js +15 -0
  36. package/dist/conformance/fixtures.js.map +1 -0
  37. package/dist/conformance/index.d.ts +14 -0
  38. package/dist/conformance/index.d.ts.map +1 -0
  39. package/dist/conformance/index.js +28 -0
  40. package/dist/conformance/index.js.map +1 -0
  41. package/dist/conformance/types.d.ts +51 -0
  42. package/dist/conformance/types.d.ts.map +1 -0
  43. package/dist/conformance/types.js +2 -0
  44. package/dist/conformance/types.js.map +1 -0
  45. package/dist/conformance/widget.d.ts +3 -0
  46. package/dist/conformance/widget.d.ts.map +1 -0
  47. package/dist/conformance/widget.js +49 -0
  48. package/dist/conformance/widget.js.map +1 -0
  49. package/dist/conformance.d.ts +1 -58
  50. package/dist/conformance.d.ts.map +1 -1
  51. package/dist/conformance.js +3 -1608
  52. package/dist/conformance.js.map +1 -1
  53. package/dist/editor/extension.d.ts +51 -5
  54. package/dist/editor/extension.d.ts.map +1 -1
  55. package/dist/features/ace.d.ts +4 -0
  56. package/dist/features/ace.d.ts.map +1 -1
  57. package/dist/features/ace.js +57 -25
  58. package/dist/features/ace.js.map +1 -1
  59. package/dist/features/block-dnd.d.ts +7 -0
  60. package/dist/features/block-dnd.d.ts.map +1 -0
  61. package/dist/features/block-dnd.js +207 -0
  62. package/dist/features/block-dnd.js.map +1 -0
  63. package/dist/features/code-block.d.ts +12 -58
  64. package/dist/features/code-block.d.ts.map +1 -1
  65. package/dist/features/code-block.js +155 -630
  66. package/dist/features/code-block.js.map +1 -1
  67. package/dist/features/code-context.d.ts +81 -0
  68. package/dist/features/code-context.d.ts.map +1 -0
  69. package/dist/features/code-context.js +322 -0
  70. package/dist/features/code-context.js.map +1 -0
  71. package/dist/features/code-edit.d.ts +50 -0
  72. package/dist/features/code-edit.d.ts.map +1 -0
  73. package/dist/features/code-edit.js +412 -0
  74. package/dist/features/code-edit.js.map +1 -0
  75. package/dist/features/code-format.d.ts +21 -0
  76. package/dist/features/code-format.d.ts.map +1 -0
  77. package/dist/features/code-format.js +410 -0
  78. package/dist/features/code-format.js.map +1 -0
  79. package/dist/features/doc.d.ts.map +1 -1
  80. package/dist/features/doc.js +1 -1
  81. package/dist/features/doc.js.map +1 -1
  82. package/dist/features/heading.d.ts.map +1 -1
  83. package/dist/features/heading.js.map +1 -1
  84. package/dist/features/image.d.ts +14 -1
  85. package/dist/features/image.d.ts.map +1 -1
  86. package/dist/features/image.js +288 -11
  87. package/dist/features/image.js.map +1 -1
  88. package/dist/features/index.d.ts +7 -0
  89. package/dist/features/index.d.ts.map +1 -1
  90. package/dist/features/index.js +16 -0
  91. package/dist/features/index.js.map +1 -1
  92. package/dist/features/inline-style.d.ts.map +1 -1
  93. package/dist/features/inline-style.js +4 -1
  94. package/dist/features/inline-style.js.map +1 -1
  95. package/dist/features/link.d.ts.map +1 -1
  96. package/dist/features/link.js +1 -1
  97. package/dist/features/link.js.map +1 -1
  98. package/dist/features/markdown.d.ts +15 -0
  99. package/dist/features/markdown.d.ts.map +1 -0
  100. package/dist/features/markdown.js +80 -0
  101. package/dist/features/markdown.js.map +1 -0
  102. package/dist/features/marks.d.ts.map +1 -1
  103. package/dist/features/marks.js +76 -4
  104. package/dist/features/marks.js.map +1 -1
  105. package/dist/features/mention.d.ts +30 -0
  106. package/dist/features/mention.d.ts.map +1 -0
  107. package/dist/features/mention.js +89 -0
  108. package/dist/features/mention.js.map +1 -0
  109. package/dist/features/script.d.ts.map +1 -1
  110. package/dist/features/script.js.map +1 -1
  111. package/dist/features/search.d.ts +73 -0
  112. package/dist/features/search.d.ts.map +1 -0
  113. package/dist/features/search.js +252 -0
  114. package/dist/features/search.js.map +1 -0
  115. package/dist/features/shared.d.ts +69 -0
  116. package/dist/features/shared.d.ts.map +1 -0
  117. package/dist/features/shared.js +272 -0
  118. package/dist/features/shared.js.map +1 -0
  119. package/dist/features/table.d.ts +16 -3
  120. package/dist/features/table.d.ts.map +1 -1
  121. package/dist/features/table.js +309 -8
  122. package/dist/features/table.js.map +1 -1
  123. package/dist/features/testkit.d.ts.map +1 -1
  124. package/dist/features/testkit.js +1 -1
  125. package/dist/features/testkit.js.map +1 -1
  126. package/dist/history.d.ts.map +1 -1
  127. package/dist/history.js +65 -20
  128. package/dist/history.js.map +1 -1
  129. package/dist/index.d.ts +20 -7
  130. package/dist/index.d.ts.map +1 -1
  131. package/dist/index.js +17 -6
  132. package/dist/index.js.map +1 -1
  133. package/dist/model/schema.d.ts.map +1 -1
  134. package/dist/model/schema.js +2 -1
  135. package/dist/model/schema.js.map +1 -1
  136. package/dist/parse/html.d.ts.map +1 -1
  137. package/dist/parse/html.js +38 -6
  138. package/dist/parse/html.js.map +1 -1
  139. package/dist/parse/sanitize.d.ts.map +1 -1
  140. package/dist/parse/sanitize.js +14 -2
  141. package/dist/parse/sanitize.js.map +1 -1
  142. package/dist/presets/highlight.d.ts +17 -0
  143. package/dist/presets/highlight.d.ts.map +1 -1
  144. package/dist/presets/highlight.js +52 -4
  145. package/dist/presets/highlight.js.map +1 -1
  146. package/dist/presets/markdown-parse.d.ts +13 -0
  147. package/dist/presets/markdown-parse.d.ts.map +1 -0
  148. package/dist/presets/markdown-parse.js +398 -0
  149. package/dist/presets/markdown-parse.js.map +1 -0
  150. package/dist/presets/markdown.d.ts +45 -0
  151. package/dist/presets/markdown.d.ts.map +1 -0
  152. package/dist/presets/markdown.js +195 -0
  153. package/dist/presets/markdown.js.map +1 -0
  154. package/dist/state/apply.d.ts.map +1 -1
  155. package/dist/state/apply.js +19 -11
  156. package/dist/state/apply.js.map +1 -1
  157. package/dist/state/delete-ops.d.ts +34 -0
  158. package/dist/state/delete-ops.d.ts.map +1 -0
  159. package/dist/state/delete-ops.js +204 -0
  160. package/dist/state/delete-ops.js.map +1 -0
  161. package/dist/state/input-rules.d.ts +30 -0
  162. package/dist/state/input-rules.d.ts.map +1 -0
  163. package/dist/state/input-rules.js +70 -0
  164. package/dist/state/input-rules.js.map +1 -0
  165. package/dist/state/insert-ops.d.ts +54 -0
  166. package/dist/state/insert-ops.d.ts.map +1 -0
  167. package/dist/state/insert-ops.js +186 -0
  168. package/dist/state/insert-ops.js.map +1 -0
  169. package/dist/state/list-ops.d.ts +46 -0
  170. package/dist/state/list-ops.d.ts.map +1 -0
  171. package/dist/state/list-ops.js +231 -0
  172. package/dist/state/list-ops.js.map +1 -0
  173. package/dist/state/navigate.d.ts.map +1 -1
  174. package/dist/state/navigate.js +3 -1
  175. package/dist/state/navigate.js.map +1 -1
  176. package/dist/state/resolve-insert.d.ts +55 -0
  177. package/dist/state/resolve-insert.d.ts.map +1 -0
  178. package/dist/state/resolve-insert.js +118 -0
  179. package/dist/state/resolve-insert.js.map +1 -0
  180. package/dist/state/slice-ops.d.ts +46 -0
  181. package/dist/state/slice-ops.d.ts.map +1 -0
  182. package/dist/state/slice-ops.js +150 -0
  183. package/dist/state/slice-ops.js.map +1 -0
  184. package/dist/state/state.d.ts +6 -1
  185. package/dist/state/state.d.ts.map +1 -1
  186. package/dist/state/state.js +10 -0
  187. package/dist/state/state.js.map +1 -1
  188. package/dist/state/transaction.d.ts +40 -53
  189. package/dist/state/transaction.d.ts.map +1 -1
  190. package/dist/state/transaction.js +62 -829
  191. package/dist/state/transaction.js.map +1 -1
  192. package/dist/styles.css +472 -46
  193. package/dist/view/adapter.d.ts +84 -0
  194. package/dist/view/adapter.d.ts.map +1 -0
  195. package/dist/view/adapter.js +76 -0
  196. package/dist/view/adapter.js.map +1 -0
  197. package/dist/view/caret.d.ts +25 -0
  198. package/dist/view/caret.d.ts.map +1 -0
  199. package/dist/view/caret.js +43 -0
  200. package/dist/view/caret.js.map +1 -0
  201. package/dist/view/decoration.d.ts +9 -0
  202. package/dist/view/decoration.d.ts.map +1 -0
  203. package/dist/view/decoration.js +214 -0
  204. package/dist/view/decoration.js.map +1 -0
  205. package/dist/view/dirty-keys.d.ts +18 -0
  206. package/dist/view/dirty-keys.d.ts.map +1 -0
  207. package/dist/view/dirty-keys.js +31 -0
  208. package/dist/view/dirty-keys.js.map +1 -0
  209. package/dist/view/dom.d.ts.map +1 -1
  210. package/dist/view/dom.js +69 -27
  211. package/dist/view/dom.js.map +1 -1
  212. package/dist/view/hook-ctx.d.ts +32 -0
  213. package/dist/view/hook-ctx.d.ts.map +1 -0
  214. package/dist/view/hook-ctx.js +64 -0
  215. package/dist/view/hook-ctx.js.map +1 -0
  216. package/dist/view/ime.d.ts +72 -0
  217. package/dist/view/ime.d.ts.map +1 -0
  218. package/dist/view/ime.js +185 -0
  219. package/dist/view/ime.js.map +1 -0
  220. package/dist/view/input.d.ts +12 -12
  221. package/dist/view/input.d.ts.map +1 -1
  222. package/dist/view/input.js +122 -435
  223. package/dist/view/input.js.map +1 -1
  224. package/dist/view/keys.d.ts +25 -0
  225. package/dist/view/keys.d.ts.map +1 -0
  226. package/dist/view/keys.js +106 -0
  227. package/dist/view/keys.js.map +1 -0
  228. package/dist/view/line-nav.d.ts +13 -0
  229. package/dist/view/line-nav.d.ts.map +1 -0
  230. package/dist/view/line-nav.js +114 -0
  231. package/dist/view/line-nav.js.map +1 -0
  232. package/dist/view/mount.d.ts.map +1 -1
  233. package/dist/view/mount.js +48 -32
  234. package/dist/view/mount.js.map +1 -1
  235. package/dist/view/node-selection.d.ts +33 -0
  236. package/dist/view/node-selection.d.ts.map +1 -0
  237. package/dist/view/node-selection.js +107 -0
  238. package/dist/view/node-selection.js.map +1 -0
  239. package/dist/view/render.d.ts +11 -2
  240. package/dist/view/render.d.ts.map +1 -1
  241. package/dist/view/render.js +17 -3
  242. package/dist/view/render.js.map +1 -1
  243. package/dist/view/serialize.d.ts +8 -0
  244. package/dist/view/serialize.d.ts.map +1 -1
  245. package/dist/view/serialize.js +33 -5
  246. package/dist/view/serialize.js.map +1 -1
  247. package/package.json +1 -1
package/dist/styles.css CHANGED
@@ -4,14 +4,16 @@
4
4
  .me-root {
5
5
  --me-border-color: #e2e8f0;
6
6
  --me-text-color: #1e293b;
7
- --me-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
8
- "Liberation Mono", monospace;
7
+ --me-font-mono:
8
+ ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
9
9
  /* 거터·활성줄 변수는 루트에 둔다 — .me-gutter 오버레이가 .me-editor의
10
10
  * 형제라 .me-editor 스코프 변수를 못 본다. 자식인 .me-editor도
11
11
  * 같은 변수를 상속해 그라디언트에 쓴다 */
12
12
  --me-gutter-bg: rgba(15, 23, 42, 0.035);
13
13
  --me-gutter-color: #94a3b8;
14
14
  --me-line-active-num: #3b82f6;
15
+ /* atom 노드 셀렉션 링 + 이미지 핸들 — 거터와 같은 이유로 루트에 둔다 */
16
+ --me-node-sel-color: #3b82f6;
15
17
  display: flex;
16
18
  flex-direction: column;
17
19
  gap: 8px;
@@ -53,11 +55,10 @@
53
55
  * 크롬을 담당한다 ─────────────────────────────────────────── */
54
56
  .me-frame {
55
57
  --me-frame-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
56
- --me-focus-ring: rgba(59, 130, 246, 0.18);
57
58
  --me-border-color: #e2e8f0;
58
59
  --me-text-color: #1e293b;
59
- --me-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
60
- "Liberation Mono", monospace;
60
+ --me-font-mono:
61
+ ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
61
62
 
62
63
  color: var(--me-text-color);
63
64
  background: #ffffff;
@@ -67,9 +68,10 @@
67
68
  overflow: hidden;
68
69
  }
69
70
 
71
+ /* 포커스 표시는 테두리 색만 — 글로우 링은 입력 중 카드 전체를
72
+ * 파란 띠로 둘러 산만했다 */
70
73
  .me-frame:focus-within {
71
74
  border-color: var(--me-editor-focus, #3b82f6);
72
- box-shadow: 0 0 0 3px var(--me-focus-ring);
73
75
  }
74
76
 
75
77
  /* ── 에디터 — Ace 계열 코드 에디터 서페이스: 모노스페이스 본문 +
@@ -82,7 +84,6 @@
82
84
  --me-code-bg: #f1f5f9;
83
85
  --me-code-border: #e2e8f0;
84
86
  --me-gutter-border: var(--me-border-color);
85
- --me-line-active-bg: rgba(59, 130, 246, 0.07);
86
87
  --me-sel-bg: rgba(59, 130, 246, 0.22);
87
88
  --me-print-margin: rgba(148, 163, 184, 0.4);
88
89
 
@@ -108,17 +109,13 @@
108
109
  ),
109
110
  /* print margin — 80열 (Ace showPrintMargin 관례) */
110
111
  linear-gradient(
111
- to right,
112
- transparent 0 calc(3.9em + 80ch),
113
- var(--me-print-margin) calc(3.9em + 80ch) calc(3.9em + 80ch + 1px),
114
- transparent calc(3.9em + 80ch + 1px)
115
- ),
112
+ to right,
113
+ transparent 0 calc(3.9em + 80ch),
114
+ var(--me-print-margin) calc(3.9em + 80ch) calc(3.9em + 80ch + 1px),
115
+ transparent calc(3.9em + 80ch + 1px)
116
+ ),
116
117
  /* 거터 컬럼 배경 */
117
- linear-gradient(
118
- to right,
119
- var(--me-gutter-bg) 0 3.9em,
120
- transparent 3.9em
121
- ),
118
+ linear-gradient(to right, var(--me-gutter-bg) 0 3.9em, transparent 3.9em),
122
119
  var(--me-editor-bg);
123
120
  }
124
121
 
@@ -182,11 +179,11 @@
182
179
  }
183
180
 
184
181
  /* 활성 라인 — aceFeature의 paintOverlay가 캐럿의 최상위 블록에
185
- * me-line-active를 단다 (Ace highlightActiveLine 관례).
186
- * 코드블록은 .me-cl.is-active가 이미 줄 단위로 칠하니 배경은 뺀다 */
187
- .me-editor > *.me-line-active:not(pre) {
188
- background-color: var(--me-line-active-bg);
189
- }
182
+ * me-line-active를 단다. 배경 띠는 칠하지 않는다(문서 편집에서
183
+ * 파란 띠가 산만하다는 피드백) — 활성 표시는 거터 번호 강조
184
+ * (.me-gnum.is-active)로만 한다. 코드블록은 코드 에디터 관례대로
185
+ * .me-cl.is-active가 줄 단위 배경을 칠한다. 클래스는 계속 달리므로
186
+ * 원하면 제품 CSS에서 배경을 되살릴 수 있다 */
190
187
 
191
188
  /* 선택 영역 — Ace 선택색 관례 (코드블록 안도 같은 변수) */
192
189
  .me-editor ::selection {
@@ -227,12 +224,20 @@
227
224
  margin-bottom: 0;
228
225
  }
229
226
 
230
- .me-editor h1 { font-size: 1.55em; }
231
- .me-editor h2 { font-size: 1.35em; }
232
- .me-editor h3 { font-size: 1.2em; }
227
+ .me-editor h1 {
228
+ font-size: 1.55em;
229
+ }
230
+ .me-editor h2 {
231
+ font-size: 1.35em;
232
+ }
233
+ .me-editor h3 {
234
+ font-size: 1.2em;
235
+ }
233
236
  .me-editor h4,
234
237
  .me-editor h5,
235
- .me-editor h6 { font-size: 1.05em; }
238
+ .me-editor h6 {
239
+ font-size: 1.05em;
240
+ }
236
241
 
237
242
  .me-editor code {
238
243
  padding: 0.08em 0.35em;
@@ -325,6 +330,280 @@
325
330
  max-width: 100%;
326
331
  border-radius: 6px;
327
332
  margin: 0 0 8px;
333
+ cursor: default;
334
+ }
335
+
336
+ /* atom 노드 셀렉션 — 클릭으로 선택된 img/hr 등에 파란 링을 둔다
337
+ * (input.ts의 paintOverlays가 is-selected를 마킹한다) */
338
+ .me-editor [data-me-path].is-selected {
339
+ outline: 2px solid var(--me-node-sel-color);
340
+ outline-offset: 2px;
341
+ }
342
+ .me-editor hr.is-selected {
343
+ /* hr은 테두리가 굵어 outline이 묻힌다 — 위아래 여백으로 링을 띄운다 */
344
+ outline-offset: 4px;
345
+ }
346
+
347
+ /* ── 이미지 선택 오버레이 — 선택된 img 위에 얹히는 편집/리사이즈 UI.
348
+ * .me-editor의 형제(.me-root의 absolute 자식)로 둬 DOM↔Point 매핑을
349
+ * 깨지 않는다. 래퍼는 pointer-events:none — 이미지 자체 클릭은 그대로
350
+ * 통과하고 핸들/바만 이벤트를 받는다 */
351
+ .me-imgui {
352
+ position: absolute;
353
+ z-index: 40;
354
+ pointer-events: none;
355
+ }
356
+ .me-imgui[hidden] {
357
+ display: none;
358
+ }
359
+ /* 우하단 크기 핸들 — nwse-resize (GDocs/Word 관례) */
360
+ .me-imgui .me-img-handle {
361
+ position: absolute;
362
+ right: -6px;
363
+ bottom: -6px;
364
+ width: 12px;
365
+ height: 12px;
366
+ border-radius: 4px;
367
+ background: var(--me-toolbar-bg, #fff);
368
+ border: 2px solid var(--me-node-sel-color);
369
+ box-shadow: 0 1px 3px rgba(15, 23, 42, 0.3);
370
+ cursor: nwse-resize;
371
+ pointer-events: auto;
372
+ touch-action: none;
373
+ }
374
+ /* 액션 바 — 이미지 위쪽. 루트 상단에 붙으면 is-below로 아래로 뒤집는다 */
375
+ .me-imgui .me-img-bar {
376
+ position: absolute;
377
+ left: 0;
378
+ top: -6px;
379
+ transform: translateY(-100%);
380
+ display: flex;
381
+ flex-wrap: wrap;
382
+ gap: 3px;
383
+ padding: 4px;
384
+ max-width: min(320px, 90vw);
385
+ background: var(--me-toolbar-bg, #fff);
386
+ border: 1px solid var(--me-border-color);
387
+ border-radius: 6px;
388
+ box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
389
+ pointer-events: auto;
390
+ }
391
+ .me-imgui.is-below .me-img-bar {
392
+ top: auto;
393
+ bottom: -6px;
394
+ transform: translateY(100%);
395
+ }
396
+ .me-imgui .me-imgbtn {
397
+ padding: 3px 8px;
398
+ font: inherit;
399
+ font-size: 12px;
400
+ color: inherit;
401
+ background: var(--me-btn-bg, transparent);
402
+ border: 1px solid var(--me-border-color);
403
+ border-radius: 4px;
404
+ cursor: pointer;
405
+ }
406
+ .me-imgui .me-imgbtn:hover {
407
+ background: var(--me-tool-hover-bg, #e2e8f0);
408
+ }
409
+ .me-imgui .me-imgbtn[data-img-act="del"]:hover {
410
+ color: #dc2626;
411
+ border-color: #dc2626;
412
+ }
413
+ /* 편집 폼 — 액션 바 안의 두 번째 행 (wrap으로 전체 폭을 차지) */
414
+ .me-imgui .me-imgedit {
415
+ flex-basis: 100%;
416
+ display: flex;
417
+ gap: 4px;
418
+ }
419
+ .me-imgui .me-imgedit[hidden] {
420
+ display: none;
421
+ }
422
+ .me-imgui .me-imged-src,
423
+ .me-imgui .me-imged-alt {
424
+ width: min(150px, 30vw);
425
+ padding: 4px 6px;
426
+ font: inherit;
427
+ font-size: 12px;
428
+ color: inherit;
429
+ background: transparent;
430
+ border: 1px solid var(--me-border-color);
431
+ border-radius: 4px;
432
+ outline: none;
433
+ }
434
+ .me-imgui .me-imged-src:focus,
435
+ .me-imgui .me-imged-alt:focus {
436
+ border-color: var(--me-accent, #2563eb);
437
+ }
438
+
439
+ /* ── 표 편집 오버레이 — 캐럿이 셀 안에 있을 때 표 위에 얹히는 UI.
440
+ * .me-imgui와 같은 패턴: 래퍼 pointer-events:none, 바/핸들만 받는다 */
441
+ .me-tableui {
442
+ position: absolute;
443
+ z-index: 40;
444
+ pointer-events: none;
445
+ }
446
+ .me-tableui[hidden] {
447
+ display: none;
448
+ }
449
+ /* 액션 바 — 표 위쪽 중앙. 루트 상단에 붙으면 is-below로 안쪽에 띄운다 */
450
+ .me-tableui .me-tbl-bar {
451
+ position: absolute;
452
+ left: 50%;
453
+ top: -6px;
454
+ transform: translate(-50%, -100%);
455
+ display: flex;
456
+ gap: 3px;
457
+ padding: 4px;
458
+ background: var(--me-toolbar-bg, #fff);
459
+ border: 1px solid var(--me-border-color);
460
+ border-radius: 6px;
461
+ box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
462
+ white-space: nowrap;
463
+ pointer-events: auto;
464
+ }
465
+ .me-tableui.is-below .me-tbl-bar {
466
+ top: 4px;
467
+ transform: translate(-50%, 0);
468
+ }
469
+ .me-tableui .me-tblbtn {
470
+ padding: 3px 8px;
471
+ font: inherit;
472
+ font-size: 12px;
473
+ color: inherit;
474
+ background: var(--me-btn-bg, transparent);
475
+ border: 1px solid var(--me-border-color);
476
+ border-radius: 4px;
477
+ cursor: pointer;
478
+ }
479
+ .me-tableui .me-tblbtn:hover {
480
+ background: var(--me-tool-hover-bg, #e2e8f0);
481
+ }
482
+ .me-tableui .me-tblbtn[data-tbl-act="tabledel"]:hover,
483
+ .me-tableui .me-tblbtn[data-tbl-act="rowdel"]:hover,
484
+ .me-tableui .me-tblbtn[data-tbl-act="coldel"]:hover {
485
+ color: #dc2626;
486
+ border-color: #dc2626;
487
+ }
488
+ /* 열 경계 핸들 — 각 열 우측 경계의 8px 스트립. 평소엔 투명하고
489
+ * hover/드래그 시 리사이즈 커서 + 강조선 (GDocs 열 리사이즈 관례) */
490
+ .me-tableui .me-tbl-cols {
491
+ position: absolute;
492
+ inset: 0;
493
+ }
494
+ .me-tableui .me-col-handle {
495
+ position: absolute;
496
+ top: 0;
497
+ width: 8px;
498
+ cursor: col-resize;
499
+ pointer-events: auto;
500
+ touch-action: none;
501
+ }
502
+ .me-tableui .me-col-handle::after {
503
+ content: "";
504
+ position: absolute;
505
+ top: 0;
506
+ bottom: 0;
507
+ left: 3px;
508
+ width: 2px;
509
+ background: transparent;
510
+ transition: background 0.1s;
511
+ }
512
+ .me-tableui .me-col-handle:hover::after,
513
+ .me-tableui .me-col-handle:active::after {
514
+ background: var(--me-node-sel-color, #2563eb);
515
+ }
516
+
517
+ /* 코드블록 크롬 바 — 캐럿이 들어간 pre의 우측 상단(언어 라벨 자리).
518
+ * Notion 코드블록 언어 피커 관례. 래퍼는 좌표만 잡고 자식이 이벤트를 받는다 */
519
+ .me-codeui {
520
+ position: absolute;
521
+ z-index: 40;
522
+ transform: translateX(-100%);
523
+ display: flex;
524
+ align-items: center;
525
+ gap: 3px;
526
+ padding: 2px 4px;
527
+ background: var(--me-toolbar-bg, #fff);
528
+ border: 1px solid var(--me-border-color);
529
+ border-radius: 6px;
530
+ box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12);
531
+ white-space: nowrap;
532
+ }
533
+ .me-codeui[hidden] {
534
+ display: none;
535
+ }
536
+ .me-codeui .me-codelang,
537
+ .me-codehead .me-codelang {
538
+ font: inherit;
539
+ font-size: 11px;
540
+ max-width: 7.5em;
541
+ padding: 1px 2px;
542
+ color: var(--me-text-muted, #64748b);
543
+ background: transparent;
544
+ border: none;
545
+ border-radius: 3px;
546
+ cursor: pointer;
547
+ }
548
+ .me-codeui .me-codelang:hover,
549
+ .me-codehead .me-codelang:hover {
550
+ background: var(--me-tool-hover-bg, #e2e8f0);
551
+ }
552
+ .me-codeui .me-codebtn,
553
+ .me-codehead .me-codebtn {
554
+ padding: 1px 7px;
555
+ font: inherit;
556
+ font-size: 11px;
557
+ color: var(--me-text-muted, #64748b);
558
+ background: transparent;
559
+ border: none;
560
+ border-radius: 3px;
561
+ cursor: pointer;
562
+ }
563
+ .me-codeui .me-codebtn:hover,
564
+ .me-codehead .me-codebtn:hover {
565
+ color: inherit;
566
+ background: var(--me-tool-hover-bg, #e2e8f0);
567
+ }
568
+ /* 캐럿이 들어간 코드블록은 첫 줄 우측에 바 자리를 넓힌다 —
569
+ * 바가 코드 텍스트를 가리지 않도록 (기본 언어 라벨 패딩 5em을 덮는다) */
570
+ .me-editor pre.me-line-active .me-cl:first-child {
571
+ padding-right: 13.5em;
572
+ }
573
+
574
+ /* 코드블록 노드 뷰 — 언어/정리/복사 크롬 헤더(.me-codehead) + pre
575
+ * 아울렛을 한 장의 카드로 묶는다 (Notion/VS Code 코드 카드 관례).
576
+ * 헤더는 .me-node-view의 ce=false 영역이라 캐럿 매핑에 무영향 */
577
+ .me-codeview {
578
+ background: var(--me-code-bg);
579
+ border: 1px solid var(--me-code-border);
580
+ border-radius: 6px;
581
+ }
582
+ .me-codehead {
583
+ display: flex;
584
+ align-items: center;
585
+ justify-content: flex-end;
586
+ gap: 3px;
587
+ padding: 2px 6px;
588
+ border-bottom: 1px solid var(--me-code-border);
589
+ border-radius: 6px 6px 0 0;
590
+ user-select: none;
591
+ }
592
+ /* Notion 관례 — 언어 표시는 좌측, 액션 버튼은 우측 */
593
+ .me-codehead .me-codelang {
594
+ margin-right: auto;
595
+ }
596
+ /* 카드 안 pre — 카드가 배경/테두리를 담당하므로 pre 자체 크롬은 뗀다 */
597
+ .me-codeview > .me-node-content {
598
+ margin: 0;
599
+ border: none;
600
+ border-radius: 0;
601
+ background: transparent;
602
+ }
603
+ /* 노드 뷰 코드블록은 헤더가 언어·액션을 담당 — 오버레이 라벨/바용
604
+ * 첫 줄 우측 패딩(5em/13.5em 규칙보다 뒤에 선언해 덮는다)을 되돌린다 */
605
+ .me-editor .me-codeview .me-cl:first-child {
606
+ padding-right: 0;
328
607
  }
329
608
 
330
609
  /* 형광펜 — 브라우저 기본 mark 색을 attr 색이 덮는다 */
@@ -415,17 +694,13 @@
415
694
  ),
416
695
  /* print margin — 80열 (Ace showPrintMargin 관례) */
417
696
  linear-gradient(
418
- to right,
419
- transparent 0 calc(3.4em + 80ch),
420
- var(--me-print-margin) calc(3.4em + 80ch) calc(3.4em + 80ch + 1px),
421
- transparent calc(3.4em + 80ch + 1px)
422
- ),
697
+ to right,
698
+ transparent 0 calc(3.4em + 80ch),
699
+ var(--me-print-margin) calc(3.4em + 80ch) calc(3.4em + 80ch + 1px),
700
+ transparent calc(3.4em + 80ch + 1px)
701
+ ),
423
702
  /* 거터 컬럼 배경 */
424
- linear-gradient(
425
- to right,
426
- var(--me-gutter-bg) 0 3.4em,
427
- transparent 3.4em
428
- ),
703
+ linear-gradient(to right, var(--me-gutter-bg) 0 3.4em, transparent 3.4em),
429
704
  var(--me-code-bg);
430
705
  }
431
706
  /* 활성 줄 — 바인딩의 restoreSelection이 DOM에 is-active를 단다
@@ -467,6 +742,33 @@
467
742
  background-color: var(--me-bracket-bg, rgba(59, 130, 246, 0.28));
468
743
  }
469
744
 
745
+ /* 검색 매치 하이라이트 — searchFeature가 CSS Custom Highlight API로
746
+ * "me-find"/"me-find-active" Range를 등록한다. DOM을 건드리지 않아
747
+ * 매핑·리렌더에 무영향 (me-bracket과 같은 계약) */
748
+ ::highlight(me-find) {
749
+ background-color: var(--me-find-bg, rgba(250, 204, 21, 0.35));
750
+ }
751
+ ::highlight(me-find-active) {
752
+ background-color: var(--me-find-active-bg, rgba(249, 115, 22, 0.45));
753
+ outline: 1px solid var(--me-find-active-bg, rgba(249, 115, 22, 0.45));
754
+ }
755
+
756
+ /* 멘션 칩 — 인라인 atom. 라벨은 DOM 텍스트 없이 ::after로 그려
757
+ * 텍스트 누적 오프셋 매핑(dom.ts)을 건드리지 않는다 */
758
+ .me-mention {
759
+ display: inline-block;
760
+ padding: 0 4px;
761
+ margin: 0 1px;
762
+ border-radius: 4px;
763
+ background: var(--me-mention-bg, rgba(59, 130, 246, 0.12));
764
+ color: var(--me-mention-color, #2563eb);
765
+ font-weight: 500;
766
+ cursor: default;
767
+ }
768
+ .me-mention::after {
769
+ content: "@" attr(data-label);
770
+ }
771
+
470
772
  /* 구분선 — atom 노드라 data-me-path를 직접 갖는다 */
471
773
  .me-editor hr {
472
774
  border: none;
@@ -680,11 +982,18 @@
680
982
  display: flex;
681
983
  align-items: center;
682
984
  /* 한 줄 원칙 — 넘치는 항목은 두 줄로 내리지 않고 ⋯ 메뉴로 보낸다
683
- * (data-rsp 티어, 아래 미디어 쿼리). 남는 초窄 폭은 overflow로 자른다 */
985
+ * (data-rsp 티어, 아래 미디어 쿼리).
986
+ * overflow:hidden을 쓰지 않는다 — absolute인 ⋯/A▾의 .me-menu가
987
+ * 툴바 아래로 열릴 때 같이 잘린다. ⋯는 absolute로 우측에 고정하고
988
+ * padding-right로 그 자리를 비워 넘치는 항목이 그 밑으로 스치게 한다 */
684
989
  flex-wrap: nowrap;
685
- overflow: hidden;
990
+ /* relative+z-index: 툴바 전체를 에디터(.me-editor relative) 위에
991
+ * 올려 ⋯/A▾ 드롭다운이 본문에 가려지지 않게 한다. 팝오버/버블
992
+ * (fixed, z 50~60)보다는 아래라 겹쳐도 그쪽이 위에 뜬다 */
993
+ position: relative;
994
+ z-index: 20;
686
995
  gap: 2px;
687
- padding: 6px 8px;
996
+ padding: 6px 44px 6px 8px;
688
997
  background: var(--me-toolbar-bg);
689
998
  border-bottom: 1px solid var(--me-border-color);
690
999
  /* IDE 크롬 — 툴 라벨도 코드 에디터 폰트로 */
@@ -714,7 +1023,9 @@
714
1023
  display: inline-flex;
715
1024
  align-items: center;
716
1025
  justify-content: center;
717
- transition: background-color 0.12s ease, color 0.12s ease;
1026
+ transition:
1027
+ background-color 0.12s ease,
1028
+ color 0.12s ease;
718
1029
  }
719
1030
 
720
1031
  /* 툴바 아이콘 — 24px viewBox stroke 아이콘을 currentColor로.
@@ -776,13 +1087,19 @@
776
1087
  position: relative;
777
1088
  display: inline-flex;
778
1089
  }
779
- /* ⋯는 항상 우측 끝에 살아있어야 한다 — 툴바가 잘려도(sticky가
780
- * 스크롤/클립 경계에 붙는다) 오버플로 진입점이 사라지지 않는다 */
1090
+ /* ⋯는 항상 우측 끝에 살아있어야 한다 — absolute로 핀 고정해 항목이
1091
+ * 넘쳐도 오버플로 진입점이 사라지지 않는다. 넘친 항목이 밑으로
1092
+ * 스치므로 불투명 배경으로 덮는다. absolute라 이 details 자체가
1093
+ * .me-menu의 containing block이다 */
781
1094
  .me-toolbar > .me-overflow {
782
- position: sticky;
783
- right: 0;
1095
+ position: absolute;
1096
+ /* translateY 중앙정렬 대신 패딩과 같은 top — transform은 스태킹
1097
+ * 컨텍스트를 만들어 자식 .me-menu의 z-index를 가둔다 */
1098
+ right: 8px;
1099
+ top: 6px;
784
1100
  flex-shrink: 0;
785
1101
  background: var(--me-toolbar-bg);
1102
+ border-radius: 6px;
786
1103
  }
787
1104
  .me-overflow > summary,
788
1105
  .me-styles > summary {
@@ -961,10 +1278,10 @@
961
1278
  --me-gutter-bg: rgba(0, 0, 0, 0.22);
962
1279
  --me-gutter-color: #8f908a;
963
1280
  --me-line-active-num: #c2c2bf;
1281
+ --me-node-sel-color: #66d9ef;
964
1282
  }
965
1283
 
966
1284
  .me-frame[data-me-theme="dark"] {
967
- --me-focus-ring: rgba(102, 217, 239, 0.25);
968
1285
  background: #1e1f1c;
969
1286
  }
970
1287
 
@@ -974,7 +1291,6 @@
974
1291
  --me-code-bg: #1e1f1c;
975
1292
  --me-code-border: #3e3d32;
976
1293
  --me-gutter-border: #3e3d32;
977
- --me-line-active-bg: rgba(255, 255, 255, 0.045);
978
1294
  --me-sel-bg: rgba(73, 72, 62, 0.95);
979
1295
  --me-print-margin: rgba(73, 72, 62, 0.9);
980
1296
  }
@@ -1037,6 +1353,14 @@
1037
1353
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
1038
1354
  }
1039
1355
 
1356
+ [data-me-theme="dark"] .me-imgui {
1357
+ --me-toolbar-bg: #1e1f1c;
1358
+ --me-btn-bg: #3e3d32;
1359
+ --me-tool-hover-bg: #575643;
1360
+ --me-accent: #66d9ef;
1361
+ box-shadow: none;
1362
+ }
1363
+
1040
1364
  [data-me-theme="dark"] .me-pop,
1041
1365
  [data-me-theme="dark"] .me-linkcard {
1042
1366
  --me-toolbar-bg: #1e1f1c;
@@ -1064,3 +1388,105 @@
1064
1388
  [data-me-theme="dark"] .me-tool[data-me-cmd="theme"] {
1065
1389
  color: var(--me-tool-active-color);
1066
1390
  }
1391
+
1392
+ /* ── 블록 드래그&드롭 — .me-dnd 오버레이(block-dnd feature)가
1393
+ * .me-editor의 형제로 그린다. 거터 스트립(왼쪽 여백)에만 겹치게 둬
1394
+ * Chrome 캐럿 줄 경계 계산을 지키고, 래퍼는 pointer-events:none이라
1395
+ * 텍스트 클릭을 가로채지 않는다 */
1396
+ .me-dnd {
1397
+ position: absolute;
1398
+ inset: 0;
1399
+ pointer-events: none;
1400
+ }
1401
+ /* 호버 블록의 왼쪽에 붙는 핸들 — 드래그 시작점. gutter 영역
1402
+ * (3.9em) 안에 두고 핸들만 이벤트를 받는다 */
1403
+ .me-drag-handle {
1404
+ position: absolute;
1405
+ left: 0.2em;
1406
+ width: 1.4em;
1407
+ height: 1.4em;
1408
+ display: none;
1409
+ align-items: center;
1410
+ justify-content: center;
1411
+ pointer-events: auto;
1412
+ cursor: grab;
1413
+ color: var(--me-gutter-color);
1414
+ font-size: 12px;
1415
+ line-height: 1;
1416
+ letter-spacing: -0.15em;
1417
+ border-radius: 4px;
1418
+ }
1419
+ .me-drag-handle.is-visible {
1420
+ display: flex;
1421
+ }
1422
+ .me-drag-handle:hover {
1423
+ background: var(--me-gutter-bg);
1424
+ color: var(--me-text-color);
1425
+ }
1426
+ .me-drag-handle:active {
1427
+ cursor: grabbing;
1428
+ }
1429
+ /* 드롭 경계 표시선 — dragover 동안 삽입 위치에 그린다 */
1430
+ .me-drop-line {
1431
+ position: absolute;
1432
+ left: 3.9em;
1433
+ right: 0;
1434
+ height: 2px;
1435
+ display: none;
1436
+ background: var(--me-node-sel-color);
1437
+ border-radius: 1px;
1438
+ }
1439
+ .me-drop-line.is-visible {
1440
+ display: block;
1441
+ }
1442
+
1443
+ /* ── 뷰 데코레이션 — Plugin.decorations가 만드는 span.me-deco.
1444
+ * 기본은 투명 — 기능/테마가 attrs.class로 모양을 준다.
1445
+ * 데모의 TODO 데코는 me-deco-todo로 밑줄을 긋는다 */
1446
+ .me-deco.me-deco-todo {
1447
+ background: rgba(245, 158, 11, 0.16);
1448
+ border-bottom: 1px dashed #d97706;
1449
+ }
1450
+
1451
+ /* ── 원격 커서 — collab-yjs의 carets extension이 paintOverlay로 그리는
1452
+ * 협업 캐럿. .me-imgui처럼 .me-editor의 형제(.me-root의 absolute
1453
+ * 자식)라 DOM↔Point 매핑과 무관하다. 피어별 색은 요소의
1454
+ * --me-remote-color 인라인 변수로 들어온다 */
1455
+ .me-carets {
1456
+ position: absolute;
1457
+ inset: 0;
1458
+ pointer-events: none;
1459
+ z-index: 35;
1460
+ overflow: hidden;
1461
+ }
1462
+ /* 캐럿 바 — 2px 세로선, 높이는 JS가 줄 높이로 맞춘다 */
1463
+ .me-remote-caret {
1464
+ position: absolute;
1465
+ width: 2px;
1466
+ background: var(--me-remote-color, #f59e0b);
1467
+ }
1468
+ /* 이름 라벨 — 캐럿 위에 붙는 작은 깃발 (y-prosemirror 관례) */
1469
+ .me-remote-caret-label {
1470
+ position: absolute;
1471
+ top: -1.15em;
1472
+ left: -1px;
1473
+ padding: 0 4px;
1474
+ border-radius: 3px 3px 3px 0;
1475
+ background: var(--me-remote-color, #f59e0b);
1476
+ color: #fff;
1477
+ font:
1478
+ 600 10px/1.5 ui-sans-serif,
1479
+ system-ui,
1480
+ sans-serif;
1481
+ white-space: nowrap;
1482
+ user-select: none;
1483
+ }
1484
+ /* 원격 선택 영역 — Range.getClientRects()로 줄별 rect를 깐다 */
1485
+ .me-remote-sel {
1486
+ position: absolute;
1487
+ background: color-mix(
1488
+ in srgb,
1489
+ var(--me-remote-color, #f59e0b) 22%,
1490
+ transparent
1491
+ );
1492
+ }