@moda-editor/core 0.1.5 → 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 (53) hide show
  1. package/dist/conformance/editor-base.d.ts.map +1 -1
  2. package/dist/conformance/editor-base.js +24 -0
  3. package/dist/conformance/editor-base.js.map +1 -1
  4. package/dist/conformance/editor-nodeview.d.ts.map +1 -1
  5. package/dist/conformance/editor-nodeview.js +49 -0
  6. package/dist/conformance/editor-nodeview.js.map +1 -1
  7. package/dist/conformance/editor-overlay.d.ts.map +1 -1
  8. package/dist/conformance/editor-overlay.js +23 -1
  9. package/dist/conformance/editor-overlay.js.map +1 -1
  10. package/dist/editor/editor.d.ts.map +1 -1
  11. package/dist/editor/editor.js +18 -1
  12. package/dist/editor/editor.js.map +1 -1
  13. package/dist/features/ace.d.ts.map +1 -1
  14. package/dist/features/ace.js +25 -7
  15. package/dist/features/ace.js.map +1 -1
  16. package/dist/features/code-block.d.ts.map +1 -1
  17. package/dist/features/code-block.js +47 -7
  18. package/dist/features/code-block.js.map +1 -1
  19. package/dist/features/doc.d.ts +16 -0
  20. package/dist/features/doc.d.ts.map +1 -1
  21. package/dist/features/doc.js +153 -1
  22. package/dist/features/doc.js.map +1 -1
  23. package/dist/features/image.d.ts +3 -1
  24. package/dist/features/image.d.ts.map +1 -1
  25. package/dist/features/image.js +16 -7
  26. package/dist/features/image.js.map +1 -1
  27. package/dist/features/search.d.ts +5 -2
  28. package/dist/features/search.d.ts.map +1 -1
  29. package/dist/features/search.js +42 -13
  30. package/dist/features/search.js.map +1 -1
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +2 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/presets/markdown.d.ts +2 -1
  36. package/dist/presets/markdown.d.ts.map +1 -1
  37. package/dist/presets/markdown.js +3 -2
  38. package/dist/presets/markdown.js.map +1 -1
  39. package/dist/state/apply.d.ts.map +1 -1
  40. package/dist/state/apply.js +6 -2
  41. package/dist/state/apply.js.map +1 -1
  42. package/dist/styles.css +253 -196
  43. package/dist/theme.d.ts +29 -0
  44. package/dist/theme.d.ts.map +1 -0
  45. package/dist/theme.js +347 -0
  46. package/dist/theme.js.map +1 -0
  47. package/dist/view/input.d.ts.map +1 -1
  48. package/dist/view/input.js +75 -3
  49. package/dist/view/input.js.map +1 -1
  50. package/dist/view/render.d.ts.map +1 -1
  51. package/dist/view/render.js +9 -0
  52. package/dist/view/render.js.map +1 -1
  53. package/package.json +1 -1
package/dist/styles.css CHANGED
@@ -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
66
  --me-font-mono:
61
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;
@@ -239,15 +275,25 @@
239
275
  font-size: 1.05em;
240
276
  }
241
277
 
278
+ /* 인라인 코드 — GitHub/Slack/Notion 관례의 옅은 배경 + 고정폭.
279
+ * 테두리를 두지 않는다 — 테두리 칩은 멘션 등 interactive atom의
280
+ * 시각 언어라 코드 마크와 겹치면 구분이 안 된다 */
242
281
  .me-editor code {
243
282
  padding: 0.08em 0.35em;
244
283
  background: var(--me-code-bg);
245
- border: 1px solid var(--me-code-border);
246
284
  border-radius: 4px;
247
285
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
248
286
  font-size: 0.88em;
249
287
  }
250
288
 
289
+ /* 빈 코드 칩 — CODE_CHIP(zwsp) 자리표시자는 내용이 없어 보이지
290
+ * 않으니 </> 힌트를 옅게 띄운다 (버튼 아이콘과 같은 모양).
291
+ * 타이핑이 zwsp를 대체하면 클래스가 빠져 힌트도 사라진다 */
292
+ .me-editor code.me-codechip::after {
293
+ content: "</>";
294
+ opacity: 0.45;
295
+ }
296
+
251
297
  /* 리스트 — li 안 문단은 자체 여백이 없다 (li가 줄 간격을 담당).
252
298
  * 패딩이 마커 열이다: outside 마커(•, 1.)가 텍스트 왼쪽에 붙어
253
299
  * 그려지므로, 마커가 거터 구분선에 닿지 않을 만큼의 들여쓰기가 필요 */
@@ -274,8 +320,6 @@
274
320
  padding-left: 24px;
275
321
  }
276
322
  .me-editor li.me-task::before {
277
- --me-checkbox-border: #94a3b8;
278
- --me-checkbox-checked: #2563eb;
279
323
  content: "";
280
324
  position: absolute;
281
325
  left: 4px;
@@ -343,6 +387,12 @@
343
387
  /* hr은 테두리가 굵어 outline이 묻힌다 — 위아래 여백으로 링을 띄운다 */
344
388
  outline-offset: 4px;
345
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
+ }
346
396
 
347
397
  /* ── 이미지 선택 오버레이 — 선택된 img 위에 얹히는 편집/리사이즈 UI.
348
398
  * .me-editor의 형제(.me-root의 absolute 자식)로 둬 DOM↔Point 매핑을
@@ -381,11 +431,11 @@
381
431
  flex-wrap: wrap;
382
432
  gap: 3px;
383
433
  padding: 4px;
384
- max-width: min(320px, 90vw);
434
+ max-width: min(400px, 92vw);
385
435
  background: var(--me-toolbar-bg, #fff);
386
436
  border: 1px solid var(--me-border-color);
387
437
  border-radius: 6px;
388
- 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));
389
439
  pointer-events: auto;
390
440
  }
391
441
  .me-imgui.is-below .me-img-bar {
@@ -394,9 +444,11 @@
394
444
  transform: translateY(100%);
395
445
  }
396
446
  .me-imgui .me-imgbtn {
447
+ flex: none;
397
448
  padding: 3px 8px;
398
449
  font: inherit;
399
450
  font-size: 12px;
451
+ white-space: nowrap;
400
452
  color: inherit;
401
453
  background: var(--me-btn-bg, transparent);
402
454
  border: 1px solid var(--me-border-color);
@@ -410,18 +462,27 @@
410
462
  color: #dc2626;
411
463
  border-color: #dc2626;
412
464
  }
413
- /* 편집 폼 — 액션 바 안의 두 번째 행 (wrap으로 전체 폭을 차지) */
465
+ /* 편집 폼 — 액션 바 안의 두 번째 행 (wrap으로 전체 폭을 차지).
466
+ * 최소 폭을 둬 버튼 행보다 바가 좁아져 입력이 찌그러지지 않게 한다 */
414
467
  .me-imgui .me-imgedit {
415
468
  flex-basis: 100%;
469
+ min-width: min(300px, 80vw);
416
470
  display: flex;
417
471
  gap: 4px;
418
472
  }
419
473
  .me-imgui .me-imgedit[hidden] {
420
474
  display: none;
421
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
+ }
422
482
  .me-imgui .me-imged-src,
423
483
  .me-imgui .me-imged-alt {
424
- width: min(150px, 30vw);
484
+ width: 0;
485
+ min-width: 0;
425
486
  padding: 4px 6px;
426
487
  font: inherit;
427
488
  font-size: 12px;
@@ -458,7 +519,7 @@
458
519
  background: var(--me-toolbar-bg, #fff);
459
520
  border: 1px solid var(--me-border-color);
460
521
  border-radius: 6px;
461
- 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));
462
523
  white-space: nowrap;
463
524
  pointer-events: auto;
464
525
  }
@@ -527,7 +588,7 @@
527
588
  background: var(--me-toolbar-bg, #fff);
528
589
  border: 1px solid var(--me-border-color);
529
590
  border-radius: 6px;
530
- 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));
531
592
  white-space: nowrap;
532
593
  }
533
594
  .me-codeui[hidden] {
@@ -614,7 +675,6 @@
614
675
 
615
676
  /* 인용구 */
616
677
  .me-editor blockquote {
617
- --me-quote-color: #64748b;
618
678
  padding: 2px 0 2px 12px;
619
679
  border-left: 3px solid var(--me-border-color);
620
680
  color: var(--me-quote-color);
@@ -634,17 +694,6 @@
634
694
  white-space: pre-wrap;
635
695
  /* 코드블록 Tab은 \t 문자를 넣는다 — 탭 폭은 4 (CodeMirror 관례) */
636
696
  tab-size: 4;
637
-
638
- /* 구문 하이라이트 토큰 팔레트 — GitHub Light 계열.
639
- * 테마는 --me-tok-* 변수로 바꾼다 */
640
- --me-tok-keyword: #cf222e;
641
- --me-tok-string: #0a3069;
642
- --me-tok-comment: #6e7781;
643
- --me-tok-number: #0550ae;
644
- --me-tok-literal: #0550ae;
645
- --me-tok-function: #8250df;
646
- --me-tok-tag: #116329;
647
- --me-tok-attr: #953800;
648
697
  }
649
698
  .me-editor pre code {
650
699
  padding: 0;
@@ -778,7 +827,6 @@
778
827
 
779
828
  /* 링크 */
780
829
  .me-editor a {
781
- --me-link-color: #2563eb;
782
830
  color: var(--me-link-color);
783
831
  text-decoration: underline;
784
832
  text-underline-offset: 2px;
@@ -787,7 +835,6 @@
787
835
  /* 플레이스홀더 — 문서가 빈 문단 하나뿐일 때만 표시 (PM 관례) */
788
836
  .me-editor > p:only-child:has(> br:only-child)::before,
789
837
  .me-editor > p:only-child:has(> span > br:only-child)::before {
790
- --me-placeholder-color: #94a3b8;
791
838
  content: var(--me-placeholder-text, "내용을 입력하세요…");
792
839
  float: left;
793
840
  height: 0;
@@ -806,7 +853,7 @@
806
853
  background: var(--me-toolbar-bg, #fff);
807
854
  border: 1px solid var(--me-border-color);
808
855
  border-radius: 8px;
809
- 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));
810
857
  }
811
858
  .me-bubble .me-tool {
812
859
  min-width: 26px;
@@ -829,7 +876,7 @@
829
876
  background: var(--me-toolbar-bg, #fff);
830
877
  border: 1px solid var(--me-border-color);
831
878
  border-radius: 8px;
832
- 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));
833
880
  }
834
881
  .me-pop-input {
835
882
  width: min(220px, 46vw);
@@ -865,6 +912,114 @@
865
912
  display: inline-flex;
866
913
  align-items: center;
867
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
+ }
868
1023
 
869
1024
  /* 표 크기 피커 — GDocs 표 삽입 그리드 관례. 열 수는 data.ts의
870
1025
  * TGRID_COLS(10)와 짝 — 바꾸면 둘 다 갱신한다 */
@@ -911,7 +1066,7 @@
911
1066
  background: var(--me-toolbar-bg, #fff);
912
1067
  border: 1px solid var(--me-border-color);
913
1068
  border-radius: 8px;
914
- 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));
915
1070
  }
916
1071
  .me-linkcard-url {
917
1072
  flex: 1;
@@ -950,9 +1105,6 @@
950
1105
  /* 데모용 callout 노드 컴포넌트 — 아이콘 크롬 + 편집 콘텐츠.
951
1106
  * 왼쪽 액센트 바는 GitHub alert/Notion callout 관례 */
952
1107
  .me-callout {
953
- --me-callout-bg: #eff6ff;
954
- --me-callout-border: #bfdbfe;
955
- --me-callout-accent: #3b82f6;
956
1108
 
957
1109
  display: flex;
958
1110
  gap: 8px;
@@ -974,19 +1126,15 @@
974
1126
  /* ── 툴바 — 데모/스타터용 에디터 크롬. 어댑터 계약이 아니라
975
1127
  * 선택적 UI라 앱이 자체 툴바를 써도 된다 ─────────────────────── */
976
1128
  .me-toolbar {
977
- --me-toolbar-bg: #f8fafc;
978
- --me-tool-hover-bg: #e2e8f0;
979
- --me-tool-active-bg: #dbeafe;
980
- --me-tool-active-color: #1d4ed8;
981
-
982
1129
  display: flex;
983
1130
  align-items: center;
984
- /* 한 줄 원칙 — 넘치는 항목은 두 줄로 내리지 않고 ⋯ 메뉴로 보낸다
985
- * (data-rsp 티어, 아래 미디어 쿼리).
986
- * overflow:hidden을 쓰지 않는다 — absolute인 ⋯/A▾의 .me-menu가
987
- * 툴바 아래로 열릴 때 같이 잘린다. ⋯는 absolute로 우측에 고정하고
988
- * padding-right로 그 자리를 비워 넘치는 항목이 그 밑으로 스치게 한다 */
989
- 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;
990
1138
  /* relative+z-index: 툴바 전체를 에디터(.me-editor relative) 위에
991
1139
  * 올려 ⋯/A▾ 드롭다운이 본문에 가려지지 않게 한다. 팝오버/버블
992
1140
  * (fixed, z 50~60)보다는 아래라 겹쳐도 그쪽이 위에 뜬다 */
@@ -994,7 +1142,7 @@
994
1142
  z-index: 20;
995
1143
  gap: 2px;
996
1144
  padding: 6px 44px 6px 8px;
997
- background: var(--me-toolbar-bg);
1145
+ background: var(--me-toolbar-bg, #f8fafc);
998
1146
  border-bottom: 1px solid var(--me-border-color);
999
1147
  /* IDE 크롬 — 툴 라벨도 코드 에디터 폰트로 */
1000
1148
  font-family: var(--me-font-mono);
@@ -1042,7 +1190,7 @@
1042
1190
  }
1043
1191
 
1044
1192
  .me-tool:hover:not(:disabled) {
1045
- background: var(--me-tool-hover-bg);
1193
+ background: var(--me-tool-hover-bg, #e2e8f0);
1046
1194
  }
1047
1195
 
1048
1196
  /* 키보드 포커스 표시 — VSCode 크롬 관례 (마우스 클릭엔 링 없음) */
@@ -1056,8 +1204,8 @@
1056
1204
  }
1057
1205
 
1058
1206
  .me-tool.is-active {
1059
- background: var(--me-tool-active-bg);
1060
- color: var(--me-tool-active-color);
1207
+ background: var(--me-tool-active-bg, #dbeafe);
1208
+ color: var(--me-tool-active-color, #1d4ed8);
1061
1209
  }
1062
1210
 
1063
1211
  .me-tool:disabled {
@@ -1098,7 +1246,7 @@
1098
1246
  right: 8px;
1099
1247
  top: 6px;
1100
1248
  flex-shrink: 0;
1101
- background: var(--me-toolbar-bg);
1249
+ background: var(--me-toolbar-bg, #f8fafc);
1102
1250
  border-radius: 6px;
1103
1251
  }
1104
1252
  .me-overflow > summary,
@@ -1124,12 +1272,12 @@
1124
1272
  }
1125
1273
  .me-overflow > summary:hover,
1126
1274
  .me-styles > summary:hover {
1127
- background: var(--me-tool-hover-bg);
1275
+ background: var(--me-tool-hover-bg, #e2e8f0);
1128
1276
  }
1129
1277
  .me-overflow[open] > summary,
1130
1278
  .me-styles[open] > summary {
1131
- background: var(--me-tool-active-bg);
1132
- color: var(--me-tool-active-color);
1279
+ background: var(--me-tool-active-bg, #dbeafe);
1280
+ color: var(--me-tool-active-color, #1d4ed8);
1133
1281
  }
1134
1282
  /* A▾ 드롭다운 표시 — 스타일 패널 버튼 뒤의 캐럿 */
1135
1283
  .me-styles > summary::after {
@@ -1154,7 +1302,7 @@
1154
1302
  background: var(--me-toolbar-bg, #fff);
1155
1303
  border: 1px solid var(--me-border-color);
1156
1304
  border-radius: 8px;
1157
- 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));
1158
1306
  white-space: nowrap;
1159
1307
  }
1160
1308
  /* A▾ 패널은 툴바 중간에서 열리므로 버튼 왼쪽 아래에 붙인다 */
@@ -1163,33 +1311,10 @@
1163
1311
  left: 0;
1164
1312
  }
1165
1313
 
1166
- /* ── 반응형 툴바 — 한 줄 원칙 + ⋯ 오버플로 축소 ────────────────
1167
- * data-rsp 티어: 1 = ≤900px(삽입/정렬 그룹), 2 = ≤620px(목록·보조
1168
- * 서식 + A▾ 패널). 본줄의 티어 요소는 숨기고, ⋯ 메뉴 안의 같은
1169
- * 항목(data-rsp가 달린 복사본)만 연다 — 항목은 양쪽에 렌더되고
1170
- * 표시 여부만 CSS가 가른다. 브레이크포인트는 TOOL_ITEMS의 rsp
1171
- * 값과 짝이다 (뷰포트 기준 — 데모 .page가 툴바 폭을 지배한다) */
1172
- .me-menu [data-rsp] {
1173
- display: none;
1174
- }
1175
- @media (max-width: 900px) {
1176
- .me-toolbar > [data-rsp="1"],
1177
- .me-toolbar > .me-styles[data-rsp="1"] {
1178
- display: none;
1179
- }
1180
- .me-menu [data-rsp="1"] {
1181
- display: inline-flex;
1182
- }
1183
- }
1184
- @media (max-width: 620px) {
1185
- .me-toolbar > [data-rsp="2"],
1186
- .me-toolbar > .me-styles[data-rsp="2"] {
1187
- display: none;
1188
- }
1189
- .me-menu [data-rsp="2"] {
1190
- display: inline-flex;
1191
- }
1192
- }
1314
+ /* ── 좁은 폭 — 툴바는 flex-wrap으로 여러 줄로 감긴다 ───────────
1315
+ * 항목을 숨기지 않는다 — 자주 안 쓰는 커맨드만 TOOL_ITEMS의 menu
1316
+ * 표시로 ⋯ 패널에 둔다 (정적 구성). ⋯ 버튼은 첫 줄 우측에 고정돼
1317
+ * 줄 수와 무관하게 같은 곳에서 연다 */
1193
1318
 
1194
1319
  /* 툴바 인라인 스타일 컨트롤 — A▾ 패널 안의 컬러 피커/크기 셀렉트 */
1195
1320
  .me-style {
@@ -1221,7 +1346,7 @@
1221
1346
  padding: 0 6px;
1222
1347
  border: 1px solid var(--me-border-color);
1223
1348
  border-radius: 6px;
1224
- background: var(--me-toolbar-bg);
1349
+ background: var(--me-toolbar-bg, #f8fafc);
1225
1350
  color: var(--me-text-color);
1226
1351
  font: inherit;
1227
1352
  font-size: 13px;
@@ -1231,7 +1356,6 @@
1231
1356
  /* 상태 표시줄 — 왼쪽은 블록/마크, 오른쪽은 Ln·Col/블록 수
1232
1357
  * (VSCode 상태바 관례 — 위치 정보는 우측 정렬) */
1233
1358
  .me-statusbar {
1234
- --me-status-color: #64748b;
1235
1359
  display: flex;
1236
1360
  align-items: center;
1237
1361
  justify-content: space-between;
@@ -1241,7 +1365,7 @@
1241
1365
  background: var(--me-toolbar-bg, #f8fafc);
1242
1366
  font-size: 11px;
1243
1367
  font-family: ui-monospace, monospace;
1244
- color: var(--me-status-color);
1368
+ color: var(--me-status-color, #64748b);
1245
1369
  white-space: nowrap;
1246
1370
  }
1247
1371
  .me-status-left,
@@ -1252,6 +1376,9 @@
1252
1376
  }
1253
1377
  .me-status-right {
1254
1378
  flex-shrink: 0;
1379
+ display: inline-flex;
1380
+ align-items: center;
1381
+ gap: 6px;
1255
1382
  }
1256
1383
 
1257
1384
  /* frame 밖 단독 사용 시 */
@@ -1262,132 +1389,62 @@
1262
1389
  opacity: 0.7;
1263
1390
  }
1264
1391
 
1265
- /* ── 다크 테마 — Ace Monokai 계열. .me-frame 또는 그 조상에
1266
- * data-me-theme="dark" ────────────────────────────────────── */
1267
- [data-me-theme="dark"] {
1268
- --me-border-color: #3e3d32;
1269
- --me-text-color: #f8f8f2;
1270
- }
1271
-
1272
- /* EditorView/WidgetView의 .me-root 래퍼가 팔레트 기본값을 갖고 있어
1273
- * frame의 다크 변수를 중간에서 덮는다 — 테마 아래의 .me-root는
1274
- * 테마 변수를 그대로 상속하도록 명시 오버라이드 */
1275
- [data-me-theme="dark"] .me-root {
1276
- --me-border-color: #3e3d32;
1277
- --me-text-color: #f8f8f2;
1278
- --me-gutter-bg: rgba(0, 0, 0, 0.22);
1279
- --me-gutter-color: #8f908a;
1280
- --me-line-active-num: #c2c2bf;
1281
- --me-node-sel-color: #66d9ef;
1282
- }
1283
-
1284
- .me-frame[data-me-theme="dark"] {
1285
- background: #1e1f1c;
1286
- }
1287
-
1288
- [data-me-theme="dark"] .me-editor {
1289
- --me-editor-bg: #272822;
1290
- --me-editor-focus: #66d9ef;
1291
- --me-code-bg: #1e1f1c;
1292
- --me-code-border: #3e3d32;
1293
- --me-gutter-border: #3e3d32;
1294
- --me-sel-bg: rgba(73, 72, 62, 0.95);
1295
- --me-print-margin: rgba(73, 72, 62, 0.9);
1296
- }
1297
-
1298
- /* 구문 하이라이트 다크 팔레트 — Monokai */
1299
- [data-me-theme="dark"] .me-editor pre {
1300
- --me-tok-keyword: #f92672;
1301
- --me-tok-string: #e6db74;
1302
- --me-tok-comment: #75715e;
1303
- --me-tok-number: #ae81ff;
1304
- --me-tok-literal: #ae81ff;
1305
- --me-tok-function: #a6e22e;
1306
- --me-tok-tag: #f92672;
1307
- --me-tok-attr: #a6e22e;
1308
- --me-code-active-bg: rgba(255, 255, 255, 0.05);
1309
- }
1310
-
1311
- [data-me-theme="dark"] .me-toolbar {
1312
- --me-toolbar-bg: #1e1f1c;
1313
- --me-tool-hover-bg: #3e3d32;
1314
- --me-tool-active-bg: rgba(102, 217, 239, 0.14);
1315
- --me-tool-active-color: #66d9ef;
1316
- }
1392
+ /* ── 테마 — 프리셋/커스텀 테마는 ME_THEMES(theme.ts)의 --me-*
1393
+ * 변수 맵을 허브(.me-frame/.me-root/.me-editor)에 인라인으로 박는다.
1394
+ * [data-me-theme] 속성은 테마가 켜져 있다는 표시만 남는다 ────────── */
1317
1395
 
1318
- /* 폼 컨트롤은 UA 라이트 기본값을 상속해 다크에서 튄다 — 명시 오버라이드 */
1319
- [data-me-theme="dark"] .me-toolbar .me-size,
1320
- [data-me-theme="dark"] .me-toolbar .me-blockfmt,
1321
- [data-me-theme="dark"] .me-toolbar .me-style input[type="color"] {
1322
- background: #1e1f1c;
1323
- border-color: #3e3d32;
1324
- color: #f8f8f2;
1396
+ /* 테마가 켜진 동안 ◐ 버튼을 활성색으로 — 팔레트가 바뀐다는 표시 */
1397
+ [data-me-theme] .me-tool[data-me-cmd="theme"] {
1398
+ color: var(--me-tool-active-color, #1d4ed8);
1325
1399
  }
1326
1400
 
1327
- [data-me-theme="dark"] .me-statusbar {
1328
- --me-toolbar-bg: #1e1f1c;
1329
- --me-status-color: #8f908a;
1330
- }
1331
-
1332
- [data-me-theme="dark"] .me-callout {
1333
- --me-callout-bg: #2d2e25;
1334
- --me-callout-border: #575643;
1335
- --me-callout-accent: #66d9ef;
1336
- }
1337
-
1338
- [data-me-theme="dark"] .me-editor blockquote {
1339
- --me-quote-color: #a09f93;
1340
- }
1341
-
1342
- [data-me-theme="dark"] .me-editor a {
1343
- --me-link-color: #66d9ef;
1344
- }
1345
-
1346
- [data-me-theme="dark"] .me-editor li.me-task::before {
1347
- --me-checkbox-border: #575643;
1348
- --me-checkbox-checked: #a6e22e;
1401
+ /* 테마 피커 — ◐ 팝오버의 세로 목록. 스와치 원은 각 테마의
1402
+ * 배경/액센트 2색 그라디언트로 미리보기다 */
1403
+ .me-pop-themes {
1404
+ flex-direction: column;
1405
+ align-items: stretch;
1406
+ gap: 1px;
1407
+ width: 200px;
1408
+ padding: 4px;
1349
1409
  }
1350
-
1351
- [data-me-theme="dark"] .me-bubble {
1352
- --me-toolbar-bg: #1e1f1c;
1353
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.5);
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;
1354
1423
  }
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;
1424
+ .me-pop-theme:hover {
1425
+ background: var(--me-tool-hover-bg, #e2e8f0);
1362
1426
  }
1363
-
1364
- [data-me-theme="dark"] .me-pop,
1365
- [data-me-theme="dark"] .me-linkcard {
1366
- --me-toolbar-bg: #1e1f1c;
1367
- --me-btn-bg: #3e3d32;
1368
- --me-btn-hover-bg: #575643;
1369
- --me-accent: #66d9ef;
1370
- --me-link-color: #66d9ef;
1371
- box-shadow: 0 8px 24px rgba(0, 0, 0, 0.5);
1427
+ .me-pop-theme.is-on {
1428
+ color: var(--me-tool-active-color, #1d4ed8);
1429
+ font-weight: 600;
1372
1430
  }
1373
-
1374
- [data-me-theme="dark"] .me-glang {
1375
- --me-text-muted: #8f908a;
1376
- --me-btn-bg: #3e3d32;
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
+ );
1377
1442
  }
1378
-
1379
- [data-me-theme="dark"] .me-editor ::placeholder,
1380
- [data-me-theme="dark"] .me-editor > p:only-child:has(> br:only-child)::before,
1381
- [data-me-theme="dark"]
1382
- .me-editor
1383
- > p:only-child:has(> span > br:only-child)::before {
1384
- --me-placeholder-color: #6a6b60;
1443
+ .me-pop-theme .me-theme-check {
1444
+ margin-left: auto;
1445
+ font-weight: 600;
1385
1446
  }
1386
1447
 
1387
- /* 테마 토글 버튼 — 다크 상태에서는 활성색으로 표시 */
1388
- [data-me-theme="dark"] .me-tool[data-me-cmd="theme"] {
1389
- color: var(--me-tool-active-color);
1390
- }
1391
1448
 
1392
1449
  /* ── 블록 드래그&드롭 — .me-dnd 오버레이(block-dnd feature)가
1393
1450
  * .me-editor의 형제로 그린다. 거터 스트립(왼쪽 여백)에만 겹치게 둬