frappe-ui 0.0.48 → 0.0.51
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/package.json +5 -1
- package/src/components/Dialog.vue +3 -10
- package/src/components/Input.vue +1 -0
- package/src/components/TextEditor/Menu.vue +19 -6
- package/src/components/TextEditor/TextEditor.vue +70 -3
- package/src/components/TextEditor/commands.js +84 -0
- package/src/components/Toast.vue +6 -2
- package/src/utils/vite-dev-server.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frappe-ui",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.51",
|
|
4
4
|
"description": "A set of components and utilities for rapid UI development",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"@tiptap/extension-link": "^2.0.0-beta.43",
|
|
27
27
|
"@tiptap/extension-mention": "^2.0.0-beta.102",
|
|
28
28
|
"@tiptap/extension-placeholder": "^2.0.0-beta.53",
|
|
29
|
+
"@tiptap/extension-table": "^2.0.0-beta.54",
|
|
30
|
+
"@tiptap/extension-table-cell": "^2.0.0-beta.23",
|
|
31
|
+
"@tiptap/extension-table-header": "^2.0.0-beta.25",
|
|
32
|
+
"@tiptap/extension-table-row": "^2.0.0-beta.22",
|
|
29
33
|
"@tiptap/extension-text-align": "^2.0.0-beta.31",
|
|
30
34
|
"@tiptap/starter-kit": "^2.0.0-beta.191",
|
|
31
35
|
"@tiptap/vue-3": "^2.0.0-beta.96",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
@close="open = false"
|
|
11
11
|
>
|
|
12
12
|
<div
|
|
13
|
-
class="flex items-
|
|
13
|
+
class="flex flex-col items-center justify-center min-h-screen px-4 pt-4 pb-20 text-center"
|
|
14
14
|
>
|
|
15
15
|
<TransitionChild
|
|
16
16
|
as="template"
|
|
@@ -26,13 +26,6 @@
|
|
|
26
26
|
/>
|
|
27
27
|
</TransitionChild>
|
|
28
28
|
|
|
29
|
-
<!-- This element is to trick the browser into centering the modal contents. -->
|
|
30
|
-
<span
|
|
31
|
-
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
|
32
|
-
aria-hidden="true"
|
|
33
|
-
>
|
|
34
|
-
​
|
|
35
|
-
</span>
|
|
36
29
|
<TransitionChild
|
|
37
30
|
as="template"
|
|
38
31
|
enter="ease-out duration-300"
|
|
@@ -43,7 +36,7 @@
|
|
|
43
36
|
leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
|
|
44
37
|
>
|
|
45
38
|
<div
|
|
46
|
-
class="inline-block overflow-hidden text-left align-
|
|
39
|
+
class="inline-block w-full max-w-lg my-8 overflow-hidden text-left align-middle transition-all transform bg-white rounded-lg shadow-xl"
|
|
47
40
|
>
|
|
48
41
|
<slot name="body">
|
|
49
42
|
<slot name="body-main">
|
|
@@ -71,7 +64,7 @@
|
|
|
71
64
|
aria-hidden="true"
|
|
72
65
|
/>
|
|
73
66
|
</div>
|
|
74
|
-
<div class="flex-1
|
|
67
|
+
<div class="flex-1">
|
|
75
68
|
<DialogTitle as="header">
|
|
76
69
|
<slot name="body-title">
|
|
77
70
|
<h3
|
package/src/components/Input.vue
CHANGED
|
@@ -6,23 +6,36 @@
|
|
|
6
6
|
class="border-l w-[2px] h-4"
|
|
7
7
|
v-if="button.type === 'separator'"
|
|
8
8
|
></div>
|
|
9
|
-
<div v-else-if="button.map">
|
|
9
|
+
<div class="shrink-0" v-else-if="button.map">
|
|
10
10
|
<Popover>
|
|
11
11
|
<template #target="{ togglePopover }">
|
|
12
12
|
<button
|
|
13
13
|
class="px-2 py-1 text-base font-medium text-gray-800 transition-colors rounded hover:bg-gray-100"
|
|
14
14
|
@click="togglePopover"
|
|
15
|
+
:set="
|
|
16
|
+
(activeBtn =
|
|
17
|
+
button.find((b) => b.isActive(editor)) || button[0])
|
|
18
|
+
"
|
|
15
19
|
>
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
<component
|
|
21
|
+
v-if="activeBtn.icon"
|
|
22
|
+
:is="activeBtn.icon"
|
|
23
|
+
class="w-4 h-4"
|
|
24
|
+
/>
|
|
25
|
+
<span v-else>
|
|
26
|
+
{{ activeBtn.label }}
|
|
27
|
+
</span>
|
|
19
28
|
</button>
|
|
20
29
|
</template>
|
|
21
30
|
<template #body="{ close }">
|
|
22
31
|
<ul class="p-1 bg-white border rounded shadow-md">
|
|
23
|
-
<li
|
|
32
|
+
<li
|
|
33
|
+
class="w-full"
|
|
34
|
+
v-for="option in button"
|
|
35
|
+
v-show="option.isDisabled ? !option.isDisabled(editor) : true"
|
|
36
|
+
>
|
|
24
37
|
<button
|
|
25
|
-
class="w-full px-2 py-1 text-base rounded hover:bg-gray-50"
|
|
38
|
+
class="w-full px-2 py-1 text-base text-left rounded hover:bg-gray-50"
|
|
26
39
|
@click="
|
|
27
40
|
() => {
|
|
28
41
|
onClick(option)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
<Menu
|
|
17
17
|
v-if="fixedMenuButtons"
|
|
18
|
-
class="w-full border border-gray-200 rounded-t-lg"
|
|
18
|
+
class="w-full overflow-x-auto border border-gray-200 rounded-t-lg"
|
|
19
19
|
:editor="editor"
|
|
20
20
|
:buttons="fixedMenuButtons"
|
|
21
21
|
/>
|
|
@@ -49,6 +49,10 @@ import { Editor, EditorContent, BubbleMenu, FloatingMenu } from '@tiptap/vue-3'
|
|
|
49
49
|
import StarterKit from '@tiptap/starter-kit'
|
|
50
50
|
import Placeholder from '@tiptap/extension-placeholder'
|
|
51
51
|
import TextAlign from '@tiptap/extension-text-align'
|
|
52
|
+
import Table from '@tiptap/extension-table'
|
|
53
|
+
import TableCell from '@tiptap/extension-table-cell'
|
|
54
|
+
import TableHeader from '@tiptap/extension-table-header'
|
|
55
|
+
import TableRow from '@tiptap/extension-table-row'
|
|
52
56
|
import Image from './image-extension'
|
|
53
57
|
import Link from '@tiptap/extension-link'
|
|
54
58
|
import configureMention from './mention'
|
|
@@ -142,13 +146,22 @@ export default {
|
|
|
142
146
|
StarterKit.configure({
|
|
143
147
|
...this.starterkitOptions,
|
|
144
148
|
}),
|
|
149
|
+
Table.configure({
|
|
150
|
+
resizable: true,
|
|
151
|
+
}),
|
|
152
|
+
TableRow,
|
|
153
|
+
TableHeader,
|
|
154
|
+
TableCell,
|
|
145
155
|
TextAlign.configure({
|
|
146
156
|
types: ['heading', 'paragraph'],
|
|
147
157
|
}),
|
|
148
158
|
Image,
|
|
149
159
|
Link,
|
|
150
160
|
Placeholder.configure({
|
|
151
|
-
|
|
161
|
+
showOnlyWhenEditable: false,
|
|
162
|
+
placeholder: () => {
|
|
163
|
+
return this.placeholder
|
|
164
|
+
},
|
|
152
165
|
}),
|
|
153
166
|
configureMention(this.mentions),
|
|
154
167
|
...(this.extensions || []),
|
|
@@ -194,6 +207,21 @@ export default {
|
|
|
194
207
|
'Blockquote',
|
|
195
208
|
'Code',
|
|
196
209
|
'Horizontal Rule',
|
|
210
|
+
[
|
|
211
|
+
'InsertTable',
|
|
212
|
+
'AddColumnBefore',
|
|
213
|
+
'AddColumnAfter',
|
|
214
|
+
'DeleteColumn',
|
|
215
|
+
'AddRowBefore',
|
|
216
|
+
'AddRowAfter',
|
|
217
|
+
'DeleteRow',
|
|
218
|
+
'MergeCells',
|
|
219
|
+
'SplitCell',
|
|
220
|
+
'ToggleHeaderColumn',
|
|
221
|
+
'ToggleHeaderRow',
|
|
222
|
+
'ToggleHeaderCell',
|
|
223
|
+
'DeleteTable',
|
|
224
|
+
],
|
|
197
225
|
'Separator',
|
|
198
226
|
'Undo',
|
|
199
227
|
'Redo',
|
|
@@ -248,7 +276,10 @@ export default {
|
|
|
248
276
|
editorProps() {
|
|
249
277
|
return {
|
|
250
278
|
attributes: {
|
|
251
|
-
class: normalizeClass([
|
|
279
|
+
class: normalizeClass([
|
|
280
|
+
'prose prose-p:my-1 prose-table:table-fixed prose-td:p-2 prose-th:p-2 prose-td:border prose-th:border prose-td:border-gray-300 prose-th:border-gray-300 prose-td:relative prose-th:relative prose-th:bg-gray-100',
|
|
281
|
+
this.editorClass,
|
|
282
|
+
]),
|
|
252
283
|
},
|
|
253
284
|
}
|
|
254
285
|
},
|
|
@@ -266,6 +297,7 @@ function createEditorButton(option) {
|
|
|
266
297
|
}
|
|
267
298
|
</script>
|
|
268
299
|
<style>
|
|
300
|
+
/* Placeholder */
|
|
269
301
|
.ProseMirror:not(.ProseMirror-focused) p.is-editor-empty:first-child::before {
|
|
270
302
|
content: attr(data-placeholder);
|
|
271
303
|
float: left;
|
|
@@ -273,8 +305,43 @@ function createEditorButton(option) {
|
|
|
273
305
|
pointer-events: none;
|
|
274
306
|
height: 0;
|
|
275
307
|
}
|
|
308
|
+
|
|
309
|
+
/* Mentions */
|
|
276
310
|
.mention {
|
|
277
311
|
font-weight: 600;
|
|
278
312
|
box-decoration-break: clone;
|
|
279
313
|
}
|
|
314
|
+
|
|
315
|
+
/* Table styles */
|
|
316
|
+
.prose table p {
|
|
317
|
+
margin: 0;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* Prosemirror specific table styles */
|
|
321
|
+
.ProseMirror table .selectedCell:after {
|
|
322
|
+
z-index: 2;
|
|
323
|
+
position: absolute;
|
|
324
|
+
content: '';
|
|
325
|
+
left: 0;
|
|
326
|
+
right: 0;
|
|
327
|
+
top: 0;
|
|
328
|
+
bottom: 0;
|
|
329
|
+
pointer-events: none;
|
|
330
|
+
background: theme('colors.blue.200 / 30%');
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.ProseMirror table .column-resize-handle {
|
|
334
|
+
position: absolute;
|
|
335
|
+
right: -1px;
|
|
336
|
+
top: 0;
|
|
337
|
+
bottom: -2px;
|
|
338
|
+
width: 4px;
|
|
339
|
+
background-color: theme('colors.blue.200');
|
|
340
|
+
pointer-events: none;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
.resize-cursor {
|
|
344
|
+
cursor: ew-resize;
|
|
345
|
+
cursor: col-resize;
|
|
346
|
+
}
|
|
280
347
|
</style>
|
|
@@ -20,6 +20,7 @@ import Image from './icons/image-add-line.vue'
|
|
|
20
20
|
import ArrowGoBack from './icons/arrow-go-back-line.vue'
|
|
21
21
|
import ArrowGoForward from './icons/arrow-go-forward-line.vue'
|
|
22
22
|
import Separator from './icons/separator.vue'
|
|
23
|
+
import Table from './icons/table-2.vue'
|
|
23
24
|
|
|
24
25
|
export default {
|
|
25
26
|
Paragraph: {
|
|
@@ -164,6 +165,89 @@ export default {
|
|
|
164
165
|
action: (editor) => editor.chain().focus().redo().run(),
|
|
165
166
|
isActive: (editor) => false,
|
|
166
167
|
},
|
|
168
|
+
InsertTable: {
|
|
169
|
+
label: 'Insert Table',
|
|
170
|
+
icon: Table,
|
|
171
|
+
action: (editor) =>
|
|
172
|
+
editor
|
|
173
|
+
.chain()
|
|
174
|
+
.focus()
|
|
175
|
+
.insertTable({ rows: 3, cols: 3, withHeaderRow: true })
|
|
176
|
+
.run(),
|
|
177
|
+
isActive: (editor) => false,
|
|
178
|
+
},
|
|
179
|
+
AddColumnBefore: {
|
|
180
|
+
label: 'Add Column Before',
|
|
181
|
+
action: (editor) => editor.chain().focus().addColumnBefore().run(),
|
|
182
|
+
isActive: (editor) => false,
|
|
183
|
+
isDisabled: (editor) => !editor.can().addColumnBefore(),
|
|
184
|
+
},
|
|
185
|
+
AddColumnAfter: {
|
|
186
|
+
label: 'Add Column After',
|
|
187
|
+
action: (editor) => editor.chain().focus().addColumnAfter().run(),
|
|
188
|
+
isActive: (editor) => false,
|
|
189
|
+
isDisabled: (editor) => !editor.can().addColumnAfter(),
|
|
190
|
+
},
|
|
191
|
+
DeleteColumn: {
|
|
192
|
+
label: 'Delete Column',
|
|
193
|
+
action: (editor) => editor.chain().focus().deleteColumn().run(),
|
|
194
|
+
isActive: (editor) => false,
|
|
195
|
+
isDisabled: (editor) => !editor.can().deleteColumn(),
|
|
196
|
+
},
|
|
197
|
+
AddRowBefore: {
|
|
198
|
+
label: 'Add Row Before',
|
|
199
|
+
action: (editor) => editor.chain().focus().addRowBefore().run(),
|
|
200
|
+
isActive: (editor) => false,
|
|
201
|
+
isDisabled: (editor) => !editor.can().addRowBefore(),
|
|
202
|
+
},
|
|
203
|
+
AddRowAfter: {
|
|
204
|
+
label: 'Add Row After',
|
|
205
|
+
action: (editor) => editor.chain().focus().addRowAfter().run(),
|
|
206
|
+
isActive: (editor) => false,
|
|
207
|
+
isDisabled: (editor) => !editor.can().addRowAfter(),
|
|
208
|
+
},
|
|
209
|
+
DeleteRow: {
|
|
210
|
+
label: 'Delete Row',
|
|
211
|
+
action: (editor) => editor.chain().focus().deleteRow().run(),
|
|
212
|
+
isActive: (editor) => false,
|
|
213
|
+
isDisabled: (editor) => !editor.can().deleteRow(),
|
|
214
|
+
},
|
|
215
|
+
DeleteTable: {
|
|
216
|
+
label: 'Delete Table',
|
|
217
|
+
action: (editor) => editor.chain().focus().deleteTable().run(),
|
|
218
|
+
isActive: (editor) => false,
|
|
219
|
+
isDisabled: (editor) => !editor.can().deleteTable(),
|
|
220
|
+
},
|
|
221
|
+
MergeCells: {
|
|
222
|
+
label: 'Merge Cells',
|
|
223
|
+
action: (editor) => editor.chain().focus().mergeCells().run(),
|
|
224
|
+
isActive: (editor) => false,
|
|
225
|
+
isDisabled: (editor) => !editor.can().mergeCells(),
|
|
226
|
+
},
|
|
227
|
+
SplitCell: {
|
|
228
|
+
label: 'Split Cell',
|
|
229
|
+
action: (editor) => editor.chain().focus().splitCell().run(),
|
|
230
|
+
isActive: (editor) => false,
|
|
231
|
+
isDisabled: (editor) => !editor.can().splitCell(),
|
|
232
|
+
},
|
|
233
|
+
ToggleHeaderColumn: {
|
|
234
|
+
label: 'Toggle Header Column',
|
|
235
|
+
action: (editor) => editor.chain().focus().toggleHeaderColumn().run(),
|
|
236
|
+
isActive: (editor) => false,
|
|
237
|
+
isDisabled: (editor) => !editor.can().toggleHeaderColumn(),
|
|
238
|
+
},
|
|
239
|
+
ToggleHeaderRow: {
|
|
240
|
+
label: 'Toggle Header Row',
|
|
241
|
+
action: (editor) => editor.chain().focus().toggleHeaderRow().run(),
|
|
242
|
+
isActive: (editor) => false,
|
|
243
|
+
isDisabled: (editor) => !editor.can().toggleHeaderRow(),
|
|
244
|
+
},
|
|
245
|
+
ToggleHeaderCell: {
|
|
246
|
+
label: 'Toggle Header Cell',
|
|
247
|
+
action: (editor) => editor.chain().focus().toggleHeaderCell().run(),
|
|
248
|
+
isActive: (editor) => false,
|
|
249
|
+
isDisabled: (editor) => !editor.can().toggleHeaderCell(),
|
|
250
|
+
},
|
|
167
251
|
Separator: {
|
|
168
252
|
type: 'separator',
|
|
169
253
|
},
|
package/src/components/Toast.vue
CHANGED
|
@@ -18,10 +18,14 @@
|
|
|
18
18
|
</div>
|
|
19
19
|
<div>
|
|
20
20
|
<slot>
|
|
21
|
-
<p
|
|
21
|
+
<p
|
|
22
|
+
v-if="title"
|
|
23
|
+
class="text-base font-medium text-gray-900"
|
|
24
|
+
:class="{ 'mb-1': text }"
|
|
25
|
+
>
|
|
22
26
|
{{ title }}
|
|
23
27
|
</p>
|
|
24
|
-
<p class="
|
|
28
|
+
<p v-if="text" class="text-base text-gray-600">
|
|
25
29
|
{{ text }}
|
|
26
30
|
</p>
|
|
27
31
|
</slot>
|