@moda-editor/core 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (252) 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 +304 -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 +169 -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 +345 -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 -1748
  52. package/dist/conformance.js.map +1 -1
  53. package/dist/editor/editor.d.ts.map +1 -1
  54. package/dist/editor/editor.js +18 -1
  55. package/dist/editor/editor.js.map +1 -1
  56. package/dist/editor/extension.d.ts +47 -3
  57. package/dist/editor/extension.d.ts.map +1 -1
  58. package/dist/features/ace.d.ts +4 -0
  59. package/dist/features/ace.d.ts.map +1 -1
  60. package/dist/features/ace.js +59 -20
  61. package/dist/features/ace.js.map +1 -1
  62. package/dist/features/block-dnd.d.ts +7 -0
  63. package/dist/features/block-dnd.d.ts.map +1 -0
  64. package/dist/features/block-dnd.js +207 -0
  65. package/dist/features/block-dnd.js.map +1 -0
  66. package/dist/features/code-block.d.ts +9 -84
  67. package/dist/features/code-block.d.ts.map +1 -1
  68. package/dist/features/code-block.js +84 -1034
  69. package/dist/features/code-block.js.map +1 -1
  70. package/dist/features/code-context.d.ts +81 -0
  71. package/dist/features/code-context.d.ts.map +1 -0
  72. package/dist/features/code-context.js +322 -0
  73. package/dist/features/code-context.js.map +1 -0
  74. package/dist/features/code-edit.d.ts +50 -0
  75. package/dist/features/code-edit.d.ts.map +1 -0
  76. package/dist/features/code-edit.js +412 -0
  77. package/dist/features/code-edit.js.map +1 -0
  78. package/dist/features/code-format.d.ts +21 -0
  79. package/dist/features/code-format.d.ts.map +1 -0
  80. package/dist/features/code-format.js +410 -0
  81. package/dist/features/code-format.js.map +1 -0
  82. package/dist/features/doc.d.ts +16 -0
  83. package/dist/features/doc.d.ts.map +1 -1
  84. package/dist/features/doc.js +154 -2
  85. package/dist/features/doc.js.map +1 -1
  86. package/dist/features/heading.d.ts.map +1 -1
  87. package/dist/features/heading.js.map +1 -1
  88. package/dist/features/image.d.ts +3 -1
  89. package/dist/features/image.d.ts.map +1 -1
  90. package/dist/features/image.js +27 -9
  91. package/dist/features/image.js.map +1 -1
  92. package/dist/features/index.d.ts +7 -0
  93. package/dist/features/index.d.ts.map +1 -1
  94. package/dist/features/index.js +16 -0
  95. package/dist/features/index.js.map +1 -1
  96. package/dist/features/inline-style.d.ts.map +1 -1
  97. package/dist/features/inline-style.js +4 -1
  98. package/dist/features/inline-style.js.map +1 -1
  99. package/dist/features/link.d.ts.map +1 -1
  100. package/dist/features/link.js +1 -1
  101. package/dist/features/link.js.map +1 -1
  102. package/dist/features/markdown.d.ts +15 -0
  103. package/dist/features/markdown.d.ts.map +1 -0
  104. package/dist/features/markdown.js +80 -0
  105. package/dist/features/markdown.js.map +1 -0
  106. package/dist/features/marks.d.ts.map +1 -1
  107. package/dist/features/marks.js +49 -4
  108. package/dist/features/marks.js.map +1 -1
  109. package/dist/features/mention.d.ts +30 -0
  110. package/dist/features/mention.d.ts.map +1 -0
  111. package/dist/features/mention.js +89 -0
  112. package/dist/features/mention.js.map +1 -0
  113. package/dist/features/script.d.ts.map +1 -1
  114. package/dist/features/script.js.map +1 -1
  115. package/dist/features/search.d.ts +76 -0
  116. package/dist/features/search.d.ts.map +1 -0
  117. package/dist/features/search.js +281 -0
  118. package/dist/features/search.js.map +1 -0
  119. package/dist/features/shared.d.ts +69 -0
  120. package/dist/features/shared.d.ts.map +1 -0
  121. package/dist/features/shared.js +272 -0
  122. package/dist/features/shared.js.map +1 -0
  123. package/dist/features/table.d.ts.map +1 -1
  124. package/dist/features/table.js +17 -3
  125. package/dist/features/table.js.map +1 -1
  126. package/dist/features/testkit.d.ts.map +1 -1
  127. package/dist/features/testkit.js +1 -1
  128. package/dist/features/testkit.js.map +1 -1
  129. package/dist/history.d.ts.map +1 -1
  130. package/dist/history.js +65 -20
  131. package/dist/history.js.map +1 -1
  132. package/dist/index.d.ts +21 -7
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +18 -6
  135. package/dist/index.js.map +1 -1
  136. package/dist/model/schema.d.ts.map +1 -1
  137. package/dist/model/schema.js +2 -1
  138. package/dist/model/schema.js.map +1 -1
  139. package/dist/parse/html.d.ts.map +1 -1
  140. package/dist/parse/html.js +38 -6
  141. package/dist/parse/html.js.map +1 -1
  142. package/dist/parse/sanitize.d.ts.map +1 -1
  143. package/dist/parse/sanitize.js +4 -1
  144. package/dist/parse/sanitize.js.map +1 -1
  145. package/dist/presets/highlight.d.ts.map +1 -1
  146. package/dist/presets/highlight.js +1 -4
  147. package/dist/presets/highlight.js.map +1 -1
  148. package/dist/presets/markdown-parse.d.ts +13 -0
  149. package/dist/presets/markdown-parse.d.ts.map +1 -0
  150. package/dist/presets/markdown-parse.js +398 -0
  151. package/dist/presets/markdown-parse.js.map +1 -0
  152. package/dist/presets/markdown.d.ts +46 -0
  153. package/dist/presets/markdown.d.ts.map +1 -0
  154. package/dist/presets/markdown.js +196 -0
  155. package/dist/presets/markdown.js.map +1 -0
  156. package/dist/state/apply.d.ts.map +1 -1
  157. package/dist/state/apply.js +25 -13
  158. package/dist/state/apply.js.map +1 -1
  159. package/dist/state/delete-ops.d.ts +34 -0
  160. package/dist/state/delete-ops.d.ts.map +1 -0
  161. package/dist/state/delete-ops.js +204 -0
  162. package/dist/state/delete-ops.js.map +1 -0
  163. package/dist/state/input-rules.d.ts +30 -0
  164. package/dist/state/input-rules.d.ts.map +1 -0
  165. package/dist/state/input-rules.js +70 -0
  166. package/dist/state/input-rules.js.map +1 -0
  167. package/dist/state/insert-ops.d.ts +54 -0
  168. package/dist/state/insert-ops.d.ts.map +1 -0
  169. package/dist/state/insert-ops.js +186 -0
  170. package/dist/state/insert-ops.js.map +1 -0
  171. package/dist/state/list-ops.d.ts +46 -0
  172. package/dist/state/list-ops.d.ts.map +1 -0
  173. package/dist/state/list-ops.js +231 -0
  174. package/dist/state/list-ops.js.map +1 -0
  175. package/dist/state/navigate.d.ts.map +1 -1
  176. package/dist/state/navigate.js +3 -1
  177. package/dist/state/navigate.js.map +1 -1
  178. package/dist/state/resolve-insert.d.ts +55 -0
  179. package/dist/state/resolve-insert.d.ts.map +1 -0
  180. package/dist/state/resolve-insert.js +118 -0
  181. package/dist/state/resolve-insert.js.map +1 -0
  182. package/dist/state/slice-ops.d.ts +46 -0
  183. package/dist/state/slice-ops.d.ts.map +1 -0
  184. package/dist/state/slice-ops.js +150 -0
  185. package/dist/state/slice-ops.js.map +1 -0
  186. package/dist/state/state.d.ts +6 -1
  187. package/dist/state/state.d.ts.map +1 -1
  188. package/dist/state/state.js +10 -0
  189. package/dist/state/state.js.map +1 -1
  190. package/dist/state/transaction.d.ts +43 -49
  191. package/dist/state/transaction.d.ts.map +1 -1
  192. package/dist/state/transaction.js +62 -858
  193. package/dist/state/transaction.js.map +1 -1
  194. package/dist/styles.css +401 -213
  195. package/dist/theme.d.ts +29 -0
  196. package/dist/theme.d.ts.map +1 -0
  197. package/dist/theme.js +347 -0
  198. package/dist/theme.js.map +1 -0
  199. package/dist/view/adapter.d.ts +84 -0
  200. package/dist/view/adapter.d.ts.map +1 -0
  201. package/dist/view/adapter.js +76 -0
  202. package/dist/view/adapter.js.map +1 -0
  203. package/dist/view/caret.d.ts +25 -0
  204. package/dist/view/caret.d.ts.map +1 -0
  205. package/dist/view/caret.js +43 -0
  206. package/dist/view/caret.js.map +1 -0
  207. package/dist/view/decoration.d.ts +9 -0
  208. package/dist/view/decoration.d.ts.map +1 -0
  209. package/dist/view/decoration.js +214 -0
  210. package/dist/view/decoration.js.map +1 -0
  211. package/dist/view/dirty-keys.d.ts +18 -0
  212. package/dist/view/dirty-keys.d.ts.map +1 -0
  213. package/dist/view/dirty-keys.js +31 -0
  214. package/dist/view/dirty-keys.js.map +1 -0
  215. package/dist/view/dom.d.ts.map +1 -1
  216. package/dist/view/dom.js +7 -5
  217. package/dist/view/dom.js.map +1 -1
  218. package/dist/view/hook-ctx.d.ts +32 -0
  219. package/dist/view/hook-ctx.d.ts.map +1 -0
  220. package/dist/view/hook-ctx.js +64 -0
  221. package/dist/view/hook-ctx.js.map +1 -0
  222. package/dist/view/ime.d.ts +72 -0
  223. package/dist/view/ime.d.ts.map +1 -0
  224. package/dist/view/ime.js +185 -0
  225. package/dist/view/ime.js.map +1 -0
  226. package/dist/view/input.d.ts +12 -12
  227. package/dist/view/input.d.ts.map +1 -1
  228. package/dist/view/input.js +156 -535
  229. package/dist/view/input.js.map +1 -1
  230. package/dist/view/keys.d.ts +25 -0
  231. package/dist/view/keys.d.ts.map +1 -0
  232. package/dist/view/keys.js +106 -0
  233. package/dist/view/keys.js.map +1 -0
  234. package/dist/view/line-nav.d.ts +13 -0
  235. package/dist/view/line-nav.d.ts.map +1 -0
  236. package/dist/view/line-nav.js +114 -0
  237. package/dist/view/line-nav.js.map +1 -0
  238. package/dist/view/mount.d.ts.map +1 -1
  239. package/dist/view/mount.js +43 -39
  240. package/dist/view/mount.js.map +1 -1
  241. package/dist/view/node-selection.d.ts +33 -0
  242. package/dist/view/node-selection.d.ts.map +1 -0
  243. package/dist/view/node-selection.js +107 -0
  244. package/dist/view/node-selection.js.map +1 -0
  245. package/dist/view/render.d.ts +4 -1
  246. package/dist/view/render.d.ts.map +1 -1
  247. package/dist/view/render.js +22 -3
  248. package/dist/view/render.js.map +1 -1
  249. package/dist/view/serialize.d.ts.map +1 -1
  250. package/dist/view/serialize.js +14 -5
  251. package/dist/view/serialize.js.map +1 -1
  252. package/package.json +1 -1
package/dist/styles.css CHANGED
@@ -4,8 +4,8 @@
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
  * 같은 변수를 상속해 그라디언트에 쓴다 */
@@ -53,19 +53,35 @@
53
53
  /* ── 에디터 크롬 — .me-frame이 툴바+에디터+상태바를 하나의 카드로
54
54
  * 묶는다. 단독 .me-editor도 테두리를 갖지만 frame 안에서는 frame이
55
55
  * 크롬을 담당한다 ─────────────────────────────────────────── */
56
+ /* ── 테마 허브 — 크롬 변수는 .me-frame에, 본문 변수는 .me-editor에
57
+ * 모아 둔다. 리프 요소(.me-toolbar/.me-statusbar/.me-pop/blockquote/
58
+ * pre 토큰 등)는 변수를 자체 정의하지 않고 var()로만 소비한다 —
59
+ * 그래야 applyTheme이 허브에 박은 변수 맵이 상속으로 전부 도달해
60
+ * 테마가 플랫한 { --me-*: 값 } 객체 하나로 표현된다 ────────────── */
56
61
  .me-frame {
62
+ --me-frame-bg: #ffffff;
57
63
  --me-frame-shadow: 0 1px 2px rgba(15, 23, 42, 0.06);
58
64
  --me-border-color: #e2e8f0;
59
65
  --me-text-color: #1e293b;
60
- --me-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas,
61
- "Liberation Mono", monospace;
66
+ --me-font-mono:
67
+ ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
68
+ /* 크롬 서페이스 — 툴바/상태바/팝오버/버블이 공유한다 */
69
+ --me-toolbar-bg: #f8fafc;
70
+ --me-tool-hover-bg: #e2e8f0;
71
+ --me-tool-active-bg: #dbeafe;
72
+ --me-tool-active-color: #1d4ed8;
73
+ --me-status-color: #64748b;
74
+ /* 뜨는 UI(팝오버/버블/카드/그리드)의 공통 그림자 */
75
+ --me-pop-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
62
76
 
63
77
  color: var(--me-text-color);
64
- background: #ffffff;
78
+ background: var(--me-frame-bg);
65
79
  border: 1px solid var(--me-border-color);
66
80
  border-radius: 10px;
67
81
  box-shadow: var(--me-frame-shadow);
68
82
  overflow: hidden;
83
+ /* 우하단 앵커 요소(상태바 탭·출력 패널)의 containing block */
84
+ position: relative;
69
85
  }
70
86
 
71
87
  /* 포커스 표시는 테두리 색만 — 글로우 링은 입력 중 카드 전체를
@@ -86,6 +102,26 @@
86
102
  --me-gutter-border: var(--me-border-color);
87
103
  --me-sel-bg: rgba(59, 130, 246, 0.22);
88
104
  --me-print-margin: rgba(148, 163, 184, 0.4);
105
+ /* 본문 콘텐츠 변수 — 인용구/링크/플레이스홀더/체크박스/콜아웃은
106
+ * 모두 .me-editor 안에 렌더되므로 여기가 기본값의 고향이다 */
107
+ --me-quote-color: #64748b;
108
+ --me-link-color: #2563eb;
109
+ --me-placeholder-color: #94a3b8;
110
+ --me-checkbox-border: #94a3b8;
111
+ --me-checkbox-checked: #2563eb;
112
+ --me-callout-bg: #eff6ff;
113
+ --me-callout-border: #bfdbfe;
114
+ --me-callout-accent: #3b82f6;
115
+ /* 구문 하이라이트 토큰 팔레트 — GitHub Light 계열 (pre가 아니라
116
+ * 허브에 둬야 테마 변수가 .me-tok-* 소비자까지 상속된다) */
117
+ --me-tok-keyword: #cf222e;
118
+ --me-tok-string: #0a3069;
119
+ --me-tok-comment: #6e7781;
120
+ --me-tok-number: #0550ae;
121
+ --me-tok-literal: #0550ae;
122
+ --me-tok-function: #8250df;
123
+ --me-tok-tag: #116329;
124
+ --me-tok-attr: #953800;
89
125
 
90
126
  min-height: 160px;
91
127
  position: relative;
@@ -109,17 +145,13 @@
109
145
  ),
110
146
  /* print margin — 80열 (Ace showPrintMargin 관례) */
111
147
  linear-gradient(
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
- ),
148
+ to right,
149
+ transparent 0 calc(3.9em + 80ch),
150
+ var(--me-print-margin) calc(3.9em + 80ch) calc(3.9em + 80ch + 1px),
151
+ transparent calc(3.9em + 80ch + 1px)
152
+ ),
117
153
  /* 거터 컬럼 배경 */
118
- linear-gradient(
119
- to right,
120
- var(--me-gutter-bg) 0 3.9em,
121
- transparent 3.9em
122
- ),
154
+ linear-gradient(to right, var(--me-gutter-bg) 0 3.9em, transparent 3.9em),
123
155
  var(--me-editor-bg);
124
156
  }
125
157
 
@@ -228,22 +260,40 @@
228
260
  margin-bottom: 0;
229
261
  }
230
262
 
231
- .me-editor h1 { font-size: 1.55em; }
232
- .me-editor h2 { font-size: 1.35em; }
233
- .me-editor h3 { font-size: 1.2em; }
263
+ .me-editor h1 {
264
+ font-size: 1.55em;
265
+ }
266
+ .me-editor h2 {
267
+ font-size: 1.35em;
268
+ }
269
+ .me-editor h3 {
270
+ font-size: 1.2em;
271
+ }
234
272
  .me-editor h4,
235
273
  .me-editor h5,
236
- .me-editor h6 { font-size: 1.05em; }
274
+ .me-editor h6 {
275
+ font-size: 1.05em;
276
+ }
237
277
 
278
+ /* 인라인 코드 — GitHub/Slack/Notion 관례의 옅은 배경 + 고정폭.
279
+ * 테두리를 두지 않는다 — 테두리 칩은 멘션 등 interactive atom의
280
+ * 시각 언어라 코드 마크와 겹치면 구분이 안 된다 */
238
281
  .me-editor code {
239
282
  padding: 0.08em 0.35em;
240
283
  background: var(--me-code-bg);
241
- border: 1px solid var(--me-code-border);
242
284
  border-radius: 4px;
243
285
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
244
286
  font-size: 0.88em;
245
287
  }
246
288
 
289
+ /* 빈 코드 칩 — CODE_CHIP(zwsp) 자리표시자는 내용이 없어 보이지
290
+ * 않으니 </> 힌트를 옅게 띄운다 (버튼 아이콘과 같은 모양).
291
+ * 타이핑이 zwsp를 대체하면 클래스가 빠져 힌트도 사라진다 */
292
+ .me-editor code.me-codechip::after {
293
+ content: "</>";
294
+ opacity: 0.45;
295
+ }
296
+
247
297
  /* 리스트 — li 안 문단은 자체 여백이 없다 (li가 줄 간격을 담당).
248
298
  * 패딩이 마커 열이다: outside 마커(•, 1.)가 텍스트 왼쪽에 붙어
249
299
  * 그려지므로, 마커가 거터 구분선에 닿지 않을 만큼의 들여쓰기가 필요 */
@@ -270,8 +320,6 @@
270
320
  padding-left: 24px;
271
321
  }
272
322
  .me-editor li.me-task::before {
273
- --me-checkbox-border: #94a3b8;
274
- --me-checkbox-checked: #2563eb;
275
323
  content: "";
276
324
  position: absolute;
277
325
  left: 4px;
@@ -339,6 +387,12 @@
339
387
  /* hr은 테두리가 굵어 outline이 묻힌다 — 위아래 여백으로 링을 띄운다 */
340
388
  outline-offset: 4px;
341
389
  }
390
+ /* 노드 뷰 컴포넌트 셀렉션 — data-me-path는 안쪽 아울렛에 달리므로
391
+ * 래퍼에 별도 룰을 둔다 (input.ts가 래퍼로 올려 마킹한다) */
392
+ .me-editor .me-node-view.is-selected {
393
+ outline: 2px solid var(--me-node-sel-color);
394
+ outline-offset: 2px;
395
+ }
342
396
 
343
397
  /* ── 이미지 선택 오버레이 — 선택된 img 위에 얹히는 편집/리사이즈 UI.
344
398
  * .me-editor의 형제(.me-root의 absolute 자식)로 둬 DOM↔Point 매핑을
@@ -377,11 +431,11 @@
377
431
  flex-wrap: wrap;
378
432
  gap: 3px;
379
433
  padding: 4px;
380
- max-width: min(320px, 90vw);
434
+ max-width: min(400px, 92vw);
381
435
  background: var(--me-toolbar-bg, #fff);
382
436
  border: 1px solid var(--me-border-color);
383
437
  border-radius: 6px;
384
- box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
438
+ box-shadow: var(--me-pop-shadow, 0 4px 14px rgba(15, 23, 42, 0.18));
385
439
  pointer-events: auto;
386
440
  }
387
441
  .me-imgui.is-below .me-img-bar {
@@ -390,9 +444,11 @@
390
444
  transform: translateY(100%);
391
445
  }
392
446
  .me-imgui .me-imgbtn {
447
+ flex: none;
393
448
  padding: 3px 8px;
394
449
  font: inherit;
395
450
  font-size: 12px;
451
+ white-space: nowrap;
396
452
  color: inherit;
397
453
  background: var(--me-btn-bg, transparent);
398
454
  border: 1px solid var(--me-border-color);
@@ -406,18 +462,27 @@
406
462
  color: #dc2626;
407
463
  border-color: #dc2626;
408
464
  }
409
- /* 편집 폼 — 액션 바 안의 두 번째 행 (wrap으로 전체 폭을 차지) */
465
+ /* 편집 폼 — 액션 바 안의 두 번째 행 (wrap으로 전체 폭을 차지).
466
+ * 최소 폭을 둬 버튼 행보다 바가 좁아져 입력이 찌그러지지 않게 한다 */
410
467
  .me-imgui .me-imgedit {
411
468
  flex-basis: 100%;
469
+ min-width: min(300px, 80vw);
412
470
  display: flex;
413
471
  gap: 4px;
414
472
  }
415
473
  .me-imgui .me-imgedit[hidden] {
416
474
  display: none;
417
475
  }
476
+ .me-imgui .me-imged-src {
477
+ flex: 3 1 0;
478
+ }
479
+ .me-imgui .me-imged-alt {
480
+ flex: 2 1 0;
481
+ }
418
482
  .me-imgui .me-imged-src,
419
483
  .me-imgui .me-imged-alt {
420
- width: min(150px, 30vw);
484
+ width: 0;
485
+ min-width: 0;
421
486
  padding: 4px 6px;
422
487
  font: inherit;
423
488
  font-size: 12px;
@@ -454,7 +519,7 @@
454
519
  background: var(--me-toolbar-bg, #fff);
455
520
  border: 1px solid var(--me-border-color);
456
521
  border-radius: 6px;
457
- box-shadow: 0 4px 14px rgba(15, 23, 42, 0.18);
522
+ box-shadow: var(--me-pop-shadow, 0 4px 14px rgba(15, 23, 42, 0.18));
458
523
  white-space: nowrap;
459
524
  pointer-events: auto;
460
525
  }
@@ -523,7 +588,7 @@
523
588
  background: var(--me-toolbar-bg, #fff);
524
589
  border: 1px solid var(--me-border-color);
525
590
  border-radius: 6px;
526
- box-shadow: 0 2px 8px rgba(15, 23, 42, 0.12);
591
+ box-shadow: var(--me-pop-shadow, 0 2px 8px rgba(15, 23, 42, 0.12));
527
592
  white-space: nowrap;
528
593
  }
529
594
  .me-codeui[hidden] {
@@ -610,7 +675,6 @@
610
675
 
611
676
  /* 인용구 */
612
677
  .me-editor blockquote {
613
- --me-quote-color: #64748b;
614
678
  padding: 2px 0 2px 12px;
615
679
  border-left: 3px solid var(--me-border-color);
616
680
  color: var(--me-quote-color);
@@ -630,17 +694,6 @@
630
694
  white-space: pre-wrap;
631
695
  /* 코드블록 Tab은 \t 문자를 넣는다 — 탭 폭은 4 (CodeMirror 관례) */
632
696
  tab-size: 4;
633
-
634
- /* 구문 하이라이트 토큰 팔레트 — GitHub Light 계열.
635
- * 테마는 --me-tok-* 변수로 바꾼다 */
636
- --me-tok-keyword: #cf222e;
637
- --me-tok-string: #0a3069;
638
- --me-tok-comment: #6e7781;
639
- --me-tok-number: #0550ae;
640
- --me-tok-literal: #0550ae;
641
- --me-tok-function: #8250df;
642
- --me-tok-tag: #116329;
643
- --me-tok-attr: #953800;
644
697
  }
645
698
  .me-editor pre code {
646
699
  padding: 0;
@@ -690,17 +743,13 @@
690
743
  ),
691
744
  /* print margin — 80열 (Ace showPrintMargin 관례) */
692
745
  linear-gradient(
693
- to right,
694
- transparent 0 calc(3.4em + 80ch),
695
- var(--me-print-margin) calc(3.4em + 80ch) calc(3.4em + 80ch + 1px),
696
- transparent calc(3.4em + 80ch + 1px)
697
- ),
746
+ to right,
747
+ transparent 0 calc(3.4em + 80ch),
748
+ var(--me-print-margin) calc(3.4em + 80ch) calc(3.4em + 80ch + 1px),
749
+ transparent calc(3.4em + 80ch + 1px)
750
+ ),
698
751
  /* 거터 컬럼 배경 */
699
- linear-gradient(
700
- to right,
701
- var(--me-gutter-bg) 0 3.4em,
702
- transparent 3.4em
703
- ),
752
+ linear-gradient(to right, var(--me-gutter-bg) 0 3.4em, transparent 3.4em),
704
753
  var(--me-code-bg);
705
754
  }
706
755
  /* 활성 줄 — 바인딩의 restoreSelection이 DOM에 is-active를 단다
@@ -742,6 +791,33 @@
742
791
  background-color: var(--me-bracket-bg, rgba(59, 130, 246, 0.28));
743
792
  }
744
793
 
794
+ /* 검색 매치 하이라이트 — searchFeature가 CSS Custom Highlight API로
795
+ * "me-find"/"me-find-active" Range를 등록한다. DOM을 건드리지 않아
796
+ * 매핑·리렌더에 무영향 (me-bracket과 같은 계약) */
797
+ ::highlight(me-find) {
798
+ background-color: var(--me-find-bg, rgba(250, 204, 21, 0.35));
799
+ }
800
+ ::highlight(me-find-active) {
801
+ background-color: var(--me-find-active-bg, rgba(249, 115, 22, 0.45));
802
+ outline: 1px solid var(--me-find-active-bg, rgba(249, 115, 22, 0.45));
803
+ }
804
+
805
+ /* 멘션 칩 — 인라인 atom. 라벨은 DOM 텍스트 없이 ::after로 그려
806
+ * 텍스트 누적 오프셋 매핑(dom.ts)을 건드리지 않는다 */
807
+ .me-mention {
808
+ display: inline-block;
809
+ padding: 0 4px;
810
+ margin: 0 1px;
811
+ border-radius: 4px;
812
+ background: var(--me-mention-bg, rgba(59, 130, 246, 0.12));
813
+ color: var(--me-mention-color, #2563eb);
814
+ font-weight: 500;
815
+ cursor: default;
816
+ }
817
+ .me-mention::after {
818
+ content: "@" attr(data-label);
819
+ }
820
+
745
821
  /* 구분선 — atom 노드라 data-me-path를 직접 갖는다 */
746
822
  .me-editor hr {
747
823
  border: none;
@@ -751,7 +827,6 @@
751
827
 
752
828
  /* 링크 */
753
829
  .me-editor a {
754
- --me-link-color: #2563eb;
755
830
  color: var(--me-link-color);
756
831
  text-decoration: underline;
757
832
  text-underline-offset: 2px;
@@ -760,7 +835,6 @@
760
835
  /* 플레이스홀더 — 문서가 빈 문단 하나뿐일 때만 표시 (PM 관례) */
761
836
  .me-editor > p:only-child:has(> br:only-child)::before,
762
837
  .me-editor > p:only-child:has(> span > br:only-child)::before {
763
- --me-placeholder-color: #94a3b8;
764
838
  content: var(--me-placeholder-text, "내용을 입력하세요…");
765
839
  float: left;
766
840
  height: 0;
@@ -779,7 +853,7 @@
779
853
  background: var(--me-toolbar-bg, #fff);
780
854
  border: 1px solid var(--me-border-color);
781
855
  border-radius: 8px;
782
- box-shadow: 0 4px 16px rgba(15, 23, 42, 0.14);
856
+ box-shadow: var(--me-pop-shadow, 0 4px 16px rgba(15, 23, 42, 0.14));
783
857
  }
784
858
  .me-bubble .me-tool {
785
859
  min-width: 26px;
@@ -802,7 +876,7 @@
802
876
  background: var(--me-toolbar-bg, #fff);
803
877
  border: 1px solid var(--me-border-color);
804
878
  border-radius: 8px;
805
- box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
879
+ box-shadow: var(--me-pop-shadow, 0 8px 24px rgba(15, 23, 42, 0.18));
806
880
  }
807
881
  .me-pop-input {
808
882
  width: min(220px, 46vw);
@@ -838,6 +912,114 @@
838
912
  display: inline-flex;
839
913
  align-items: center;
840
914
  }
915
+ /* 찾기 팝 — 검색 줄 + 바꾸기 줄 두 행 (VS Code/GDocs find-replace 관례).
916
+ * 너비를 고정해 dev-shared의 위치 추정치(POP_SIZE.find)와 맞춘다 —
917
+ * 우상단 정렬이 실측 너비에 흔들리지 않게.
918
+ * absolute라 .me-frame 안에 갇힌다 — fixed면 스크롤 시 프레임과
919
+ * 분리돼 컴포넌트 밖으로 새나간다 */
920
+ .me-pop-find {
921
+ position: absolute;
922
+ flex-direction: column;
923
+ align-items: stretch;
924
+ width: 320px;
925
+ max-width: calc(100vw - 16px);
926
+ box-sizing: border-box;
927
+ }
928
+ .me-pop-row {
929
+ display: flex;
930
+ align-items: center;
931
+ gap: 4px;
932
+ }
933
+ .me-pop-row > .me-pop-input {
934
+ flex: 1;
935
+ min-width: 0;
936
+ }
937
+ /* 찾기 팝의 n/total 카운터 — GDocs 찾기 바 관례 */
938
+ .me-pop-count {
939
+ min-width: 34px;
940
+ font-size: 11px;
941
+ color: var(--me-muted-color, #64748b);
942
+ text-align: center;
943
+ }
944
+ /* 보기 전환 탭 — 상태바 우측의 에디터/마크다운 세그먼트
945
+ * (VS Code editor|preview 관례). .me-frame의 data-me-view를 바꾼다 */
946
+ .me-viewtabs {
947
+ display: inline-flex;
948
+ margin-left: 8px;
949
+ border: 1px solid var(--me-border-color);
950
+ border-radius: 5px;
951
+ overflow: hidden;
952
+ }
953
+ .me-viewtabs button {
954
+ padding: 0 8px;
955
+ font: inherit;
956
+ color: inherit;
957
+ background: transparent;
958
+ border: none;
959
+ cursor: pointer;
960
+ }
961
+ .me-viewtabs button + button {
962
+ border-left: 1px solid var(--me-border-color);
963
+ }
964
+ .me-viewtabs button:hover {
965
+ background: var(--me-btn-hover-bg, #e2e8f0);
966
+ }
967
+ .me-viewtabs button.is-on {
968
+ background: var(--me-btn-hover-bg, #e2e8f0);
969
+ color: var(--me-accent, #2563eb);
970
+ }
971
+
972
+ /* 마크다운 뷰 — [data-me-view="md"]일 때 에디터 영역을 대체한다.
973
+ * .me-root는 display:none으로 숨기되 DOM은 유지해 셀렉션/바인딩이
974
+ * 깨지지 않는다 — 돌아오면 그대로 이어진다 */
975
+ .me-md-view {
976
+ display: none;
977
+ }
978
+ .me-frame[data-me-view="md"] .me-root {
979
+ display: none;
980
+ }
981
+ /* 숨은 에디터 위에 떠 있는 플로팅 요소도 함께 가린다 */
982
+ .me-frame[data-me-view="md"] .me-bubble,
983
+ .me-frame[data-me-view="md"] .me-linkcard {
984
+ display: none;
985
+ }
986
+ .me-frame[data-me-view="md"] > .me-md-view {
987
+ display: flex;
988
+ flex-direction: column;
989
+ }
990
+ .me-md-view .me-md-head {
991
+ display: flex;
992
+ justify-content: flex-end;
993
+ padding: 4px 8px;
994
+ border-bottom: 1px solid var(--me-border-color);
995
+ }
996
+ .me-md-view .me-md-text {
997
+ min-height: 220px;
998
+ padding: 10px 16px;
999
+ border: none;
1000
+ resize: vertical;
1001
+ font-family: var(--me-font-mono);
1002
+ font-size: 12.5px;
1003
+ line-height: 1.6;
1004
+ color: var(--me-text-color);
1005
+ background: transparent;
1006
+ }
1007
+ .me-md-view .me-md-text:focus {
1008
+ outline: none;
1009
+ }
1010
+ .me-pop-textarea {
1011
+ width: 100%;
1012
+ height: 160px;
1013
+ padding: 6px 8px;
1014
+ font-family: var(--me-font-mono, monospace);
1015
+ font-size: 12px;
1016
+ color: inherit;
1017
+ background: transparent;
1018
+ border: 1px solid var(--me-border-color);
1019
+ border-radius: 5px;
1020
+ outline: none;
1021
+ resize: vertical;
1022
+ }
841
1023
 
842
1024
  /* 표 크기 피커 — GDocs 표 삽입 그리드 관례. 열 수는 data.ts의
843
1025
  * TGRID_COLS(10)와 짝 — 바꾸면 둘 다 갱신한다 */
@@ -884,7 +1066,7 @@
884
1066
  background: var(--me-toolbar-bg, #fff);
885
1067
  border: 1px solid var(--me-border-color);
886
1068
  border-radius: 8px;
887
- box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
1069
+ box-shadow: var(--me-pop-shadow, 0 8px 24px rgba(15, 23, 42, 0.18));
888
1070
  }
889
1071
  .me-linkcard-url {
890
1072
  flex: 1;
@@ -923,9 +1105,6 @@
923
1105
  /* 데모용 callout 노드 컴포넌트 — 아이콘 크롬 + 편집 콘텐츠.
924
1106
  * 왼쪽 액센트 바는 GitHub alert/Notion callout 관례 */
925
1107
  .me-callout {
926
- --me-callout-bg: #eff6ff;
927
- --me-callout-border: #bfdbfe;
928
- --me-callout-accent: #3b82f6;
929
1108
 
930
1109
  display: flex;
931
1110
  gap: 8px;
@@ -947,19 +1126,15 @@
947
1126
  /* ── 툴바 — 데모/스타터용 에디터 크롬. 어댑터 계약이 아니라
948
1127
  * 선택적 UI라 앱이 자체 툴바를 써도 된다 ─────────────────────── */
949
1128
  .me-toolbar {
950
- --me-toolbar-bg: #f8fafc;
951
- --me-tool-hover-bg: #e2e8f0;
952
- --me-tool-active-bg: #dbeafe;
953
- --me-tool-active-color: #1d4ed8;
954
-
955
1129
  display: flex;
956
1130
  align-items: center;
957
- /* 한 줄 원칙 — 넘치는 항목은 두 줄로 내리지 않고 ⋯ 메뉴로 보낸다
958
- * (data-rsp 티어, 아래 미디어 쿼리).
959
- * overflow:hidden을 쓰지 않는다 — absolute인 ⋯/A▾의 .me-menu가
960
- * 툴바 아래로 열릴 때 같이 잘린다. ⋯는 absolute로 우측에 고정하고
961
- * padding-right로 그 자리를 비워 넘치는 항목이 그 밑으로 스치게 한다 */
962
- flex-wrap: nowrap;
1131
+ /* 좁은 폭에서는 항목을 숨기지 않고 다음 줄로 감는다 (GDocs/Word
1132
+ * 리본 관례 — 2~3줄까지 늘어난다). overflow:hidden을 쓰지 않는다 —
1133
+ * absolute인 ⋯/A▾의 .me-menu가 툴바 아래로 열릴 때 같이 잘린다.
1134
+ * ⋯는 absolute로 우측 상단에 고정하고 padding-right로 첫 줄 자리를
1135
+ * 비워 둔다 — 줄이 늘어나도 ⋯ 위치는 항상 같다 */
1136
+ flex-wrap: wrap;
1137
+ row-gap: 4px;
963
1138
  /* relative+z-index: 툴바 전체를 에디터(.me-editor relative) 위에
964
1139
  * 올려 ⋯/A▾ 드롭다운이 본문에 가려지지 않게 한다. 팝오버/버블
965
1140
  * (fixed, z 50~60)보다는 아래라 겹쳐도 그쪽이 위에 뜬다 */
@@ -967,7 +1142,7 @@
967
1142
  z-index: 20;
968
1143
  gap: 2px;
969
1144
  padding: 6px 44px 6px 8px;
970
- background: var(--me-toolbar-bg);
1145
+ background: var(--me-toolbar-bg, #f8fafc);
971
1146
  border-bottom: 1px solid var(--me-border-color);
972
1147
  /* IDE 크롬 — 툴 라벨도 코드 에디터 폰트로 */
973
1148
  font-family: var(--me-font-mono);
@@ -996,7 +1171,9 @@
996
1171
  display: inline-flex;
997
1172
  align-items: center;
998
1173
  justify-content: center;
999
- transition: background-color 0.12s ease, color 0.12s ease;
1174
+ transition:
1175
+ background-color 0.12s ease,
1176
+ color 0.12s ease;
1000
1177
  }
1001
1178
 
1002
1179
  /* 툴바 아이콘 — 24px viewBox stroke 아이콘을 currentColor로.
@@ -1013,7 +1190,7 @@
1013
1190
  }
1014
1191
 
1015
1192
  .me-tool:hover:not(:disabled) {
1016
- background: var(--me-tool-hover-bg);
1193
+ background: var(--me-tool-hover-bg, #e2e8f0);
1017
1194
  }
1018
1195
 
1019
1196
  /* 키보드 포커스 표시 — VSCode 크롬 관례 (마우스 클릭엔 링 없음) */
@@ -1027,8 +1204,8 @@
1027
1204
  }
1028
1205
 
1029
1206
  .me-tool.is-active {
1030
- background: var(--me-tool-active-bg);
1031
- color: var(--me-tool-active-color);
1207
+ background: var(--me-tool-active-bg, #dbeafe);
1208
+ color: var(--me-tool-active-color, #1d4ed8);
1032
1209
  }
1033
1210
 
1034
1211
  .me-tool:disabled {
@@ -1069,7 +1246,7 @@
1069
1246
  right: 8px;
1070
1247
  top: 6px;
1071
1248
  flex-shrink: 0;
1072
- background: var(--me-toolbar-bg);
1249
+ background: var(--me-toolbar-bg, #f8fafc);
1073
1250
  border-radius: 6px;
1074
1251
  }
1075
1252
  .me-overflow > summary,
@@ -1095,12 +1272,12 @@
1095
1272
  }
1096
1273
  .me-overflow > summary:hover,
1097
1274
  .me-styles > summary:hover {
1098
- background: var(--me-tool-hover-bg);
1275
+ background: var(--me-tool-hover-bg, #e2e8f0);
1099
1276
  }
1100
1277
  .me-overflow[open] > summary,
1101
1278
  .me-styles[open] > summary {
1102
- background: var(--me-tool-active-bg);
1103
- color: var(--me-tool-active-color);
1279
+ background: var(--me-tool-active-bg, #dbeafe);
1280
+ color: var(--me-tool-active-color, #1d4ed8);
1104
1281
  }
1105
1282
  /* A▾ 드롭다운 표시 — 스타일 패널 버튼 뒤의 캐럿 */
1106
1283
  .me-styles > summary::after {
@@ -1125,7 +1302,7 @@
1125
1302
  background: var(--me-toolbar-bg, #fff);
1126
1303
  border: 1px solid var(--me-border-color);
1127
1304
  border-radius: 8px;
1128
- box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
1305
+ box-shadow: var(--me-pop-shadow, 0 8px 24px rgba(15, 23, 42, 0.18));
1129
1306
  white-space: nowrap;
1130
1307
  }
1131
1308
  /* A▾ 패널은 툴바 중간에서 열리므로 버튼 왼쪽 아래에 붙인다 */
@@ -1134,33 +1311,10 @@
1134
1311
  left: 0;
1135
1312
  }
1136
1313
 
1137
- /* ── 반응형 툴바 — 한 줄 원칙 + ⋯ 오버플로 축소 ────────────────
1138
- * data-rsp 티어: 1 = ≤900px(삽입/정렬 그룹), 2 = ≤620px(목록·보조
1139
- * 서식 + A▾ 패널). 본줄의 티어 요소는 숨기고, ⋯ 메뉴 안의 같은
1140
- * 항목(data-rsp가 달린 복사본)만 연다 — 항목은 양쪽에 렌더되고
1141
- * 표시 여부만 CSS가 가른다. 브레이크포인트는 TOOL_ITEMS의 rsp
1142
- * 값과 짝이다 (뷰포트 기준 — 데모 .page가 툴바 폭을 지배한다) */
1143
- .me-menu [data-rsp] {
1144
- display: none;
1145
- }
1146
- @media (max-width: 900px) {
1147
- .me-toolbar > [data-rsp="1"],
1148
- .me-toolbar > .me-styles[data-rsp="1"] {
1149
- display: none;
1150
- }
1151
- .me-menu [data-rsp="1"] {
1152
- display: inline-flex;
1153
- }
1154
- }
1155
- @media (max-width: 620px) {
1156
- .me-toolbar > [data-rsp="2"],
1157
- .me-toolbar > .me-styles[data-rsp="2"] {
1158
- display: none;
1159
- }
1160
- .me-menu [data-rsp="2"] {
1161
- display: inline-flex;
1162
- }
1163
- }
1314
+ /* ── 좁은 폭 — 툴바는 flex-wrap으로 여러 줄로 감긴다 ───────────
1315
+ * 항목을 숨기지 않는다 — 자주 안 쓰는 커맨드만 TOOL_ITEMS의 menu
1316
+ * 표시로 ⋯ 패널에 둔다 (정적 구성). ⋯ 버튼은 첫 줄 우측에 고정돼
1317
+ * 줄 수와 무관하게 같은 곳에서 연다 */
1164
1318
 
1165
1319
  /* 툴바 인라인 스타일 컨트롤 — A▾ 패널 안의 컬러 피커/크기 셀렉트 */
1166
1320
  .me-style {
@@ -1192,7 +1346,7 @@
1192
1346
  padding: 0 6px;
1193
1347
  border: 1px solid var(--me-border-color);
1194
1348
  border-radius: 6px;
1195
- background: var(--me-toolbar-bg);
1349
+ background: var(--me-toolbar-bg, #f8fafc);
1196
1350
  color: var(--me-text-color);
1197
1351
  font: inherit;
1198
1352
  font-size: 13px;
@@ -1202,7 +1356,6 @@
1202
1356
  /* 상태 표시줄 — 왼쪽은 블록/마크, 오른쪽은 Ln·Col/블록 수
1203
1357
  * (VSCode 상태바 관례 — 위치 정보는 우측 정렬) */
1204
1358
  .me-statusbar {
1205
- --me-status-color: #64748b;
1206
1359
  display: flex;
1207
1360
  align-items: center;
1208
1361
  justify-content: space-between;
@@ -1212,7 +1365,7 @@
1212
1365
  background: var(--me-toolbar-bg, #f8fafc);
1213
1366
  font-size: 11px;
1214
1367
  font-family: ui-monospace, monospace;
1215
- color: var(--me-status-color);
1368
+ color: var(--me-status-color, #64748b);
1216
1369
  white-space: nowrap;
1217
1370
  }
1218
1371
  .me-status-left,
@@ -1223,6 +1376,9 @@
1223
1376
  }
1224
1377
  .me-status-right {
1225
1378
  flex-shrink: 0;
1379
+ display: inline-flex;
1380
+ align-items: center;
1381
+ gap: 6px;
1226
1382
  }
1227
1383
 
1228
1384
  /* frame 밖 단독 사용 시 */
@@ -1233,129 +1389,161 @@
1233
1389
  opacity: 0.7;
1234
1390
  }
1235
1391
 
1236
- /* ── 다크 테마 — Ace Monokai 계열. .me-frame 또는 그 조상에
1237
- * data-me-theme="dark" ────────────────────────────────────── */
1238
- [data-me-theme="dark"] {
1239
- --me-border-color: #3e3d32;
1240
- --me-text-color: #f8f8f2;
1241
- }
1392
+ /* ── 테마 — 프리셋/커스텀 테마는 ME_THEMES(theme.ts)의 --me-*
1393
+ * 변수 맵을 허브(.me-frame/.me-root/.me-editor)에 인라인으로 박는다.
1394
+ * [data-me-theme] 속성은 테마가 켜져 있다는 표시만 남는다 ────────── */
1242
1395
 
1243
- /* EditorView/WidgetView의 .me-root 래퍼가 팔레트 기본값을 갖고 있어
1244
- * frame의 다크 변수를 중간에서 덮는다 — 테마 아래의 .me-root는
1245
- * 테마 변수를 그대로 상속하도록 명시 오버라이드 */
1246
- [data-me-theme="dark"] .me-root {
1247
- --me-border-color: #3e3d32;
1248
- --me-text-color: #f8f8f2;
1249
- --me-gutter-bg: rgba(0, 0, 0, 0.22);
1250
- --me-gutter-color: #8f908a;
1251
- --me-line-active-num: #c2c2bf;
1252
- --me-node-sel-color: #66d9ef;
1396
+ /* 테마가 켜진 동안 ◐ 버튼을 활성색으로 — 팔레트가 바뀐다는 표시 */
1397
+ [data-me-theme] .me-tool[data-me-cmd="theme"] {
1398
+ color: var(--me-tool-active-color, #1d4ed8);
1253
1399
  }
1254
1400
 
1255
- .me-frame[data-me-theme="dark"] {
1256
- background: #1e1f1c;
1401
+ /* 테마 피커 — ◐ 팝오버의 세로 목록. 스와치 원은 각 테마의
1402
+ * 배경/액센트 2색 그라디언트로 미리보기다 */
1403
+ .me-pop-themes {
1404
+ flex-direction: column;
1405
+ align-items: stretch;
1406
+ gap: 1px;
1407
+ width: 200px;
1408
+ padding: 4px;
1257
1409
  }
1258
-
1259
- [data-me-theme="dark"] .me-editor {
1260
- --me-editor-bg: #272822;
1261
- --me-editor-focus: #66d9ef;
1262
- --me-code-bg: #1e1f1c;
1263
- --me-code-border: #3e3d32;
1264
- --me-gutter-border: #3e3d32;
1265
- --me-sel-bg: rgba(73, 72, 62, 0.95);
1266
- --me-print-margin: rgba(73, 72, 62, 0.9);
1410
+ .me-pop-theme {
1411
+ display: flex;
1412
+ align-items: center;
1413
+ gap: 9px;
1414
+ padding: 6px 9px;
1415
+ border: none;
1416
+ border-radius: 6px;
1417
+ background: none;
1418
+ color: var(--me-text-color);
1419
+ font: inherit;
1420
+ font-size: 13px;
1421
+ text-align: left;
1422
+ cursor: pointer;
1267
1423
  }
1268
-
1269
- /* 구문 하이라이트 다크 팔레트 — Monokai */
1270
- [data-me-theme="dark"] .me-editor pre {
1271
- --me-tok-keyword: #f92672;
1272
- --me-tok-string: #e6db74;
1273
- --me-tok-comment: #75715e;
1274
- --me-tok-number: #ae81ff;
1275
- --me-tok-literal: #ae81ff;
1276
- --me-tok-function: #a6e22e;
1277
- --me-tok-tag: #f92672;
1278
- --me-tok-attr: #a6e22e;
1279
- --me-code-active-bg: rgba(255, 255, 255, 0.05);
1424
+ .me-pop-theme:hover {
1425
+ background: var(--me-tool-hover-bg, #e2e8f0);
1280
1426
  }
1281
-
1282
- [data-me-theme="dark"] .me-toolbar {
1283
- --me-toolbar-bg: #1e1f1c;
1284
- --me-tool-hover-bg: #3e3d32;
1285
- --me-tool-active-bg: rgba(102, 217, 239, 0.14);
1286
- --me-tool-active-color: #66d9ef;
1427
+ .me-pop-theme.is-on {
1428
+ color: var(--me-tool-active-color, #1d4ed8);
1429
+ font-weight: 600;
1287
1430
  }
1288
-
1289
- /* 폼 컨트롤은 UA 라이트 기본값을 상속해 다크에서 튄다 — 명시 오버라이드 */
1290
- [data-me-theme="dark"] .me-toolbar .me-size,
1291
- [data-me-theme="dark"] .me-toolbar .me-blockfmt,
1292
- [data-me-theme="dark"] .me-toolbar .me-style input[type="color"] {
1293
- background: #1e1f1c;
1294
- border-color: #3e3d32;
1295
- color: #f8f8f2;
1431
+ .me-theme-swatch {
1432
+ flex: none;
1433
+ width: 16px;
1434
+ height: 16px;
1435
+ border-radius: 50%;
1436
+ border: 1px solid var(--me-border-color);
1437
+ background: linear-gradient(
1438
+ 135deg,
1439
+ var(--me-swatch-a) 0 55%,
1440
+ var(--me-swatch-b) 55% 100%
1441
+ );
1296
1442
  }
1297
-
1298
- [data-me-theme="dark"] .me-statusbar {
1299
- --me-toolbar-bg: #1e1f1c;
1300
- --me-status-color: #8f908a;
1443
+ .me-pop-theme .me-theme-check {
1444
+ margin-left: auto;
1445
+ font-weight: 600;
1301
1446
  }
1302
1447
 
1303
- [data-me-theme="dark"] .me-callout {
1304
- --me-callout-bg: #2d2e25;
1305
- --me-callout-border: #575643;
1306
- --me-callout-accent: #66d9ef;
1307
- }
1308
1448
 
1309
- [data-me-theme="dark"] .me-editor blockquote {
1310
- --me-quote-color: #a09f93;
1449
+ /* ── 블록 드래그&드롭 — .me-dnd 오버레이(block-dnd feature)가
1450
+ * .me-editor의 형제로 그린다. 거터 스트립(왼쪽 여백)에만 겹치게 둬
1451
+ * Chrome 캐럿 줄 경계 계산을 지키고, 래퍼는 pointer-events:none이라
1452
+ * 텍스트 클릭을 가로채지 않는다 */
1453
+ .me-dnd {
1454
+ position: absolute;
1455
+ inset: 0;
1456
+ pointer-events: none;
1311
1457
  }
1312
-
1313
- [data-me-theme="dark"] .me-editor a {
1314
- --me-link-color: #66d9ef;
1458
+ /* 호버 블록의 왼쪽에 붙는 핸들 — 드래그 시작점. gutter 영역
1459
+ * (3.9em) 안에 두고 핸들만 이벤트를 받는다 */
1460
+ .me-drag-handle {
1461
+ position: absolute;
1462
+ left: 0.2em;
1463
+ width: 1.4em;
1464
+ height: 1.4em;
1465
+ display: none;
1466
+ align-items: center;
1467
+ justify-content: center;
1468
+ pointer-events: auto;
1469
+ cursor: grab;
1470
+ color: var(--me-gutter-color);
1471
+ font-size: 12px;
1472
+ line-height: 1;
1473
+ letter-spacing: -0.15em;
1474
+ border-radius: 4px;
1315
1475
  }
1316
-
1317
- [data-me-theme="dark"] .me-editor li.me-task::before {
1318
- --me-checkbox-border: #575643;
1319
- --me-checkbox-checked: #a6e22e;
1476
+ .me-drag-handle.is-visible {
1477
+ display: flex;
1320
1478
  }
1321
-
1322
- [data-me-theme="dark"] .me-bubble {
1323
- --me-toolbar-bg: #1e1f1c;
1324
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
1479
+ .me-drag-handle:hover {
1480
+ background: var(--me-gutter-bg);
1481
+ color: var(--me-text-color);
1325
1482
  }
1326
-
1327
- [data-me-theme="dark"] .me-imgui {
1328
- --me-toolbar-bg: #1e1f1c;
1329
- --me-btn-bg: #3e3d32;
1330
- --me-tool-hover-bg: #575643;
1331
- --me-accent: #66d9ef;
1332
- box-shadow: none;
1483
+ .me-drag-handle:active {
1484
+ cursor: grabbing;
1333
1485
  }
1334
-
1335
- [data-me-theme="dark"] .me-pop,
1336
- [data-me-theme="dark"] .me-linkcard {
1337
- --me-toolbar-bg: #1e1f1c;
1338
- --me-btn-bg: #3e3d32;
1339
- --me-btn-hover-bg: #575643;
1340
- --me-accent: #66d9ef;
1341
- --me-link-color: #66d9ef;
1342
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
1486
+ /* 드롭 경계 표시선 — dragover 동안 삽입 위치에 그린다 */
1487
+ .me-drop-line {
1488
+ position: absolute;
1489
+ left: 3.9em;
1490
+ right: 0;
1491
+ height: 2px;
1492
+ display: none;
1493
+ background: var(--me-node-sel-color);
1494
+ border-radius: 1px;
1343
1495
  }
1344
-
1345
- [data-me-theme="dark"] .me-glang {
1346
- --me-text-muted: #8f908a;
1347
- --me-btn-bg: #3e3d32;
1496
+ .me-drop-line.is-visible {
1497
+ display: block;
1348
1498
  }
1349
1499
 
1350
- [data-me-theme="dark"] .me-editor ::placeholder,
1351
- [data-me-theme="dark"] .me-editor > p:only-child:has(> br:only-child)::before,
1352
- [data-me-theme="dark"]
1353
- .me-editor
1354
- > p:only-child:has(> span > br:only-child)::before {
1355
- --me-placeholder-color: #6a6b60;
1500
+ /* ── 뷰 데코레이션 — Plugin.decorations가 만드는 span.me-deco.
1501
+ * 기본은 투명 — 기능/테마가 attrs.class로 모양을 준다.
1502
+ * 데모의 TODO 데코는 me-deco-todo로 밑줄을 긋는다 */
1503
+ .me-deco.me-deco-todo {
1504
+ background: rgba(245, 158, 11, 0.16);
1505
+ border-bottom: 1px dashed #d97706;
1356
1506
  }
1357
1507
 
1358
- /* 테마 토글 버튼 — 다크 상태에서는 활성색으로 표시 */
1359
- [data-me-theme="dark"] .me-tool[data-me-cmd="theme"] {
1360
- color: var(--me-tool-active-color);
1508
+ /* ── 원격 커서 — collab-yjs의 carets extension이 paintOverlay로 그리는
1509
+ * 협업 캐럿. .me-imgui처럼 .me-editor의 형제(.me-root의 absolute
1510
+ * 자식)라 DOM↔Point 매핑과 무관하다. 피어별 색은 요소의
1511
+ * --me-remote-color 인라인 변수로 들어온다 */
1512
+ .me-carets {
1513
+ position: absolute;
1514
+ inset: 0;
1515
+ pointer-events: none;
1516
+ z-index: 35;
1517
+ overflow: hidden;
1518
+ }
1519
+ /* 캐럿 바 — 2px 세로선, 높이는 JS가 줄 높이로 맞춘다 */
1520
+ .me-remote-caret {
1521
+ position: absolute;
1522
+ width: 2px;
1523
+ background: var(--me-remote-color, #f59e0b);
1524
+ }
1525
+ /* 이름 라벨 — 캐럿 위에 붙는 작은 깃발 (y-prosemirror 관례) */
1526
+ .me-remote-caret-label {
1527
+ position: absolute;
1528
+ top: -1.15em;
1529
+ left: -1px;
1530
+ padding: 0 4px;
1531
+ border-radius: 3px 3px 3px 0;
1532
+ background: var(--me-remote-color, #f59e0b);
1533
+ color: #fff;
1534
+ font:
1535
+ 600 10px/1.5 ui-sans-serif,
1536
+ system-ui,
1537
+ sans-serif;
1538
+ white-space: nowrap;
1539
+ user-select: none;
1540
+ }
1541
+ /* 원격 선택 영역 — Range.getClientRects()로 줄별 rect를 깐다 */
1542
+ .me-remote-sel {
1543
+ position: absolute;
1544
+ background: color-mix(
1545
+ in srgb,
1546
+ var(--me-remote-color, #f59e0b) 22%,
1547
+ transparent
1548
+ );
1361
1549
  }