@bagelink/vue 0.0.988 → 0.0.992
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/components/Btn.vue.d.ts.map +1 -1
- package/dist/components/Loading.vue.d.ts +16 -0
- package/dist/components/Loading.vue.d.ts.map +1 -0
- package/dist/components/form/BglField.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts +12 -57
- package/dist/components/form/inputs/CodeEditor/Index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/FileUpload.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/components/gridBox.vue.d.ts +3 -7
- package/dist/components/form/inputs/RichText/components/gridBox.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/composables/useEditor.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/index.vue.d.ts.map +1 -1
- package/dist/components/form/inputs/RichText/utils/table.d.ts +2 -1
- package/dist/components/form/inputs/RichText/utils/table.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/layout/TabsNav.vue.d.ts.map +1 -1
- package/dist/editor-a8DSbb6P.js +4 -0
- package/dist/editor-xBt_vIha.cjs +4 -0
- package/dist/index.cjs +10289 -48576
- package/dist/index.mjs +10290 -48577
- package/dist/style.css +815 -20218
- package/package.json +6 -34
- package/src/components/Btn.vue +110 -136
- package/src/components/Loading.vue +177 -0
- package/src/components/form/BglField.vue +2 -0
- package/src/components/form/inputs/CodeEditor/Index.vue +77 -400
- package/src/components/form/inputs/CodeEditor/format.ts +2 -2
- package/src/components/form/inputs/FileUpload.vue +2 -1
- package/src/components/form/inputs/RichText/components/gridBox.vue +37 -8
- package/src/components/form/inputs/RichText/composables/useEditor.ts +11 -4
- package/src/components/form/inputs/RichText/config.ts +1 -1
- package/src/components/form/inputs/RichText/editor.css +14 -14
- package/src/components/form/inputs/RichText/index.vue +11 -10
- package/src/components/form/inputs/RichText/utils/table.ts +60 -58
- package/src/components/index.ts +2 -2
- package/src/components/layout/TabsNav.vue +1 -0
- package/src/styles/theme.css +256 -256
- package/src/components/form/inputs/CodeEditor/themes/brown-papersq.png +0 -0
- package/src/components/form/inputs/CodeEditor/themes/pojoaque.jpg +0 -0
- package/src/components/form/inputs/CodeEditor/themes/themes-base16.css +0 -12809
- package/src/components/form/inputs/CodeEditor/themes/themes.css +0 -6740
- package/src/components/formkit/FileUploader.vue +0 -406
- package/src/components/formkit/MiscFields.vue +0 -74
- package/src/components/formkit/Toggle.vue +0 -149
|
@@ -1,440 +1,117 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const {
|
|
12
|
-
showLineNumbers = false,
|
|
13
|
-
modelValue = '',
|
|
14
|
-
theme = 'github-dark',
|
|
15
|
-
tabSpaces = 2,
|
|
16
|
-
wrap = true,
|
|
17
|
-
readOnly = false,
|
|
18
|
-
autofocus = false,
|
|
19
|
-
header = true,
|
|
20
|
-
width = '400px',
|
|
21
|
-
height = '600px',
|
|
22
|
-
maxWidth,
|
|
23
|
-
minWidth,
|
|
24
|
-
maxHeight,
|
|
25
|
-
minHeight,
|
|
26
|
-
borderRadius = '12px',
|
|
27
|
-
languages = ['javascript'],
|
|
28
|
-
displayLanguage = true,
|
|
29
|
-
copyCode = true,
|
|
30
|
-
fontSize = '17px',
|
|
31
|
-
padding = '20px'
|
|
32
|
-
} = defineProps<{
|
|
33
|
-
showLineNumbers?: boolean
|
|
34
|
-
modelValue?: string
|
|
35
|
-
theme?: CodeTheme
|
|
36
|
-
tabSpaces?: number
|
|
37
|
-
wrap?: boolean
|
|
38
|
-
readOnly?: boolean
|
|
39
|
-
autofocus?: boolean
|
|
40
|
-
header?: boolean
|
|
41
|
-
width?: string
|
|
42
|
-
height?: string
|
|
43
|
-
maxWidth?: string
|
|
44
|
-
minWidth?: string
|
|
45
|
-
maxHeight?: string
|
|
46
|
-
minHeight?: string
|
|
47
|
-
borderRadius?: string
|
|
48
|
-
languages?: Language[]
|
|
49
|
-
displayLanguage?: boolean
|
|
50
|
-
copyCode?: boolean
|
|
51
|
-
fontSize?: string
|
|
52
|
-
padding?: string
|
|
2
|
+
import hljsVuePlugin from '@highlightjs/vue-plugin'
|
|
3
|
+
import { nextTick } from 'vue'
|
|
4
|
+
import 'highlight.js/lib/common'
|
|
5
|
+
import 'highlight.js/styles/atom-one-dark.css'
|
|
6
|
+
|
|
7
|
+
const { readonly = false, language } = defineProps<{
|
|
8
|
+
language?: string
|
|
9
|
+
readonly?: boolean
|
|
53
10
|
}>()
|
|
54
11
|
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
let top = $ref(0)
|
|
60
|
-
let left = $ref(0)
|
|
61
|
-
let currentLanguage = $ref(languages[0])
|
|
62
|
-
let content = $ref(formatCode(modelValue, currentLanguage))
|
|
63
|
-
let cursorPosition = $ref(0)
|
|
64
|
-
let insertTab = $ref(false)
|
|
65
|
-
let lineNum = $ref(0)
|
|
66
|
-
let lineNumsWidth = $ref(0)
|
|
67
|
-
let scrolling = $ref(false)
|
|
68
|
-
let textareaHeight = $ref(0)
|
|
69
|
-
const langListHeight = $ref('200px') // Define langListHeight with a default value
|
|
70
|
-
|
|
71
|
-
const textarea = $ref<HTMLTextAreaElement>()
|
|
72
|
-
const code = $ref<HTMLElement>()
|
|
73
|
-
const lineNums = $ref<HTMLElement>()
|
|
74
|
-
|
|
75
|
-
const languageClass = $computed(() => `hljs language-${currentLanguage}`)
|
|
76
|
-
const languageTitle = $computed(() => codeLanguages[currentLanguage as Language])
|
|
77
|
-
const tabWidth = $computed(() => ' '.repeat(tabSpaces))
|
|
78
|
-
const scroll = $computed(() => height !== 'auto')
|
|
79
|
-
|
|
80
|
-
const showLineNums = $computed(() => showLineNumbers || wrap)
|
|
81
|
-
|
|
82
|
-
const autoClosePairs = {
|
|
83
|
-
'(': ')',
|
|
84
|
-
'[': ']',
|
|
85
|
-
'{': '}',
|
|
86
|
-
'"': '"',
|
|
87
|
-
'\'': '\'',
|
|
88
|
-
'`': '`'
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function updateValue(e: Event) {
|
|
92
|
-
const target = e.target as HTMLTextAreaElement
|
|
93
|
-
const char = target.value[target.selectionStart - 1]
|
|
12
|
+
const code = defineModel('modelValue', {
|
|
13
|
+
type: String,
|
|
14
|
+
default: ''
|
|
15
|
+
})
|
|
94
16
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
const cursorPos = target.selectionStart
|
|
103
|
-
content = target.value
|
|
104
|
-
emit('update:modelValue', content)
|
|
17
|
+
function tabKeyDown(event: KeyboardEvent) {
|
|
18
|
+
const target = event.target as HTMLTextAreaElement
|
|
19
|
+
const start = target.selectionStart
|
|
20
|
+
const end = target.selectionEnd
|
|
21
|
+
const tab = ' '
|
|
22
|
+
code.value = code.value.slice(0, start) + tab + code.value.slice(end)
|
|
105
23
|
nextTick(() => {
|
|
106
|
-
target.
|
|
107
|
-
})
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
function changeLang(lang: Language) {
|
|
111
|
-
currentLanguage = lang
|
|
112
|
-
emit('lang', lang)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
function tab() {
|
|
116
|
-
if (document.execCommand('insertText')) {
|
|
117
|
-
document.execCommand('insertText', false, tabWidth)
|
|
118
|
-
} else {
|
|
119
|
-
const cursorPos = textarea?.selectionStart ?? 0
|
|
120
|
-
content
|
|
121
|
-
= content.substring(0, cursorPos) + tabWidth + content.substring(cursorPos)
|
|
122
|
-
cursorPosition = cursorPos + tabWidth.length
|
|
123
|
-
insertTab = true
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function calcScrollDistance(e: Event) {
|
|
128
|
-
const target = e.target as HTMLTextAreaElement
|
|
129
|
-
code?.setAttribute('scrolling', 'true')
|
|
130
|
-
scrolling = true
|
|
131
|
-
top = -target.scrollTop
|
|
132
|
-
left = -target.scrollLeft
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function resizer() {
|
|
136
|
-
const textareaResizer = new ResizeObserver((entries) => {
|
|
137
|
-
const target = entries[0].target as HTMLElement
|
|
138
|
-
scrollBarWidth = target.offsetWidth - target.clientWidth
|
|
139
|
-
scrollBarHeight = target.offsetHeight - target.clientHeight
|
|
140
|
-
textareaHeight = target.offsetHeight
|
|
141
|
-
})
|
|
142
|
-
if (textarea) {
|
|
143
|
-
textareaResizer.observe(textarea)
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const lineNumsResizer = new ResizeObserver((entries) => {
|
|
147
|
-
lineNumsWidth = (entries[0].target as HTMLElement).offsetWidth
|
|
24
|
+
target.selectionStart = target.selectionEnd = start + 2
|
|
148
25
|
})
|
|
149
|
-
if (lineNums) {
|
|
150
|
-
lineNumsResizer.observe(lineNums)
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function getLineNum() {
|
|
155
|
-
const str = textarea!.value
|
|
156
|
-
let lineNumCount = 0
|
|
157
|
-
let position = str.indexOf('\n')
|
|
158
|
-
while (position !== -1) {
|
|
159
|
-
lineNumCount++
|
|
160
|
-
position = str.indexOf('\n', position + 1)
|
|
161
|
-
}
|
|
162
|
-
const firstChild = lineNums!.firstChild as HTMLElement
|
|
163
|
-
const singleLineHeight = firstChild!.offsetHeight
|
|
164
|
-
const heightNum = Math.floor(textareaHeight / singleLineHeight) - 1
|
|
165
|
-
lineNum = height === 'auto' ? lineNumCount : Math.max(lineNumCount, heightNum)
|
|
166
26
|
}
|
|
167
27
|
|
|
168
|
-
|
|
169
|
-
if (newVal !== undefined) {
|
|
170
|
-
content = newVal
|
|
171
|
-
}
|
|
172
|
-
})
|
|
173
|
-
|
|
174
|
-
onMounted(() => {
|
|
175
|
-
emit('lang', languages[0])
|
|
176
|
-
emit('content', content)
|
|
177
|
-
emit('textarea', textarea)
|
|
178
|
-
resizer()
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
watch(() => insertTab, (newVal) => {
|
|
182
|
-
if (newVal) {
|
|
183
|
-
textarea!.setSelectionRange(cursorPosition, cursorPosition)
|
|
184
|
-
insertTab = false
|
|
185
|
-
}
|
|
186
|
-
})
|
|
187
|
-
|
|
188
|
-
watch(() => showLineNumbers, (newVal) => {
|
|
189
|
-
if (newVal) {
|
|
190
|
-
if (scrolling) scrolling = false
|
|
191
|
-
else getLineNum()
|
|
192
|
-
}
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
const highlight: Directive = {
|
|
196
|
-
mounted(el, binding) {
|
|
197
|
-
el.textContent = binding
|
|
198
|
-
hljs.highlightElement(el)
|
|
199
|
-
},
|
|
200
|
-
updated(el, binding) {
|
|
201
|
-
if (el.getAttribute('data-scrolling') === 'true') {
|
|
202
|
-
el.setAttribute('data-scrolling', 'false')
|
|
203
|
-
} else {
|
|
204
|
-
el.textContent = binding
|
|
205
|
-
hljs.highlightElement(el)
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
defineExpose({ highlight })
|
|
28
|
+
const Highlightjs = hljsVuePlugin.component
|
|
211
29
|
</script>
|
|
212
30
|
|
|
213
31
|
<template>
|
|
214
|
-
<div
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
'scroll': scroll,
|
|
218
|
-
'read-only': readOnly,
|
|
219
|
-
'wrap': wrap,
|
|
220
|
-
}" :style="{
|
|
221
|
-
width,
|
|
222
|
-
height,
|
|
223
|
-
maxWidth,
|
|
224
|
-
minWidth,
|
|
225
|
-
maxHeight,
|
|
226
|
-
minHeight,
|
|
227
|
-
}"
|
|
228
|
-
>
|
|
229
|
-
<div class="hljs" :style="{ borderRadius }">
|
|
230
|
-
<div
|
|
231
|
-
v-if="header" class="p-025 flex space-between" :class="{ border: showLineNums }"
|
|
232
|
-
:style="{ borderRadius: `${borderRadius} ${borderRadius} 0 0` }"
|
|
233
|
-
>
|
|
234
|
-
<Dropdown v-if="displayLanguage" :value="languageTitle" flat thin :disabled="languages.length <= 1">
|
|
235
|
-
<ul class="lang-list hljs" :style="{ height: langListHeight }">
|
|
236
|
-
<li v-for="(lang, index) in languages" :key="index" @click="changeLang(lang)">
|
|
237
|
-
{{ codeLanguages[lang] }}
|
|
238
|
-
</li>
|
|
239
|
-
</ul>
|
|
240
|
-
</Dropdown>
|
|
241
|
-
<Btn v-if="copyCode" v-tooltip.left="'Copy'" class="color-white" flat thin icon="content_copy" @click="copyText(content)" />
|
|
242
|
-
</div>
|
|
243
|
-
<div class="code-area" :style="{ borderRadius: header ? `0 0 ${borderRadius} ${borderRadius}` : borderRadius }">
|
|
32
|
+
<div style="max-height: 900px; height: 100vh; overflow: scroll;">
|
|
33
|
+
<div class="relative block h-100 ltr code-editor-wrap" style="height: 800px;">
|
|
34
|
+
<div class="numbers absolute inset-0 py-1 px-05 txt16 line-height-15 overflow-hidden z-999 w50px txt-start opacity-3 color-gray">
|
|
244
35
|
<div
|
|
245
|
-
v-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
paddingBottom: padding,
|
|
249
|
-
top: `${top}px`,
|
|
250
|
-
}"
|
|
36
|
+
v-for="(_, index) in code.split('\n')"
|
|
37
|
+
:key="index"
|
|
38
|
+
class="number txt-end"
|
|
251
39
|
>
|
|
252
|
-
|
|
253
|
-
<div v-for="num in lineNum" :key="num">
|
|
254
|
-
{{ num + 1 }}
|
|
255
|
-
</div>
|
|
256
|
-
<div> </div>
|
|
40
|
+
{{ index + 1 }}
|
|
257
41
|
</div>
|
|
258
|
-
<textarea
|
|
259
|
-
ref="textarea" title="textarea" :readOnly="readOnly" :style="{
|
|
260
|
-
fontSize,
|
|
261
|
-
padding: !header ? padding : lineNums ? `10px ${padding} ${padding}` : `0 ${padding} ${padding}`,
|
|
262
|
-
marginLeft: showLineNums ? `${lineNumsWidth}px` : '0',
|
|
263
|
-
width: showLineNums ? `calc(100% - ${lineNumsWidth}px)` : '100%',
|
|
264
|
-
}" :autofocus="autofocus" spellcheck="false" :value="content"
|
|
265
|
-
@keydown.tab.prevent.stop="tab" @scroll="calcScrollDistance" @input="updateValue"
|
|
266
|
-
/>
|
|
267
|
-
<pre
|
|
268
|
-
:style="{
|
|
269
|
-
paddingRight: `${scrollBarWidth}px`,
|
|
270
|
-
paddingBottom: `${scrollBarHeight}px`,
|
|
271
|
-
marginLeft: showLineNums ? `${lineNumsWidth}px` : '0',
|
|
272
|
-
width: showLineNums ? `calc(100% - ${lineNumsWidth}px)` : '100%',
|
|
273
|
-
}"
|
|
274
|
-
>
|
|
275
|
-
<code
|
|
276
|
-
ref="code"
|
|
277
|
-
:innerHTML="hljs.highlight(content, { language: currentLanguage }).value"
|
|
278
|
-
:class="languageClass"
|
|
279
|
-
:style="{
|
|
280
|
-
top: `${top}px`,
|
|
281
|
-
left: `${left}px`,
|
|
282
|
-
fontSize,
|
|
283
|
-
padding: !header ? padding : lineNums ? `10px ${padding} ${padding}` : `0 ${padding} ${padding}`,
|
|
284
|
-
}"
|
|
285
|
-
/>
|
|
286
|
-
</pre>
|
|
287
42
|
</div>
|
|
43
|
+
<Highlightjs
|
|
44
|
+
class="highlighted-code absolute inset-0"
|
|
45
|
+
:autodetect="!language"
|
|
46
|
+
:code="code"
|
|
47
|
+
:wrap="true"
|
|
48
|
+
:language="language"
|
|
49
|
+
/>
|
|
50
|
+
<textarea
|
|
51
|
+
v-if="!readonly"
|
|
52
|
+
v-model="code"
|
|
53
|
+
:spellcheck="false"
|
|
54
|
+
class="code-editor absolute inset-0 overflow-hidden bg-transparent line-height-15 border-none m-0"
|
|
55
|
+
placeholder="Write your code here"
|
|
56
|
+
aria-label="Code Editor"
|
|
57
|
+
data-gramm="false"
|
|
58
|
+
@keydown.tab.prevent="tabKeyDown"
|
|
59
|
+
/>
|
|
288
60
|
</div>
|
|
289
61
|
</div>
|
|
290
62
|
</template>
|
|
291
63
|
|
|
292
64
|
<style>
|
|
293
|
-
.code-editor
|
|
294
|
-
|
|
65
|
+
.code-editor-wrap{
|
|
66
|
+
background: #282c34;
|
|
67
|
+
overflow: scroll;
|
|
295
68
|
}
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
height: 100%;
|
|
69
|
+
.numbers {
|
|
70
|
+
font-family: monospace;
|
|
71
|
+
border-inline-end: 1px solid var(--bgl-gray);
|
|
300
72
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
position: relative;
|
|
304
|
-
z-index: 0;
|
|
305
|
-
text-align: left;
|
|
306
|
-
overflow: hidden;
|
|
73
|
+
.number{
|
|
74
|
+
scale: 0.9;
|
|
307
75
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
76
|
+
/* Highlight.js styles */
|
|
77
|
+
.highlighted-code {
|
|
78
|
+
white-space: pre-wrap;
|
|
79
|
+
word-wrap: break-word;
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
margin: 0;
|
|
82
|
+
padding: 0;
|
|
315
83
|
}
|
|
316
84
|
|
|
317
|
-
.code
|
|
318
|
-
|
|
85
|
+
.highlighted-code code {
|
|
86
|
+
padding-left: 70px !important;
|
|
87
|
+
overflow: hidden !important;
|
|
319
88
|
}
|
|
320
89
|
|
|
321
|
-
/* Textarea
|
|
322
|
-
.code-editor
|
|
323
|
-
|
|
324
|
-
z-index: 1;
|
|
325
|
-
inset: 0;
|
|
326
|
-
box-sizing: border-box;
|
|
327
|
-
caret-color: rgb(127, 127, 127);
|
|
90
|
+
/* Textarea aligned with Highlight.js */
|
|
91
|
+
.code-editor {
|
|
92
|
+
font-family: monospace;
|
|
328
93
|
color: transparent;
|
|
329
|
-
white-space: pre;
|
|
330
|
-
word-wrap: normal;
|
|
331
|
-
border: 0;
|
|
332
|
-
width: 100%;
|
|
333
|
-
height: 100%;
|
|
334
|
-
background: none;
|
|
335
94
|
resize: none;
|
|
336
|
-
outline: none;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
/* Pre and code styles */
|
|
340
|
-
.code-editor .code-area>pre {
|
|
341
|
-
box-sizing: border-box;
|
|
342
|
-
position: relative;
|
|
343
|
-
margin: 0;
|
|
344
|
-
font-size: 0;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
.code-editor .code-area>pre>code {
|
|
348
|
-
display: block;
|
|
349
|
-
position: relative;
|
|
350
|
-
overflow-x: visible !important;
|
|
351
|
-
background: none;
|
|
352
|
-
margin: 0;
|
|
353
|
-
box-sizing: border-box;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
/* Wrap styles */
|
|
357
|
-
.code-editor.wrap .code-area>textarea,
|
|
358
|
-
.code-editor.wrap .code-area>pre>code {
|
|
359
95
|
white-space: pre-wrap;
|
|
360
96
|
word-wrap: break-word;
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
.code-editor.scroll .code-area {
|
|
366
|
-
height: calc(100% - 34px);
|
|
367
|
-
}
|
|
97
|
+
caret-color: var(--bgl-white);
|
|
98
|
+
font-size: 16px;
|
|
99
|
+
padding: 1rem;
|
|
100
|
+
padding-left: 70px !important;
|
|
368
101
|
|
|
369
|
-
.code-editor.hide-header.scroll .code-area {
|
|
370
|
-
height: 100%;
|
|
371
102
|
}
|
|
372
103
|
|
|
373
|
-
.code-editor
|
|
374
|
-
|
|
104
|
+
.code-editor::-moz-selection {
|
|
105
|
+
background: #2466bc30;
|
|
106
|
+
color: inherit;
|
|
375
107
|
}
|
|
376
108
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
height: 100%;
|
|
381
|
-
font-family: sans-serif;
|
|
109
|
+
.code-editor::selection {
|
|
110
|
+
background: #2466bc30;
|
|
111
|
+
color: inherit;
|
|
382
112
|
}
|
|
383
113
|
|
|
384
|
-
.code-editor
|
|
385
|
-
|
|
386
|
-
padding: 0;
|
|
387
|
-
margin: 0;
|
|
388
|
-
list-style: none;
|
|
389
|
-
font-size: 13px;
|
|
390
|
-
overflow: auto;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
.code-editor .list>.lang-list>li {
|
|
394
|
-
padding: 0 12px;
|
|
395
|
-
line-height: 30px;
|
|
396
|
-
white-space: nowrap;
|
|
397
|
-
overflow: hidden;
|
|
398
|
-
text-overflow: ellipsis;
|
|
399
|
-
transition: background 0.16s ease;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
.code-editor .list>.lang-list>li:first-child {
|
|
403
|
-
padding-top: 5px;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
.code-editor .list>.lang-list>li:last-child {
|
|
407
|
-
padding-bottom: 5px;
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
.code-editor .list>.lang-list>li:hover {
|
|
411
|
-
background: rgba(160, 160, 160, 0.4);
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/* Line numbers */
|
|
415
|
-
.code-editor .line-nums {
|
|
416
|
-
min-width: 36px;
|
|
417
|
-
position: absolute;
|
|
418
|
-
left: 0;
|
|
419
|
-
padding: 0 8px;
|
|
420
|
-
text-align: right;
|
|
421
|
-
opacity: 0.3;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
.code-editor .line-nums::after {
|
|
425
|
-
content: "";
|
|
426
|
-
position: absolute;
|
|
427
|
-
inset: 0;
|
|
428
|
-
border-right: 1px solid currentColor;
|
|
429
|
-
opacity: 0.5;
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
.code-editor .header.border::after {
|
|
433
|
-
content: "";
|
|
434
|
-
position: absolute;
|
|
435
|
-
inset: auto 0 0;
|
|
436
|
-
height: 1px;
|
|
437
|
-
background: currentColor;
|
|
438
|
-
opacity: 0.15;
|
|
114
|
+
.code-editor:focus {
|
|
115
|
+
outline: none;
|
|
439
116
|
}
|
|
440
117
|
</style>
|
|
@@ -68,8 +68,8 @@ const format = {
|
|
|
68
68
|
continue
|
|
69
69
|
}
|
|
70
70
|
if (
|
|
71
|
-
(char === ')' && nextChar === '{')
|
|
72
|
-
(char === ')' && nextChar === ' ')
|
|
71
|
+
(char === ')' && nextChar === '{')
|
|
72
|
+
|| (char === ')' && nextChar === ' ')
|
|
73
73
|
) {
|
|
74
74
|
formatted += `${char}\n${tab.repeat(level)}`
|
|
75
75
|
continue
|
|
@@ -405,7 +405,7 @@ function drop(e: DragEvent) {
|
|
|
405
405
|
class="single-image-item-preview"
|
|
406
406
|
:class="{ 'bgl_fill-image': fill }"
|
|
407
407
|
>
|
|
408
|
-
<div class="position-start m-05 flex opacity-7 z-99">
|
|
408
|
+
<div class="position-start m-05 flex opacity-7 z-99 gap-025">
|
|
409
409
|
<Btn
|
|
410
410
|
v-tooltip="'Delete'"
|
|
411
411
|
color="gray"
|
|
@@ -588,6 +588,7 @@ function drop(e: DragEvent) {
|
|
|
588
588
|
height: calc(100% - 2rem);
|
|
589
589
|
object-fit: cover;
|
|
590
590
|
background: var(--bgl-gray-light);
|
|
591
|
+
width: 90%;
|
|
591
592
|
}
|
|
592
593
|
.single-image-item-preview:hover::after {
|
|
593
594
|
content: 'zoom_in';
|
|
@@ -1,22 +1,51 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
defineProps<{ gridSize: number }>()
|
|
3
2
|
const emit = defineEmits(['select'])
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
const fb = 1
|
|
4
|
+
const base = 5
|
|
5
|
+
const hoveredRow = $ref(fb)
|
|
6
|
+
const hoveredCol = $ref(fb)
|
|
7
|
+
|
|
8
|
+
const rowSize = $computed(() => {
|
|
9
|
+
const enlarge = Math.min(hoveredRow + 1, 20)
|
|
10
|
+
return hoveredRow > (base - 1) ? enlarge : base
|
|
11
|
+
})
|
|
12
|
+
const colSize = $computed(() => {
|
|
13
|
+
const enlarge = Math.min(hoveredCol + 1, 20)
|
|
14
|
+
return hoveredCol > (base - 1) ? enlarge : base
|
|
15
|
+
})
|
|
6
16
|
</script>
|
|
7
17
|
|
|
8
18
|
<template>
|
|
9
19
|
<div class="grid grid-wrap p-05">
|
|
10
20
|
<div
|
|
11
|
-
v-for="row in
|
|
12
|
-
@focusout="hoveredRow =
|
|
21
|
+
v-for="row in rowSize" :key="`row-${row}`" class="flex" @mouseout="hoveredRow = fb; hoveredCol = fb"
|
|
22
|
+
@focusout="hoveredRow = fb; hoveredCol = fb"
|
|
13
23
|
>
|
|
14
24
|
<div
|
|
15
|
-
v-for="col in
|
|
16
|
-
:style="{ width: '20px', height: '20px' }" class="
|
|
17
|
-
:class="{
|
|
25
|
+
v-for="col in colSize" :key="`col-${col}`" role="button" tabindex="0" aria-label="Insert Table"
|
|
26
|
+
:style="{ width: '20px', height: '20px' }" class="flex pointer gap-025 tableBoxSelect"
|
|
27
|
+
:class="{ borderSelect: hoveredRow >= row && hoveredCol >= col }"
|
|
18
28
|
@mousemove="hoveredRow = row; hoveredCol = col" @click="emit('select', `${row}x${col}`)"
|
|
19
29
|
/>
|
|
20
30
|
</div>
|
|
31
|
+
<p class="txt-center txt-12 color-gray">
|
|
32
|
+
{{ hoveredRow }}x{{ hoveredCol }}
|
|
33
|
+
</p>
|
|
21
34
|
</div>
|
|
22
35
|
</template>
|
|
36
|
+
|
|
37
|
+
<style scoped>
|
|
38
|
+
.tableBoxSelect::after {
|
|
39
|
+
content: '';
|
|
40
|
+
display: block;
|
|
41
|
+
width: calc(100% - 4px);
|
|
42
|
+
height: calc(100% - 4px);
|
|
43
|
+
border: 1px solid var(--bgl-gray);
|
|
44
|
+
background: var(--bgl-gray-light);
|
|
45
|
+
|
|
46
|
+
}
|
|
47
|
+
.borderSelect::after {
|
|
48
|
+
border-color: var(--bgl-primary-tint);
|
|
49
|
+
background: var(--bgl-primary-light);
|
|
50
|
+
}
|
|
51
|
+
</style>
|
|
@@ -3,7 +3,7 @@ import { reactive } from 'vue'
|
|
|
3
3
|
import { formatting } from '../utils/formatting'
|
|
4
4
|
import { insertImage, insertLink } from '../utils/media'
|
|
5
5
|
import { isStyleActive } from '../utils/selection'
|
|
6
|
-
import { addRow, deleteRow, mergeCells, splitCell } from '../utils/table'
|
|
6
|
+
import { addRow, deleteRow, mergeCells, splitCell, insertTable } from '../utils/table'
|
|
7
7
|
|
|
8
8
|
export function useEditor() {
|
|
9
9
|
const state = reactive<
|
|
@@ -127,8 +127,13 @@ export function useEditor() {
|
|
|
127
127
|
if (!state.doc.body.contains(selection.anchorNode)) {
|
|
128
128
|
state.doc.body.focus()
|
|
129
129
|
}
|
|
130
|
-
|
|
130
|
+
console.log(command)
|
|
131
131
|
switch (command) {
|
|
132
|
+
case 'insertTable': {
|
|
133
|
+
const [rows, cols] = value?.split('x').map(Number) || [3, 3]
|
|
134
|
+
insertTable(rows, cols, state)
|
|
135
|
+
break
|
|
136
|
+
}
|
|
132
137
|
case 'mergeCells':
|
|
133
138
|
if (isCaret) return
|
|
134
139
|
mergeCells(range, state.doc)
|
|
@@ -160,10 +165,12 @@ export function useEditor() {
|
|
|
160
165
|
format().list(command)
|
|
161
166
|
break
|
|
162
167
|
case 'image':
|
|
163
|
-
case 'youtube':
|
|
164
|
-
if (isCaret) return
|
|
165
168
|
insertImage(state.modal, state.doc, range)
|
|
166
169
|
break
|
|
170
|
+
// case 'youtube':
|
|
171
|
+
// if (isCaret) return
|
|
172
|
+
// insertImage(state.modal, state.doc, range)
|
|
173
|
+
// break
|
|
167
174
|
case 'link':
|
|
168
175
|
if (isCaret) return
|
|
169
176
|
insertLink(state.modal, state.doc, range)
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
body {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
margin: 0;
|
|
3
|
+
padding: 8px;
|
|
4
|
+
min-height: 200px;
|
|
5
|
+
font-family: sans-serif;
|
|
6
|
+
color: inherit;
|
|
7
|
+
background: transparent;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
table {
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
border-collapse: collapse;
|
|
12
|
+
margin-bottom: 1rem;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
th,
|
|
16
16
|
td {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
padding: 1rem;
|
|
18
|
+
text-align: left;
|
|
19
|
+
border: 1px solid #2a2a2a;
|
|
20
|
+
line-height: 1.5;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
th {
|
|
24
|
-
|
|
25
|
-
}
|
|
24
|
+
background-color: #f4f4f4;
|
|
25
|
+
}
|