podo-ui 0.3.0 → 0.3.2

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/next.ts CHANGED
@@ -3,6 +3,8 @@ import dynamic from 'next/dynamic';
3
3
 
4
4
  import Input from './react/atom/input';
5
5
  import Textarea from './react/atom/textarea';
6
+ import EditorView from './react/atom/editor-view';
7
+ import Pagination from './react/molecule/pagination';
6
8
  import Field from './react/molecule/field';
7
9
  const Editor = dynamic(() => import('./react/atom/editor'), { ssr: false });
8
10
 
@@ -10,9 +12,10 @@ const Form = {
10
12
  Input,
11
13
  Textarea,
12
14
  Editor,
15
+ EditorView,
13
16
  Field,
14
17
  };
15
18
 
16
19
  export default Form;
17
20
 
18
- export { Input, Textarea, Editor, Field };
21
+ export { Input, Textarea, Editor, EditorView, Pagination, Field };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "podo-ui",
3
- "version": "0.3.0",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "author": "hada0127 <work@tarucy.net>",
6
6
  "license": "MIT",
@@ -0,0 +1,251 @@
1
+ @use '../../scss/color/function.scss' as *;
2
+ @use '../../scss/typo/mixin.scss' as typo;
3
+ @use '../../scss/layout/radius.scss' as *;
4
+
5
+ .editorView {
6
+ color: color(text-body);
7
+ font-family: inherit;
8
+ word-wrap: break-word;
9
+ overflow-wrap: break-word;
10
+
11
+ // 텍스트 서식
12
+ strong,
13
+ b {
14
+ font-weight: bold;
15
+ }
16
+
17
+ em,
18
+ i {
19
+ font-style: italic;
20
+ }
21
+
22
+ u {
23
+ text-decoration: underline;
24
+ }
25
+
26
+ s,
27
+ strike {
28
+ text-decoration: line-through;
29
+ }
30
+
31
+ // 제목 - podo-ui 스타일 상속
32
+ h1 {
33
+ @include typo.h1;
34
+ margin: 0.67em 0;
35
+ }
36
+
37
+ h2 {
38
+ @include typo.h2;
39
+ margin: 0.75em 0;
40
+ }
41
+
42
+ h3 {
43
+ @include typo.h3;
44
+ margin: 0.83em 0;
45
+ }
46
+
47
+ // p1~p5 스타일 클래스
48
+ .p1 {
49
+ @include typo.p1;
50
+ }
51
+
52
+ .p2 {
53
+ @include typo.p2;
54
+ }
55
+
56
+ .p3 {
57
+ @include typo.p3;
58
+ }
59
+
60
+ .p4 {
61
+ @include typo.p4;
62
+ }
63
+
64
+ .p5 {
65
+ @include typo.p5;
66
+ }
67
+
68
+ // Semibold 스타일
69
+ .p1_semibold {
70
+ @include typo.p1;
71
+ font-weight: 600;
72
+ }
73
+
74
+ .p2_semibold {
75
+ @include typo.p2;
76
+ font-weight: 600;
77
+ }
78
+
79
+ .p3_semibold {
80
+ @include typo.p3-semibold;
81
+ }
82
+
83
+ .p4_semibold {
84
+ @include typo.p4-semibold;
85
+ }
86
+
87
+ .p5_semibold {
88
+ @include typo.p5-semibold;
89
+ }
90
+
91
+ // 단락 - 기본 본문 스타일 p3 적용
92
+ p {
93
+ @include typo.p3;
94
+ margin: 1em 0;
95
+
96
+ &:first-child {
97
+ margin-top: 0;
98
+ }
99
+
100
+ &:last-child {
101
+ margin-bottom: 0;
102
+ }
103
+ }
104
+
105
+ // 링크
106
+ a {
107
+ color: color(link);
108
+ text-decoration: underline;
109
+ cursor: pointer;
110
+
111
+ &:hover {
112
+ color: color(link-hover);
113
+ }
114
+ }
115
+
116
+ // 목록 - podo-ui p3 스타일 적용
117
+ ul,
118
+ ol {
119
+ @include typo.p3;
120
+ margin: 1em 0 !important;
121
+ padding-left: 2em !important;
122
+ padding-top: 0 !important;
123
+ padding-right: 0 !important;
124
+ padding-bottom: 0 !important;
125
+
126
+ &:first-child {
127
+ margin-top: 0 !important;
128
+ }
129
+
130
+ &:last-child {
131
+ margin-bottom: 0 !important;
132
+ }
133
+ }
134
+
135
+ ul {
136
+ list-style: disc !important;
137
+ list-style-type: disc !important;
138
+ list-style-position: outside !important;
139
+ }
140
+
141
+ ol {
142
+ list-style: decimal !important;
143
+ list-style-type: decimal !important;
144
+ list-style-position: outside !important;
145
+ }
146
+
147
+ li {
148
+ display: list-item !important;
149
+ margin: 0.5em 0 !important;
150
+ padding: 0 !important;
151
+ list-style: inherit !important;
152
+ list-style-position: outside !important;
153
+
154
+ // 중첩된 리스트
155
+ ul,
156
+ ol {
157
+ margin: 0.5em 0 !important;
158
+ padding-left: 1.5em !important;
159
+ }
160
+
161
+ ul {
162
+ list-style-type: circle !important;
163
+ }
164
+
165
+ ol {
166
+ list-style-type: lower-alpha !important;
167
+ }
168
+ }
169
+
170
+ // 이미지
171
+ img {
172
+ display: inline-block !important;
173
+ vertical-align: middle;
174
+ max-width: 100%;
175
+ height: auto;
176
+ }
177
+
178
+ // 인용
179
+ blockquote {
180
+ @include typo.p3;
181
+ margin: 1em 0;
182
+ padding-left: 1em;
183
+ border-left: 4px solid color(border);
184
+ color: color(text-sub);
185
+ font-style: italic;
186
+ }
187
+
188
+ // 유튜브 컨테이너 (editor에서 삽입된 스타일 유지)
189
+ :global(.youtube-container) {
190
+ position: relative;
191
+ display: inline-block;
192
+ max-width: 100%;
193
+
194
+ iframe {
195
+ width: 100%;
196
+ height: 100%;
197
+ display: block;
198
+ }
199
+
200
+ :global(.youtube-overlay) {
201
+ display: none; // view 모드에서는 오버레이 숨김
202
+ }
203
+ }
204
+
205
+ // 인라인 코드
206
+ code {
207
+ @include typo.p4;
208
+ background: color(bg-elevation-1);
209
+ color: color(text-body);
210
+ padding: 2px 6px;
211
+ border-radius: r(1);
212
+ border: 1px solid color(default-outline);
213
+ }
214
+
215
+ // 코드 블록
216
+ pre {
217
+ @include typo.p3;
218
+ background: color(bg-elevation-1);
219
+ color: color(text-body);
220
+ padding: 12px 16px;
221
+ border-radius: r(2);
222
+ border: 1px solid color(default-outline);
223
+ overflow-x: auto;
224
+ margin: 1em 0;
225
+
226
+ code {
227
+ background: transparent;
228
+ border: none;
229
+ padding: 0;
230
+ }
231
+ }
232
+
233
+ // 하이라이트/배경색이 있는 요소 (다크모드 대응)
234
+ span[style*="background-color"] {
235
+ padding: 2px 4px;
236
+ border-radius: 2px;
237
+ }
238
+
239
+ // 텍스트 색상이 너무 밝거나 어두운 경우 자동 조정
240
+ span[style*="color: #fff"],
241
+ span[style*="color: white"],
242
+ span[style*="color: rgb(255, 255, 255)"] {
243
+ color: color(text-body) !important;
244
+ }
245
+
246
+ span[style*="color: #000"],
247
+ span[style*="color: black"],
248
+ span[style*="color: rgb(0, 0, 0)"] {
249
+ color: color(text-body) !important;
250
+ }
251
+ }
@@ -0,0 +1,17 @@
1
+ import styles from './editor-view.module.scss';
2
+
3
+ interface Props {
4
+ value: string;
5
+ className?: string;
6
+ }
7
+
8
+ const EditorView = ({ value, className }: Props) => {
9
+ return (
10
+ <div
11
+ className={`${styles.editorView} ${className || ''}`}
12
+ dangerouslySetInnerHTML={{ __html: value }}
13
+ />
14
+ );
15
+ };
16
+
17
+ export default EditorView;
@@ -85,10 +85,6 @@
85
85
  background: color(primary-fill);
86
86
  border-color: color(primary);
87
87
  color: color(primary);
88
-
89
- i {
90
- filter: brightness(0) saturate(100%) invert(30%) sepia(88%) saturate(1838%) hue-rotate(250deg) brightness(95%) contrast(109%);
91
- }
92
88
  }
93
89
 
94
90
  &:focus {
@@ -96,99 +92,132 @@
96
92
  outline-offset: -1px;
97
93
  }
98
94
 
95
+ &:disabled {
96
+ opacity: 0.65;
97
+ cursor: not-allowed;
98
+
99
+ i {
100
+ opacity: 1;
101
+ }
102
+ }
103
+
99
104
  i {
100
105
  display: inline-block;
101
106
  width: 16px;
102
107
  height: 16px;
103
- background-size: 16px 16px;
104
- background-repeat: no-repeat;
105
- background-position: center;
106
- filter: opacity(0.7);
107
- transition: filter 0.2s;
108
+ background-color: currentColor;
109
+ mask-size: 16px 16px;
110
+ mask-repeat: no-repeat;
111
+ mask-position: center;
112
+ -webkit-mask-size: 16px 16px;
113
+ -webkit-mask-repeat: no-repeat;
114
+ -webkit-mask-position: center;
115
+ opacity: 1;
116
+ transition: opacity 0.2s;
108
117
 
109
118
  &.undo {
110
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M125.7 160H176c17.7 0 32 14.3 32 32s-14.3 32-32 32H48c-17.7 0-32-14.3-32-32V64c0-17.7 14.3-32 32-32s32 14.3 32 32v51.2L97.6 97.6c87.5-87.5 229.3-87.5 316.8 0s87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3s-163.8-62.5-226.3 0L125.7 160z"/></svg>');
119
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M125.7 160H176c17.7 0 32 14.3 32 32s-14.3 32-32 32H48c-17.7 0-32-14.3-32-32V64c0-17.7 14.3-32 32-32s32 14.3 32 32v51.2L97.6 97.6c87.5-87.5 229.3-87.5 316.8 0s87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3s-163.8-62.5-226.3 0L125.7 160z"/></svg>');
120
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M125.7 160H176c17.7 0 32 14.3 32 32s-14.3 32-32 32H48c-17.7 0-32-14.3-32-32V64c0-17.7 14.3-32 32-32s32 14.3 32 32v51.2L97.6 97.6c87.5-87.5 229.3-87.5 316.8 0s87.5 229.3 0 316.8s-229.3 87.5-316.8 0c-12.5-12.5-12.5-32.8 0-45.3s32.8-12.5 45.3 0c62.5 62.5 163.8 62.5 226.3 0s62.5-163.8 0-226.3s-163.8-62.5-226.3 0L125.7 160z"/></svg>');
111
121
  }
112
122
 
113
123
  &.redo {
114
- background-image: url('data:image/svg+xml,<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path d="m386.3 160h-50.3c-17.7 0-32 14.3-32 32s14.3 32 32 32h128c17.7 0 32-14.3 32-32v-128c0-17.7-14.3-32-32-32s-32 14.3-32 32v51.2l-17.6-17.6c-87.5-87.5-229.3-87.5-316.8 0s-87.5 229.3 0 316.8 229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3 163.8-62.5 226.3 0z"/></svg>');
124
+ mask-image: url('data:image/svg+xml,<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="m386.3 160h-50.3c-17.7 0-32 14.3-32 32s14.3 32 32 32h128c17.7 0 32-14.3 32-32v-128c0-17.7-14.3-32-32-32s-32 14.3-32 32v51.2l-17.6-17.6c-87.5-87.5-229.3-87.5-316.8 0s-87.5 229.3 0 316.8 229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3 163.8-62.5 226.3 0z"/></svg>');
125
+ -webkit-mask-image: url('data:image/svg+xml,<svg viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path fill="currentColor" d="m386.3 160h-50.3c-17.7 0-32 14.3-32 32s14.3 32 32 32h128c17.7 0 32-14.3 32-32v-128c0-17.7-14.3-32-32-32s-32 14.3-32 32v51.2l-17.6-17.6c-87.5-87.5-229.3-87.5-316.8 0s-87.5 229.3 0 316.8 229.3 87.5 316.8 0c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0c-62.5 62.5-163.8 62.5-226.3 0s-62.5-163.8 0-226.3 163.8-62.5 226.3 0z"/></svg>');
115
126
  }
116
127
 
117
128
  &.bold {
118
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M0 64C0 46.3 14.3 32 32 32H80 96 224c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128H96 80 32c-17.7 0-32-14.3-32-32s14.3-32 32-32H48V256 96H32C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64H112V224H224zM112 288V416H256c35.3 0 64-28.7 64-64s-28.7-64-64-64H224 112z"/></svg>');
129
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M0 64C0 46.3 14.3 32 32 32H80 96 224c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128H96 80 32c-17.7 0-32-14.3-32-32s14.3-32 32-32H48V256 96H32C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64H112V224H224zM112 288V416H256c35.3 0 64-28.7 64-64s-28.7-64-64-64H224 112z"/></svg>');
130
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M0 64C0 46.3 14.3 32 32 32H80 96 224c70.7 0 128 57.3 128 128c0 31.3-11.3 60.1-30 82.3c37.1 22.4 62 63.1 62 109.7c0 70.7-57.3 128-128 128H96 80 32c-17.7 0-32-14.3-32-32s14.3-32 32-32H48V256 96H32C14.3 96 0 81.7 0 64zM224 224c35.3 0 64-28.7 64-64s-28.7-64-64-64H112V224H224zM112 288V416H256c35.3 0 64-28.7 64-64s-28.7-64-64-64H224 112z"/></svg>');
119
131
  }
120
132
 
121
133
  &.italic {
122
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M128 64c0-17.7 14.3-32 32-32H352c17.7 0 32 14.3 32 32s-14.3 32-32 32H293.3L160 416h64c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H90.7L224 96H160c-17.7 0-32-14.3-32-32z"/></svg>');
134
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M128 64c0-17.7 14.3-32 32-32H352c17.7 0 32 14.3 32 32s-14.3 32-32 32H293.3L160 416h64c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H90.7L224 96H160c-17.7 0-32-14.3-32-32z"/></svg>');
135
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path fill="currentColor" d="M128 64c0-17.7 14.3-32 32-32H352c17.7 0 32 14.3 32 32s-14.3 32-32 32H293.3L160 416h64c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H90.7L224 96H160c-17.7 0-32-14.3-32-32z"/></svg>');
123
136
  }
124
137
 
125
138
  &.underline {
126
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M16 64c0-17.7 14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H128V224c0 53 43 96 96 96s96-43 96-96V96H304c-17.7 0-32-14.3-32-32s14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H384V224c0 88.4-71.6 160-160 160s-160-71.6-160-160V96H48C30.3 96 16 81.7 16 64zM0 448c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32z"/></svg>');
139
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M16 64c0-17.7 14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H128V224c0 53 43 96 96 96s96-43 96-96V96H304c-17.7 0-32-14.3-32-32s14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H384V224c0 88.4-71.6 160-160 160s-160-71.6-160-160V96H48C30.3 96 16 81.7 16 64zM0 448c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32z"/></svg>');
140
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M16 64c0-17.7 14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H128V224c0 53 43 96 96 96s96-43 96-96V96H304c-17.7 0-32-14.3-32-32s14.3-32 32-32h96c17.7 0 32 14.3 32 32s-14.3 32-32 32H384V224c0 88.4-71.6 160-160 160s-160-71.6-160-160V96H48C30.3 96 16 81.7 16 64zM0 448c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32z"/></svg>');
127
141
  }
128
142
 
129
143
  &.strikethrough {
130
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M161.3 144c3.2-17.2 14-30.1 33.7-38.6c21.1-9 51.8-12.3 88.6-6.5c11.9 1.9 48.8 9.1 60.1 12c17.1 4.5 34.6-5.6 39.2-22.7s-5.6-34.6-22.7-39.2c-14.3-3.8-53.6-11.4-66.6-13.4c-44.7-7-88.3-4.2-123.7 10.9c-36.5 15.6-64.4 44.8-71.8 87.3c-.1 .6-.2 1.1-.2 1.7c-2.8 23.9 .5 45.6 10.1 64.6c4.5 9 10.2 16.9 16.7 23.9H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H270.1c-.1 0-.3-.1-.4-.1l-1.1-.3c-36-10.8-65.2-19.6-85.2-33.1c-9.3-6.3-15-12.6-18.2-19.1c-3.1-6.1-5.2-14.6-3.8-27.4zM348.9 337.2c2.7 6.5 4.4 15.8 1.9 30.1c-3 17.6-13.8 30.8-33.9 39.4c-21.1 9-51.7 12.3-88.5 6.5c-18-2.9-49.1-13.5-74.4-22.1c-5.6-1.9-11-3.7-15.9-5.4c-16.8-5.6-34.9 3.5-40.5 20.3s3.5 34.9 20.3 40.5c3.6 1.2 7.9 2.7 12.7 4.3l0 0 0 0c24.9 8.5 63.6 21.7 87.6 25.6l0 0 .2 0c44.7 7 88.3 4.2 123.7-10.9c36.5-15.6 64.4-44.8 71.8-87.3c3.6-21 2.7-40.4-3.1-58.1H335.1c7 5.6 11.4 11.2 13.9 17.2z"/></svg>');
144
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M161.3 144c3.2-17.2 14-30.1 33.7-38.6c21.1-9 51.8-12.3 88.6-6.5c11.9 1.9 48.8 9.1 60.1 12c17.1 4.5 34.6-5.6 39.2-22.7s-5.6-34.6-22.7-39.2c-14.3-3.8-53.6-11.4-66.6-13.4c-44.7-7-88.3-4.2-123.7 10.9c-36.5 15.6-64.4 44.8-71.8 87.3c-.1 .6-.2 1.1-.2 1.7c-2.8 23.9 .5 45.6 10.1 64.6c4.5 9 10.2 16.9 16.7 23.9H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H270.1c-.1 0-.3-.1-.4-.1l-1.1-.3c-36-10.8-65.2-19.6-85.2-33.1c-9.3-6.3-15-12.6-18.2-19.1c-3.1-6.1-5.2-14.6-3.8-27.4zM348.9 337.2c2.7 6.5 4.4 15.8 1.9 30.1c-3 17.6-13.8 30.8-33.9 39.4c-21.1 9-51.7 12.3-88.5 6.5c-18-2.9-49.1-13.5-74.4-22.1c-5.6-1.9-11-3.7-15.9-5.4c-16.8-5.6-34.9 3.5-40.5 20.3s3.5 34.9 20.3 40.5c3.6 1.2 7.9 2.7 12.7 4.3l0 0 0 0c24.9 8.5 63.6 21.7 87.6 25.6l0 0 .2 0c44.7 7 88.3 4.2 123.7-10.9c36.5-15.6 64.4-44.8 71.8-87.3c3.6-21 2.7-40.4-3.1-58.1H335.1c7 5.6 11.4 11.2 13.9 17.2z"/></svg>');
145
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M161.3 144c3.2-17.2 14-30.1 33.7-38.6c21.1-9 51.8-12.3 88.6-6.5c11.9 1.9 48.8 9.1 60.1 12c17.1 4.5 34.6-5.6 39.2-22.7s-5.6-34.6-22.7-39.2c-14.3-3.8-53.6-11.4-66.6-13.4c-44.7-7-88.3-4.2-123.7 10.9c-36.5 15.6-64.4 44.8-71.8 87.3c-.1 .6-.2 1.1-.2 1.7c-2.8 23.9 .5 45.6 10.1 64.6c4.5 9 10.2 16.9 16.7 23.9H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H270.1c-.1 0-.3-.1-.4-.1l-1.1-.3c-36-10.8-65.2-19.6-85.2-33.1c-9.3-6.3-15-12.6-18.2-19.1c-3.1-6.1-5.2-14.6-3.8-27.4zM348.9 337.2c2.7 6.5 4.4 15.8 1.9 30.1c-3 17.6-13.8 30.8-33.9 39.4c-21.1 9-51.7 12.3-88.5 6.5c-18-2.9-49.1-13.5-74.4-22.1c-5.6-1.9-11-3.7-15.9-5.4c-16.8-5.6-34.9 3.5-40.5 20.3s3.5 34.9 20.3 40.5c3.6 1.2 7.9 2.7 12.7 4.3l0 0 0 0c24.9 8.5 63.6 21.7 87.6 25.6l0 0 .2 0c44.7 7 88.3 4.2 123.7-10.9c36.5-15.6 64.4-44.8 71.8-87.3c3.6-21 2.7-40.4-3.1-58.1H335.1c7 5.6 11.4 11.2 13.9 17.2z"/></svg>');
131
146
  }
132
147
 
133
148
  &.alignLeft {
134
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
149
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
150
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
135
151
  }
136
152
 
137
153
  &.alignCenter {
138
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
154
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
155
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
139
156
  }
140
157
 
141
158
  &.alignRight {
142
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
159
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
160
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
143
161
  }
144
162
 
145
163
  &.alignJustify {
146
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 64c0-17.7-14.3-32-32-32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32zm0 256c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 192c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM448 448c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32z"/></svg>');
164
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0-17.7-14.3-32-32-32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32zm0 256c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 192c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM448 448c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32z"/></svg>');
165
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0-17.7-14.3-32-32-32H32C14.3 32 0 46.3 0 64S14.3 96 32 96H416c17.7 0 32-14.3 32-32zm0 256c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 192c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM448 448c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32z"/></svg>');
147
166
  }
148
167
 
149
168
  &.listUl {
150
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M64 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zM64 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm48-208a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z"/></svg>');
169
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M64 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zM64 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm48-208a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z"/></svg>');
170
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M64 144a48 48 0 1 0 0-96 48 48 0 1 0 0 96zM192 64c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zm0 160c-17.7 0-32 14.3-32 32s14.3 32 32 32H480c17.7 0 32-14.3 32-32s-14.3-32-32-32H192zM64 464a48 48 0 1 0 0-96 48 48 0 1 0 0 96zm48-208a48 48 0 1 0 -96 0 48 48 0 1 0 96 0z"/></svg>');
151
171
  }
152
172
 
153
173
  &.listOl {
154
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M24 56c0-13.3 10.7-24 24-24H80c13.3 0 24 10.7 24 24V176h16c13.3 0 24 10.7 24 24s-10.7 24-24 24H40c-13.3 0-24-10.7-24-24s10.7-24 24-24H56V80H48C34.7 80 24 69.3 24 56zM86.7 341.2c-6.5-7.4-18.3-6.9-24 1.2L51.5 357.9c-7.7 10.8-22.7 13.3-33.5 5.6s-13.3-22.7-5.6-33.5l11.1-15.6c23.7-33.2 72.3-35.6 99.2-4.9c21.3 24.4 20.8 60.9-1.1 84.7L86.8 432H120c13.3 0 24 10.7 24 24s-10.7 24-24 24H32c-9.5 0-18.2-5.6-22-14.4s-2.1-18.9 4.3-25.9l72-78c5.3-5.8 5.4-14.6 .3-20.5zM224 64H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>');
174
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M24 56c0-13.3 10.7-24 24-24H80c13.3 0 24 10.7 24 24V176h16c13.3 0 24 10.7 24 24s-10.7 24-24 24H40c-13.3 0-24-10.7-24-24s10.7-24 24-24H56V80H48C34.7 80 24 69.3 24 56zM86.7 341.2c-6.5-7.4-18.3-6.9-24 1.2L51.5 357.9c-7.7 10.8-22.7 13.3-33.5 5.6s-13.3-22.7-5.6-33.5l11.1-15.6c23.7-33.2 72.3-35.6 99.2-4.9c21.3 24.4 20.8 60.9-1.1 84.7L86.8 432H120c13.3 0 24 10.7 24 24s-10.7 24-24 24H32c-9.5 0-18.2-5.6-22-14.4s-2.1-18.9 4.3-25.9l72-78c5.3-5.8 5.4-14.6 .3-20.5zM224 64H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>');
175
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M24 56c0-13.3 10.7-24 24-24H80c13.3 0 24 10.7 24 24V176h16c13.3 0 24 10.7 24 24s-10.7 24-24 24H40c-13.3 0-24-10.7-24-24s10.7-24 24-24H56V80H48C34.7 80 24 69.3 24 56zM86.7 341.2c-6.5-7.4-18.3-6.9-24 1.2L51.5 357.9c-7.7 10.8-22.7 13.3-33.5 5.6s-13.3-22.7-5.6-33.5l11.1-15.6c23.7-33.2 72.3-35.6 99.2-4.9c21.3 24.4 20.8 60.9-1.1 84.7L86.8 432H120c13.3 0 24 10.7 24 24s-10.7 24-24 24H32c-9.5 0-18.2-5.6-22-14.4s-2.1-18.9 4.3-25.9l72-78c5.3-5.8 5.4-14.6 .3-20.5zM224 64H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32zm0 160H480c17.7 0 32 14.3 32 32s-14.3 32-32 32H224c-17.7 0-32-14.3-32-32s14.3-32 32-32z"/></svg>');
155
176
  }
156
177
 
157
178
  &.link {
158
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"/></svg>');
179
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"/></svg>');
180
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M579.8 267.7c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-1.1 1.6C206.5 251.2 213 330 263 380c56.5 56.5 148 56.5 204.5 0L579.8 267.7zM60.2 244.3c-56.5 56.5-56.5 148 0 204.5c50 50 128.8 56.5 186.3 15.4l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C74 372 74 321 105.5 289.5L217.7 177.2c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.9l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6C433.5 260.8 427 182 377 132c-56.5-56.5-148-56.5-204.5 0L60.2 244.3z"/></svg>');
159
181
  }
160
182
 
161
183
  &.unlink {
162
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L489.3 358.2l90.5-90.5c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-.5 .7L38.8 5.1zM34 189.1l90.5 90.5c-10.4 10.4-18 22.3-22.6 35.1L5.1 466.9c-10.4 8.2-12.3 23.3-4.1 33.7s23.3 12.3 33.7 4.1l127.4-99.9c29.5 33.7 80.5 39.9 119.8 15l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C109.4 328.6 109.4 277.6 140.9 246.1l33-33 .2-.2 55.4-55.4 .2-.2 33-33c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.8l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6c41.2-57.4 34.7-136.2-15.3-186.2c-56.5-56.5-148-56.5-204.5 0L34 189.1z"/></svg>');
184
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L489.3 358.2l90.5-90.5c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-.5 .7L38.8 5.1zM34 189.1l90.5 90.5c-10.4 10.4-18 22.3-22.6 35.1L5.1 466.9c-10.4 8.2-12.3 23.3-4.1 33.7s23.3 12.3 33.7 4.1l127.4-99.9c29.5 33.7 80.5 39.9 119.8 15l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C109.4 328.6 109.4 277.6 140.9 246.1l33-33 .2-.2 55.4-55.4 .2-.2 33-33c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.8l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6c41.2-57.4 34.7-136.2-15.3-186.2c-56.5-56.5-148-56.5-204.5 0L34 189.1z"/></svg>');
185
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L489.3 358.2l90.5-90.5c56.5-56.5 56.5-148 0-204.5c-50-50-128.8-56.5-186.3-15.4l-1.6 1.1c-14.4 10.3-17.7 30.3-7.4 44.6s30.3 17.7 44.6 7.4l1.6-1.1c32.1-22.9 76-19.3 103.8 8.6c31.5 31.5 31.5 82.5 0 114L422.3 334.8c-31.5 31.5-82.5 31.5-114 0c-27.9-27.9-31.5-71.8-8.6-103.8l1.1-1.6c10.3-14.4 6.9-34.4-7.4-44.6s-34.4-6.9-44.6 7.4l-.5 .7L38.8 5.1zM34 189.1l90.5 90.5c-10.4 10.4-18 22.3-22.6 35.1L5.1 466.9c-10.4 8.2-12.3 23.3-4.1 33.7s23.3 12.3 33.7 4.1l127.4-99.9c29.5 33.7 80.5 39.9 119.8 15l1.6-1.1c14.4-10.3 17.7-30.3 7.4-44.6s-30.3-17.7-44.6-7.4l-1.6 1.1c-32.1 22.9-76 19.3-103.8-8.6C109.4 328.6 109.4 277.6 140.9 246.1l33-33 .2-.2 55.4-55.4 .2-.2 33-33c31.5-31.5 82.5-31.5 114 0c27.9 27.9 31.5 71.8 8.6 103.8l-1.1 1.6c-10.3 14.4-6.9 34.4 7.4 44.6s34.4 6.9 44.6-7.4l1.1-1.6c41.2-57.4 34.7-136.2-15.3-186.2c-56.5-56.5-148-56.5-204.5 0L34 189.1z"/></svg>');
163
186
  }
164
187
 
165
188
  &.eraser {
166
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M290.7 57.4L57.4 290.7c-25 25-25 65.5 0 90.5l80 80c12 12 28.3 18.7 45.3 18.7H288h9.4H512c17.7 0 32-14.3 32-32s-14.3-32-32-32H387.9L518.6 285.3c25-25 25-65.5 0-90.5L381.3 57.4c-25-25-65.5-25-90.5 0zM297.4 416H288l-105.4 0-80-80L227.3 211.3 364.7 348.7 297.4 416z"/></svg>');
189
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M290.7 57.4L57.4 290.7c-25 25-25 65.5 0 90.5l80 80c12 12 28.3 18.7 45.3 18.7H288h9.4H512c17.7 0 32-14.3 32-32s-14.3-32-32-32H387.9L518.6 285.3c25-25 25-65.5 0-90.5L381.3 57.4c-25-25-65.5-25-90.5 0zM297.4 416H288l-105.4 0-80-80L227.3 211.3 364.7 348.7 297.4 416z"/></svg>');
190
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M290.7 57.4L57.4 290.7c-25 25-25 65.5 0 90.5l80 80c12 12 28.3 18.7 45.3 18.7H288h9.4H512c17.7 0 32-14.3 32-32s-14.3-32-32-32H387.9L518.6 285.3c25-25 25-65.5 0-90.5L381.3 57.4c-25-25-65.5-25-90.5 0zM297.4 416H288l-105.4 0-80-80L227.3 211.3 364.7 348.7 297.4 416z"/></svg>');
167
191
  }
168
192
 
169
193
  &.fontColor {
170
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M254 52.8C249.3 40.3 237.3 32 224 32s-25.3 8.3-30 20.8L57.8 416H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32h-1.8l18-48H303.8l18 48H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H390.2L254 52.8zM279.8 304H168.2L224 155.1 279.8 304z"/></svg>');
194
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M254 52.8C249.3 40.3 237.3 32 224 32s-25.3 8.3-30 20.8L57.8 416H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32h-1.8l18-48H303.8l18 48H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H390.2L254 52.8zM279.8 304H168.2L224 155.1 279.8 304z"/></svg>');
195
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M254 52.8C249.3 40.3 237.3 32 224 32s-25.3 8.3-30 20.8L57.8 416H32c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32h-1.8l18-48H303.8l18 48H320c-17.7 0-32 14.3-32 32s14.3 32 32 32h96c17.7 0 32-14.3 32-32s-14.3-32-32-32H390.2L254 52.8zM279.8 304H168.2L224 155.1 279.8 304z"/></svg>');
171
196
  }
172
197
 
173
198
  &.highlight {
174
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M315 315l158.4-215L444.1 70.6 229 229 315 315zm-187 5l0 0V248.3c0-15.3 7.2-29.6 19.5-38.6L420.6 8.4C428 2.9 437 0 446.2 0c11.4 0 22.4 4.5 30.5 12.6l54.8 54.8c8.1 8.1 12.6 19 12.6 30.5c0 9.2-2.9 18.2-8.4 25.6L334.4 396.5c-9 12.3-23.4 19.5-38.6 19.5H224l-25.4 25.4c-12.5 12.5-32.8 12.5-45.3 0l-50.7-50.7c-12.5-12.5-12.5-32.8 0-45.3L128 320zM7 466.3l63-63 70.6 70.6-31 31c-4.5 4.5-10.6 7-17 7H24c-13.3 0-24-10.7-24-24v-4.7c0-6.4 2.5-12.5 7-17z"/></svg>');
199
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M315 315l158.4-215L444.1 70.6 229 229 315 315zm-187 5l0 0V248.3c0-15.3 7.2-29.6 19.5-38.6L420.6 8.4C428 2.9 437 0 446.2 0c11.4 0 22.4 4.5 30.5 12.6l54.8 54.8c8.1 8.1 12.6 19 12.6 30.5c0 9.2-2.9 18.2-8.4 25.6L334.4 396.5c-9 12.3-23.4 19.5-38.6 19.5H224l-25.4 25.4c-12.5 12.5-32.8 12.5-45.3 0l-50.7-50.7c-12.5-12.5-12.5-32.8 0-45.3L128 320zM7 466.3l63-63 70.6 70.6-31 31c-4.5 4.5-10.6 7-17 7H24c-13.3 0-24-10.7-24-24v-4.7c0-6.4 2.5-12.5 7-17z"/></svg>');
200
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M315 315l158.4-215L444.1 70.6 229 229 315 315zm-187 5l0 0V248.3c0-15.3 7.2-29.6 19.5-38.6L420.6 8.4C428 2.9 437 0 446.2 0c11.4 0 22.4 4.5 30.5 12.6l54.8 54.8c8.1 8.1 12.6 19 12.6 30.5c0 9.2-2.9 18.2-8.4 25.6L334.4 396.5c-9 12.3-23.4 19.5-38.6 19.5H224l-25.4 25.4c-12.5 12.5-32.8 12.5-45.3 0l-50.7-50.7c-12.5-12.5-12.5-32.8 0-45.3L128 320zM7 466.3l63-63 70.6 70.6-31 31c-4.5 4.5-10.6 7-17 7H24c-13.3 0-24-10.7-24-24v-4.7c0-6.4 2.5-12.5 7-17z"/></svg>');
175
201
  }
176
202
 
177
203
  &.image {
178
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM323.8 202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2.9 25.4s12.4 13.6 21.6 13.6h96 32H424c8.9 0 17.1-4.9 21.2-12.8s3.6-17.4-1.4-24.7l-120-176zM112 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"/></svg>');
204
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM323.8 202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2.9 25.4s12.4 13.6 21.6 13.6h96 32H424c8.9 0 17.1-4.9 21.2-12.8s3.6-17.4-1.4-24.7l-120-176zM112 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"/></svg>');
205
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M0 96C0 60.7 28.7 32 64 32H448c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM323.8 202.5c-4.5-6.6-11.9-10.5-19.8-10.5s-15.4 3.9-19.8 10.5l-87 127.6L170.7 297c-4.6-5.7-11.5-9-18.7-9s-14.2 3.3-18.7 9l-64 80c-5.8 7.2-6.9 17.1-2.9 25.4s12.4 13.6 21.6 13.6h96 32H424c8.9 0 17.1-4.9 21.2-12.8s3.6-17.4-1.4-24.7l-120-176zM112 192a48 48 0 1 0 0-96 48 48 0 1 0 0 96z"/></svg>');
179
206
  }
180
207
 
181
208
  &.youtube {
182
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>');
209
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>');
210
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path fill="currentColor" d="M549.655 124.083c-6.281-23.65-24.787-42.276-48.284-48.597C458.781 64 288 64 288 64S117.22 64 74.629 75.486c-23.497 6.322-42.003 24.947-48.284 48.597-11.412 42.867-11.412 132.305-11.412 132.305s0 89.438 11.412 132.305c6.281 23.65 24.787 41.5 48.284 47.821C117.22 448 288 448 288 448s170.78 0 213.371-11.486c23.497-6.321 42.003-24.171 48.284-47.821 11.412-42.867 11.412-132.305 11.412-132.305s0-89.438-11.412-132.305zm-317.51 213.508V175.185l142.739 81.205-142.739 81.201z"/></svg>');
183
211
  }
184
212
 
185
213
  &.code {
186
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z"/></svg>');
214
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z"/></svg>');
215
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M392.8 1.2c-17-4.9-34.7 5-39.6 22l-128 448c-4.9 17 5 34.7 22 39.6s34.7-5 39.6-22l128-448c4.9-17-5-34.7-22-39.6zm80.6 120.1c-12.5 12.5-12.5 32.8 0 45.3L562.7 256l-89.4 89.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0l112-112c12.5-12.5 12.5-32.8 0-45.3l-112-112c-12.5-12.5-32.8-12.5-45.3 0zm-306.7 0c-12.5-12.5-32.8-12.5-45.3 0l-112 112c-12.5 12.5-12.5 32.8 0 45.3l112 112c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256l89.4-89.4c12.5-12.5 12.5-32.8 0-45.3z"/></svg>');
187
216
  }
188
217
  }
189
218
 
190
219
  &:hover i {
191
- filter: opacity(1);
220
+ opacity: 1;
192
221
  }
193
222
  }
194
223
 
@@ -310,6 +339,7 @@
310
339
  border: 1px solid transparent;
311
340
  border-radius: r(2);
312
341
  background: transparent;
342
+ color: color(text-action);
313
343
  cursor: pointer;
314
344
  transition: all 0.2s;
315
345
 
@@ -317,24 +347,31 @@
317
347
  display: inline-block;
318
348
  width: 16px;
319
349
  height: 16px;
320
- background-size: 16px 16px;
321
- background-repeat: no-repeat;
322
- background-position: center;
323
- filter: opacity(0.7);
324
- transition: filter 0.2s;
350
+ background-color: currentColor;
351
+ mask-size: 16px 16px;
352
+ mask-repeat: no-repeat;
353
+ mask-position: center;
354
+ -webkit-mask-size: 16px 16px;
355
+ -webkit-mask-repeat: no-repeat;
356
+ -webkit-mask-position: center;
357
+ opacity: 1;
358
+ transition: opacity 0.2s;
325
359
  }
326
360
 
327
361
  // 아이콘 정의 (toolbarButton과 동일)
328
362
  .alignLeft {
329
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
363
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
364
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
330
365
  }
331
366
 
332
367
  .alignCenter {
333
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
368
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
369
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
334
370
  }
335
371
 
336
372
  .alignRight {
337
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
373
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
374
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
338
375
  }
339
376
 
340
377
  &:hover {
@@ -342,17 +379,14 @@
342
379
  border-color: color(border-hover);
343
380
 
344
381
  i {
345
- filter: opacity(1);
382
+ opacity: 1;
346
383
  }
347
384
  }
348
385
 
349
386
  &.active {
350
387
  background: color(primary-fill);
351
388
  border-color: color(primary);
352
-
353
- i {
354
- filter: brightness(0) saturate(100%) invert(30%) sepia(88%) saturate(1838%) hue-rotate(250deg) brightness(95%) contrast(109%);
355
- }
389
+ color: color(primary);
356
390
  }
357
391
  }
358
392
 
@@ -973,20 +1007,29 @@
973
1007
  display: inline-block;
974
1008
  width: 14px;
975
1009
  height: 14px;
976
- background-size: 14px 14px;
977
- background-repeat: no-repeat;
978
- background-position: center;
1010
+ background-color: currentColor;
1011
+ mask-size: 14px 14px;
1012
+ mask-repeat: no-repeat;
1013
+ mask-position: center;
1014
+ -webkit-mask-size: 14px 14px;
1015
+ -webkit-mask-repeat: no-repeat;
1016
+ -webkit-mask-position: center;
1017
+ opacity: 0.85;
1018
+ transition: opacity 0.2s;
979
1019
 
980
1020
  &.alignLeft {
981
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
1021
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
1022
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M288 64c0 17.7-14.3 32-32 32H32C14.3 96 0 81.7 0 64S14.3 32 32 32H256c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H256c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
982
1023
  }
983
1024
 
984
1025
  &.alignCenter {
985
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
1026
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
1027
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M352 64c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32zm96 128c0-17.7-14.3-32-32-32H32c-17.7 0-32 14.3-32 32s14.3 32 32 32H416c17.7 0 32-14.3 32-32zM0 448c0 17.7 14.3 32 32 32H416c17.7 0 32-14.3 32-32s-14.3-32-32-32H32c-17.7 0-32 14.3-32 32zM352 320c0-17.7-14.3-32-32-32H128c-17.7 0-32 14.3-32 32s14.3 32 32 32H320c17.7 0 32-14.3 32-32z"/></svg>');
986
1028
  }
987
1029
 
988
1030
  &.alignRight {
989
- background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
1031
+ mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
1032
+ -webkit-mask-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M448 64c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zm0 256c0 17.7-14.3 32-32 32H192c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32zM0 192c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 448c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/></svg>');
990
1033
  }
991
1034
  }
992
1035
 
@@ -995,7 +1038,7 @@
995
1038
  color: color(text-body);
996
1039
 
997
1040
  i {
998
- filter: opacity(0.8);
1041
+ opacity: 1;
999
1042
  }
1000
1043
  }
1001
1044
 
@@ -1003,10 +1046,6 @@
1003
1046
  background: color(primary);
1004
1047
  color: white;
1005
1048
  border-color: color(primary);
1006
-
1007
- i {
1008
- filter: brightness(0) invert(1);
1009
- }
1010
1049
  }
1011
1050
  }
1012
1051
  }
@@ -1188,7 +1227,6 @@
1188
1227
  // 코드 에디터
1189
1228
  .codeEditor {
1190
1229
  padding: 16px 20px;
1191
- font-family: 'Courier New', monospace;
1192
1230
  font-size: 13px;
1193
1231
  line-height: 1.5;
1194
1232
  background: transparent;
@@ -72,6 +72,15 @@ const Editor = ({
72
72
  const [isCodeView, setIsCodeView] = useState(false); // 코드보기 모드
73
73
  const [codeContent, setCodeContent] = useState(''); // 코드보기 내용
74
74
  const [savedEditorHeight, setSavedEditorHeight] = useState<number | null>(null); // 위지윅 에디터 높이 저장
75
+
76
+ // Undo/Redo 히스토리 관리
77
+ const [history, setHistory] = useState<string[]>([value]);
78
+ const [historyIndex, setHistoryIndex] = useState(0);
79
+ const historyTimerRef = useRef<NodeJS.Timeout | null>(null);
80
+ const historyRef = useRef<string[]>([value]);
81
+ const historyIndexRef = useRef(0);
82
+ const isUndoRedoRef = useRef(false); // undo/redo 실행 중 플래그
83
+
75
84
  const editorRef = useRef<HTMLDivElement>(null);
76
85
  const codeEditorRef = useRef<HTMLTextAreaElement>(null);
77
86
  const containerRef = useRef<HTMLDivElement>(null);
@@ -87,16 +96,20 @@ const Editor = ({
87
96
  // 클라이언트에서만 ID 생성 (Vite React용)
88
97
  const [editorID, setEditorID] = useState<string>('podo-editor');
89
98
 
90
- // 색상 팔레트 정의
99
+ // 색상 팔레트 정의 (이미지 기반)
91
100
  const colorPalette = [
92
- // 첫 번째 줄: 기본 색상
93
- ['#000000', '#ff0000', '#ffff00', '#00ff00', '#00ffff', '#0000ff', '#ff00ff', '#ffffff'],
94
- // 두 번째 줄: 밝은 톤
95
- ['#808080', '#ff8080', '#ffff80', '#80ff80', '#80ffff', '#8080ff', '#ff80ff', '#c0c0c0'],
96
- // 세 번째 줄: 중간
97
- ['#404040', '#800000', '#808000', '#008000', '#008080', '#000080', '#800080', '#808080'],
98
- // 네 번째 줄: 어두운
99
- ['#202020', '#400000', '#404000', '#004000', '#004040', '#000040', '#400040', '#404040'],
101
+ // 첫 번째 줄: 순수 색상
102
+ ['#ff0000', '#ff8000', '#ffff00', '#80ff00', '#00ffff', '#0080ff', '#0000ff', '#8000ff', '#ff00ff', '#000000'],
103
+ // 두 번째 줄: 매우 밝은 톤 (90% 밝기)
104
+ ['#ffcccc', '#ffe0cc', '#ffffcc', '#e0ffcc', '#ccffff', '#cce0ff', '#ccccff', '#e0ccff', '#ffccff', '#cccccc'],
105
+ // 세 번째 줄: 밝은 (70% 밝기)
106
+ ['#ff9999', '#ffcc99', '#ffff99', '#ccff99', '#99ffff', '#99ccff', '#9999ff', '#cc99ff', '#ff99ff', '#999999'],
107
+ // 네 번째 줄: 중간 (50% 밝기)
108
+ ['#ff6666', '#ffb366', '#ffff66', '#b3ff66', '#66ffff', '#66b3ff', '#6666ff', '#b366ff', '#ff66ff', '#666666'],
109
+ // 다섯 번째 줄: 어두운 톤 (30% 밝기)
110
+ ['#cc0000', '#cc6600', '#cccc00', '#66cc00', '#00cccc', '#0066cc', '#0000cc', '#6600cc', '#cc00cc', '#333333'],
111
+ // 여섯 번째 줄: 매우 어두운 톤 (15% 밝기)
112
+ ['#800000', '#804000', '#808000', '#408000', '#008080', '#004080', '#000080', '#400080', '#800080', '#1a1a1a'],
100
113
  ];
101
114
 
102
115
  // 정렬 옵션 정의
@@ -227,6 +240,106 @@ const Editor = ({
227
240
  setCurrentParagraphStyle('p');
228
241
  };
229
242
 
243
+ // ref와 state 동기화
244
+ useEffect(() => {
245
+ historyRef.current = history;
246
+ historyIndexRef.current = historyIndex;
247
+ }, [history, historyIndex]);
248
+
249
+ // 히스토리에 추가 (디바운스 적용)
250
+ const addToHistory = useCallback((content: string) => {
251
+ // 기존 타이머 취소
252
+ if (historyTimerRef.current) {
253
+ clearTimeout(historyTimerRef.current);
254
+ }
255
+
256
+ // 500ms 후에 히스토리 추가 (연속 입력 시 하나로 묶음)
257
+ historyTimerRef.current = setTimeout(() => {
258
+ // ref에서 최신 값 가져오기
259
+ const currentHistory = historyRef.current;
260
+ const currentIndex = historyIndexRef.current;
261
+
262
+ // 현재 인덱스 이후의 히스토리 제거
263
+ const newHistory = currentHistory.slice(0, currentIndex + 1);
264
+
265
+ // 마지막 항목과 동일하면 추가하지 않음
266
+ if (newHistory[newHistory.length - 1] === content) {
267
+ return;
268
+ }
269
+
270
+ // 새 항목 추가 (최대 200개)
271
+ const updated = [...newHistory, content];
272
+ if (updated.length > 200) {
273
+ updated.shift(); // 가장 오래된 항목 제거
274
+ setHistory(updated);
275
+ setHistoryIndex(currentIndex); // 인덱스는 그대로 유지
276
+ } else {
277
+ setHistory(updated);
278
+ setHistoryIndex(updated.length - 1);
279
+ }
280
+ }, 500);
281
+ }, []);
282
+
283
+ // Undo 실행
284
+ const performUndo = useCallback(() => {
285
+ // debounce 타이머 취소 (undo 중에는 히스토리 추가 안 함)
286
+ if (historyTimerRef.current) {
287
+ clearTimeout(historyTimerRef.current);
288
+ historyTimerRef.current = null;
289
+ }
290
+
291
+ const currentIndex = historyIndexRef.current;
292
+ const currentHistory = historyRef.current;
293
+
294
+ if (currentIndex > 0) {
295
+ const newIndex = currentIndex - 1;
296
+ const content = currentHistory[newIndex];
297
+ setHistoryIndex(newIndex);
298
+
299
+ if (editorRef.current) {
300
+ isUndoRedoRef.current = true; // undo 실행 중 플래그 설정
301
+ editorRef.current.innerHTML = content;
302
+ onChange(content);
303
+ detectCurrentParagraphStyle();
304
+ detectCurrentAlign();
305
+ // 다음 틱에서 플래그 해제
306
+ setTimeout(() => {
307
+ isUndoRedoRef.current = false;
308
+ }, 0);
309
+ }
310
+ }
311
+ }, [onChange]);
312
+
313
+ // Redo 실행
314
+ const performRedo = useCallback(() => {
315
+ // debounce 타이머 취소 (redo 중에는 히스토리 추가 안 함)
316
+ if (historyTimerRef.current) {
317
+ clearTimeout(historyTimerRef.current);
318
+ historyTimerRef.current = null;
319
+ }
320
+
321
+ const currentIndex = historyIndexRef.current;
322
+ const currentHistory = historyRef.current;
323
+
324
+ if (currentIndex < currentHistory.length - 1) {
325
+ const newIndex = currentIndex + 1;
326
+ const content = currentHistory[newIndex];
327
+ setHistoryIndex(newIndex);
328
+
329
+ if (editorRef.current) {
330
+ isUndoRedoRef.current = true; // redo 실행 중 플래그 설정
331
+ editorRef.current.innerHTML = content;
332
+ onChange(content);
333
+ detectCurrentParagraphStyle();
334
+ detectCurrentAlign();
335
+ // 다음 틱에서 플래그 해제
336
+ setTimeout(() => {
337
+ isUndoRedoRef.current = false;
338
+ }, 0);
339
+ }
340
+ }
341
+ }, [onChange]);
342
+
230
343
  const handleInput = useCallback(() => {
231
344
  if (editorRef.current) {
232
345
  const content = editorRef.current.innerHTML;
@@ -235,11 +348,150 @@ const Editor = ({
235
348
  validateHandler(content);
236
349
  detectCurrentParagraphStyle();
237
350
  detectCurrentAlign();
351
+
352
+ // 히스토리에 추가
353
+ addToHistory(content);
238
354
  }
239
355
  // eslint-disable-next-line react-hooks/exhaustive-deps
240
- }, [onChange]);
356
+ }, [onChange, addToHistory]);
357
+
358
+ // 붙여넣기 이벤트 핸들러 - 지원하지 않는 스타일 제거
359
+ const handlePaste = useCallback((e: React.ClipboardEvent<HTMLDivElement>) => {
360
+ e.preventDefault();
361
+
362
+ const clipboardData = e.clipboardData;
363
+ if (!clipboardData) return;
364
+
365
+ // HTML 데이터 가져오기
366
+ const html = clipboardData.getData('text/html');
367
+ const text = clipboardData.getData('text/plain');
368
+
369
+ if (html) {
370
+ // 임시 div를 만들어서 HTML 파싱
371
+ const tempDiv = document.createElement('div');
372
+ tempDiv.innerHTML = html;
373
+
374
+ // 지원하는 태그와 스타일 정의
375
+ const allowedTags = ['P', 'BR', 'STRONG', 'B', 'EM', 'I', 'U', 'S', 'STRIKE', 'DEL',
376
+ 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'BLOCKQUOTE', 'PRE',
377
+ 'UL', 'OL', 'LI', 'A', 'IMG', 'SPAN', 'DIV'];
378
+ const allowedStyles = ['color', 'background-color', 'text-align'];
379
+
380
+ // 모든 요소를 순회하면서 정리
381
+ const cleanElement = (element: Element): Node | null => {
382
+ const tagName = element.tagName;
383
+
384
+ // 지원하지 않는 태그는 내용만 유지
385
+ if (!allowedTags.includes(tagName)) {
386
+ const fragment = document.createDocumentFragment();
387
+ Array.from(element.childNodes).forEach(child => {
388
+ if (child.nodeType === Node.ELEMENT_NODE) {
389
+ const cleaned = cleanElement(child as Element);
390
+ if (cleaned) fragment.appendChild(cleaned);
391
+ } else if (child.nodeType === Node.TEXT_NODE) {
392
+ fragment.appendChild(child.cloneNode(true));
393
+ }
394
+ });
395
+ return fragment.childNodes.length > 0 ? fragment : null;
396
+ }
397
+
398
+ // 지원하는 태그는 복제하고 스타일 정리
399
+ const newElement = element.cloneNode(false) as HTMLElement;
400
+
401
+ // 모든 속성 제거 후 필요한 것만 복원
402
+ const attrs = Array.from(element.attributes);
403
+ attrs.forEach(attr => newElement.removeAttribute(attr.name));
404
+
405
+ // href, src, alt 등 필수 속성만 복원
406
+ if (tagName === 'A' && element.getAttribute('href')) {
407
+ newElement.setAttribute('href', element.getAttribute('href')!);
408
+ }
409
+ if (tagName === 'IMG') {
410
+ if (element.getAttribute('src')) {
411
+ newElement.setAttribute('src', element.getAttribute('src')!);
412
+ }
413
+ if (element.getAttribute('alt')) {
414
+ newElement.setAttribute('alt', element.getAttribute('alt')!);
415
+ }
416
+ }
417
+
418
+ // 스타일 복원 (허용된 것만)
419
+ if (element instanceof HTMLElement && element.style) {
420
+ allowedStyles.forEach(styleName => {
421
+ const value = element.style.getPropertyValue(styleName);
422
+ if (value) {
423
+ (newElement as HTMLElement).style.setProperty(styleName, value);
424
+ }
425
+ });
426
+ }
427
+
428
+ // 자식 요소 처리
429
+ Array.from(element.childNodes).forEach(child => {
430
+ if (child.nodeType === Node.ELEMENT_NODE) {
431
+ const cleaned = cleanElement(child as Element);
432
+ if (cleaned) newElement.appendChild(cleaned);
433
+ } else if (child.nodeType === Node.TEXT_NODE) {
434
+ newElement.appendChild(child.cloneNode(true));
435
+ }
436
+ });
437
+
438
+ return newElement;
439
+ };
440
+
441
+ // 정리된 HTML 생성
442
+ const cleanedDiv = document.createElement('div');
443
+ Array.from(tempDiv.childNodes).forEach(child => {
444
+ if (child.nodeType === Node.ELEMENT_NODE) {
445
+ const cleaned = cleanElement(child as Element);
446
+ if (cleaned) cleanedDiv.appendChild(cleaned);
447
+ } else if (child.nodeType === Node.TEXT_NODE) {
448
+ cleanedDiv.appendChild(child.cloneNode(true));
449
+ }
450
+ });
451
+
452
+ // 현재 커서 위치에 삽입
453
+ const selection = window.getSelection();
454
+ if (selection && selection.rangeCount > 0) {
455
+ const range = selection.getRangeAt(0);
456
+ range.deleteContents();
457
+
458
+ const fragment = document.createDocumentFragment();
459
+ while (cleanedDiv.firstChild) {
460
+ fragment.appendChild(cleanedDiv.firstChild);
461
+ }
462
+ range.insertNode(fragment);
463
+
464
+ // 커서를 삽입된 내용의 끝으로 이동
465
+ range.collapse(false);
466
+ selection.removeAllRanges();
467
+ selection.addRange(range);
468
+ }
469
+ } else if (text) {
470
+ // HTML이 없으면 일반 텍스트 삽입
471
+ const selection = window.getSelection();
472
+ if (selection && selection.rangeCount > 0) {
473
+ const range = selection.getRangeAt(0);
474
+ range.deleteContents();
475
+ range.insertNode(document.createTextNode(text));
476
+ range.collapse(false);
477
+ }
478
+ }
479
+
480
+ // 변경사항 반영
481
+ handleInput();
482
+ }, [handleInput]);
241
483
 
242
484
  const execCommand = (command: string, value: string | undefined = undefined) => {
485
+ // undo/redo는 커스텀 함수 사용
486
+ if (command === 'undo') {
487
+ performUndo();
488
+ return;
489
+ }
490
+ if (command === 'redo') {
491
+ performRedo();
492
+ return;
493
+ }
494
+
243
495
  // bold, italic, underline, strikeThrough일 때 선택 영역이 없으면 아무것도 하지 않음
244
496
  if (['bold', 'italic', 'underline', 'strikeThrough'].includes(command)) {
245
497
  const selection = window.getSelection();
@@ -1929,6 +2181,18 @@ const Editor = ({
1929
2181
  };
1930
2182
  }, [selectedYoutube]);
1931
2183
 
2184
+ // 외부에서 value가 변경되면 히스토리 초기화 (단, undo/redo 중에는 제외)
2185
+ useEffect(() => {
2186
+ if (isUndoRedoRef.current) {
2187
+ return;
2188
+ }
2189
+ if (editorRef.current && editorRef.current.innerHTML !== value) {
2190
+ editorRef.current.innerHTML = value;
2191
+ setHistory([value]);
2192
+ setHistoryIndex(0);
2193
+ }
2194
+ }, [value]);
2195
+
1932
2196
  // 초기 로드 시 문단 형식 감지 (기본 p 태그는 추가하지 않음)
1933
2197
  useEffect(() => {
1934
2198
  // 약간의 지연을 주어 DOM이 완전히 렌더링된 후 감지
@@ -1951,7 +2215,14 @@ const Editor = ({
1951
2215
  type="button"
1952
2216
  className={styles.toolbarButton}
1953
2217
  onClick={() => execCommand('undo')}
2218
+ disabled={historyIndex <= 0}
1954
2219
  title="실행 취소"
2220
+ style={{
2221
+ opacity: historyIndex <= 0 ? 0.65 : 1,
2222
+ backgroundColor: 'transparent',
2223
+ border: 'none',
2224
+ cursor: historyIndex <= 0 ? 'not-allowed' : 'pointer'
2225
+ }}
1955
2226
  >
1956
2227
  <i className={styles.undo} />
1957
2228
  </button>
@@ -1959,7 +2230,14 @@ const Editor = ({
1959
2230
  type="button"
1960
2231
  className={styles.toolbarButton}
1961
2232
  onClick={() => execCommand('redo')}
2233
+ disabled={historyIndex >= history.length - 1}
1962
2234
  title="다시 실행"
2235
+ style={{
2236
+ opacity: historyIndex >= history.length - 1 ? 0.65 : 1,
2237
+ backgroundColor: 'transparent',
2238
+ border: 'none',
2239
+ cursor: historyIndex >= history.length - 1 ? 'not-allowed' : 'pointer'
2240
+ }}
1963
2241
  >
1964
2242
  <i className={styles.redo} />
1965
2243
  </button>
@@ -2686,6 +2964,7 @@ const Editor = ({
2686
2964
  className={styles.editorContent}
2687
2965
  contentEditable
2688
2966
  onInput={handleInput}
2967
+ onPaste={handlePaste}
2689
2968
  onClick={handleEditorClick}
2690
2969
  onKeyUp={() => {
2691
2970
  detectCurrentParagraphStyle();
package/react.ts CHANGED
@@ -1,15 +1,17 @@
1
1
  import Input from './react/atom/input';
2
2
  import Textarea from './react/atom/textarea';
3
3
  import Editor from './react/atom/editor';
4
- import Pagination from './react/atom/pagination';
4
+ import EditorView from './react/atom/editor-view';
5
+ import Pagination from './react/molecule/pagination';
5
6
  import Field from './react/molecule/field';
6
7
  const Form = {
7
8
  Input,
8
9
  Textarea,
9
10
  Editor,
11
+ EditorView,
10
12
  Field,
11
13
  };
12
14
 
13
15
  export default Form;
14
16
 
15
- export { Input, Textarea, Editor, Pagination, Field };
17
+ export { Input, Textarea, Editor, EditorView, Pagination, Field };
File without changes
File without changes