quasar-ui-danx 0.3.47 → 0.3.49

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": "quasar-ui-danx",
3
- "version": "0.3.47",
3
+ "version": "0.3.49",
4
4
  "author": "Dan <dan@flytedesk.com>",
5
5
  "description": "DanX Vue / Quasar component library",
6
6
  "license": "MIT",
@@ -11,7 +11,7 @@
11
11
  class="text-sm font-semibold"
12
12
  />
13
13
  <div
14
- v-if="!disable && !readonly"
14
+ v-if="!disable && !readonly && !hideControls"
15
15
  class="text-sm my-2"
16
16
  >
17
17
  <a
@@ -23,20 +23,21 @@
23
23
  class="ml-3 text-red-900"
24
24
  @click="clearUploadedFiles"
25
25
  >Clear</a>
26
- <input
27
- ref="file"
28
- class="hidden"
29
- type="file"
30
- multiple
31
- @change="onFilesSelected"
32
- >
33
26
  </div>
34
27
 
28
+ <input
29
+ ref="file"
30
+ class="hidden"
31
+ type="file"
32
+ multiple
33
+ @change="onFilesSelected"
34
+ >
35
+
35
36
  <div class="max-w-[50em] flex items-stretch justify-start">
36
37
  <FilePreview
37
38
  v-for="file in uploadedFiles"
38
39
  :key="'file-upload-' + file.id"
39
- class="w-32 m-2 cursor-pointer bg-gray-200"
40
+ class="w-32 h-32 m-2 cursor-pointer bg-gray-200"
40
41
  :class="{'border border-dashed border-blue-600': !uploadedFiles.length}"
41
42
  :image="file"
42
43
  :related-files="uploadedFiles"
@@ -46,7 +47,7 @@
46
47
  />
47
48
  <FilePreview
48
49
  v-if="!disable && !readonly"
49
- class="w-32 m-2 cursor-pointer border border-dashed border-blue-600"
50
+ class="w-32 h-32 m-2 cursor-pointer border border-dashed border-blue-600"
50
51
  disabled
51
52
  @click="$refs.file.click()"
52
53
  />
@@ -61,31 +62,33 @@
61
62
  </template>
62
63
 
63
64
  <script setup>
64
- import { onMounted } from "vue";
65
+ import { onMounted, watch } from "vue";
65
66
  import { useMultiFileUpload } from "../../../../helpers";
66
67
  import { FilePreview } from "../../../Utility";
67
68
  import FieldLabel from "./FieldLabel";
68
69
 
69
70
  const emit = defineEmits(["update:model-value"]);
70
71
  const props = defineProps({
71
- modelValue: {
72
- type: [Object, String],
73
- default: null
74
- },
75
- field: {
76
- type: Object,
77
- required: true
78
- },
79
- showName: Boolean,
80
- disable: Boolean,
81
- readonly: Boolean
72
+ modelValue: {
73
+ type: [Object, String],
74
+ default: null
75
+ },
76
+ field: {
77
+ type: Object,
78
+ required: true
79
+ },
80
+ showName: Boolean,
81
+ disable: Boolean,
82
+ readonly: Boolean,
83
+ hideControls: Boolean
82
84
  });
83
85
 
84
86
  const { onComplete, onDrop, onFilesSelected, uploadedFiles, clearUploadedFiles, onRemove } = useMultiFileUpload();
85
87
  onMounted(() => {
86
- if (props.modelValue) {
87
- uploadedFiles.value = props.modelValue;
88
- }
88
+ if (props.modelValue) {
89
+ uploadedFiles.value = props.modelValue;
90
+ }
89
91
  });
92
+ watch(() => props.modelValue, () => uploadedFiles.value = props.modelValue);
90
93
  onComplete(() => emit("update:model-value", uploadedFiles.value));
91
94
  </script>
@@ -24,10 +24,12 @@
24
24
  @update:model-value="onUpdate"
25
25
  >
26
26
  <template #append>
27
- <DropDownIcon
28
- class="w-4 transition"
29
- :class="isShowing ? 'rotate-180' : ''"
30
- />
27
+ <slot name="append">
28
+ <DropDownIcon
29
+ class="w-4 transition"
30
+ :class="isShowing ? 'rotate-180' : ''"
31
+ />
32
+ </slot>
31
33
  </template>
32
34
  <template #selected>
33
35
  <div
@@ -71,40 +73,40 @@ import { computed, isRef, nextTick, ref } from "vue";
71
73
 
72
74
  const emit = defineEmits(["update:model-value", "search", "update"]);
73
75
  const props = defineProps({
74
- ...QSelect.props,
75
- modelValue: {
76
- type: [Array, String, Number, Object],
77
- default: undefined
78
- },
79
- placeholder: {
80
- type: String,
81
- default: ""
82
- },
83
- selectionLabel: {
84
- type: String,
85
- default: null
86
- },
87
- chipLimit: {
88
- type: Number,
89
- default: 3
90
- },
91
- inputClass: {
92
- type: String,
93
- default: ""
94
- },
95
- selectionClass: {
96
- type: String,
97
- default: ""
98
- },
99
- options: {
100
- type: Array,
101
- default: () => []
102
- },
103
- filterable: Boolean,
104
- filterFn: {
105
- type: Function,
106
- default: null
107
- }
76
+ ...QSelect.props,
77
+ modelValue: {
78
+ type: [Array, String, Number, Object],
79
+ default: undefined
80
+ },
81
+ placeholder: {
82
+ type: String,
83
+ default: ""
84
+ },
85
+ selectionLabel: {
86
+ type: String,
87
+ default: null
88
+ },
89
+ chipLimit: {
90
+ type: Number,
91
+ default: 3
92
+ },
93
+ inputClass: {
94
+ type: String,
95
+ default: ""
96
+ },
97
+ selectionClass: {
98
+ type: String,
99
+ default: ""
100
+ },
101
+ options: {
102
+ type: Array,
103
+ default: () => []
104
+ },
105
+ filterable: Boolean,
106
+ filterFn: {
107
+ type: Function,
108
+ default: null
109
+ }
108
110
  });
109
111
 
110
112
  const selectField = ref(null);
@@ -119,27 +121,27 @@ const isShowing = ref(false);
119
121
  * @type {ComputedRef<{selectionLabel: string, label: string, value: string|*}[]>}
120
122
  */
121
123
  const computedOptions = computed(() => {
122
- let options = props.options;
123
- if (props.placeholder && !props.multiple && !props.filterable) {
124
- options = [{ label: props.placeholder, value: null }, ...props.options];
125
- }
126
- options = options.map((o) => {
127
- let opt = isRef(o) ? o.value : o;
128
- return {
129
- label: resolveLabel(opt),
130
- value: resolveValue(opt),
131
- selectionLabel: resolveSelectionLabel(opt)
132
- };
133
- });
134
- return options;
124
+ let options = props.options;
125
+ if (props.placeholder && !props.multiple && !props.filterable) {
126
+ options = [{ label: props.placeholder, value: null }, ...props.options];
127
+ }
128
+ options = options.map((o) => {
129
+ let opt = isRef(o) ? o.value : o;
130
+ return {
131
+ label: resolveLabel(opt),
132
+ value: resolveValue(opt),
133
+ selectionLabel: resolveSelectionLabel(opt)
134
+ };
135
+ });
136
+ return options;
135
137
  });
136
138
 
137
139
  const filteredOptions = computed(() => {
138
- if (filter.value && !props.filterFn) {
139
- return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value.toLowerCase()) > -1);
140
- } else {
141
- return computedOptions.value;
142
- }
140
+ if (filter.value && !props.filterFn) {
141
+ return computedOptions.value.filter(o => o.label.toLocaleLowerCase().indexOf(filter.value.toLowerCase()) > -1);
142
+ } else {
143
+ return computedOptions.value;
144
+ }
143
145
  });
144
146
 
145
147
  /**
@@ -147,14 +149,14 @@ const filteredOptions = computed(() => {
147
149
  * @type {ComputedRef<unknown>}
148
150
  */
149
151
  const selectedValue = computed(() => {
150
- if (props.multiple) {
151
- const arrVal = Array.isArray(props.modelValue) ? props.modelValue : [];
152
- return arrVal.map((v) => {
153
- return v === null ? "__null__" : v;
154
- }) || [];
155
- } else {
156
- return props.modelValue === null ? "__null__" : props.modelValue;
157
- }
152
+ if (props.multiple) {
153
+ const arrVal = Array.isArray(props.modelValue) ? props.modelValue : [];
154
+ return arrVal.map((v) => {
155
+ return v === null ? "__null__" : v;
156
+ }) || [];
157
+ } else {
158
+ return props.modelValue === null ? "__null__" : props.modelValue;
159
+ }
158
160
  });
159
161
 
160
162
  /**
@@ -162,13 +164,13 @@ const selectedValue = computed(() => {
162
164
  * @type {ComputedRef<*>}
163
165
  */
164
166
  const selectedOptions = computed(() => {
165
- let values = selectedValue.value;
166
- if (!props.multiple) {
167
- values = (values || values === 0) ? [values] : [];
168
- }
169
- return computedOptions.value.filter((o) => {
170
- return values.includes(o.value) || values.map(v => typeof v === "object" && v.id).includes(o.value?.id);
171
- });
167
+ let values = selectedValue.value;
168
+ if (!props.multiple) {
169
+ values = (values || values === 0) ? [values] : [];
170
+ }
171
+ return computedOptions.value.filter((o) => {
172
+ return values.includes(o.value) || values.map(v => typeof v === "object" && v.id).includes(o.value?.id);
173
+ });
172
174
  });
173
175
 
174
176
  /**
@@ -177,12 +179,12 @@ const selectedOptions = computed(() => {
177
179
  * @type {ComputedRef<unknown>}
178
180
  */
179
181
  const selectedLabel = computed(() => {
180
- if (props.filterable && isShowing.value) return "";
182
+ if (props.filterable && isShowing.value) return "";
181
183
 
182
- if (!selectedOptions.value || selectedOptions.value.length === 0) {
183
- return props.placeholder || "(Select Option)";
184
- }
185
- return selectedOptions.value[0].selectionLabel;
184
+ if (!selectedOptions.value || selectedOptions.value.length === 0) {
185
+ return props.placeholder || "(Select Option)";
186
+ }
187
+ return selectedOptions.value[0].selectionLabel;
186
188
  });
187
189
 
188
190
  /**
@@ -190,7 +192,7 @@ const selectedLabel = computed(() => {
190
192
  * @type {ComputedRef<*>}
191
193
  */
192
194
  const chipOptions = computed(() => {
193
- return selectedOptions.value.slice(0, props.chipLimit);
195
+ return selectedOptions.value.slice(0, props.chipLimit);
194
196
  });
195
197
 
196
198
  /**
@@ -199,16 +201,16 @@ const chipOptions = computed(() => {
199
201
  * @returns {*|string}
200
202
  */
201
203
  function resolveLabel(option) {
202
- if (typeof option === "string") {
203
- return option;
204
- }
205
- if (typeof props.optionLabel === "string") {
206
- return option[props.optionLabel];
207
- }
208
- if (typeof props.optionLabel === "function") {
209
- return props.optionLabel(option);
210
- }
211
- return option?.label;
204
+ if (typeof option === "string") {
205
+ return option;
206
+ }
207
+ if (typeof props.optionLabel === "string") {
208
+ return option[props.optionLabel];
209
+ }
210
+ if (typeof props.optionLabel === "function") {
211
+ return props.optionLabel(option);
212
+ }
213
+ return option?.label;
212
214
  }
213
215
 
214
216
  /**
@@ -218,16 +220,16 @@ function resolveLabel(option) {
218
220
  * @returns {*|{default: null, type: String | StringConstructor}|string}
219
221
  */
220
222
  function resolveSelectionLabel(option) {
221
- if (typeof option === "string") {
222
- return option;
223
- }
224
- if (typeof props.selectionLabel === "string") {
225
- return option[props.selectionLabel];
226
- }
227
- if (typeof props.selectionLabel === "function") {
228
- return props.selectionLabel(option);
229
- }
230
- return option?.selectionLabel || option?.label;
223
+ if (typeof option === "string") {
224
+ return option;
225
+ }
226
+ if (typeof props.selectionLabel === "string") {
227
+ return option[props.selectionLabel];
228
+ }
229
+ if (typeof props.selectionLabel === "function") {
230
+ return props.selectionLabel(option);
231
+ }
232
+ return option?.selectionLabel || option?.label;
231
233
  }
232
234
 
233
235
  /**
@@ -236,17 +238,17 @@ function resolveSelectionLabel(option) {
236
238
  * @returns {string|*|string}
237
239
  */
238
240
  function resolveValue(option) {
239
- if (!option || typeof option === "string") {
240
- return option;
241
- }
242
- let value = option.value;
243
- if (typeof props.optionValue === "string") {
244
- value = option[props.optionValue];
245
- } else if (typeof props.optionValue === "function") {
246
- value = props.optionValue(option);
247
- }
248
- // Note the __null__ special case here. See the onUpdate function for more details
249
- return value === null ? "__null__" : value;
241
+ if (!option || typeof option === "string") {
242
+ return option;
243
+ }
244
+ let value = option.value;
245
+ if (typeof props.optionValue === "string") {
246
+ value = option[props.optionValue];
247
+ } else if (typeof props.optionValue === "function") {
248
+ value = props.optionValue(option);
249
+ }
250
+ // Note the __null__ special case here. See the onUpdate function for more details
251
+ return value === null ? "__null__" : value;
250
252
  }
251
253
 
252
254
  /**
@@ -256,14 +258,14 @@ function resolveValue(option) {
256
258
  * @param value
257
259
  */
258
260
  function onUpdate(value) {
259
- if (Array.isArray(value)) {
260
- value = value.map((v) => v === "__null__" ? null : v);
261
- }
261
+ if (Array.isArray(value)) {
262
+ value = value.map((v) => v === "__null__" ? null : v);
263
+ }
262
264
 
263
- value = value === "__null__" ? null : value;
265
+ value = value === "__null__" ? null : value;
264
266
 
265
- emit("update", value);
266
- emit("update:model-value", value);
267
+ emit("update", value);
268
+ emit("update:model-value", value);
267
269
  }
268
270
 
269
271
  /** XXX: This tells us when we should apply the filter. QSelect likes to trigger a new filter everytime you open the dropdown
@@ -277,19 +279,19 @@ const shouldFilter = ref(false);
277
279
  * @param update
278
280
  */
279
281
  async function onFilter(val, update) {
280
- if (!props.filterFn) {
281
- filter.value = val;
282
- await nextTick(update);
283
- } else {
284
- update();
285
- if (shouldFilter.value === false) return;
286
- if (val !== null && val !== filter.value) {
287
- filter.value = val;
288
- if (props.filterFn) {
289
- await props.filterFn(val);
290
- }
291
- }
292
- }
282
+ if (!props.filterFn) {
283
+ filter.value = val;
284
+ await nextTick(update);
285
+ } else {
286
+ update();
287
+ if (shouldFilter.value === false) return;
288
+ if (val !== null && val !== filter.value) {
289
+ filter.value = val;
290
+ if (props.filterFn) {
291
+ await props.filterFn(val);
292
+ }
293
+ }
294
+ }
293
295
  }
294
296
 
295
297
  /**
@@ -297,29 +299,29 @@ async function onFilter(val, update) {
297
299
  * See the onUpdate function for more details
298
300
  */
299
301
  function onClear() {
300
- emit("update:model-value", undefined);
301
- emit("update", undefined);
302
+ emit("update:model-value", undefined);
303
+ emit("update", undefined);
302
304
  }
303
305
 
304
306
  /**
305
307
  * Handle behavior when showing the dropdown
306
308
  */
307
309
  function onShow() {
308
- isShowing.value = true;
310
+ isShowing.value = true;
309
311
 
310
- // XXX: See description on shouldFilter declaration. Only allow filtering after dropdown is ALREADY opened
311
- shouldFilter.value = false;
312
- nextTick(() => {
313
- shouldFilter.value = true;
314
- selectField.value.focus();
315
- });
312
+ // XXX: See description on shouldFilter declaration. Only allow filtering after dropdown is ALREADY opened
313
+ shouldFilter.value = false;
314
+ nextTick(() => {
315
+ shouldFilter.value = true;
316
+ selectField.value.focus();
317
+ });
316
318
  }
317
319
 
318
320
  /**
319
321
  * Handle behavior when hiding the dropdown
320
322
  */
321
323
  function onHide() {
322
- isShowing.value = false;
323
- shouldFilter.value = false;
324
+ isShowing.value = false;
325
+ shouldFilter.value = false;
324
326
  }
325
327
  </script>
@@ -156,7 +156,7 @@ export function useListControls({
156
156
  }
157
157
 
158
158
  // Add a reactive isSaving property to each item (for performance reasons in checking saving state)
159
- data = data.map((item: any) => {
159
+ data = data?.map((item: any) => {
160
160
  // We want to keep the isSaving state if it is already set, as optimizations prevent reloading the
161
161
  // components, and therefore reactivity is not responding to the new isSaving state
162
162
  const oldItem = pagedItems.value?.data?.find(i => i.id === item.id);
@@ -182,7 +182,7 @@ export function useListControls({
182
182
  const data = pagedItems.value?.data?.map(item => (item.id === updatedItem.id && (item.updated_at === null || item.updated_at <= updatedItem.updated_at)) ? updatedItem : item);
183
183
  setPagedItems({
184
184
  data,
185
- meta: { total: pagedItems.value.meta.total }
185
+ meta: { total: pagedItems.value?.meta?.total || 0 }
186
186
  });
187
187
 
188
188
  // Update the active item as well if it is set
@@ -205,8 +205,8 @@ export function useListControls({
205
205
 
206
206
  if (newItems && newItems.length > 0) {
207
207
  setPagedItems({
208
- data: [...pagedItems.value.data, ...newItems],
209
- meta: { total: pagedItems.value.meta.total }
208
+ data: [...pagedItems.value?.data || [], ...newItems],
209
+ meta: { total: pagedItems.value?.meta?.total || 0 }
210
210
  });
211
211
  return true;
212
212
  }
@@ -34,6 +34,7 @@
34
34
  <slot>{{ content }}</slot>
35
35
  </QCardSection>
36
36
  <div
37
+ v-if="!hideButtons"
37
38
  class="flex items-center justify-center px-6 py-4 border-t border-gray-300"
38
39
  >
39
40
  <div class="flex-grow text-right">
@@ -61,35 +62,36 @@ import { XIcon as CloseIcon } from "@heroicons/vue/outline";
61
62
 
62
63
  const emit = defineEmits(["update:model-value", "close"]);
63
64
  defineProps({
64
- modelValue: { type: [Boolean, Object], default: true },
65
- title: {
66
- type: String,
67
- default: ""
68
- },
69
- titleClass: {
70
- type: String,
71
- default: ""
72
- },
73
- subtitle: {
74
- type: String,
75
- default: ""
76
- },
77
- content: {
78
- type: String,
79
- default: ""
80
- },
81
- backdropDismiss: Boolean,
82
- maximized: Boolean,
83
- fullWidth: Boolean,
84
- fullHeight: Boolean,
85
- doneText: {
86
- type: String,
87
- default: "Done"
88
- }
65
+ modelValue: { type: [Boolean, Object], default: true },
66
+ title: {
67
+ type: String,
68
+ default: ""
69
+ },
70
+ titleClass: {
71
+ type: String,
72
+ default: ""
73
+ },
74
+ subtitle: {
75
+ type: String,
76
+ default: ""
77
+ },
78
+ content: {
79
+ type: String,
80
+ default: ""
81
+ },
82
+ backdropDismiss: Boolean,
83
+ hideButtons: Boolean,
84
+ maximized: Boolean,
85
+ fullWidth: Boolean,
86
+ fullHeight: Boolean,
87
+ doneText: {
88
+ type: String,
89
+ default: "Done"
90
+ }
89
91
  });
90
92
 
91
93
  function onClose() {
92
- emit("update:model-value", false);
93
- emit("close");
94
+ emit("update:model-value", false);
95
+ emit("close");
94
96
  }
95
97
  </script>