frappe-ui 0.0.39 → 0.0.44

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.39",
3
+ "version": "0.0.44",
4
4
  "description": "A set of components and utilities for rapid UI development",
5
5
  "main": "./src/index.js",
6
6
  "scripts": {
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="overflow-hidden" :class="styleClasses">
2
+ <div class="overflow-hidden shrink-0" :class="styleClasses">
3
3
  <img
4
4
  v-if="imageURL"
5
5
  :src="imageURL"
@@ -1,5 +1,9 @@
1
1
  <template>
2
- <TransitionRoot as="template" :show="open">
2
+ <TransitionRoot
3
+ as="template"
4
+ :show="open"
5
+ @after-leave="$emit('after-leave')"
6
+ >
3
7
  <HDialog
4
8
  as="div"
5
9
  class="fixed inset-0 z-10 overflow-y-auto"
@@ -137,7 +141,7 @@ export default {
137
141
  },
138
142
  },
139
143
  },
140
- emits: ['update:modelValue', 'close'],
144
+ emits: ['update:modelValue', 'close', 'after-leave'],
141
145
  components: {
142
146
  HDialog,
143
147
  DialogOverlay,
@@ -67,18 +67,56 @@
67
67
  </Button>
68
68
  </template>
69
69
  </Dialog>
70
+ <Dialog
71
+ :options="{ title: 'Add Image' }"
72
+ v-model="addImageDialog.show"
73
+ @after-leave="resetAddImage"
74
+ >
75
+ <template #body-content>
76
+ <label
77
+ class="relative py-1 bg-gray-100 rounded-lg cursor-pointer focus-within:bg-gray-200 hover:bg-gray-200"
78
+ >
79
+ <input
80
+ type="file"
81
+ class="w-full opacity-0"
82
+ @change="onImageSelect"
83
+ accept="image/*"
84
+ />
85
+ <span class="absolute inset-0 px-2 py-1 text-base select-none">
86
+ {{
87
+ addImageDialog.file ? 'Select another image' : 'Select an image'
88
+ }}
89
+ </span>
90
+ </label>
91
+ <img
92
+ v-if="addImageDialog.url"
93
+ :src="addImageDialog.url"
94
+ class="w-full mt-2 rounded-lg"
95
+ />
96
+ </template>
97
+ <template #actions>
98
+ <Button appearance="primary" @click="addImage(addImageDialog.url)">
99
+ Insert Image
100
+ </Button>
101
+ </template>
102
+ </Dialog>
70
103
  </div>
71
104
  </template>
72
105
  <script>
73
- import { Popover } from 'frappe-ui'
74
-
106
+ import { Popover, Dialog, Input, Button } from 'frappe-ui'
75
107
  export default {
76
108
  name: 'TipTapMenu',
77
109
  props: ['editor', 'buttons'],
78
- components: { Popover },
110
+ components: {
111
+ Popover,
112
+ Dialog,
113
+ Input,
114
+ Button,
115
+ },
79
116
  data() {
80
117
  return {
81
118
  setLinkDialog: { url: '', show: false },
119
+ addImageDialog: { url: '', file: null, show: false },
82
120
  }
83
121
  },
84
122
  methods: {
@@ -89,6 +127,8 @@ export default {
89
127
  if (existingURL) {
90
128
  this.setLinkDialog.url = existingURL
91
129
  }
130
+ } else if (button.label === 'Image') {
131
+ this.addImageDialog.show = true
92
132
  } else {
93
133
  button.action(this.editor)
94
134
  }
@@ -110,6 +150,26 @@ export default {
110
150
  this.setLinkDialog.show = false
111
151
  this.setLinkDialog.url = ''
112
152
  },
153
+ onImageSelect(e) {
154
+ let file = e.target.files[0]
155
+ if (!file) {
156
+ return
157
+ }
158
+ this.addImageDialog.file = file
159
+ let reader = new FileReader()
160
+ reader.onloadend = () => {
161
+ let base64string = reader.result
162
+ this.addImageDialog.url = base64string
163
+ }
164
+ reader.readAsDataURL(file)
165
+ },
166
+ addImage(src) {
167
+ this.editor.chain().focus().setImage({ src }).run()
168
+ this.resetAddImage()
169
+ },
170
+ resetAddImage() {
171
+ this.addImageDialog = { show: false, url: null, file: null }
172
+ },
113
173
  },
114
174
  }
115
175
  </script>
@@ -41,6 +41,12 @@
41
41
  </button>
42
42
  </FloatingMenu>
43
43
  <editor-content :editor="editor" />
44
+ <span
45
+ v-if="!content"
46
+ class="absolute inset-y-0 text-base text-gray-500 pointer-events-none"
47
+ >
48
+ {{ placeholder }}
49
+ </span>
44
50
  </div>
45
51
  </template>
46
52
 
@@ -113,7 +119,9 @@ export default {
113
119
  TextAlign.configure({
114
120
  types: ['heading', 'paragraph'],
115
121
  }),
116
- Image,
122
+ Image.configure({
123
+ allowBase64: true,
124
+ }),
117
125
  Link,
118
126
  Placeholder.configure({
119
127
  placeholder: this.placeholder || 'Write something...',
@@ -157,6 +165,7 @@ export default {
157
165
  'Align Center',
158
166
  'Align Right',
159
167
  'Separator',
168
+ 'Image',
160
169
  'Blockquote',
161
170
  'Code',
162
171
  'Horizontal Rule',
@@ -16,6 +16,7 @@ import ListUnordered from './icons/list-unordered.vue'
16
16
  import DoubleQuotes from './icons/double-quotes-r.vue'
17
17
  import CodeView from './icons/code-view.vue'
18
18
  import Link from './icons/link.vue'
19
+ import Image from './icons/image-add-line.vue'
19
20
  import ArrowGoBack from './icons/arrow-go-back-line.vue'
20
21
  import ArrowGoForward from './icons/arrow-go-forward-line.vue'
21
22
  import Separator from './icons/separator.vue'
@@ -146,6 +147,11 @@ export default {
146
147
  icon: Link,
147
148
  isActive: (editor) => editor.isActive('link'),
148
149
  },
150
+ Image: {
151
+ label: 'Image',
152
+ icon: Image,
153
+ isActive: (editor) => false,
154
+ },
149
155
  Undo: {
150
156
  label: 'Undo',
151
157
  icon: ArrowGoBack,
@@ -0,0 +1,14 @@
1
+ <template>
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ viewBox="0 0 24 24"
5
+ width="24"
6
+ height="24"
7
+ >
8
+ <path fill="none" d="M0 0h24v24H0z" />
9
+ <path
10
+ d="M21 15v3h3v2h-3v3h-2v-3h-3v-2h3v-3h2zm.008-12c.548 0 .992.445.992.993V13h-2V5H4v13.999L14 9l3 3v2.829l-3-3L6.827 19H14v2H2.992A.993.993 0 0 1 2 20.007V3.993A1 1 0 0 1 2.992 3h18.016zM8 7a2 2 0 1 1 0 4 2 2 0 0 1 0-4z"
11
+ fill="currentColor"
12
+ />
13
+ </svg>
14
+ </template>
@@ -212,6 +212,7 @@ export function createDocumentResource(options, vm) {
212
212
  },
213
213
  onSuccess(data) {
214
214
  out.doc = transform(data)
215
+ options.onSuccess?.call(vm, out.doc)
215
216
  },
216
217
  onError: options.onError,
217
218
  },
@@ -316,10 +317,12 @@ export function createListResource(options, vm, getResource) {
316
317
  fields: options.fields,
317
318
  filters: options.filters,
318
319
  order_by: options.order_by,
319
- start: options.start,
320
- limit: options.limit,
320
+ start: options.start || 0,
321
+ limit: options.limit || 20,
321
322
  originalData: null,
322
323
  data: null,
324
+ next,
325
+ hasNextPage: true,
323
326
  list: createResource(
324
327
  {
325
328
  method: 'frappe.client.get_list',
@@ -334,8 +337,15 @@ export function createListResource(options, vm, getResource) {
334
337
  }
335
338
  },
336
339
  onSuccess(data) {
337
- out.originalData = data
338
- out.data = transform(data)
340
+ if (data.length < out.limit) {
341
+ out.hasNextPage = false
342
+ }
343
+ if (!out.start || out.start == 0) {
344
+ out.originalData = data
345
+ } else if (out.start > 0) {
346
+ out.originalData = out.originalData.concat(data)
347
+ }
348
+ out.data = transform(out.originalData)
339
349
  options.onSuccess?.call(vm, out.data)
340
350
  },
341
351
  onError: options.onError,
@@ -455,6 +465,7 @@ export function createListResource(options, vm, getResource) {
455
465
  }
456
466
 
457
467
  function reload() {
468
+ out.start = 0
458
469
  return out.list.fetch()
459
470
  }
460
471
 
@@ -465,6 +476,11 @@ export function createListResource(options, vm, getResource) {
465
476
  out.data = data
466
477
  }
467
478
 
479
+ function next() {
480
+ out.start = out.start + out.limit
481
+ out.list.fetch()
482
+ }
483
+
468
484
  // fetch list
469
485
  out.list.fetch()
470
486
 
@@ -480,7 +496,7 @@ export function createListResource(options, vm, getResource) {
480
496
  }
481
497
 
482
498
  function updateRowInListResource(doctype, doc) {
483
- let resources = listResources[doctype]
499
+ let resources = listResources[doctype] || []
484
500
  for (let resource of resources) {
485
501
  if (resource.originalData) {
486
502
  for (let row of resource.originalData) {
@@ -500,7 +516,7 @@ function updateRowInListResource(doctype, doc) {
500
516
  }
501
517
 
502
518
  function revertRowInListResource(doctype, doc) {
503
- let resources = listResources[doctype]
519
+ let resources = listResources[doctype] || []
504
520
  for (let resource of resources) {
505
521
  if (resource.originalData) {
506
522
  for (let row of resource.originalData) {