@lumir-company/editor 0.4.14 → 0.4.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/style.css CHANGED
@@ -1,6 +1,18 @@
1
- @import "@blocknote/core/fonts/inter.css";
2
- @import "@blocknote/mantine/style.css";
3
- @import "@blocknote/react/style.css";
1
+ @import '@blocknote/core/fonts/inter.css';
2
+ @import '@blocknote/mantine/style.css';
3
+ @import '@blocknote/react/style.css';
4
+
5
+ /* Pretendard 한글 글꼴 (가변 폰트, swap).
6
+ @import url()은 번들 시 @import 순서 규칙을 위반해 사용 불가 → @font-face로 로드.
7
+ 호스트 앱이 Pretendard를 자체 로드한다면 이 블록은 제거해도 된다. */
8
+ @font-face {
9
+ font-family: 'Pretendard';
10
+ font-weight: 100 900;
11
+ font-style: normal;
12
+ font-display: swap;
13
+ src: url('https://cdn.jsdelivr.net/npm/pretendard@1.3.9/dist/web/variable/woff2/PretendardVariable.woff2')
14
+ format('woff2-variations');
15
+ }
4
16
 
5
17
  .lumirEditor {
6
18
  width: 100%;
@@ -8,6 +20,15 @@
8
20
  min-width: 200px;
9
21
  overflow: visible; /* 슬래시 메뉴가 컨테이너를 넘어서 표시되도록 변경 */
10
22
  background-color: #ffffff;
23
+ /* 에디터 전체(본문·툴바·인-DOM 드롭다운) 한글 글꼴 Pretendard */
24
+ font-family:
25
+ 'Pretendard',
26
+ 'Noto Sans KR',
27
+ -apple-system,
28
+ BlinkMacSystemFont,
29
+ 'Segoe UI',
30
+ 'Roboto',
31
+ sans-serif;
11
32
  }
12
33
 
13
34
  /* 에디터 내부 콘텐츠 영역만 스크롤 가능하게 설정 */
@@ -23,6 +44,23 @@
23
44
  .mantine-Popover-dropdown {
24
45
  z-index: 9999 !important;
25
46
  }
47
+
48
+ /* 포털(body)로 빠지는 메뉴/드롭다운에도 Pretendard 적용 */
49
+ .bn-suggestion-menu,
50
+ .bn-slash-menu,
51
+ .mantine-Menu-dropdown,
52
+ .mantine-Popover-dropdown,
53
+ .bn-table-handle-menu,
54
+ .bn-menu-dropdown {
55
+ font-family:
56
+ 'Pretendard',
57
+ 'Noto Sans KR',
58
+ -apple-system,
59
+ BlinkMacSystemFont,
60
+ 'Segoe UI',
61
+ 'Roboto',
62
+ sans-serif;
63
+ }
26
64
  /* 포커스 상태 스타일 - 테두리 없음 */
27
65
  .lumirEditor:focus-within {
28
66
  outline: none;
@@ -36,15 +74,15 @@
36
74
  .lumirEditor .bn-editor,
37
75
  .lumirEditor .bn-inline-content {
38
76
  font-family:
39
- "Pretendard",
40
- "Noto Sans KR",
77
+ 'Pretendard',
78
+ 'Noto Sans KR',
41
79
  -apple-system,
42
80
  BlinkMacSystemFont,
43
- "Segoe UI",
44
- "Roboto",
45
- "Oxygen",
46
- "Ubuntu",
47
- "Cantarell",
81
+ 'Segoe UI',
82
+ 'Roboto',
83
+ 'Oxygen',
84
+ 'Ubuntu',
85
+ 'Cantarell',
48
86
  sans-serif;
49
87
  }
50
88
 
@@ -76,24 +114,24 @@
76
114
  * `p.bn-inline-content`에 명시적으로 14px (`.bn-block-content`에 data-type이 붙음)
77
115
  */
78
116
  .lumirEditor
79
- .bn-block-content[data-content-type="paragraph"]
117
+ .bn-block-content[data-content-type='paragraph']
80
118
  p.bn-inline-content,
81
119
  .lumirEditor
82
- .bn-block-content[data-content-type="numberedListItem"]
120
+ .bn-block-content[data-content-type='numberedListItem']
83
121
  p.bn-inline-content,
84
122
  .lumirEditor
85
- .bn-block-content[data-content-type="bulletListItem"]
123
+ .bn-block-content[data-content-type='bulletListItem']
86
124
  p.bn-inline-content,
87
125
  .lumirEditor
88
- .bn-block-content[data-content-type="checkListItem"]
126
+ .bn-block-content[data-content-type='checkListItem']
89
127
  p.bn-inline-content {
90
128
  font-size: 14px;
91
129
  }
92
130
 
93
131
  /* 마커(번호·불릿)·체크 행 */
94
- .lumirEditor .bn-block-content[data-content-type="numberedListItem"],
95
- .lumirEditor .bn-block-content[data-content-type="bulletListItem"],
96
- .lumirEditor .bn-block-content[data-content-type="checkListItem"] {
132
+ .lumirEditor .bn-block-content[data-content-type='numberedListItem'],
133
+ .lumirEditor .bn-block-content[data-content-type='bulletListItem'],
134
+ .lumirEditor .bn-block-content[data-content-type='checkListItem'] {
97
135
  font-size: 14px;
98
136
  }
99
137
 
@@ -102,7 +140,7 @@
102
140
  }
103
141
 
104
142
  /* File Panel: Embed 탭 미노출 (URL 입력 방식 비활성화) */
105
- .lumirEditor [data-test="embed-tab"] {
143
+ .lumirEditor [data-test='embed-tab'] {
106
144
  display: none !important;
107
145
  }
108
146
 
@@ -114,7 +152,7 @@
114
152
  }
115
153
 
116
154
  /* 우측 정렬 시 빈 블록 placeholder 위치 수정 */
117
- .lumirEditor [data-text-alignment="right"] .bn-inline-content::before {
155
+ .lumirEditor [data-text-alignment='right'] .bn-inline-content::before {
118
156
  position: relative;
119
157
  max-width: 100%;
120
158
  }
@@ -203,12 +241,12 @@
203
241
  padding: 0;
204
242
  }
205
243
 
206
- .lumir-floating-toolbar-wrapper[data-position="sticky"] {
244
+ .lumir-floating-toolbar-wrapper[data-position='sticky'] {
207
245
  position: sticky;
208
246
  top: 0;
209
247
  }
210
248
 
211
- .lumir-floating-toolbar-wrapper[data-position="fixed"] {
249
+ .lumir-floating-toolbar-wrapper[data-position='fixed'] {
212
250
  position: fixed;
213
251
  top: 64px;
214
252
  left: 0;
@@ -504,6 +542,23 @@
504
542
  color: #3b82f6 !important;
505
543
  }
506
544
 
545
+ /* Font Size Dropdown Button (글자 크기) */
546
+ .lumir-font-size-btn {
547
+ min-width: 52px;
548
+ max-width: 72px;
549
+ }
550
+
551
+ .lumir-font-size-label {
552
+ flex: 1;
553
+ text-align: center;
554
+ }
555
+
556
+ .lumir-font-size-menu {
557
+ min-width: 96px;
558
+ max-height: 280px;
559
+ overflow-y: auto;
560
+ }
561
+
507
562
  /* Block Type Dropdown Button */
508
563
  .lumir-block-type-btn {
509
564
  min-width: 110px;
@@ -743,7 +798,7 @@
743
798
  }
744
799
 
745
800
  .lumir-color-swatch.is-active::after {
746
- content: "";
801
+ content: '';
747
802
  position: absolute;
748
803
  top: 50%;
749
804
  left: 50%;
@@ -989,53 +1044,215 @@
989
1044
  }
990
1045
 
991
1046
  /* 다크 테마 대응 */
992
- [data-color-scheme="dark"] .lumir-link-preview-card,
993
- .bn-container[data-color-scheme="dark"] .lumir-link-preview-card {
1047
+ [data-color-scheme='dark'] .lumir-link-preview-card,
1048
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-card {
994
1049
  background-color: #292524 !important;
995
1050
  border-color: #44403c !important;
996
1051
  }
997
1052
 
998
- [data-color-scheme="dark"] .lumir-link-preview-card:hover,
999
- .bn-container[data-color-scheme="dark"] .lumir-link-preview-card:hover {
1053
+ [data-color-scheme='dark'] .lumir-link-preview-card:hover,
1054
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-card:hover {
1000
1055
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3) !important;
1001
1056
  }
1002
1057
 
1003
- [data-color-scheme="dark"] .lumir-link-preview-skeleton,
1004
- .bn-container[data-color-scheme="dark"] .lumir-link-preview-skeleton {
1058
+ [data-color-scheme='dark'] .lumir-link-preview-skeleton,
1059
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-skeleton {
1005
1060
  background-color: #292524 !important;
1006
1061
  border-color: #44403c !important;
1007
1062
  }
1008
1063
 
1009
- [data-color-scheme="dark"] .lumir-link-preview-error,
1010
- .bn-container[data-color-scheme="dark"] .lumir-link-preview-error {
1064
+ [data-color-scheme='dark'] .lumir-link-preview-error,
1065
+ .bn-container[data-color-scheme='dark'] .lumir-link-preview-error {
1011
1066
  background-color: #292524 !important;
1012
1067
  border-color: #44403c !important;
1013
1068
  }
1014
1069
 
1015
1070
  /* 인용·코드·테이블 본문 14px */
1016
- .lumirEditor .bn-block-content[data-content-type="quote"] p.bn-inline-content,
1017
- .lumirEditor [data-content-type="quote"] blockquote {
1071
+ .lumirEditor .bn-block-content[data-content-type='quote'] p.bn-inline-content,
1072
+ .lumirEditor [data-content-type='quote'] blockquote {
1018
1073
  font-size: 14px;
1019
1074
  }
1020
1075
 
1021
- .lumirEditor .bn-block-content[data-content-type="codeBlock"] pre,
1022
- .lumirEditor .bn-block-content[data-content-type="codeBlock"] pre code {
1076
+ .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre,
1077
+ .lumirEditor .bn-block-content[data-content-type='codeBlock'] pre code {
1023
1078
  font-size: 14px;
1024
1079
  }
1025
1080
 
1026
- .lumirEditor .bn-editor [data-content-type="table"] th,
1027
- .lumirEditor .bn-editor [data-content-type="table"] td,
1028
- .lumirEditor .bn-editor [data-content-type="table"] p.bn-inline-content {
1081
+ .lumirEditor .bn-editor [data-content-type='table'] th,
1082
+ .lumirEditor .bn-editor [data-content-type='table'] td,
1083
+ .lumirEditor .bn-editor [data-content-type='table'] p.bn-inline-content {
1029
1084
  font-size: 14px;
1030
1085
  }
1031
1086
 
1032
1087
  /* 테이블 셀 세로 정렬 (VerticalAlignmentExtension) */
1033
- .lumirEditor .bn-editor [data-content-type="table"] td[data-vertical-alignment="middle"],
1034
- .lumirEditor .bn-editor [data-content-type="table"] th[data-vertical-alignment="middle"] {
1088
+ .lumirEditor
1089
+ .bn-editor
1090
+ [data-content-type='table']
1091
+ td[data-vertical-alignment='middle'],
1092
+ .lumirEditor
1093
+ .bn-editor
1094
+ [data-content-type='table']
1095
+ th[data-vertical-alignment='middle'] {
1035
1096
  vertical-align: middle;
1036
1097
  }
1037
1098
 
1038
- .lumirEditor .bn-editor [data-content-type="table"] td[data-vertical-alignment="bottom"],
1039
- .lumirEditor .bn-editor [data-content-type="table"] th[data-vertical-alignment="bottom"] {
1099
+ .lumirEditor
1100
+ .bn-editor
1101
+ [data-content-type='table']
1102
+ td[data-vertical-alignment='bottom'],
1103
+ .lumirEditor
1104
+ .bn-editor
1105
+ [data-content-type='table']
1106
+ th[data-vertical-alignment='bottom'] {
1040
1107
  vertical-align: bottom;
1041
1108
  }
1109
+
1110
+ /* ==========================================================================
1111
+ Notion 스타일 FOCUS 기반 테이블 gutter/grip (LumirTableHandlesController)
1112
+ - 셀 focus 시: 셀 테두리 하이라이트(파란 보더, 셀을 살짝 감쌈)
1113
+ - 상단(열)·좌측(행): 짧고 두꺼운 회색 gutter 바 / 우측(셀): 작은 파란 앵커
1114
+ - gutter hover 시: 발판 grip 노출 → 클릭 시 드롭다운
1115
+ - active(메뉴 열림/드래그): 발판이 파란 배경 + 흰 점
1116
+ 기본 BlockNote hover 핸들은 tableHandles={false}로 비활성.
1117
+ ========================================================================== */
1118
+
1119
+ /* focus된 셀 테두리 하이라이트 (셀을 ~2px 바깥에서 감싸는 비클릭 오버레이) */
1120
+ .lumirEditor .lumir-tbl-cell-focus {
1121
+ position: absolute;
1122
+ top: 0;
1123
+ left: 0;
1124
+ box-sizing: border-box;
1125
+ border: 2px solid #2383e2;
1126
+ border-radius: 2px;
1127
+ pointer-events: none;
1128
+ z-index: 1;
1129
+ }
1130
+
1131
+ /* gutter wrapper = hover 히트 영역. 보더에 걸쳐 중앙 배치(positioner offset -7). */
1132
+ .lumirEditor .lumir-tbl-gutter-wrap {
1133
+ position: absolute;
1134
+ z-index: 2;
1135
+ cursor: pointer;
1136
+ }
1137
+
1138
+ .lumirEditor .lumir-tbl-gutter-wrap--col {
1139
+ width: 34px;
1140
+ height: 14px;
1141
+ }
1142
+
1143
+ .lumirEditor .lumir-tbl-gutter-wrap--row,
1144
+ .lumirEditor .lumir-tbl-gutter-wrap--cell {
1145
+ width: 14px;
1146
+ height: 34px;
1147
+ }
1148
+
1149
+ /* 기본 노출: 짧고 두꺼운 gutter 바. wrapper가 셀 보더에 중앙 정렬되어 있으므로,
1150
+ gutter를 wrapper 중앙에 두면 "거터 중앙이 셀 보더선 위"에 오도록 걸쳐진다
1151
+ (절반은 셀 안쪽, 절반은 바깥쪽). */
1152
+ .lumirEditor .lumir-tbl-gutter {
1153
+ position: absolute;
1154
+ inset: 0;
1155
+ margin: auto;
1156
+ box-sizing: border-box;
1157
+ background-color: #c0c0c2;
1158
+ transition: opacity 0.1s ease;
1159
+ }
1160
+
1161
+ /* 상(top): 가로 pill — 상단 보더 중앙 */
1162
+ .lumirEditor .lumir-tbl-gutter-wrap--col .lumir-tbl-gutter {
1163
+ width: 14px;
1164
+ height: 4px;
1165
+ border-left: 1px solid #fff;
1166
+ border-right: 1px solid #fff;
1167
+ }
1168
+
1169
+ /* 좌(left): 세로 pill — 좌측 보더 중앙 (Notion도 좌측에 표시) */
1170
+ .lumirEditor .lumir-tbl-gutter-wrap--row .lumir-tbl-gutter {
1171
+ width: 4px;
1172
+ height: 14px;
1173
+ border-top: 1px solid #fff;
1174
+ border-bottom: 1px solid #fff;
1175
+ }
1176
+
1177
+ /* 우(right): Notion의 파란 선택 앵커 — 우측 보더 중앙 */
1178
+ /* 우(right): 셀 우측 보더의 파란 세로 앵커 */
1179
+ .lumirEditor .lumir-tbl-gutter-wrap--cell .lumir-tbl-gutter {
1180
+ width: 4px;
1181
+ height: 14px;
1182
+ background-color: #2383e2;
1183
+ border-top: 1px solid #fff;
1184
+ border-bottom: 1px solid #fff;
1185
+ }
1186
+
1187
+ .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-gutter {
1188
+ opacity: 0;
1189
+ }
1190
+
1191
+ /* 발판 grip: 기본 숨김, gutter hover 시 노출 */
1192
+ .lumirEditor .lumir-tbl-grip {
1193
+ position: absolute;
1194
+ inset: 0;
1195
+ display: flex;
1196
+ align-items: center;
1197
+ justify-content: center;
1198
+ opacity: 0;
1199
+ pointer-events: none;
1200
+ cursor: pointer;
1201
+ transition: opacity 0.1s ease;
1202
+ }
1203
+
1204
+ .lumirEditor .lumir-tbl-gutter-wrap:hover .lumir-tbl-grip {
1205
+ opacity: 1;
1206
+ pointer-events: auto;
1207
+ }
1208
+
1209
+ /* 메뉴 열림(active) 동안 발판 유지(마우스가 떠나도) + rest 바 숨김 */
1210
+ .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-grip {
1211
+ opacity: 1;
1212
+ pointer-events: auto;
1213
+ }
1214
+
1215
+ .lumirEditor .lumir-tbl-gutter-wrap--active .lumir-tbl-gutter {
1216
+ opacity: 0;
1217
+ }
1218
+
1219
+ /* 드롭다운 오픈(active)·드래그 시 발판: 배경·보더 파랑(#2383e2) + 흰 아이콘 */
1220
+ .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-handle,
1221
+ .lumirEditor .lumir-tbl-gutter-wrap--active .bn-table-cell-handle,
1222
+ .lumirEditor .lumir-tbl-grip .bn-table-handle-dragging {
1223
+ background-color: #2383e2 !important;
1224
+ border-color: #2383e2 !important;
1225
+ color: #fff !important;
1226
+ }
1227
+
1228
+ /* 발판 크기: 너비(11)↓·높이(14) 유지. 상단 발판은 90° 회전이라 너비↓ = 시각적 높이↓.
1229
+ 배경 흰색 + 보더 진하게(#999). */
1230
+ .lumirEditor .lumir-tbl-grip .bn-table-handle,
1231
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle {
1232
+ width: 12px;
1233
+ min-width: 12px;
1234
+ height: 16px;
1235
+ padding: 0;
1236
+ border-radius: 3px;
1237
+ cursor: pointer; /* mantine 기본 grab → pointer */
1238
+ background-color: #fff;
1239
+ border: 1px solid #cfcfcf;
1240
+ box-shadow: none; /* mantine 기본 그림자(--bn-shadow-light, 블러처럼 보임) 제거 */
1241
+ }
1242
+
1243
+ /* hover 시에도 흰 배경 유지 (mantine hover 회색 오버라이드) */
1244
+ .lumirEditor .lumir-tbl-grip .bn-table-handle:hover,
1245
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle:hover {
1246
+ background-color: #fff;
1247
+ }
1248
+
1249
+ .lumirEditor .lumir-tbl-grip .bn-table-handle svg {
1250
+ width: 12px;
1251
+ height: 12px;
1252
+ margin-inline: 0;
1253
+ }
1254
+
1255
+ .lumirEditor .lumir-tbl-grip .bn-table-cell-handle svg {
1256
+ width: 12px;
1257
+ height: 12px;
1258
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumir-company/editor",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "private": false,
5
5
  "description": "Image-only BlockNote rich text editor with S3 upload, customizable filename transforms, UUID support, and loading spinner",
6
6
  "keywords": [
@@ -16,6 +16,7 @@
16
16
  "filename-transform",
17
17
  "uuid",
18
18
  "file-upload",
19
+ "table",
19
20
  "lumir"
20
21
  ],
21
22
  "main": "dist/index.js",
@@ -70,7 +71,8 @@
70
71
  "dependencies": {
71
72
  "@blocknote/core": "^0.35.0",
72
73
  "@blocknote/react": "^0.35.0",
73
- "@blocknote/mantine": "^0.35.0"
74
+ "@blocknote/mantine": "^0.35.0",
75
+ "@floating-ui/react": "^0.26.28"
74
76
  },
75
77
  "devDependencies": {
76
78
  "typescript": "^5.4.0",