vzcode 0.84.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/{index-J8-kRnnE.css → index-9yhZQKtK.css} +1 -1
- package/dist/assets/{index-9InCi-kT.js → index-DzsReLik.js} +53 -54
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/src/client/CodeEditor/InteractiveWidgets/boolToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorPicker.ts +91 -0
- package/src/client/CodeEditor/InteractiveWidgets/colorsInTextPlugin.ts +139 -0
- package/src/client/CodeEditor/InteractiveWidgets/highlightWidgets.ts +79 -0
- package/src/client/CodeEditor/InteractiveWidgets/index.ts +44 -0
- package/src/client/CodeEditor/InteractiveWidgets/markdownCheckboxToggler.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/numberDragger.ts +20 -0
- package/src/client/CodeEditor/InteractiveWidgets/rotateWidget.ts +143 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.test.ts +48 -0
- package/src/client/CodeEditor/InteractiveWidgets/urlClicker.ts +12 -0
- package/src/client/CodeEditor/InteractiveWidgets/vec2Slider.ts +25 -0
- package/src/client/CodeEditor/getOrCreateEditor.ts +4 -3
- package/src/client/VZCodeContext.tsx +36 -0
- package/src/client/VZLeft.tsx +2 -0
- package/src/client/VZSettings.tsx +14 -17
- package/src/client/VZSidebar/CreateDirModal.tsx +99 -0
- package/src/client/VZSidebar/index.tsx +21 -1
- package/src/client/VZSidebar/useDragAndDrop.tsx +29 -18
- package/src/client/useFileCRUD.ts +18 -0
- package/src/server/index.js +8 -2
- package/src/client/CodeEditor/widgets.ts +0 -509
|
@@ -1,509 +0,0 @@
|
|
|
1
|
-
import interact, {
|
|
2
|
-
InteractRule,
|
|
3
|
-
} from '@replit/codemirror-interact';
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
ViewPlugin,
|
|
7
|
-
Decoration,
|
|
8
|
-
WidgetType,
|
|
9
|
-
} from '@codemirror/view';
|
|
10
|
-
import { Extension, RangeSet } from '@codemirror/state';
|
|
11
|
-
import { EditorView } from 'codemirror';
|
|
12
|
-
|
|
13
|
-
// Regular expression for hex colors.
|
|
14
|
-
const colorRegex = /#[0-9A-Fa-f]{6}/g;
|
|
15
|
-
|
|
16
|
-
// Interactive code widgets.
|
|
17
|
-
// * Number dragger
|
|
18
|
-
// * Boolean toggler
|
|
19
|
-
// * URL clicker
|
|
20
|
-
// * color picker
|
|
21
|
-
// Inspired by:
|
|
22
|
-
// https://github.com/replit/codemirror-interact/blob/master/dev/index.ts
|
|
23
|
-
// `onInteract` is called when the user interacts with a widget.
|
|
24
|
-
export const widgets = ({
|
|
25
|
-
onInteract,
|
|
26
|
-
customInteractRules,
|
|
27
|
-
}: {
|
|
28
|
-
onInteract?: () => void;
|
|
29
|
-
customInteractRules?: Array<InteractRule>;
|
|
30
|
-
}) => {
|
|
31
|
-
const rules: Array<InteractRule> = [
|
|
32
|
-
// hex color picker
|
|
33
|
-
// Inspired by https://github.com/replit/codemirror-interact/blob/master/dev/index.ts#L71
|
|
34
|
-
// Works without quotes to support CSS.
|
|
35
|
-
{
|
|
36
|
-
regexp: colorRegex,
|
|
37
|
-
cursor: 'pointer',
|
|
38
|
-
onClick(
|
|
39
|
-
text: string,
|
|
40
|
-
setText: (newText: string) => void,
|
|
41
|
-
) {
|
|
42
|
-
const startingColor: string = text;
|
|
43
|
-
|
|
44
|
-
const sel: HTMLInputElement =
|
|
45
|
-
document.createElement('input');
|
|
46
|
-
sel.type = 'color';
|
|
47
|
-
sel.value = startingColor.toLowerCase();
|
|
48
|
-
|
|
49
|
-
// valueIsUpper maintains the style of the user's code. It keeps the case of a-f the same case as the original.
|
|
50
|
-
const valueIsUpper: boolean =
|
|
51
|
-
startingColor.toUpperCase() === startingColor;
|
|
52
|
-
|
|
53
|
-
const updateHex = (e: Event) => {
|
|
54
|
-
const el: HTMLInputElement =
|
|
55
|
-
e.target as HTMLInputElement;
|
|
56
|
-
if (onInteract) onInteract();
|
|
57
|
-
if (el.value) {
|
|
58
|
-
setText(
|
|
59
|
-
valueIsUpper
|
|
60
|
-
? el.value.toUpperCase()
|
|
61
|
-
: el.value,
|
|
62
|
-
);
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
sel.addEventListener('input', updateHex);
|
|
66
|
-
sel.click();
|
|
67
|
-
},
|
|
68
|
-
},
|
|
69
|
-
|
|
70
|
-
// a rule for a number dragger
|
|
71
|
-
{
|
|
72
|
-
// the regexp matching the value
|
|
73
|
-
regexp: /(?<!\#)-?\b\d+\.?\d*\b/g,
|
|
74
|
-
// set cursor to "ew-resize" on hover
|
|
75
|
-
cursor: 'ew-resize',
|
|
76
|
-
// change number value based on mouse X movement on drag
|
|
77
|
-
onDrag: (text, setText, e) => {
|
|
78
|
-
if (onInteract) onInteract();
|
|
79
|
-
const newVal = Number(text) + e.movementX;
|
|
80
|
-
if (isNaN(newVal)) return;
|
|
81
|
-
setText(newVal.toString());
|
|
82
|
-
},
|
|
83
|
-
},
|
|
84
|
-
// bool toggler
|
|
85
|
-
{
|
|
86
|
-
regexp: /true|false/g,
|
|
87
|
-
cursor: 'pointer',
|
|
88
|
-
onClick: (text, setText) => {
|
|
89
|
-
if (onInteract) onInteract();
|
|
90
|
-
switch (text) {
|
|
91
|
-
case 'true':
|
|
92
|
-
return setText('false');
|
|
93
|
-
case 'false':
|
|
94
|
-
return setText('true');
|
|
95
|
-
}
|
|
96
|
-
},
|
|
97
|
-
},
|
|
98
|
-
// vec2 slider
|
|
99
|
-
// Inspired by: https://github.com/replit/codemirror-interact/blob/master/dev/index.ts#L61
|
|
100
|
-
{
|
|
101
|
-
regexp:
|
|
102
|
-
/vec2\(-?\b\d+\.?\d*\b\s*(,\s*-?\b\d+\.?\d*\b)?\)/g,
|
|
103
|
-
cursor: 'move',
|
|
104
|
-
|
|
105
|
-
onDrag: (text, setText, e) => {
|
|
106
|
-
const res =
|
|
107
|
-
/vec2\((?<x>-?\b\d+\.?\d*\b)\s*(,\s*(?<y>-?\b\d+\.?\d*\b))?\)/.exec(
|
|
108
|
-
text,
|
|
109
|
-
);
|
|
110
|
-
const x = Number(res?.groups?.x);
|
|
111
|
-
let y = Number(res?.groups?.y);
|
|
112
|
-
if (isNaN(x)) return;
|
|
113
|
-
if (isNaN(y)) y = x;
|
|
114
|
-
setText(
|
|
115
|
-
`vec2(${x + e.movementX}, ${y - e.movementY})`,
|
|
116
|
-
);
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
// rgb color picker
|
|
120
|
-
// Inspired by https://github.com/replit/codemirror-interact/blob/master/dev/index.ts#L71
|
|
121
|
-
//TODO: create color picker for hsl colors
|
|
122
|
-
{
|
|
123
|
-
regexp: /rgb\(.*\)/g,
|
|
124
|
-
cursor: 'pointer',
|
|
125
|
-
onClick: (text, setText, e) => {
|
|
126
|
-
const res =
|
|
127
|
-
/rgb\((?<r>\d+)\s*,\s*(?<g>\d+)\s*,\s*(?<b>\d+)\)/.exec(
|
|
128
|
-
text,
|
|
129
|
-
);
|
|
130
|
-
const r = Number(res?.groups?.r);
|
|
131
|
-
const g = Number(res?.groups?.g);
|
|
132
|
-
const b = Number(res?.groups?.b);
|
|
133
|
-
|
|
134
|
-
//sel will open the color picker when sel.click is called.
|
|
135
|
-
const sel = document.createElement('input');
|
|
136
|
-
sel.type = 'color';
|
|
137
|
-
|
|
138
|
-
if (!isNaN(r + g + b)) sel.value = rgb2Hex(r, g, b);
|
|
139
|
-
|
|
140
|
-
const updateRGB = (e: Event) => {
|
|
141
|
-
const el = e.target as HTMLInputElement;
|
|
142
|
-
if (onInteract) onInteract();
|
|
143
|
-
|
|
144
|
-
if (el.value) {
|
|
145
|
-
const [r, g, b] = hex2RGB(el.value);
|
|
146
|
-
setText(`rgb(${r}, ${g}, ${b})`);
|
|
147
|
-
}
|
|
148
|
-
sel.removeEventListener('change', updateRGB);
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
sel.addEventListener('change', updateRGB);
|
|
152
|
-
sel.click();
|
|
153
|
-
},
|
|
154
|
-
},
|
|
155
|
-
// url clicker
|
|
156
|
-
{
|
|
157
|
-
regexp: /https?:\/\/[^ ")]+/g,
|
|
158
|
-
cursor: 'pointer',
|
|
159
|
-
onClick: (text) => {
|
|
160
|
-
window.open(text);
|
|
161
|
-
},
|
|
162
|
-
},
|
|
163
|
-
|
|
164
|
-
//Set rotation to the angle between the x-axis and a line from the word "rotate" to the mouse pointer (while dragging).
|
|
165
|
-
//The rotation is in range (-180,180]
|
|
166
|
-
{
|
|
167
|
-
regexp: /rotate\(-?\d*\.?\d*\)/g,
|
|
168
|
-
cursor: 'move',
|
|
169
|
-
onDragStart(text, setText, e) {
|
|
170
|
-
rotationOrigin = { x: e.clientX, y: e.clientY };
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
onDrag(text, setText, e) {
|
|
174
|
-
if (rotationOrigin == null) return;
|
|
175
|
-
const rotationDegree = Math.round(
|
|
176
|
-
(Math.atan2(
|
|
177
|
-
rotationOrigin.y - e.clientY,
|
|
178
|
-
e.clientX - rotationOrigin.x,
|
|
179
|
-
) *
|
|
180
|
-
180) /
|
|
181
|
-
Math.PI,
|
|
182
|
-
);
|
|
183
|
-
//Calculate the angle between the x axis and a line from where the user first clicks to the current location of the mouse.
|
|
184
|
-
setText(`rotate(${rotationDegree})`);
|
|
185
|
-
const updateDragEvent = new CustomEvent(
|
|
186
|
-
'updateRotateDrag',
|
|
187
|
-
{ detail: rotationDegree },
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
document.dispatchEvent(updateDragEvent);
|
|
191
|
-
},
|
|
192
|
-
onDragEnd() {
|
|
193
|
-
rotationOrigin = null;
|
|
194
|
-
},
|
|
195
|
-
},
|
|
196
|
-
];
|
|
197
|
-
if (customInteractRules) {
|
|
198
|
-
rules.push(...customInteractRules);
|
|
199
|
-
}
|
|
200
|
-
return interact({ rules });
|
|
201
|
-
};
|
|
202
|
-
|
|
203
|
-
let rotationOrigin: { x: number; y: number } = null;
|
|
204
|
-
|
|
205
|
-
// Inspired by https://github.com/replit/codemirror-interact/blob/master/dev/index.ts#L108
|
|
206
|
-
const hex2RGB = (hex: string): [number, number, number] => {
|
|
207
|
-
const v = parseInt(hex.substring(1), 16);
|
|
208
|
-
return [(v >> 16) & 255, (v >> 8) & 255, v & 255];
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
// Inspired by https://github.com/replit/codemirror-interact/blob/master/dev/index.ts#L117
|
|
212
|
-
const rgb2Hex = (r: number, g: number, b: number): string =>
|
|
213
|
-
'#' + r.toString(16) + g.toString(16) + b.toString(16);
|
|
214
|
-
|
|
215
|
-
const colorCircleTheme = EditorView.baseTheme({
|
|
216
|
-
'.color-circle-parent': {
|
|
217
|
-
display: 'inline-block',
|
|
218
|
-
cursor: 'inherit',
|
|
219
|
-
},
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
export const colorsInTextPlugin: Extension = [
|
|
223
|
-
ViewPlugin.fromClass(
|
|
224
|
-
class {
|
|
225
|
-
decorations: any;
|
|
226
|
-
view: EditorView;
|
|
227
|
-
constructor(view: EditorView) {
|
|
228
|
-
this.decorations = RangeSet.of([]);
|
|
229
|
-
this.view = view;
|
|
230
|
-
}
|
|
231
|
-
},
|
|
232
|
-
{
|
|
233
|
-
decorations: (v) => {
|
|
234
|
-
const colorInfos = [];
|
|
235
|
-
|
|
236
|
-
const lines = v.view.state.doc.iter();
|
|
237
|
-
let line = lines.next();
|
|
238
|
-
|
|
239
|
-
// Offset is the number of characters before the hex
|
|
240
|
-
// so the circle can be placed properly.
|
|
241
|
-
let offset = 0;
|
|
242
|
-
while (!line.done) {
|
|
243
|
-
if (line.value === '\n') {
|
|
244
|
-
offset++;
|
|
245
|
-
line = lines.next();
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
const hexColorOccurences = line.value.matchAll(
|
|
249
|
-
// /\"\#([0-9]|[A-F]|[a-f]){6}\"/g,
|
|
250
|
-
// /["']\#([0-9]|[A-F]|[a-f]){6}["']/g,
|
|
251
|
-
colorRegex,
|
|
252
|
-
);
|
|
253
|
-
let hexOccurance = hexColorOccurences.next();
|
|
254
|
-
while (!hexOccurance.done) {
|
|
255
|
-
const offsetColorInfo = hexOccurance.value;
|
|
256
|
-
offsetColorInfo.index += offset;
|
|
257
|
-
colorInfos.push(offsetColorInfo);
|
|
258
|
-
hexOccurance = hexColorOccurences.next();
|
|
259
|
-
}
|
|
260
|
-
offset += line.value.length;
|
|
261
|
-
line = lines.next();
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
return Decoration.set(
|
|
265
|
-
colorInfos.map((colorInfo) => {
|
|
266
|
-
return {
|
|
267
|
-
// 7 is the length of the hex color string
|
|
268
|
-
from: colorInfo.index + 7,
|
|
269
|
-
to: colorInfo.index + 7,
|
|
270
|
-
value: Decoration.widget({
|
|
271
|
-
side: -1,
|
|
272
|
-
widget: new ColorWidget(colorInfo[0]),
|
|
273
|
-
}),
|
|
274
|
-
};
|
|
275
|
-
}),
|
|
276
|
-
);
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
|
-
),
|
|
280
|
-
colorCircleTheme,
|
|
281
|
-
];
|
|
282
|
-
|
|
283
|
-
class ColorWidget extends WidgetType {
|
|
284
|
-
color: string;
|
|
285
|
-
constructor(color: string) {
|
|
286
|
-
super();
|
|
287
|
-
this.color = color;
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
eq(widget: ColorWidget): boolean {
|
|
291
|
-
// TODO consider possibly adding a random ID to support multiple instances with the same color
|
|
292
|
-
return widget.color === this.color;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
toDOM(): HTMLElement {
|
|
296
|
-
const parent = document.createElement('div');
|
|
297
|
-
const size = 20;
|
|
298
|
-
const innerSize = 14;
|
|
299
|
-
|
|
300
|
-
parent.setAttribute(
|
|
301
|
-
'style',
|
|
302
|
-
`width:${size}px;height:${size}px`,
|
|
303
|
-
);
|
|
304
|
-
parent.className = 'color-circle-parent';
|
|
305
|
-
const svg = document.createElementNS(
|
|
306
|
-
'http://www.w3.org/2000/svg',
|
|
307
|
-
'svg',
|
|
308
|
-
);
|
|
309
|
-
const colorCircle = document.createElementNS(
|
|
310
|
-
'http://www.w3.org/2000/svg',
|
|
311
|
-
'circle',
|
|
312
|
-
);
|
|
313
|
-
colorCircle.setAttributeNS(
|
|
314
|
-
null,
|
|
315
|
-
'fill',
|
|
316
|
-
this.color.replace(/["']/g, ''),
|
|
317
|
-
);
|
|
318
|
-
// colorCircle.setAttributeNS(null, 'stroke', 'black');
|
|
319
|
-
colorCircle.setAttributeNS(
|
|
320
|
-
null,
|
|
321
|
-
'r',
|
|
322
|
-
'' + innerSize / 2,
|
|
323
|
-
);
|
|
324
|
-
colorCircle.setAttributeNS(null, 'cx', '' + size / 2);
|
|
325
|
-
colorCircle.setAttributeNS(
|
|
326
|
-
null,
|
|
327
|
-
'cy',
|
|
328
|
-
'' + (size / 2 - 1),
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
svg.setAttributeNS(null, 'width', '' + size);
|
|
332
|
-
svg.setAttributeNS(null, 'height', '' + size);
|
|
333
|
-
|
|
334
|
-
svg.appendChild(colorCircle);
|
|
335
|
-
|
|
336
|
-
parent.appendChild(svg);
|
|
337
|
-
return parent;
|
|
338
|
-
}
|
|
339
|
-
ignoreEvent() {
|
|
340
|
-
return false;
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export const highlightWidgets = ViewPlugin.fromClass(
|
|
345
|
-
class {
|
|
346
|
-
showHighlight: boolean;
|
|
347
|
-
view: EditorView;
|
|
348
|
-
constructor(view: EditorView) {
|
|
349
|
-
this.showHighlight = false;
|
|
350
|
-
this.view = view;
|
|
351
|
-
}
|
|
352
|
-
},
|
|
353
|
-
{
|
|
354
|
-
decorations: (v) => {
|
|
355
|
-
if (!v.showHighlight) {
|
|
356
|
-
return Decoration.none;
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const interactOpportunities = [];
|
|
360
|
-
const lines = v.view.state.doc.iter();
|
|
361
|
-
let line = lines.next();
|
|
362
|
-
|
|
363
|
-
//Offset is the number of characters before the regex so the highlighting can be placed properly.
|
|
364
|
-
let offset = 0;
|
|
365
|
-
while (!line.done) {
|
|
366
|
-
if (line.value === '\n') {
|
|
367
|
-
offset++;
|
|
368
|
-
line = lines.next();
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
const interactiveOccurances = line.value.matchAll(
|
|
372
|
-
//The below line contains all of the Regexes for all of the interactive widgets.
|
|
373
|
-
/\"\#([0-9]|[A-F]|[a-f]){6}\"|rotate\(-?\d*\.?\d*\)|https?:\/\/[^ "]+|vec2\(-?\b\d+\.?\d*\b\s*(,\s*-?\b\d+\.?\d*\b)?\)|true|false|(?<!\#)-?\b\d+\.?\d*\b|rgb\(.*\)/dg,
|
|
374
|
-
);
|
|
375
|
-
let interactOccurance =
|
|
376
|
-
interactiveOccurances.next();
|
|
377
|
-
while (!interactOccurance.done) {
|
|
378
|
-
const offsetInteract = interactOccurance.value;
|
|
379
|
-
offsetInteract.indices[0][0] += offset;
|
|
380
|
-
offsetInteract.indices[0][1] += offset;
|
|
381
|
-
interactOpportunities.push(offsetInteract);
|
|
382
|
-
interactOccurance = interactiveOccurances.next();
|
|
383
|
-
}
|
|
384
|
-
offset += line.value.length;
|
|
385
|
-
line = lines.next();
|
|
386
|
-
}
|
|
387
|
-
return Decoration.set(
|
|
388
|
-
interactOpportunities.map((opportunity) => {
|
|
389
|
-
return {
|
|
390
|
-
from: opportunity.indices[0][0],
|
|
391
|
-
to: opportunity.indices[0][1],
|
|
392
|
-
value: Decoration.mark({
|
|
393
|
-
class: 'cm-interact ',
|
|
394
|
-
}),
|
|
395
|
-
};
|
|
396
|
-
}),
|
|
397
|
-
);
|
|
398
|
-
},
|
|
399
|
-
eventHandlers: {
|
|
400
|
-
keydown(event, view) {
|
|
401
|
-
if (event.key == 'Alt') {
|
|
402
|
-
this.showHighlight = true;
|
|
403
|
-
}
|
|
404
|
-
},
|
|
405
|
-
keyup(event, view) {
|
|
406
|
-
if (event.key == 'Alt') {
|
|
407
|
-
this.showHighlight = false;
|
|
408
|
-
}
|
|
409
|
-
},
|
|
410
|
-
},
|
|
411
|
-
},
|
|
412
|
-
);
|
|
413
|
-
|
|
414
|
-
export const rotationIndicator = ViewPlugin.fromClass(
|
|
415
|
-
class {
|
|
416
|
-
view: EditorView;
|
|
417
|
-
textPosition?: number;
|
|
418
|
-
rotation: number;
|
|
419
|
-
constructor(view) {
|
|
420
|
-
this.view = view;
|
|
421
|
-
this.textPosition = null;
|
|
422
|
-
this.rotation = 0;
|
|
423
|
-
|
|
424
|
-
document.addEventListener(
|
|
425
|
-
'updateRotateDrag',
|
|
426
|
-
(e: CustomEvent) => {
|
|
427
|
-
this.textPosition = this.view.posAtCoords(
|
|
428
|
-
rotationOrigin,
|
|
429
|
-
false,
|
|
430
|
-
);
|
|
431
|
-
|
|
432
|
-
this.rotation = e.detail;
|
|
433
|
-
},
|
|
434
|
-
);
|
|
435
|
-
}
|
|
436
|
-
},
|
|
437
|
-
{
|
|
438
|
-
decorations: (v) => {
|
|
439
|
-
if (rotationOrigin === null) {
|
|
440
|
-
return Decoration.none;
|
|
441
|
-
}
|
|
442
|
-
return Decoration.set([
|
|
443
|
-
{
|
|
444
|
-
from: v.textPosition,
|
|
445
|
-
to: v.textPosition,
|
|
446
|
-
value: Decoration.widget({
|
|
447
|
-
side: -1,
|
|
448
|
-
widget: new RotationCircle(v.rotation),
|
|
449
|
-
}),
|
|
450
|
-
},
|
|
451
|
-
]);
|
|
452
|
-
},
|
|
453
|
-
},
|
|
454
|
-
);
|
|
455
|
-
|
|
456
|
-
class RotationCircle extends WidgetType {
|
|
457
|
-
angle: number;
|
|
458
|
-
constructor(angle: number) {
|
|
459
|
-
super();
|
|
460
|
-
this.angle = angle;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
toDOM(view: EditorView): HTMLElement {
|
|
464
|
-
const parent = document.createElement('div');
|
|
465
|
-
|
|
466
|
-
parent.setAttribute('style', 'width:20px;height:20px');
|
|
467
|
-
parent.className = 'color-circle-parent';
|
|
468
|
-
const svg = document.createElementNS(
|
|
469
|
-
'http://www.w3.org/2000/svg',
|
|
470
|
-
'svg',
|
|
471
|
-
);
|
|
472
|
-
const colorCircle = document.createElementNS(
|
|
473
|
-
'http://www.w3.org/2000/svg',
|
|
474
|
-
'circle',
|
|
475
|
-
);
|
|
476
|
-
colorCircle.setAttributeNS(null, 'fill', '#808080');
|
|
477
|
-
colorCircle.setAttributeNS(null, 'r', '5');
|
|
478
|
-
colorCircle.setAttributeNS(null, 'cx', '5');
|
|
479
|
-
colorCircle.setAttributeNS(null, 'cy', '5');
|
|
480
|
-
|
|
481
|
-
const indicatorLine = document.createElementNS(
|
|
482
|
-
'http://www.w3.org/2000/svg',
|
|
483
|
-
'line',
|
|
484
|
-
);
|
|
485
|
-
indicatorLine.setAttributeNS(null, 'x1', '10');
|
|
486
|
-
indicatorLine.setAttributeNS(null, 'x2', '5');
|
|
487
|
-
indicatorLine.setAttributeNS(null, 'y1', '5');
|
|
488
|
-
indicatorLine.setAttributeNS(null, 'y2', '5');
|
|
489
|
-
indicatorLine.setAttributeNS(null, 'stroke', 'black');
|
|
490
|
-
indicatorLine.setAttributeNS(
|
|
491
|
-
null,
|
|
492
|
-
'transform',
|
|
493
|
-
`rotate(${360 - this.angle},5,5)`,
|
|
494
|
-
);
|
|
495
|
-
|
|
496
|
-
svg.setAttributeNS(null, 'viewBox', '0 0 10 10');
|
|
497
|
-
svg.setAttributeNS(null, 'width', '20');
|
|
498
|
-
svg.setAttributeNS(null, 'height', '20');
|
|
499
|
-
|
|
500
|
-
svg.appendChild(colorCircle);
|
|
501
|
-
svg.appendChild(indicatorLine);
|
|
502
|
-
|
|
503
|
-
parent.appendChild(svg);
|
|
504
|
-
return parent;
|
|
505
|
-
}
|
|
506
|
-
ignoreEvent() {
|
|
507
|
-
return false;
|
|
508
|
-
}
|
|
509
|
-
}
|