@aeriz/wysiwyg 1.0.2 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +634 -96
- package/angular/README.md +112 -0
- package/angular/aeriz-editor.directive.ts +243 -0
- package/angular/aeriz-wysiwyg.module.ts +14 -0
- package/angular/index.ts +5 -0
- package/dist/adapters/jquery.cjs +1 -0
- package/dist/adapters/jquery.js +91 -0
- package/dist/adapters/react.cjs +1 -0
- package/dist/adapters/react.js +66 -0
- package/dist/adapters/shared.cjs +1 -0
- package/dist/adapters/shared.js +87 -0
- package/dist/adapters/svelte.cjs +1 -0
- package/dist/adapters/svelte.js +29 -0
- package/dist/adapters/vue.cjs +1 -0
- package/dist/adapters/vue.js +110 -0
- package/dist/adapters/vue2.cjs +1 -0
- package/dist/adapters/vue2.js +117 -0
- package/dist/adapters/wc.cjs +1 -0
- package/dist/adapters/wc.js +207 -0
- package/dist/aeriz-wysiwyg-adapter.js +169 -0
- package/dist/aeriz-wysiwyg-adapter.min.js +1 -0
- package/dist/aeriz-wysiwyg-jquery.js +275 -0
- package/dist/aeriz-wysiwyg-jquery.min.js +1 -0
- package/dist/aeriz-wysiwyg-wc.js +401 -0
- package/dist/aeriz-wysiwyg-wc.min.js +1 -0
- package/dist/aeriz-wysiwyg.cjs +8759 -0
- package/dist/aeriz-wysiwyg.css +587 -163
- package/dist/aeriz-wysiwyg.esm.js +4249 -1381
- package/dist/aeriz-wysiwyg.esm.min.js +4456 -1995
- package/dist/aeriz-wysiwyg.js +4249 -1381
- package/dist/aeriz-wysiwyg.min.cjs +56 -0
- package/dist/aeriz-wysiwyg.min.css +1 -1
- package/dist/aeriz-wysiwyg.min.js +54 -21
- package/dist/server.cjs +34 -0
- package/dist/server.js +798 -0
- package/dist-types/adapters/jquery.d.ts +34 -0
- package/dist-types/adapters/jquery.d.ts.map +1 -0
- package/dist-types/adapters/react.d.ts +28 -0
- package/dist-types/adapters/react.d.ts.map +1 -0
- package/dist-types/adapters/shared.d.ts +83 -0
- package/dist-types/adapters/shared.d.ts.map +1 -0
- package/dist-types/adapters/svelte.d.ts +38 -0
- package/dist-types/adapters/svelte.d.ts.map +1 -0
- package/dist-types/adapters/vue.d.ts +189 -0
- package/dist-types/adapters/vue.d.ts.map +1 -0
- package/dist-types/adapters/vue2.d.ts +175 -0
- package/dist-types/adapters/vue2.d.ts.map +1 -0
- package/dist-types/adapters/wc.d.ts +96 -0
- package/dist-types/adapters/wc.d.ts.map +1 -0
- package/dist-types/cjs/adapters/jquery.d.cts +34 -0
- package/dist-types/cjs/adapters/react.d.cts +28 -0
- package/dist-types/cjs/adapters/shared.d.cts +83 -0
- package/dist-types/cjs/adapters/svelte.d.cts +38 -0
- package/dist-types/cjs/adapters/vue.d.cts +189 -0
- package/dist-types/cjs/adapters/vue2.d.cts +175 -0
- package/dist-types/cjs/adapters/wc.d.cts +96 -0
- package/dist-types/cjs/core/AerizEditor.d.cts +530 -0
- package/dist-types/cjs/core/AerizViewer.d.cts +61 -0
- package/dist-types/cjs/core/block-meta.d.cts +98 -0
- package/dist-types/cjs/core/block-policy.d.cts +43 -0
- package/dist-types/cjs/core/blocks.d.cts +411 -0
- package/dist-types/cjs/core/fonts.d.cts +60 -0
- package/dist-types/cjs/core/highlight.d.cts +44 -0
- package/dist-types/cjs/core/history.d.cts +86 -0
- package/dist-types/cjs/core/html-mini.d.cts +65 -0
- package/dist-types/cjs/core/i18n.d.cts +221 -0
- package/dist-types/cjs/core/import-html.d.cts +40 -0
- package/dist-types/cjs/core/import-markdown.d.cts +33 -0
- package/dist-types/cjs/core/input-rules.d.cts +46 -0
- package/dist-types/cjs/core/markdown-export.d.cts +30 -0
- package/dist-types/cjs/core/plain-text.d.cts +17 -0
- package/dist-types/cjs/core/render-string.d.cts +68 -0
- package/dist-types/cjs/core/selection.d.cts +46 -0
- package/dist-types/cjs/core/snapshot.d.cts +51 -0
- package/dist-types/cjs/core/table-ops.d.cts +30 -0
- package/dist-types/cjs/index.d.cts +22 -0
- package/dist-types/cjs/server/index.d.cts +37 -0
- package/dist-types/cjs/types/index.d.cts +61 -0
- package/dist-types/cjs/ui/Toolbar.d.cts +21 -0
- package/dist-types/cjs/ui/dialogs.d.cts +74 -0
- package/dist-types/cjs/ui/icons.d.cts +2 -0
- package/dist-types/cjs/ui/popovers.d.cts +70 -0
- package/dist-types/core/AerizEditor.d.ts +210 -17
- package/dist-types/core/AerizEditor.d.ts.map +1 -1
- package/dist-types/core/AerizViewer.d.ts +16 -4
- package/dist-types/core/AerizViewer.d.ts.map +1 -1
- package/dist-types/core/block-meta.d.ts +98 -0
- package/dist-types/core/block-meta.d.ts.map +1 -0
- package/dist-types/core/block-policy.d.ts +43 -0
- package/dist-types/core/block-policy.d.ts.map +1 -0
- package/dist-types/core/blocks.d.ts +109 -11
- package/dist-types/core/blocks.d.ts.map +1 -1
- package/dist-types/core/fonts.d.ts +11 -0
- package/dist-types/core/fonts.d.ts.map +1 -1
- package/dist-types/core/history.d.ts +86 -0
- package/dist-types/core/history.d.ts.map +1 -0
- package/dist-types/core/html-mini.d.ts +65 -0
- package/dist-types/core/html-mini.d.ts.map +1 -0
- package/dist-types/core/i18n.d.ts +12 -0
- package/dist-types/core/i18n.d.ts.map +1 -1
- package/dist-types/core/import-html.d.ts +1 -0
- package/dist-types/core/import-html.d.ts.map +1 -1
- package/dist-types/core/import-markdown.d.ts +0 -4
- package/dist-types/core/import-markdown.d.ts.map +1 -1
- package/dist-types/core/input-rules.d.ts +46 -0
- package/dist-types/core/input-rules.d.ts.map +1 -0
- package/dist-types/core/markdown-export.d.ts +30 -0
- package/dist-types/core/markdown-export.d.ts.map +1 -0
- package/dist-types/core/plain-text.d.ts +17 -0
- package/dist-types/core/plain-text.d.ts.map +1 -0
- package/dist-types/core/render-string.d.ts +68 -0
- package/dist-types/core/render-string.d.ts.map +1 -0
- package/dist-types/core/selection.d.ts +46 -0
- package/dist-types/core/selection.d.ts.map +1 -0
- package/dist-types/core/snapshot.d.ts +51 -0
- package/dist-types/core/snapshot.d.ts.map +1 -0
- package/dist-types/core/table-ops.d.ts +30 -0
- package/dist-types/core/table-ops.d.ts.map +1 -0
- package/dist-types/index.d.ts +21 -10
- package/dist-types/index.d.ts.map +1 -1
- package/dist-types/server/index.d.ts +37 -0
- package/dist-types/server/index.d.ts.map +1 -0
- package/dist-types/types/index.d.ts +21 -0
- package/dist-types/types/index.d.ts.map +1 -1
- package/dist-types/ui/Toolbar.d.ts +1 -1
- package/dist-types/ui/Toolbar.d.ts.map +1 -1
- package/dist-types/ui/dialogs.d.ts.map +1 -1
- package/dist-types/ui/icons.d.ts.map +1 -1
- package/dist-types/ui/popovers.d.ts +1 -1
- package/dist-types/ui/popovers.d.ts.map +1 -1
- package/package.json +213 -58
package/dist/aeriz-wysiwyg.css
CHANGED
|
@@ -21,6 +21,19 @@
|
|
|
21
21
|
'Noto Sans KR', 'Malgun Gothic', sans-serif;
|
|
22
22
|
--aw-font-mono: 'SF Mono', Menlo, Monaco, Consolas, 'D2Coding', monospace;
|
|
23
23
|
|
|
24
|
+
/* ─── 모션 ──────────────────────────────────────────────────────────
|
|
25
|
+
블록 UI 의 전환은 전부 이 토큰들을 쓴다. 값이 한 군데 모여 있어야
|
|
26
|
+
"누르면 즉각, 사라질 땐 느긋하게" 같은 규칙이 화면 전체에서 일관된다.
|
|
27
|
+
· fast — 눌림/색 변화처럼 손끝에 바로 붙어야 하는 것
|
|
28
|
+
· base — 나타남/사라짐
|
|
29
|
+
· slow — 위치 이동처럼 눈으로 따라가는 것
|
|
30
|
+
· ease-out : 등장(감속). ease-spring : 살짝 튕기며 자리잡는 등장. */
|
|
31
|
+
--aw-dur-fast: 90ms;
|
|
32
|
+
--aw-dur-base: 160ms;
|
|
33
|
+
--aw-dur-slow: 240ms;
|
|
34
|
+
--aw-ease-out: cubic-bezier(0.22, 0.85, 0.3, 1);
|
|
35
|
+
--aw-ease-spring: cubic-bezier(0.2, 1.3, 0.4, 1);
|
|
36
|
+
|
|
24
37
|
--aw-toolbar-height: 44px;
|
|
25
38
|
--aw-z-toolbar: 10;
|
|
26
39
|
--aw-z-popover: 100;
|
|
@@ -42,7 +55,6 @@
|
|
|
42
55
|
--aw-primary-hover: #8ad6ff;
|
|
43
56
|
--aw-divider: rgba(100, 200, 255, 0.12);
|
|
44
57
|
}
|
|
45
|
-
|
|
46
58
|
.aeriz-wysiwyg {
|
|
47
59
|
font-family: var(--aw-font);
|
|
48
60
|
background-color: var(--aw-bg);
|
|
@@ -78,18 +90,15 @@
|
|
|
78
90
|
/* ─── 뷰어 모드 ─────────────────────────────────────────────────────
|
|
79
91
|
AerizViewer 는 컨텐츠 길이만큼 자연스럽게 늘어난다 (스크롤 / 고정 높이 X).
|
|
80
92
|
에디터 기본 규칙을 viewer 클래스가 좁게 덮어쓴다. */
|
|
81
|
-
|
|
82
93
|
.aeriz-wysiwyg-viewer {
|
|
83
94
|
height: auto;
|
|
84
95
|
min-height: 0;
|
|
85
96
|
}
|
|
86
|
-
|
|
87
97
|
.aeriz-wysiwyg-viewer .aw-content-wrap {
|
|
88
98
|
flex: 0 0 auto;
|
|
89
99
|
overflow: visible;
|
|
90
100
|
min-height: 0;
|
|
91
101
|
}
|
|
92
|
-
|
|
93
102
|
.aeriz-wysiwyg-viewer .aw-content {
|
|
94
103
|
min-height: 0;
|
|
95
104
|
}
|
|
@@ -100,37 +109,49 @@
|
|
|
100
109
|
position: absolute;
|
|
101
110
|
top: 0;
|
|
102
111
|
left: 0;
|
|
103
|
-
width:
|
|
112
|
+
width: 20px;
|
|
104
113
|
height: 100%;
|
|
105
114
|
pointer-events: none;
|
|
106
115
|
z-index: 2;
|
|
107
116
|
}
|
|
108
117
|
|
|
109
|
-
/* 블록별 컨트롤 그룹 — 드래그 핸들 + 단락 추가 버튼을 세로로 묶는다.
|
|
110
|
-
|
|
118
|
+
/* 블록별 컨트롤 그룹 — 드래그 핸들 + 단락 추가 버튼을 세로로 묶는다.
|
|
119
|
+
지금 다루는 블록(포인터가 올라간 블록 / 캐럿이 있는 블록) 것만 드러난다.
|
|
120
|
+
본문 어디에나 마우스만 올리면 모든 블록의 핸들이 한꺼번에 떠오르던
|
|
121
|
+
예전 동작은, 글이 길어질수록 왼쪽에 점 기둥을 세워 놓는 꼴이었다. */
|
|
111
122
|
.aw-block-controls {
|
|
112
123
|
position: absolute;
|
|
113
|
-
left:
|
|
124
|
+
left: 3px;
|
|
114
125
|
display: flex;
|
|
115
126
|
flex-direction: column;
|
|
116
127
|
gap: 0;
|
|
117
128
|
pointer-events: none;
|
|
118
129
|
opacity: 0;
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
/* 살짝 왼쪽에서 밀려 들어온다 — 나타남에 방향이 생기면 어느 블록에
|
|
131
|
+
붙은 컨트롤인지가 눈으로 더 빨리 읽힌다. */
|
|
132
|
+
transform: translateX(-3px);
|
|
133
|
+
transition:
|
|
134
|
+
opacity var(--aw-dur-base) var(--aw-ease-out),
|
|
135
|
+
transform var(--aw-dur-base) var(--aw-ease-out);
|
|
136
|
+
}
|
|
137
|
+
/* 캐럿이 있는 블록 — 은은하게 상주. 포인터가 올라오면 완전히 또렷하게. */
|
|
138
|
+
.aw-block-controls.is-active {
|
|
139
|
+
opacity: 0.5;
|
|
140
|
+
transform: none;
|
|
141
|
+
}
|
|
142
|
+
.aw-block-controls.is-hovered,
|
|
143
|
+
.aw-block-controls:hover,
|
|
144
|
+
.aw-block-controls:focus-within {
|
|
127
145
|
opacity: 1;
|
|
146
|
+
transform: none;
|
|
128
147
|
}
|
|
129
148
|
|
|
149
|
+
/* 높이는 AerizEditor.positionHandle 의 HANDLE_HEIGHT 와 짝을 이룬다 —
|
|
150
|
+
한쪽만 바꾸면 짧은 블록(hr) 위에서 핸들의 수직 정렬이 어긋난다. */
|
|
130
151
|
.aw-block-handle,
|
|
131
152
|
.aw-block-add {
|
|
132
|
-
width:
|
|
133
|
-
height:
|
|
153
|
+
width: 14px;
|
|
154
|
+
height: 18px;
|
|
134
155
|
display: inline-flex;
|
|
135
156
|
align-items: center;
|
|
136
157
|
justify-content: center;
|
|
@@ -143,15 +164,18 @@
|
|
|
143
164
|
appearance: none;
|
|
144
165
|
padding: 0;
|
|
145
166
|
cursor: pointer;
|
|
146
|
-
transition:
|
|
167
|
+
transition:
|
|
168
|
+
color var(--aw-dur-fast) var(--aw-ease-out),
|
|
169
|
+
background-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
170
|
+
border-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
171
|
+
transform var(--aw-dur-fast) var(--aw-ease-out);
|
|
147
172
|
}
|
|
148
|
-
|
|
149
173
|
.aw-block-handle { cursor: grab; }
|
|
150
174
|
|
|
151
175
|
.aw-block-handle svg,
|
|
152
176
|
.aw-block-add svg {
|
|
153
|
-
width:
|
|
154
|
-
height:
|
|
177
|
+
width: 10px;
|
|
178
|
+
height: 11px;
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
.aw-block-handle:hover,
|
|
@@ -160,17 +184,47 @@
|
|
|
160
184
|
background-color: var(--aw-btn-hover-bg);
|
|
161
185
|
border-color: var(--aw-border);
|
|
162
186
|
}
|
|
187
|
+
/* 눌린 순간 살짝 눌러앉는다 — 클릭이 먹었다는 신호가 색보다 빠르다. */
|
|
188
|
+
.aw-block-handle:active,
|
|
189
|
+
.aw-block-add:active {
|
|
190
|
+
transform: scale(0.88);
|
|
191
|
+
}
|
|
192
|
+
/* 키보드 사용자에게도 같은 위치를 알려 준다. */
|
|
193
|
+
.aw-block-handle:focus-visible,
|
|
194
|
+
.aw-block-add:focus-visible {
|
|
195
|
+
outline: 2px solid var(--aw-primary);
|
|
196
|
+
outline-offset: 1px;
|
|
197
|
+
color: var(--aw-primary);
|
|
198
|
+
}
|
|
199
|
+
/* 추가 버튼의 '+' 는 hover 시 1/4 바퀴 돌아 "여기서 새로 시작한다" 는
|
|
200
|
+
느낌을 준다. 회전은 8px 아이콘에서도 확실히 읽히는 몇 안 되는 변화다. */
|
|
201
|
+
.aw-block-add svg {
|
|
202
|
+
transition: transform var(--aw-dur-base) var(--aw-ease-spring);
|
|
203
|
+
}
|
|
204
|
+
.aw-block-add:hover svg {
|
|
205
|
+
transform: rotate(90deg);
|
|
206
|
+
}
|
|
163
207
|
|
|
164
208
|
.aw-block-handle.is-dragging {
|
|
165
209
|
cursor: grabbing;
|
|
166
210
|
color: var(--aw-primary);
|
|
211
|
+
background-color: var(--aw-btn-active-bg);
|
|
212
|
+
border-color: var(--aw-primary);
|
|
213
|
+
transform: scale(1.05);
|
|
167
214
|
}
|
|
168
215
|
|
|
216
|
+
/* 끌고 있는 블록 자신 — 자리만 남기고 물러난다. */
|
|
169
217
|
.is-block-dragging {
|
|
170
|
-
opacity: 0.
|
|
218
|
+
opacity: 0.35;
|
|
219
|
+
filter: saturate(0.6);
|
|
220
|
+
transition:
|
|
221
|
+
opacity var(--aw-dur-base) var(--aw-ease-out),
|
|
222
|
+
filter var(--aw-dur-base) var(--aw-ease-out);
|
|
171
223
|
}
|
|
172
224
|
|
|
173
|
-
/* ─── 드롭 위치 인디케이터 ─────────────────────────────────────────────
|
|
225
|
+
/* ─── 드롭 위치 인디케이터 ─────────────────────────────────────────────
|
|
226
|
+
선 왼쪽 끝에 점을 하나 찍는다. 얇은 선만 있으면 어느 쪽 여백에 걸린
|
|
227
|
+
건지 애매한데, 점이 있으면 "여기서부터" 가 분명해진다. */
|
|
174
228
|
|
|
175
229
|
.aw-block-drop-indicator {
|
|
176
230
|
position: absolute;
|
|
@@ -182,7 +236,29 @@
|
|
|
182
236
|
pointer-events: none;
|
|
183
237
|
z-index: 3;
|
|
184
238
|
transform: translateY(-1px);
|
|
185
|
-
box-shadow: 0 0 6px var(--aw-primary);
|
|
239
|
+
box-shadow: 0 0 6px color-mix(in srgb, var(--aw-primary) 70%, transparent);
|
|
240
|
+
animation: aw-drop-in var(--aw-dur-base) var(--aw-ease-out);
|
|
241
|
+
}
|
|
242
|
+
.aw-block-drop-indicator::before {
|
|
243
|
+
content: '';
|
|
244
|
+
position: absolute;
|
|
245
|
+
left: -3px;
|
|
246
|
+
top: 50%;
|
|
247
|
+
width: 7px;
|
|
248
|
+
height: 7px;
|
|
249
|
+
border-radius: 50%;
|
|
250
|
+
background: var(--aw-primary);
|
|
251
|
+
transform: translateY(-50%);
|
|
252
|
+
}
|
|
253
|
+
@keyframes aw-drop-in {
|
|
254
|
+
from {
|
|
255
|
+
opacity: 0;
|
|
256
|
+
transform: translateY(-1px) scaleX(0.94);
|
|
257
|
+
}
|
|
258
|
+
to {
|
|
259
|
+
opacity: 1;
|
|
260
|
+
transform: translateY(-1px) scaleX(1);
|
|
261
|
+
}
|
|
186
262
|
}
|
|
187
263
|
|
|
188
264
|
/* ─── Status Bar ─────────────────────────────────────────────────────
|
|
@@ -232,7 +308,6 @@
|
|
|
232
308
|
}
|
|
233
309
|
|
|
234
310
|
/* status bar 안의 작은 아이콘 액션 버튼 (undo/redo 등) */
|
|
235
|
-
|
|
236
311
|
.aw-status-action {
|
|
237
312
|
appearance: none;
|
|
238
313
|
cursor: pointer;
|
|
@@ -249,18 +324,15 @@
|
|
|
249
324
|
flex-shrink: 0;
|
|
250
325
|
transition: color 0.12s, background-color 0.12s, border-color 0.12s;
|
|
251
326
|
}
|
|
252
|
-
|
|
253
327
|
.aw-status-action svg {
|
|
254
328
|
width: 13px;
|
|
255
329
|
height: 13px;
|
|
256
330
|
}
|
|
257
|
-
|
|
258
331
|
.aw-status-action:hover {
|
|
259
332
|
color: var(--aw-btn-active-fg, var(--aw-primary));
|
|
260
333
|
background-color: var(--aw-btn-hover-bg);
|
|
261
334
|
border-color: var(--aw-border);
|
|
262
335
|
}
|
|
263
|
-
|
|
264
336
|
.aw-status-action:active {
|
|
265
337
|
background-color: var(--aw-btn-active-bg);
|
|
266
338
|
}
|
|
@@ -271,21 +343,121 @@
|
|
|
271
343
|
|
|
272
344
|
/* ─── 블록 포커스 인디케이터 + 라벨 태그 ─────────────────────────────── */
|
|
273
345
|
|
|
346
|
+
/* 활성 블록 표시는 **레일(왼쪽 세로선) + 옅은 바탕** 두 겹이다.
|
|
347
|
+
레일은 색이 아니라 길이로 자란다 — `box-shadow` 를 켜고 끄면 선이 툭
|
|
348
|
+
나타나는데, 세로로 자라 올라오면 "이 블록이 지금 잡혔다" 가 동작으로
|
|
349
|
+
읽힌다. 레일은 별도 pseudo 로 그려서 블록 자신의 배경(코드 블록 ·
|
|
350
|
+
인용구) 과 겹치지 않는다. 어떤 태그에도 레이아웃 영향을 주지 않도록
|
|
351
|
+
position:absolute 만 쓰고 블록의 박스 크기는 건드리지 않는다. */
|
|
274
352
|
.aw-content > [data-block-id] {
|
|
275
353
|
position: relative;
|
|
276
|
-
transition: background-color
|
|
354
|
+
transition: background-color var(--aw-dur-base) var(--aw-ease-out);
|
|
277
355
|
}
|
|
278
356
|
|
|
279
|
-
.aw-content > [data-block-
|
|
280
|
-
|
|
281
|
-
|
|
357
|
+
.aw-content > [data-block-id]::before {
|
|
358
|
+
content: '';
|
|
359
|
+
position: absolute;
|
|
360
|
+
left: -10px;
|
|
361
|
+
top: 0;
|
|
362
|
+
width: 3px;
|
|
363
|
+
height: 100%;
|
|
282
364
|
border-radius: 2px;
|
|
365
|
+
background: var(--aw-primary);
|
|
366
|
+
opacity: 0;
|
|
367
|
+
transform: scaleY(0.25);
|
|
368
|
+
transform-origin: center;
|
|
369
|
+
pointer-events: none;
|
|
370
|
+
transition:
|
|
371
|
+
opacity var(--aw-dur-base) var(--aw-ease-out),
|
|
372
|
+
transform var(--aw-dur-base) var(--aw-ease-spring);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
.aw-content > [data-block-focused] {
|
|
376
|
+
background-color: color-mix(in srgb, var(--aw-primary) 7%, transparent);
|
|
377
|
+
border-radius: 3px;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.aw-content > [data-block-focused]::before {
|
|
381
|
+
opacity: 1;
|
|
382
|
+
transform: scaleY(1);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* 포인터가 올라간 블록 — 아직 잡은 건 아니므로 레일 없이 바탕만 살짝.
|
|
386
|
+
활성 블록의 강조를 덮지 않도록 :not() 으로 비켜 준다. */
|
|
387
|
+
.aw-content > [data-block-id]:hover:not([data-block-focused]) {
|
|
388
|
+
background-color: color-mix(in srgb, var(--aw-fg) 3%, transparent);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
/* 표는 pseudo 요소가 익명 테이블 박스로 감싸여 위치가 어긋난다. 레일 대신
|
|
392
|
+
테두리 강조로 같은 뜻을 전한다. */
|
|
393
|
+
.aw-content > table::before {
|
|
394
|
+
display: none;
|
|
395
|
+
}
|
|
396
|
+
.aw-content > table[data-block-focused] {
|
|
397
|
+
outline: 1px solid color-mix(in srgb, var(--aw-primary) 55%, transparent);
|
|
398
|
+
outline-offset: 3px;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/* 유형이 막 바뀐 블록 — 한 번만 반짝. AerizEditor 가 애니메이션이 끝나면
|
|
402
|
+
속성을 지운다. */
|
|
403
|
+
.aw-content > [data-block-flash] {
|
|
404
|
+
animation: aw-block-flash 520ms var(--aw-ease-out);
|
|
405
|
+
}
|
|
406
|
+
@keyframes aw-block-flash {
|
|
407
|
+
0% {
|
|
408
|
+
background-color: color-mix(in srgb, var(--aw-primary) 26%, transparent);
|
|
409
|
+
}
|
|
410
|
+
100% {
|
|
411
|
+
background-color: transparent;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/* 캐럿이 놓인 빈 본문 블록 — 무엇을 하면 되는지 한 줄로 알려 준다.
|
|
416
|
+
문서 전체가 비었을 때 뜨는 에디터 placeholder 와 겹치지 않도록, 블록이
|
|
417
|
+
둘 이상일 때만(`:has(> :nth-child(2))`) 나타난다. */
|
|
418
|
+
.aw-content:has(> :nth-child(2))
|
|
419
|
+
> p[data-block-focused]:has(> br:only-child)::after {
|
|
420
|
+
content: var(--aw-empty-hint, '');
|
|
421
|
+
position: absolute;
|
|
422
|
+
left: 0;
|
|
423
|
+
top: 0;
|
|
424
|
+
color: var(--aw-fg-muted);
|
|
425
|
+
opacity: 0;
|
|
426
|
+
pointer-events: none;
|
|
427
|
+
user-select: none;
|
|
428
|
+
font-size: 0.95em;
|
|
429
|
+
animation: aw-hint-in var(--aw-dur-slow) var(--aw-ease-out) 120ms forwards;
|
|
430
|
+
}
|
|
431
|
+
@keyframes aw-hint-in {
|
|
432
|
+
from {
|
|
433
|
+
opacity: 0;
|
|
434
|
+
transform: translateX(-2px);
|
|
435
|
+
}
|
|
436
|
+
to {
|
|
437
|
+
opacity: 0.45;
|
|
438
|
+
transform: none;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
/* 구분선은 높이가 사실상 0 이라 레일이 안 보인다 — 최소 길이를 주고
|
|
443
|
+
세로 가운데에 건다 (핸들의 HANDLE_HEIGHT 정렬과 같은 규칙). */
|
|
444
|
+
.aw-content > hr::before {
|
|
445
|
+
height: 14px;
|
|
446
|
+
top: 50%;
|
|
447
|
+
margin-top: -7px;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/* 읽기 전용 뷰어에는 편집 상태 표시가 의미 없다. */
|
|
451
|
+
.aeriz-wysiwyg-viewer .aw-content > [data-block-id]::before {
|
|
452
|
+
display: none;
|
|
453
|
+
}
|
|
454
|
+
.aeriz-wysiwyg-viewer .aw-content > [data-block-id]:hover {
|
|
455
|
+
background-color: transparent;
|
|
283
456
|
}
|
|
284
457
|
|
|
285
458
|
/* ─── 인터랙티브 블록 라벨 pill ───────────────────────────────────────
|
|
286
459
|
활성 블록 위에 떠 있는 작은 버튼. 정적 ::before pseudo 라벨을 대체하며
|
|
287
460
|
클릭 시 블록 유형 드롭다운을 열어 마이크로 인터랙션으로 유형 변경. */
|
|
288
|
-
|
|
289
461
|
.aw-block-label-pill {
|
|
290
462
|
position: absolute;
|
|
291
463
|
z-index: 4;
|
|
@@ -297,39 +469,101 @@
|
|
|
297
469
|
text-transform: uppercase;
|
|
298
470
|
color: var(--aw-primary);
|
|
299
471
|
background: var(--aw-bg);
|
|
300
|
-
padding: 2px
|
|
301
|
-
border: 1px solid var(--aw-primary);
|
|
302
|
-
border-radius:
|
|
472
|
+
padding: 2px 5px 2px 4px;
|
|
473
|
+
border: 1px solid color-mix(in srgb, var(--aw-primary) 45%, transparent);
|
|
474
|
+
border-radius: 4px;
|
|
303
475
|
cursor: pointer;
|
|
304
476
|
user-select: none;
|
|
305
477
|
display: inline-flex;
|
|
306
478
|
align-items: center;
|
|
307
479
|
gap: 4px;
|
|
308
480
|
line-height: 1;
|
|
309
|
-
|
|
310
|
-
|
|
481
|
+
white-space: nowrap;
|
|
482
|
+
transition:
|
|
483
|
+
transform var(--aw-dur-fast) var(--aw-ease-out),
|
|
484
|
+
background-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
485
|
+
color var(--aw-dur-fast) var(--aw-ease-out),
|
|
486
|
+
border-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
487
|
+
box-shadow var(--aw-dur-base) var(--aw-ease-out);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/* 유형 기호 — 라벨을 읽기 전에 눈이 먼저 잡는 부분이라 한 칸 더 진하게. */
|
|
491
|
+
.aw-block-label-pill .aw-pill-glyph {
|
|
492
|
+
display: inline-flex;
|
|
493
|
+
align-items: center;
|
|
494
|
+
justify-content: center;
|
|
495
|
+
min-width: 13px;
|
|
496
|
+
height: 13px;
|
|
497
|
+
padding: 0 2px;
|
|
498
|
+
border-radius: 3px;
|
|
499
|
+
background: color-mix(in srgb, var(--aw-primary) 16%, transparent);
|
|
500
|
+
font-size: 9px;
|
|
501
|
+
letter-spacing: 0;
|
|
502
|
+
transition: background-color var(--aw-dur-fast) var(--aw-ease-out);
|
|
311
503
|
}
|
|
312
504
|
|
|
313
505
|
.aw-block-label-pill::after {
|
|
314
506
|
content: '▾';
|
|
315
507
|
font-size: 9px;
|
|
316
|
-
opacity: 0.
|
|
508
|
+
opacity: 0.55;
|
|
509
|
+
transition:
|
|
510
|
+
opacity var(--aw-dur-fast) var(--aw-ease-out),
|
|
511
|
+
transform var(--aw-dur-base) var(--aw-ease-out);
|
|
317
512
|
}
|
|
318
|
-
|
|
319
513
|
.aw-block-label-pill:hover {
|
|
320
514
|
background: var(--aw-primary);
|
|
321
|
-
color: var(--aw-
|
|
515
|
+
color: var(--aw-primary-fg);
|
|
516
|
+
border-color: var(--aw-primary);
|
|
322
517
|
transform: translateY(-1px);
|
|
323
|
-
box-shadow: 0
|
|
518
|
+
box-shadow: 0 3px 10px color-mix(in srgb, var(--aw-primary) 32%, transparent);
|
|
519
|
+
}
|
|
520
|
+
.aw-block-label-pill:hover .aw-pill-glyph {
|
|
521
|
+
background: color-mix(in srgb, var(--aw-primary-fg) 22%, transparent);
|
|
522
|
+
}
|
|
523
|
+
.aw-block-label-pill:hover::after {
|
|
524
|
+
opacity: 1;
|
|
525
|
+
transform: translateY(1px);
|
|
324
526
|
}
|
|
325
|
-
|
|
326
527
|
.aw-block-label-pill:active {
|
|
327
|
-
transform: translateY(0);
|
|
528
|
+
transform: translateY(0) scale(0.97);
|
|
529
|
+
box-shadow: none;
|
|
530
|
+
}
|
|
531
|
+
.aw-block-label-pill:focus-visible {
|
|
532
|
+
outline: 2px solid var(--aw-primary);
|
|
533
|
+
outline-offset: 2px;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
/* 다른 블록으로 캐럿이 옮겨갈 때만 재생된다 (AerizEditor 가 클래스를 다시
|
|
537
|
+
붙인다). 같은 블록에서 타이핑하는 동안에는 미동도 없어야 한다. */
|
|
538
|
+
.aw-block-label-pill.is-entering {
|
|
539
|
+
animation: aw-pill-in var(--aw-dur-slow) var(--aw-ease-spring);
|
|
540
|
+
}
|
|
541
|
+
/* pill 에서 연 블록 유형 메뉴가 떠 있는 동안 */
|
|
542
|
+
.aw-block-label-pill.is-popover-open {
|
|
543
|
+
background: var(--aw-primary);
|
|
544
|
+
color: var(--aw-primary-fg);
|
|
545
|
+
border-color: var(--aw-primary);
|
|
546
|
+
}
|
|
547
|
+
.aw-block-label-pill.is-popover-open::after {
|
|
548
|
+
transform: rotate(180deg);
|
|
549
|
+
opacity: 1;
|
|
550
|
+
}
|
|
551
|
+
@keyframes aw-pill-in {
|
|
552
|
+
from {
|
|
553
|
+
opacity: 0;
|
|
554
|
+
transform: translateY(3px) scale(0.92);
|
|
555
|
+
}
|
|
556
|
+
to {
|
|
557
|
+
opacity: 1;
|
|
558
|
+
transform: translateY(0) scale(1);
|
|
559
|
+
}
|
|
328
560
|
}
|
|
329
561
|
|
|
330
562
|
.aw-content {
|
|
331
563
|
outline: none;
|
|
332
|
-
|
|
564
|
+
/* 위쪽 여백은 라벨 pill(약 15px) + 여유가 들어갈 만큼 둔다 — 문서 첫
|
|
565
|
+
블록에서도 pill 이 글자를 덮지 않아야 한다. */
|
|
566
|
+
padding: 28px 28px 24px;
|
|
333
567
|
min-height: 240px;
|
|
334
568
|
font-size: 15px;
|
|
335
569
|
line-height: 1.7;
|
|
@@ -348,11 +582,26 @@
|
|
|
348
582
|
.aw-content > p {
|
|
349
583
|
margin: 0 0 0.8em 0;
|
|
350
584
|
}
|
|
351
|
-
|
|
352
585
|
.aw-content > p:last-child {
|
|
353
586
|
margin-bottom: 0;
|
|
354
587
|
}
|
|
355
588
|
|
|
589
|
+
/* 정렬 클래스 — getHTML({ styles: 'class' }) 출력이 style="text-align:…" 대신
|
|
590
|
+
사용한다. style 속성을 제거하는 서버 sanitizer 를 통과해도 정렬이 남는다.
|
|
591
|
+
에디터 자체는 계속 인라인 style 로 정렬하므로 편집 중 동작에는 영향이 없다. */
|
|
592
|
+
.aw-content .aw-align-left {
|
|
593
|
+
text-align: left;
|
|
594
|
+
}
|
|
595
|
+
.aw-content .aw-align-center {
|
|
596
|
+
text-align: center;
|
|
597
|
+
}
|
|
598
|
+
.aw-content .aw-align-right {
|
|
599
|
+
text-align: right;
|
|
600
|
+
}
|
|
601
|
+
.aw-content .aw-align-justify {
|
|
602
|
+
text-align: justify;
|
|
603
|
+
}
|
|
604
|
+
|
|
356
605
|
.aw-content h1,
|
|
357
606
|
.aw-content h2,
|
|
358
607
|
.aw-content h3 {
|
|
@@ -361,11 +610,8 @@
|
|
|
361
610
|
padding-bottom: 0.25em;
|
|
362
611
|
border-bottom: 1px solid var(--aw-border);
|
|
363
612
|
}
|
|
364
|
-
|
|
365
613
|
.aw-content h1 { font-size: 1.875rem; line-height: 1.3; }
|
|
366
|
-
|
|
367
614
|
.aw-content h2 { font-size: 1.5rem; line-height: 1.35; }
|
|
368
|
-
|
|
369
615
|
.aw-content h3 { font-size: 1.25rem; line-height: 1.4; }
|
|
370
616
|
|
|
371
617
|
.aw-content blockquote {
|
|
@@ -393,7 +639,6 @@
|
|
|
393
639
|
/* 코드 블록 우상단의 언어 라벨 — `<code data-language="javascript">` 의
|
|
394
640
|
* data-language 가 있을 때만 표시. attr() 로 자동 동기화돼 별도 JS 갱신
|
|
395
641
|
* 불필요. 사용자가 드롭다운으로 언어 변경 시 CSS 가 즉시 반영. */
|
|
396
|
-
|
|
397
642
|
.aw-content > pre > code[data-language]:not([data-language=""])::before {
|
|
398
643
|
content: attr(data-language);
|
|
399
644
|
position: absolute;
|
|
@@ -418,48 +663,30 @@
|
|
|
418
663
|
padding: 0.15em 0.4em;
|
|
419
664
|
border-radius: 3px;
|
|
420
665
|
}
|
|
421
|
-
|
|
422
666
|
.aw-content pre code {
|
|
423
667
|
background: transparent;
|
|
424
668
|
padding: 0;
|
|
425
669
|
}
|
|
426
670
|
|
|
427
671
|
/* ─── Syntax highlight 토큰 색 (자체 highlight.ts 출력) ──────────── */
|
|
428
|
-
|
|
429
672
|
.aw-content pre code .hl-keyword { color: #c678dd; font-weight: 600; }
|
|
430
|
-
|
|
431
673
|
.aw-content pre code .hl-string { color: #98c379; }
|
|
432
|
-
|
|
433
674
|
.aw-content pre code .hl-number { color: #d19a66; }
|
|
434
|
-
|
|
435
675
|
.aw-content pre code .hl-comment { color: var(--aw-fg-muted); font-style: italic; }
|
|
436
|
-
|
|
437
676
|
.aw-content pre code .hl-fn { color: #61afef; }
|
|
438
|
-
|
|
439
677
|
.aw-content pre code .hl-builtin { color: #56b6c2; }
|
|
440
|
-
|
|
441
678
|
.aw-content pre code .hl-tag { color: #e06c75; }
|
|
442
|
-
|
|
443
679
|
.aw-content pre code .hl-attr { color: #d19a66; }
|
|
444
|
-
|
|
445
680
|
.aw-content pre code .hl-prop { color: #61afef; }
|
|
446
|
-
|
|
447
681
|
.aw-content pre code .hl-punct { color: var(--aw-fg-muted); }
|
|
448
682
|
|
|
449
683
|
/* light 테마 보정 */
|
|
450
|
-
|
|
451
684
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-keyword { color: #a626a4; }
|
|
452
|
-
|
|
453
685
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-string { color: #50a14f; }
|
|
454
|
-
|
|
455
686
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-number { color: #986801; }
|
|
456
|
-
|
|
457
687
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-fn { color: #4078f2; }
|
|
458
|
-
|
|
459
688
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-builtin { color: #0184bc; }
|
|
460
|
-
|
|
461
689
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-tag { color: #e45649; }
|
|
462
|
-
|
|
463
690
|
.aeriz-wysiwyg[data-theme='light'] .aw-content pre code .hl-prop { color: #4078f2; }
|
|
464
691
|
|
|
465
692
|
.aw-content ul,
|
|
@@ -472,6 +699,72 @@
|
|
|
472
699
|
margin: 0.2em 0;
|
|
473
700
|
}
|
|
474
701
|
|
|
702
|
+
/* ─── 체크리스트 ─────────────────────────────────────────────────────
|
|
703
|
+
체크박스는 `<input>` 이 아니라 `<li>` 의 ::before 다. contentEditable 안의
|
|
704
|
+
폼 요소는 캐럿이 들어가고 서버 sanitizer 가 지우는데, ::before 는 둘 다
|
|
705
|
+
해당이 없다. 완료 여부는 `data-checked` 한 글자로 남는다. */
|
|
706
|
+
.aw-content ul.aw-task-list {
|
|
707
|
+
list-style: none;
|
|
708
|
+
padding-left: 1.9em;
|
|
709
|
+
}
|
|
710
|
+
.aw-content ul.aw-task-list > li {
|
|
711
|
+
position: relative;
|
|
712
|
+
}
|
|
713
|
+
.aw-content ul.aw-task-list > li::before {
|
|
714
|
+
content: '';
|
|
715
|
+
position: absolute;
|
|
716
|
+
left: -1.5em;
|
|
717
|
+
top: 0.28em;
|
|
718
|
+
width: 15px;
|
|
719
|
+
height: 15px;
|
|
720
|
+
border: 1.5px solid var(--aw-fg-muted);
|
|
721
|
+
border-radius: 4px;
|
|
722
|
+
background: transparent;
|
|
723
|
+
cursor: pointer;
|
|
724
|
+
box-sizing: border-box;
|
|
725
|
+
transition:
|
|
726
|
+
background-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
727
|
+
border-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
728
|
+
transform var(--aw-dur-base) var(--aw-ease-spring);
|
|
729
|
+
}
|
|
730
|
+
.aw-content ul.aw-task-list > li:hover::before {
|
|
731
|
+
border-color: var(--aw-primary);
|
|
732
|
+
transform: scale(1.1);
|
|
733
|
+
}
|
|
734
|
+
/* 체크 표시는 두 번째 pseudo 로 그린다 — 네모와 따로 움직여야 "찍히는"
|
|
735
|
+
느낌이 난다. 회전한 ㄴ 자 두 획이 체크 모양이다. */
|
|
736
|
+
.aw-content ul.aw-task-list > li::after {
|
|
737
|
+
content: '';
|
|
738
|
+
position: absolute;
|
|
739
|
+
left: -1.16em;
|
|
740
|
+
top: 0.42em;
|
|
741
|
+
width: 4px;
|
|
742
|
+
height: 8px;
|
|
743
|
+
border: solid var(--aw-primary-fg);
|
|
744
|
+
border-width: 0 2px 2px 0;
|
|
745
|
+
transform: rotate(45deg) scale(0.4);
|
|
746
|
+
opacity: 0;
|
|
747
|
+
pointer-events: none;
|
|
748
|
+
transition:
|
|
749
|
+
opacity var(--aw-dur-fast) var(--aw-ease-out),
|
|
750
|
+
transform var(--aw-dur-base) var(--aw-ease-spring);
|
|
751
|
+
}
|
|
752
|
+
.aw-content ul.aw-task-list > li[data-checked='true']::before {
|
|
753
|
+
background: var(--aw-primary);
|
|
754
|
+
border-color: var(--aw-primary);
|
|
755
|
+
}
|
|
756
|
+
.aw-content ul.aw-task-list > li[data-checked='true']::after {
|
|
757
|
+
opacity: 1;
|
|
758
|
+
transform: rotate(45deg) scale(1);
|
|
759
|
+
}
|
|
760
|
+
/* 완료한 항목은 한 걸음 물러난다. 지우지는 않는다 — 무엇을 끝냈는지도
|
|
761
|
+
목록의 일부다. */
|
|
762
|
+
.aw-content ul.aw-task-list > li[data-checked='true'] {
|
|
763
|
+
color: var(--aw-fg-muted);
|
|
764
|
+
text-decoration: line-through;
|
|
765
|
+
text-decoration-color: color-mix(in srgb, var(--aw-fg-muted) 60%, transparent);
|
|
766
|
+
}
|
|
767
|
+
|
|
475
768
|
.aw-content a {
|
|
476
769
|
color: var(--aw-primary);
|
|
477
770
|
text-decoration: underline;
|
|
@@ -491,7 +784,6 @@
|
|
|
491
784
|
}
|
|
492
785
|
|
|
493
786
|
/* ─── 유튜브 임베드 (16:9 반응형 컨테이너) ──────────────────── */
|
|
494
|
-
|
|
495
787
|
.aw-content > div.aw-youtube-embed {
|
|
496
788
|
position: relative;
|
|
497
789
|
width: 100%;
|
|
@@ -502,7 +794,6 @@
|
|
|
502
794
|
background: #000;
|
|
503
795
|
border: 1px solid var(--aw-border);
|
|
504
796
|
}
|
|
505
|
-
|
|
506
797
|
.aw-content > div.aw-youtube-embed iframe {
|
|
507
798
|
position: absolute;
|
|
508
799
|
inset: 0;
|
|
@@ -513,7 +804,6 @@
|
|
|
513
804
|
}
|
|
514
805
|
|
|
515
806
|
/* ─── 파일 첨부 (다운로드 카드) ──────────────────── */
|
|
516
|
-
|
|
517
807
|
.aw-content > a.aw-file-attachment {
|
|
518
808
|
display: flex;
|
|
519
809
|
align-items: center;
|
|
@@ -529,12 +819,10 @@
|
|
|
529
819
|
cursor: pointer;
|
|
530
820
|
user-select: none;
|
|
531
821
|
}
|
|
532
|
-
|
|
533
822
|
.aw-content > a.aw-file-attachment:hover {
|
|
534
823
|
background: color-mix(in srgb, var(--aw-fg) 5%, var(--aw-bg));
|
|
535
824
|
border-color: color-mix(in srgb, var(--aw-primary) 40%, var(--aw-border));
|
|
536
825
|
}
|
|
537
|
-
|
|
538
826
|
.aw-content > a.aw-file-attachment .aw-file-icon {
|
|
539
827
|
flex: 0 0 auto;
|
|
540
828
|
display: inline-flex;
|
|
@@ -546,12 +834,10 @@
|
|
|
546
834
|
background: color-mix(in srgb, var(--aw-primary) 12%, transparent);
|
|
547
835
|
color: var(--aw-primary);
|
|
548
836
|
}
|
|
549
|
-
|
|
550
837
|
.aw-content > a.aw-file-attachment .aw-file-icon svg {
|
|
551
838
|
width: 20px;
|
|
552
839
|
height: 20px;
|
|
553
840
|
}
|
|
554
|
-
|
|
555
841
|
.aw-content > a.aw-file-attachment .aw-file-meta {
|
|
556
842
|
flex: 1 1 auto;
|
|
557
843
|
min-width: 0;
|
|
@@ -559,7 +845,6 @@
|
|
|
559
845
|
flex-direction: column;
|
|
560
846
|
gap: 2px;
|
|
561
847
|
}
|
|
562
|
-
|
|
563
848
|
.aw-content > a.aw-file-attachment .aw-file-name {
|
|
564
849
|
font-weight: 600;
|
|
565
850
|
font-size: 0.95rem;
|
|
@@ -567,14 +852,12 @@
|
|
|
567
852
|
word-break: break-all;
|
|
568
853
|
line-height: 1.3;
|
|
569
854
|
}
|
|
570
|
-
|
|
571
855
|
.aw-content > a.aw-file-attachment .aw-file-info {
|
|
572
856
|
font-size: 0.75rem;
|
|
573
857
|
color: var(--aw-fg-muted);
|
|
574
858
|
font-family: var(--aw-mono, ui-monospace, SFMono-Regular, Menlo, Consolas, monospace);
|
|
575
859
|
letter-spacing: 0.02em;
|
|
576
860
|
}
|
|
577
|
-
|
|
578
861
|
.aw-content > a.aw-file-attachment .aw-file-action {
|
|
579
862
|
flex: 0 0 auto;
|
|
580
863
|
display: inline-flex;
|
|
@@ -584,18 +867,15 @@
|
|
|
584
867
|
justify-content: center;
|
|
585
868
|
color: var(--aw-fg-muted);
|
|
586
869
|
}
|
|
587
|
-
|
|
588
870
|
.aw-content > a.aw-file-attachment .aw-file-action svg {
|
|
589
871
|
width: 18px;
|
|
590
872
|
height: 18px;
|
|
591
873
|
}
|
|
592
|
-
|
|
593
874
|
.aw-content > a.aw-file-attachment:hover .aw-file-action {
|
|
594
875
|
color: var(--aw-primary);
|
|
595
876
|
}
|
|
596
877
|
|
|
597
878
|
/* ─── 링크 카드 (Open Graph 스타일 미리보기) ──────────────────── */
|
|
598
|
-
|
|
599
879
|
.aw-content > a.aw-link-card {
|
|
600
880
|
display: flex;
|
|
601
881
|
align-items: stretch;
|
|
@@ -610,14 +890,12 @@
|
|
|
610
890
|
overflow: hidden;
|
|
611
891
|
transition: border-color 0.12s, background-color 0.12s;
|
|
612
892
|
}
|
|
613
|
-
|
|
614
893
|
.aw-content > a.aw-link-card:hover {
|
|
615
894
|
border-color: var(--aw-primary);
|
|
616
895
|
background-color: color-mix(in srgb, var(--aw-primary) 9%, var(--aw-bg));
|
|
617
896
|
}
|
|
618
897
|
|
|
619
898
|
/* 좌측 og:image 썸네일 — 있을 때만. */
|
|
620
|
-
|
|
621
899
|
.aw-content > a.aw-link-card > .aw-link-card-image {
|
|
622
900
|
flex: 0 0 auto;
|
|
623
901
|
width: 120px;
|
|
@@ -628,7 +906,6 @@
|
|
|
628
906
|
}
|
|
629
907
|
|
|
630
908
|
/* 우측 본문 — title / desc / url 행. */
|
|
631
|
-
|
|
632
909
|
.aw-content > a.aw-link-card > .aw-link-card-body {
|
|
633
910
|
flex: 1 1 auto;
|
|
634
911
|
min-width: 0;
|
|
@@ -637,7 +914,6 @@
|
|
|
637
914
|
gap: 4px;
|
|
638
915
|
padding: 12px 14px;
|
|
639
916
|
}
|
|
640
|
-
|
|
641
917
|
.aw-content > a.aw-link-card .aw-link-card-title {
|
|
642
918
|
font-weight: 600;
|
|
643
919
|
font-size: 1rem;
|
|
@@ -648,7 +924,6 @@
|
|
|
648
924
|
-webkit-box-orient: vertical;
|
|
649
925
|
overflow: hidden;
|
|
650
926
|
}
|
|
651
|
-
|
|
652
927
|
.aw-content > a.aw-link-card .aw-link-card-desc {
|
|
653
928
|
font-size: 0.85rem;
|
|
654
929
|
line-height: 1.4;
|
|
@@ -658,7 +933,6 @@
|
|
|
658
933
|
-webkit-box-orient: vertical;
|
|
659
934
|
overflow: hidden;
|
|
660
935
|
}
|
|
661
|
-
|
|
662
936
|
.aw-content > a.aw-link-card .aw-link-card-url {
|
|
663
937
|
display: flex;
|
|
664
938
|
align-items: center;
|
|
@@ -669,7 +943,6 @@
|
|
|
669
943
|
font-family: var(--aw-font-mono);
|
|
670
944
|
word-break: break-all;
|
|
671
945
|
}
|
|
672
|
-
|
|
673
946
|
.aw-content > a.aw-link-card .aw-link-card-favicon {
|
|
674
947
|
flex: 0 0 auto;
|
|
675
948
|
width: 14px;
|
|
@@ -677,7 +950,6 @@
|
|
|
677
950
|
border-radius: 2px;
|
|
678
951
|
background: transparent;
|
|
679
952
|
}
|
|
680
|
-
|
|
681
953
|
.aw-content > a.aw-link-card .aw-link-card-url-text {
|
|
682
954
|
flex: 1 1 auto;
|
|
683
955
|
min-width: 0;
|
|
@@ -691,7 +963,6 @@
|
|
|
691
963
|
width: 100%;
|
|
692
964
|
margin: 1em 0;
|
|
693
965
|
}
|
|
694
|
-
|
|
695
966
|
.aw-content table td,
|
|
696
967
|
.aw-content table th {
|
|
697
968
|
border: 1px solid var(--aw-border);
|
|
@@ -701,35 +972,71 @@
|
|
|
701
972
|
/* td/th 의 inline background-color 가 overflow 자식에 가려지지 않도록 */
|
|
702
973
|
background-clip: padding-box;
|
|
703
974
|
}
|
|
704
|
-
|
|
705
975
|
.aw-content table th {
|
|
706
976
|
background-color: color-mix(in srgb, var(--aw-fg) 5%, var(--aw-bg));
|
|
707
977
|
font-weight: 600;
|
|
708
978
|
}
|
|
709
979
|
|
|
710
|
-
|
|
980
|
+
.aw-content table td,
|
|
981
|
+
.aw-content table th {
|
|
982
|
+
transition: background-color var(--aw-dur-fast) var(--aw-ease-out);
|
|
983
|
+
}
|
|
711
984
|
|
|
985
|
+
/* 커스텀 드래그-셀렉션으로 마킹된 표 셀 — 다중 선택 시각 강조. */
|
|
712
986
|
.aw-content table td.aw-cell-selected,
|
|
713
987
|
.aw-content table th.aw-cell-selected {
|
|
714
988
|
outline: 2px solid var(--aw-primary);
|
|
715
989
|
outline-offset: -2px;
|
|
716
990
|
background-color: color-mix(in srgb, var(--aw-primary) 18%, transparent) !important;
|
|
717
991
|
}
|
|
718
|
-
|
|
719
992
|
.aeriz-wysiwyg-viewer .aw-cell-selected {
|
|
720
993
|
outline: none;
|
|
721
994
|
background-color: revert !important;
|
|
722
995
|
}
|
|
723
996
|
|
|
724
997
|
/* ─── 리사이즈 핸들 + 정렬 컨트롤 (이미지·유튜브) ──────────────────── */
|
|
725
|
-
|
|
726
998
|
.aw-content > figure,
|
|
727
999
|
.aw-content > div.aw-youtube-embed {
|
|
728
1000
|
position: relative;
|
|
1001
|
+
/* 인라인 width 가 본문보다 커도 넘치지 않게 막는다. 드래그 리사이즈는
|
|
1002
|
+
JS 에서 본문 폭으로 상한을 두지만, 외부에서 들어온 값(HTML 가져오기,
|
|
1003
|
+
예전에 더 넓은 화면에서 저장된 스냅샷)까지 막아 주는 건 이 규칙이다.
|
|
1004
|
+
이게 없으면 본문이 가로로 넓어지면서 에디터 전체가 늘어난다. */
|
|
1005
|
+
max-width: 100%;
|
|
729
1006
|
}
|
|
730
1007
|
|
|
731
|
-
/*
|
|
1008
|
+
/* figure 의 좌우 여백을 0 으로 명시한다.
|
|
1009
|
+
브라우저 UA 기본값은 `figure { margin: 1em 40px }` 인데, getHTML() 이
|
|
1010
|
+
베이크하는 portable 스타일은 `margin: 1em 0` 이다. 그대로 두면 에디터에서는
|
|
1011
|
+
80px 좁게 보이고 내보낸 HTML 에서는 넓게 보이는 WYSIWYG 불일치가 생긴다. */
|
|
1012
|
+
.aw-content > figure {
|
|
1013
|
+
margin: 1em 0;
|
|
1014
|
+
}
|
|
732
1015
|
|
|
1016
|
+
/* ─── 이미지 캡션 ────────────────────────────────────────────────────
|
|
1017
|
+
그림에 딸린 설명. 본문보다 한 단계 작고 흐리게 — 그림을 읽고 나서 눈이
|
|
1018
|
+
내려오는 자리다. 그림 정렬(가운데/오른쪽) 을 따라가도록 figure 의
|
|
1019
|
+
text-align 을 그대로 상속받는다. */
|
|
1020
|
+
.aw-content > figure > figcaption {
|
|
1021
|
+
margin-top: 0.5em;
|
|
1022
|
+
font-size: 0.85em;
|
|
1023
|
+
line-height: 1.5;
|
|
1024
|
+
color: var(--aw-fg-muted);
|
|
1025
|
+
outline: none;
|
|
1026
|
+
}
|
|
1027
|
+
/* 비어 있는 동안만 안내를 띄운다. 캡션은 캐럿이 떠나면 사라지므로, 이
|
|
1028
|
+
안내가 보이는 시간은 "지금 쓰면 된다" 는 순간뿐이다. */
|
|
1029
|
+
.aw-content > figure > figcaption:empty::before {
|
|
1030
|
+
content: var(--aw-caption-hint, '');
|
|
1031
|
+
color: var(--aw-fg-muted);
|
|
1032
|
+
opacity: 0.5;
|
|
1033
|
+
pointer-events: none;
|
|
1034
|
+
}
|
|
1035
|
+
.aeriz-wysiwyg-viewer .aw-content > figure > figcaption:empty {
|
|
1036
|
+
display: none;
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
/* 좌상단 정렬 컨트롤 — 좌/중/우 3 버튼. hover 시 위에서 내려오며 fade-in. */
|
|
733
1040
|
.aw-block-align-controls {
|
|
734
1041
|
position: absolute;
|
|
735
1042
|
top: 6px;
|
|
@@ -737,21 +1044,34 @@
|
|
|
737
1044
|
display: flex;
|
|
738
1045
|
gap: 1px;
|
|
739
1046
|
background: rgba(0, 0, 0, 0.55);
|
|
740
|
-
|
|
1047
|
+
backdrop-filter: blur(6px);
|
|
1048
|
+
border-radius: 6px;
|
|
741
1049
|
padding: 2px;
|
|
742
1050
|
z-index: 11;
|
|
743
1051
|
opacity: 0;
|
|
744
|
-
|
|
1052
|
+
transform: translateY(-4px);
|
|
1053
|
+
transition:
|
|
1054
|
+
opacity var(--aw-dur-base) var(--aw-ease-out),
|
|
1055
|
+
transform var(--aw-dur-base) var(--aw-ease-out);
|
|
745
1056
|
user-select: none;
|
|
746
1057
|
}
|
|
747
|
-
|
|
748
1058
|
.aw-content > figure:hover .aw-block-align-controls,
|
|
749
1059
|
.aw-content > div.aw-youtube-embed:hover .aw-block-align-controls,
|
|
1060
|
+
.aw-content > figure:focus-within .aw-block-align-controls,
|
|
750
1061
|
.aw-resizing .aw-block-align-controls {
|
|
751
1062
|
opacity: 1;
|
|
1063
|
+
transform: none;
|
|
1064
|
+
}
|
|
1065
|
+
/* 정렬 버튼과 캡션 버튼 사이 구분선 — 하는 일이 다르다는 표시. */
|
|
1066
|
+
.aw-block-ctl-divider {
|
|
1067
|
+
width: 1px;
|
|
1068
|
+
align-self: stretch;
|
|
1069
|
+
margin: 2px 2px;
|
|
1070
|
+
background: rgba(255, 255, 255, 0.25);
|
|
752
1071
|
}
|
|
753
1072
|
|
|
754
|
-
.aw-block-align-btn
|
|
1073
|
+
.aw-block-align-btn,
|
|
1074
|
+
.aw-block-caption-btn {
|
|
755
1075
|
width: 22px;
|
|
756
1076
|
height: 22px;
|
|
757
1077
|
display: inline-flex;
|
|
@@ -761,19 +1081,30 @@
|
|
|
761
1081
|
border: none;
|
|
762
1082
|
color: #fff;
|
|
763
1083
|
cursor: pointer;
|
|
764
|
-
border-radius:
|
|
1084
|
+
border-radius: 4px;
|
|
765
1085
|
padding: 0;
|
|
1086
|
+
transition:
|
|
1087
|
+
background-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
1088
|
+
transform var(--aw-dur-fast) var(--aw-ease-out);
|
|
766
1089
|
}
|
|
767
|
-
|
|
768
|
-
.aw-block-
|
|
1090
|
+
.aw-block-align-btn:hover,
|
|
1091
|
+
.aw-block-caption-btn:hover {
|
|
769
1092
|
background: rgba(255, 255, 255, 0.18);
|
|
770
1093
|
}
|
|
771
|
-
|
|
772
|
-
.aw-block-
|
|
1094
|
+
.aw-block-align-btn:active,
|
|
1095
|
+
.aw-block-caption-btn:active {
|
|
1096
|
+
transform: scale(0.9);
|
|
1097
|
+
}
|
|
1098
|
+
.aw-block-align-btn:focus-visible,
|
|
1099
|
+
.aw-block-caption-btn:focus-visible {
|
|
1100
|
+
outline: 2px solid #fff;
|
|
1101
|
+
outline-offset: -2px;
|
|
1102
|
+
}
|
|
1103
|
+
.aw-block-align-btn svg,
|
|
1104
|
+
.aw-block-caption-btn svg {
|
|
773
1105
|
width: 14px;
|
|
774
1106
|
height: 14px;
|
|
775
1107
|
}
|
|
776
|
-
|
|
777
1108
|
.aw-resize-handle {
|
|
778
1109
|
position: absolute;
|
|
779
1110
|
right: -1px;
|
|
@@ -782,45 +1113,85 @@
|
|
|
782
1113
|
height: 14px;
|
|
783
1114
|
background: var(--aw-primary);
|
|
784
1115
|
border: 2px solid var(--aw-bg);
|
|
785
|
-
border-radius:
|
|
1116
|
+
border-radius: 4px;
|
|
786
1117
|
cursor: nwse-resize;
|
|
787
1118
|
z-index: 10;
|
|
788
1119
|
user-select: none;
|
|
789
1120
|
opacity: 0;
|
|
790
|
-
|
|
1121
|
+
transform: scale(0.7);
|
|
1122
|
+
transition:
|
|
1123
|
+
opacity var(--aw-dur-base) var(--aw-ease-out),
|
|
1124
|
+
transform var(--aw-dur-base) var(--aw-ease-spring),
|
|
1125
|
+
box-shadow var(--aw-dur-base) var(--aw-ease-out);
|
|
1126
|
+
}
|
|
1127
|
+
/* 실제로 잡히는 면적은 보이는 것보다 넓다 — 14px 짜리 점을 정확히 겨냥해야
|
|
1128
|
+
하면 리사이즈가 스트레스가 된다. */
|
|
1129
|
+
.aw-resize-handle::before {
|
|
1130
|
+
content: '';
|
|
1131
|
+
position: absolute;
|
|
1132
|
+
inset: -7px;
|
|
791
1133
|
}
|
|
792
|
-
|
|
793
1134
|
.aw-content > figure:hover .aw-resize-handle,
|
|
794
1135
|
.aw-content > div.aw-youtube-embed:hover .aw-resize-handle,
|
|
795
1136
|
.aw-resizing .aw-resize-handle {
|
|
796
1137
|
opacity: 1;
|
|
1138
|
+
transform: none;
|
|
797
1139
|
}
|
|
798
|
-
|
|
799
1140
|
.aw-resize-handle:hover {
|
|
800
|
-
transform: scale(1.
|
|
1141
|
+
transform: scale(1.18);
|
|
1142
|
+
box-shadow: 0 0 0 4px color-mix(in srgb, var(--aw-primary) 22%, transparent);
|
|
1143
|
+
}
|
|
1144
|
+
/* 크기를 조절하는 동안은 그 블록만 또렷하게 남기고 나머지 UI 는 조용해진다. */
|
|
1145
|
+
.aw-resizing .aw-resize-handle {
|
|
1146
|
+
transform: scale(1.18);
|
|
1147
|
+
box-shadow: 0 0 0 5px color-mix(in srgb, var(--aw-primary) 28%, transparent);
|
|
1148
|
+
}
|
|
1149
|
+
.aw-resizing {
|
|
1150
|
+
outline: 1px solid color-mix(in srgb, var(--aw-primary) 60%, transparent);
|
|
1151
|
+
outline-offset: 2px;
|
|
801
1152
|
}
|
|
802
1153
|
|
|
803
1154
|
/* 유튜브 임베드는 iframe 안에 자체 워터마크/컨트롤이 있어 코너에 핸들을 두면
|
|
804
1155
|
* 클릭이 충돌한다. embed 안쪽 우하단에 약간 들여서 배치 — YouTube 자체 UI
|
|
805
1156
|
* 영역과 약간 떨어진 위치. */
|
|
806
|
-
|
|
807
1157
|
.aw-content > div.aw-youtube-embed > .aw-resize-handle {
|
|
808
1158
|
right: 0px;
|
|
809
1159
|
bottom: -15px;
|
|
810
1160
|
}
|
|
811
|
-
|
|
812
1161
|
.aw-resizing {
|
|
813
1162
|
user-select: none;
|
|
814
1163
|
}
|
|
815
1164
|
|
|
816
1165
|
/* 뷰어(읽기 전용) 모드에서는 편집용 컨트롤(리사이즈 핸들 / 정렬 컨트롤) 을
|
|
817
1166
|
* 모두 숨긴다. AerizViewer.root 의 className 'aeriz-wysiwyg-viewer' 를 타겟. */
|
|
818
|
-
|
|
819
1167
|
.aeriz-wysiwyg-viewer .aw-resize-handle,
|
|
820
1168
|
.aeriz-wysiwyg-viewer .aw-block-align-controls {
|
|
821
1169
|
display: none !important;
|
|
822
1170
|
}
|
|
823
1171
|
|
|
1172
|
+
/* ─── 모션 민감 사용자 ───────────────────────────────────────────────
|
|
1173
|
+
움직임은 전부 걷어내되 **상태는 그대로 보이게** 한다. transition 만 0 으로
|
|
1174
|
+
만들면 애니메이션으로 나타나던 요소가 영영 안 보이는 사고가 나므로,
|
|
1175
|
+
등장 애니메이션은 끝 상태를 직접 지정한다. */
|
|
1176
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1177
|
+
.aeriz-wysiwyg *,
|
|
1178
|
+
.aeriz-wysiwyg *::before,
|
|
1179
|
+
.aeriz-wysiwyg *::after {
|
|
1180
|
+
transition-duration: 1ms !important;
|
|
1181
|
+
animation-duration: 1ms !important;
|
|
1182
|
+
animation-iteration-count: 1 !important;
|
|
1183
|
+
}
|
|
1184
|
+
.aw-content > [data-block-focused]::before {
|
|
1185
|
+
transform: none;
|
|
1186
|
+
}
|
|
1187
|
+
.aw-block-add:hover svg,
|
|
1188
|
+
.aw-block-label-pill:hover,
|
|
1189
|
+
.aw-block-handle:active,
|
|
1190
|
+
.aw-block-add:active,
|
|
1191
|
+
.aw-block-align-btn:active {
|
|
1192
|
+
transform: none;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
824
1195
|
.aw-toolbar {
|
|
825
1196
|
display: flex;
|
|
826
1197
|
align-items: center;
|
|
@@ -866,13 +1237,28 @@
|
|
|
866
1237
|
border-radius: var(--aw-radius-sm);
|
|
867
1238
|
cursor: pointer;
|
|
868
1239
|
color: var(--aw-toolbar-fg);
|
|
869
|
-
|
|
1240
|
+
position: relative;
|
|
1241
|
+
transition:
|
|
1242
|
+
background-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
1243
|
+
color var(--aw-dur-fast) var(--aw-ease-out),
|
|
1244
|
+
border-color var(--aw-dur-fast) var(--aw-ease-out),
|
|
1245
|
+
transform var(--aw-dur-fast) var(--aw-ease-out);
|
|
870
1246
|
}
|
|
871
1247
|
|
|
872
1248
|
.aw-toolbar-btn:hover:not(:disabled) {
|
|
873
1249
|
background-color: var(--aw-btn-hover-bg);
|
|
874
1250
|
}
|
|
875
1251
|
|
|
1252
|
+
/* 누르는 순간의 반응 — 색보다 먼저 손끝에 닿는 신호. */
|
|
1253
|
+
.aw-toolbar-btn:active:not(:disabled) {
|
|
1254
|
+
transform: scale(0.94);
|
|
1255
|
+
}
|
|
1256
|
+
|
|
1257
|
+
.aw-toolbar-btn:focus-visible {
|
|
1258
|
+
outline: 2px solid var(--aw-primary);
|
|
1259
|
+
outline-offset: -1px;
|
|
1260
|
+
}
|
|
1261
|
+
|
|
876
1262
|
.aw-toolbar-btn:disabled {
|
|
877
1263
|
opacity: 0.4;
|
|
878
1264
|
cursor: not-allowed;
|
|
@@ -887,6 +1273,42 @@
|
|
|
887
1273
|
background-color: var(--aw-btn-active-bg);
|
|
888
1274
|
}
|
|
889
1275
|
|
|
1276
|
+
/* 켜진 항목 아래 2px 밑줄이 가운데에서 좌우로 펼쳐진다. 배경색만 바뀌면
|
|
1277
|
+
어두운 테마에서 on/off 차이가 잘 안 읽힌다. */
|
|
1278
|
+
.aw-toolbar-btn::after {
|
|
1279
|
+
content: '';
|
|
1280
|
+
position: absolute;
|
|
1281
|
+
left: 6px;
|
|
1282
|
+
right: 6px;
|
|
1283
|
+
bottom: 3px;
|
|
1284
|
+
height: 2px;
|
|
1285
|
+
border-radius: 1px;
|
|
1286
|
+
background: currentColor;
|
|
1287
|
+
transform: scaleX(0);
|
|
1288
|
+
opacity: 0;
|
|
1289
|
+
transition:
|
|
1290
|
+
transform var(--aw-dur-base) var(--aw-ease-out),
|
|
1291
|
+
opacity var(--aw-dur-base) var(--aw-ease-out);
|
|
1292
|
+
}
|
|
1293
|
+
.aw-toolbar-btn-active::after {
|
|
1294
|
+
transform: scaleX(1);
|
|
1295
|
+
opacity: 0.8;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
/* 이 버튼에서 열린 드롭다운이 떠 있는 동안 — 셰브론이 뒤집혀 "다시 누르면
|
|
1299
|
+
닫힌다" 를 알린다. */
|
|
1300
|
+
.aw-toolbar-btn.is-popover-open {
|
|
1301
|
+
background-color: var(--aw-btn-active-bg);
|
|
1302
|
+
color: var(--aw-btn-active-fg);
|
|
1303
|
+
}
|
|
1304
|
+
.aw-toolbar-btn .aw-toolbar-btn-chevron {
|
|
1305
|
+
transition: transform var(--aw-dur-base) var(--aw-ease-out), opacity var(--aw-dur-fast);
|
|
1306
|
+
}
|
|
1307
|
+
.aw-toolbar-btn.is-popover-open .aw-toolbar-btn-chevron {
|
|
1308
|
+
transform: rotate(180deg);
|
|
1309
|
+
opacity: 1;
|
|
1310
|
+
}
|
|
1311
|
+
|
|
890
1312
|
.aw-toolbar-btn-icon {
|
|
891
1313
|
display: inline-flex;
|
|
892
1314
|
width: 18px;
|
|
@@ -910,7 +1332,6 @@
|
|
|
910
1332
|
width: 100%;
|
|
911
1333
|
height: 100%;
|
|
912
1334
|
}
|
|
913
|
-
|
|
914
1335
|
/*
|
|
915
1336
|
* Dialog / popover 는 .aeriz-wysiwyg 의 자식이 아닌 document.body 에 attach
|
|
916
1337
|
* 되므로 에디터의 CSS 변수를 직접 받지 못한다. 대신 자기 자신에
|
|
@@ -935,6 +1356,14 @@
|
|
|
935
1356
|
--d-on-primary: #050810;
|
|
936
1357
|
--d-overlay: rgba(0, 0, 0, 0.45);
|
|
937
1358
|
--d-mono: ui-monospace, SFMono-Regular, 'JetBrains Mono', Menlo, Consolas, monospace;
|
|
1359
|
+
/* 다이얼로그/팝오버는 body 에 붙어 에디터 토큰을 상속받지 못한다.
|
|
1360
|
+
같은 값을 여기에도 둔다 — 두 표면의 모션이 어긋나면 한 제품처럼 안 느껴진다.
|
|
1361
|
+
(tokens.css 의 --aw-dur-* / --aw-ease-* 와 값이 같아야 한다.) */
|
|
1362
|
+
--aw-dur-fast: 90ms;
|
|
1363
|
+
--aw-dur-base: 160ms;
|
|
1364
|
+
--aw-dur-slow: 240ms;
|
|
1365
|
+
--aw-ease-out: cubic-bezier(0.22, 0.85, 0.3, 1);
|
|
1366
|
+
--aw-ease-spring: cubic-bezier(0.2, 1.3, 0.4, 1);
|
|
938
1367
|
}
|
|
939
1368
|
|
|
940
1369
|
.aw-dialog-overlay[data-theme='dark'],
|
|
@@ -1015,9 +1444,7 @@
|
|
|
1015
1444
|
color: var(--d-fg-muted);
|
|
1016
1445
|
transition: background-color 0.12s, color 0.12s;
|
|
1017
1446
|
}
|
|
1018
|
-
|
|
1019
1447
|
.aw-dialog-close:hover { background-color: var(--d-hover-bg); color: var(--d-fg); }
|
|
1020
|
-
|
|
1021
1448
|
.aw-dialog-close svg { width: 18px; height: 18px; }
|
|
1022
1449
|
|
|
1023
1450
|
.aw-dialog-body {
|
|
@@ -1034,7 +1461,6 @@
|
|
|
1034
1461
|
}
|
|
1035
1462
|
|
|
1036
1463
|
.aw-field { display: flex; flex-direction: column; gap: 6px; }
|
|
1037
|
-
|
|
1038
1464
|
.aw-field-label { font-size: 13px; font-weight: 600; color: var(--d-fg); }
|
|
1039
1465
|
|
|
1040
1466
|
.aw-input {
|
|
@@ -1049,7 +1475,6 @@
|
|
|
1049
1475
|
color: var(--d-input-fg);
|
|
1050
1476
|
background-color: var(--d-input-bg);
|
|
1051
1477
|
}
|
|
1052
|
-
|
|
1053
1478
|
.aw-input:focus {
|
|
1054
1479
|
border-color: var(--d-primary);
|
|
1055
1480
|
box-shadow: 0 0 0 3px var(--d-primary-soft);
|
|
@@ -1069,7 +1494,6 @@
|
|
|
1069
1494
|
color: var(--d-fg);
|
|
1070
1495
|
cursor: pointer; user-select: none;
|
|
1071
1496
|
}
|
|
1072
|
-
|
|
1073
1497
|
.aw-checkbox input { width: 16px; height: 16px; accent-color: var(--d-primary); }
|
|
1074
1498
|
|
|
1075
1499
|
.aw-btn {
|
|
@@ -1082,17 +1506,13 @@
|
|
|
1082
1506
|
font-family: inherit;
|
|
1083
1507
|
transition: background-color 0.12s, border-color 0.12s, color 0.12s;
|
|
1084
1508
|
}
|
|
1085
|
-
|
|
1086
1509
|
.aw-btn-primary { background-color: var(--d-primary); color: var(--d-on-primary); }
|
|
1087
|
-
|
|
1088
1510
|
.aw-btn-primary:hover { background-color: var(--d-primary-hover); }
|
|
1089
|
-
|
|
1090
1511
|
.aw-btn-ghost {
|
|
1091
1512
|
background-color: transparent;
|
|
1092
1513
|
color: var(--d-fg);
|
|
1093
1514
|
border-color: var(--d-border-strong);
|
|
1094
1515
|
}
|
|
1095
|
-
|
|
1096
1516
|
.aw-btn-ghost:hover { background-color: var(--d-hover-bg); }
|
|
1097
1517
|
|
|
1098
1518
|
.aw-tabs {
|
|
@@ -1100,7 +1520,6 @@
|
|
|
1100
1520
|
border-bottom: 1px solid var(--d-border);
|
|
1101
1521
|
margin: -4px -4px 8px;
|
|
1102
1522
|
}
|
|
1103
|
-
|
|
1104
1523
|
.aw-tab {
|
|
1105
1524
|
padding: 8px 14px;
|
|
1106
1525
|
background: transparent;
|
|
@@ -1113,11 +1532,8 @@
|
|
|
1113
1532
|
cursor: pointer;
|
|
1114
1533
|
transition: color 0.12s, border-color 0.12s;
|
|
1115
1534
|
}
|
|
1116
|
-
|
|
1117
1535
|
.aw-tab:hover { color: var(--d-fg); }
|
|
1118
|
-
|
|
1119
1536
|
.aw-tab-active { color: var(--d-primary); border-bottom-color: var(--d-primary); }
|
|
1120
|
-
|
|
1121
1537
|
.aw-tab-disabled,
|
|
1122
1538
|
.aw-tab[disabled] {
|
|
1123
1539
|
opacity: 0.4;
|
|
@@ -1125,7 +1541,6 @@
|
|
|
1125
1541
|
text-decoration: line-through;
|
|
1126
1542
|
color: var(--d-fg-muted);
|
|
1127
1543
|
}
|
|
1128
|
-
|
|
1129
1544
|
.aw-tab-disabled:hover,
|
|
1130
1545
|
.aw-tab[disabled]:hover { color: var(--d-fg-muted); }
|
|
1131
1546
|
|
|
@@ -1160,17 +1575,13 @@
|
|
|
1160
1575
|
transition: border-color 0.12s, background-color 0.12s, color 0.12s;
|
|
1161
1576
|
background-color: var(--d-input-bg);
|
|
1162
1577
|
}
|
|
1163
|
-
|
|
1164
1578
|
.aw-dropzone:hover {
|
|
1165
1579
|
border-color: var(--d-primary);
|
|
1166
1580
|
background-color: var(--d-hover-bg);
|
|
1167
1581
|
color: var(--d-primary);
|
|
1168
1582
|
}
|
|
1169
|
-
|
|
1170
1583
|
.aw-dropzone svg { width: 36px; height: 36px; }
|
|
1171
|
-
|
|
1172
1584
|
.aw-dropzone-text { font-size: 13px; line-height: 1.5; }
|
|
1173
|
-
|
|
1174
1585
|
.aw-dropzone-loading { opacity: 0.6; pointer-events: none; }
|
|
1175
1586
|
|
|
1176
1587
|
.aw-preview {
|
|
@@ -1191,7 +1602,6 @@
|
|
|
1191
1602
|
width: max-content;
|
|
1192
1603
|
margin: 0 auto;
|
|
1193
1604
|
}
|
|
1194
|
-
|
|
1195
1605
|
.aw-table-cell {
|
|
1196
1606
|
background-color: var(--d-input-bg);
|
|
1197
1607
|
border: 1px solid var(--d-border-strong);
|
|
@@ -1199,12 +1609,10 @@
|
|
|
1199
1609
|
cursor: pointer;
|
|
1200
1610
|
transition: background-color 0.08s;
|
|
1201
1611
|
}
|
|
1202
|
-
|
|
1203
1612
|
.aw-table-cell-active {
|
|
1204
1613
|
background-color: var(--d-primary-soft);
|
|
1205
1614
|
border-color: var(--d-primary);
|
|
1206
1615
|
}
|
|
1207
|
-
|
|
1208
1616
|
.aw-table-status {
|
|
1209
1617
|
text-align: center;
|
|
1210
1618
|
font-size: 13px;
|
|
@@ -1247,11 +1655,22 @@
|
|
|
1247
1655
|
border: 1px solid var(--d-border);
|
|
1248
1656
|
cursor: pointer;
|
|
1249
1657
|
padding: 0;
|
|
1250
|
-
transition:
|
|
1658
|
+
transition:
|
|
1659
|
+
transform var(--aw-dur-base, 160ms) var(--aw-ease-spring, ease),
|
|
1660
|
+
box-shadow var(--aw-dur-fast, 90ms) ease;
|
|
1661
|
+
}
|
|
1662
|
+
/* 색은 손톱만 한 사각형이라, 확대만으로는 어느 칸에 있는지 확신이 안 선다.
|
|
1663
|
+
같은 색 링을 한 겹 둘러 커서가 놓인 칸을 못 박아 준다. */
|
|
1664
|
+
.aw-color-swatch:hover {
|
|
1665
|
+
transform: scale(1.18);
|
|
1666
|
+
box-shadow: 0 0 0 2px var(--d-bg), 0 0 0 3px var(--d-primary);
|
|
1667
|
+
}
|
|
1668
|
+
.aw-color-swatch:active { transform: scale(1.02); }
|
|
1669
|
+
.aw-color-swatch:focus-visible {
|
|
1670
|
+
outline: none;
|
|
1671
|
+
box-shadow: 0 0 0 2px var(--d-bg), 0 0 0 3px var(--d-primary);
|
|
1251
1672
|
}
|
|
1252
1673
|
|
|
1253
|
-
.aw-color-swatch:hover { transform: scale(1.15); }
|
|
1254
|
-
|
|
1255
1674
|
.aw-color-section {
|
|
1256
1675
|
font-size: 10px;
|
|
1257
1676
|
letter-spacing: 0.08em;
|
|
@@ -1260,7 +1679,6 @@
|
|
|
1260
1679
|
font-weight: 700;
|
|
1261
1680
|
padding: 6px 2px 4px;
|
|
1262
1681
|
}
|
|
1263
|
-
|
|
1264
1682
|
.aw-color-section + .aw-color-grid { margin-bottom: 4px; }
|
|
1265
1683
|
|
|
1266
1684
|
.aw-popover-action {
|
|
@@ -1278,7 +1696,6 @@
|
|
|
1278
1696
|
margin-top: 4px;
|
|
1279
1697
|
position: relative;
|
|
1280
1698
|
}
|
|
1281
|
-
|
|
1282
1699
|
.aw-popover-action:hover { background-color: var(--d-hover-bg); }
|
|
1283
1700
|
|
|
1284
1701
|
.aw-popover-item {
|
|
@@ -1295,9 +1712,16 @@
|
|
|
1295
1712
|
color: var(--d-fg);
|
|
1296
1713
|
font-family: inherit;
|
|
1297
1714
|
font-size: 12.5px;
|
|
1715
|
+
transition:
|
|
1716
|
+
background-color var(--aw-dur-fast, 90ms) ease,
|
|
1717
|
+
color var(--aw-dur-fast, 90ms) ease;
|
|
1298
1718
|
}
|
|
1299
|
-
|
|
1300
1719
|
.aw-popover-item:hover { background-color: var(--d-hover-bg); }
|
|
1720
|
+
.aw-popover-item:active { background-color: var(--d-primary-soft); }
|
|
1721
|
+
.aw-popover-item:focus-visible {
|
|
1722
|
+
outline: 2px solid var(--d-primary);
|
|
1723
|
+
outline-offset: -2px;
|
|
1724
|
+
}
|
|
1301
1725
|
|
|
1302
1726
|
.aw-popover-item-glyph {
|
|
1303
1727
|
display: inline-flex;
|
|
@@ -1310,8 +1734,18 @@
|
|
|
1310
1734
|
font-family: var(--d-mono);
|
|
1311
1735
|
font-size: 10px;
|
|
1312
1736
|
font-weight: 700;
|
|
1737
|
+
transition:
|
|
1738
|
+
background-color var(--aw-dur-fast, 90ms) ease,
|
|
1739
|
+
color var(--aw-dur-fast, 90ms) ease,
|
|
1740
|
+
transform var(--aw-dur-base, 160ms) var(--aw-ease-spring, ease);
|
|
1741
|
+
}
|
|
1742
|
+
/* 항목을 훑을 때 기호만 살짝 커진다 — 행 전체가 움직이면 목록이 출렁이지만,
|
|
1743
|
+
18px 짜리 기호 하나는 커서를 따라오는 느낌만 남기고 레이아웃을 흔들지 않는다. */
|
|
1744
|
+
.aw-popover-item:hover .aw-popover-item-glyph {
|
|
1745
|
+
background: var(--d-primary-soft);
|
|
1746
|
+
color: var(--d-primary);
|
|
1747
|
+
transform: scale(1.12);
|
|
1313
1748
|
}
|
|
1314
|
-
|
|
1315
1749
|
.aw-popover-item-glyph svg { width: 11px; height: 11px; }
|
|
1316
1750
|
|
|
1317
1751
|
.aw-popover-item-label { flex: 1; min-width: 0; }
|
|
@@ -1323,7 +1757,6 @@
|
|
|
1323
1757
|
align-items: center; justify-content: center;
|
|
1324
1758
|
gap: 0;
|
|
1325
1759
|
}
|
|
1326
|
-
|
|
1327
1760
|
.aw-popover-item-icon svg { width: 18px; height: 18px; }
|
|
1328
1761
|
|
|
1329
1762
|
.aw-popover-divider {
|
|
@@ -1334,33 +1767,28 @@
|
|
|
1334
1767
|
|
|
1335
1768
|
/* 블록 유형 드롭다운 — 항목이 많아 세로로 길어지지 않도록 2 컬럼 그리드.
|
|
1336
1769
|
* 섹션 구분 divider 는 grid-column 으로 두 컬럼을 모두 가로지른다. */
|
|
1337
|
-
|
|
1338
1770
|
.aw-block-type-popover {
|
|
1339
1771
|
display: grid;
|
|
1340
1772
|
grid-template-columns: repeat(2, minmax(150px, 1fr));
|
|
1341
1773
|
column-gap: 2px;
|
|
1342
1774
|
min-width: 320px;
|
|
1343
1775
|
}
|
|
1344
|
-
|
|
1345
1776
|
.aw-block-type-popover .aw-popover-divider {
|
|
1346
1777
|
grid-column: 1 / -1;
|
|
1347
1778
|
}
|
|
1348
1779
|
|
|
1349
1780
|
/* 글꼴 드롭다운 — 라벨(작게) + '가A' 미리보기(글꼴 자체) 두 영역. */
|
|
1350
|
-
|
|
1351
1781
|
.aw-font-family-popover {
|
|
1352
1782
|
min-width: 180px;
|
|
1353
1783
|
max-height: 360px;
|
|
1354
1784
|
overflow-y: auto;
|
|
1355
1785
|
}
|
|
1356
|
-
|
|
1357
1786
|
.aw-font-family-item {
|
|
1358
1787
|
padding: 4px 8px;
|
|
1359
1788
|
display: flex;
|
|
1360
1789
|
align-items: center;
|
|
1361
1790
|
gap: 8px;
|
|
1362
1791
|
}
|
|
1363
|
-
|
|
1364
1792
|
.aw-font-family-name {
|
|
1365
1793
|
flex: 1 1 auto;
|
|
1366
1794
|
min-width: 0;
|
|
@@ -1371,7 +1799,6 @@
|
|
|
1371
1799
|
overflow: hidden;
|
|
1372
1800
|
text-overflow: ellipsis;
|
|
1373
1801
|
}
|
|
1374
|
-
|
|
1375
1802
|
.aw-font-family-preview {
|
|
1376
1803
|
flex: 0 0 auto;
|
|
1377
1804
|
font-size: 13px;
|
|
@@ -1381,29 +1808,24 @@
|
|
|
1381
1808
|
}
|
|
1382
1809
|
|
|
1383
1810
|
/* 표 편집 드롭다운 — 행/열 추가·삭제 텍스트 항목 */
|
|
1384
|
-
|
|
1385
1811
|
.aw-table-menu-popover {
|
|
1386
1812
|
min-width: 160px;
|
|
1387
1813
|
}
|
|
1388
|
-
|
|
1389
1814
|
.aw-table-menu-item {
|
|
1390
1815
|
font-size: 12px;
|
|
1391
1816
|
padding: 6px 10px;
|
|
1392
1817
|
}
|
|
1393
1818
|
|
|
1394
1819
|
/* 글자 크기 드롭다운 — 한 줄당 px 라벨이 그 크기로 렌더되는 컴팩트 리스트 */
|
|
1395
|
-
|
|
1396
1820
|
.aw-font-size-popover {
|
|
1397
1821
|
min-width: 80px;
|
|
1398
1822
|
max-height: 320px;
|
|
1399
1823
|
overflow-y: auto;
|
|
1400
1824
|
}
|
|
1401
|
-
|
|
1402
1825
|
.aw-font-size-item {
|
|
1403
1826
|
padding: 2px 10px;
|
|
1404
1827
|
justify-content: space-between;
|
|
1405
1828
|
}
|
|
1406
|
-
|
|
1407
1829
|
.aw-font-size-label {
|
|
1408
1830
|
font-size: 11px;
|
|
1409
1831
|
color: var(--d-fg);
|
|
@@ -1415,7 +1837,6 @@
|
|
|
1415
1837
|
background-color: color-mix(in srgb, var(--d-primary) 14%, transparent);
|
|
1416
1838
|
color: var(--d-primary);
|
|
1417
1839
|
}
|
|
1418
|
-
|
|
1419
1840
|
.aw-popover-item-active::after {
|
|
1420
1841
|
content: '✓';
|
|
1421
1842
|
margin-left: auto;
|
|
@@ -1429,18 +1850,15 @@
|
|
|
1429
1850
|
}
|
|
1430
1851
|
|
|
1431
1852
|
/* 표 삽입 드롭다운 — 호버에 따라 동적으로 늘어나는 셀 그리드 */
|
|
1432
|
-
|
|
1433
1853
|
.aw-table-popover {
|
|
1434
1854
|
padding: 10px;
|
|
1435
1855
|
min-width: auto;
|
|
1436
1856
|
}
|
|
1437
|
-
|
|
1438
1857
|
.aw-table-picker-grid {
|
|
1439
1858
|
display: grid;
|
|
1440
1859
|
gap: 2px;
|
|
1441
1860
|
margin-bottom: 6px;
|
|
1442
1861
|
}
|
|
1443
|
-
|
|
1444
1862
|
.aw-table-picker-grid .aw-table-cell {
|
|
1445
1863
|
width: 18px;
|
|
1446
1864
|
height: 18px;
|
|
@@ -1450,12 +1868,19 @@
|
|
|
1450
1868
|
cursor: pointer;
|
|
1451
1869
|
transition: background-color 0.06s, border-color 0.06s;
|
|
1452
1870
|
}
|
|
1453
|
-
|
|
1871
|
+
/* 선택된 칸은 살짝 안으로 눌러 담긴다 — 몇 칸이 잡혔는지 숫자를 읽지 않고도
|
|
1872
|
+
면적으로 먼저 보인다. */
|
|
1454
1873
|
.aw-table-picker-grid .aw-table-cell.aw-table-cell-active {
|
|
1455
1874
|
background-color: var(--d-primary-soft);
|
|
1456
1875
|
border-color: var(--d-primary);
|
|
1876
|
+
transform: scale(0.9);
|
|
1877
|
+
}
|
|
1878
|
+
.aw-table-picker-grid .aw-table-cell {
|
|
1879
|
+
transition:
|
|
1880
|
+
background-color var(--aw-dur-fast, 90ms) ease,
|
|
1881
|
+
border-color var(--aw-dur-fast, 90ms) ease,
|
|
1882
|
+
transform var(--aw-dur-fast, 90ms) var(--aw-ease-out, ease);
|
|
1457
1883
|
}
|
|
1458
|
-
|
|
1459
1884
|
.aw-table-popover .aw-table-status {
|
|
1460
1885
|
text-align: center;
|
|
1461
1886
|
font-size: 12px;
|
|
@@ -1472,7 +1897,6 @@
|
|
|
1472
1897
|
padding: 4px 8px;
|
|
1473
1898
|
font-weight: 700;
|
|
1474
1899
|
}
|
|
1475
|
-
|
|
1476
1900
|
.aw-coming-soon-popover .aw-popover-empty {
|
|
1477
1901
|
padding: 10px 8px;
|
|
1478
1902
|
font-size: 13px;
|