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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frappe-ui",
3
- "version": "0.0.48",
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-end justify-center min-h-screen px-4 pt-4 pb-20 text-center sm:block sm:p-0"
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
- &#8203;
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-bottom transition-all transform bg-white rounded-lg shadow-xl sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
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 text-center sm:text-left">
67
+ <div class="flex-1">
75
68
  <DialogTitle as="header">
76
69
  <slot name="body-title">
77
70
  <h3
@@ -77,6 +77,7 @@ export default {
77
77
  },
78
78
  type: {
79
79
  type: String,
80
+ default: 'text',
80
81
  validator(value) {
81
82
  let isValid = [
82
83
  'text',
@@ -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
- (button.find((b) => b.isActive(editor)) || button[0]).label
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 class="w-full" v-for="option in button">
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
- placeholder: this.placeholder,
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(['prose prose-p:my-1', this.editorClass]),
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
  },
@@ -18,10 +18,14 @@
18
18
  </div>
19
19
  <div>
20
20
  <slot>
21
- <p class="text-base font-medium text-gray-900">
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="mt-1 text-base text-gray-600">
28
+ <p v-if="text" class="text-base text-gray-600">
25
29
  {{ text }}
26
30
  </p>
27
31
  </slot>
@@ -1,7 +1,7 @@
1
1
  module.exports = {
2
2
  getProxyOptions({ port }) {
3
3
  return {
4
- '^/(app|api|assets|files)': {
4
+ '^/(app|login|api|assets|files)': {
5
5
  target: `http://localhost:${port}`,
6
6
  ws: true,
7
7
  router: function (req) {