@qikdev/vue-ui 0.0.1 → 0.0.2

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.
Files changed (72) hide show
  1. package/package.json +6 -2
  2. package/src/components.js +209 -6
  3. package/src/content/browser.vue +477 -0
  4. package/src/content/item.vue +48 -0
  5. package/src/content/render/field.vue +423 -0
  6. package/src/content/render/group.vue +65 -0
  7. package/src/content/render/render-mixin.js +101 -0
  8. package/src/content/render/render.vue +86 -0
  9. package/src/filter/FilterBuilder.vue +147 -0
  10. package/src/filter/FilterCondition.vue +335 -0
  11. package/src/filter/FilterRule.vue +257 -0
  12. package/src/form/expressions/index.js +83 -0
  13. package/src/form/field.vue +624 -0
  14. package/src/form/form.vue +280 -0
  15. package/src/form/getDefaultValue.js +224 -0
  16. package/src/form/inputs/button-select.vue +208 -0
  17. package/src/form/inputs/checkbox.vue +91 -0
  18. package/src/form/inputs/content-select.vue +187 -0
  19. package/src/form/inputs/currency.vue +205 -0
  20. package/src/form/inputs/datefield.vue +132 -0
  21. package/src/form/inputs/group.vue +155 -0
  22. package/src/form/inputs/input-mixin.js +440 -0
  23. package/src/form/inputs/native-select-old.vue +43 -0
  24. package/src/form/inputs/object-field.vue +50 -0
  25. package/src/form/inputs/option.vue +19 -0
  26. package/src/form/inputs/options-manager.vue +244 -0
  27. package/src/form/inputs/phone-number-input.vue +235 -0
  28. package/src/form/inputs/search.vue +117 -0
  29. package/src/form/inputs/select.vue +211 -0
  30. package/src/form/inputs/switch.vue +87 -0
  31. package/src/form/inputs/textarea.vue +80 -0
  32. package/src/form/inputs/textfield.vue +165 -0
  33. package/src/form/inputs/timezone.vue +642 -0
  34. package/src/form/inputs/upload/filedrop.vue +72 -0
  35. package/src/form/inputs/upload/upload.vue +323 -0
  36. package/src/form/parseBoolean.js +24 -0
  37. package/src/layout/flex-body.vue +3 -2
  38. package/src/layout/flex-cell.vue +45 -0
  39. package/src/layout/flex-column.vue +1 -1
  40. package/src/layout/flex-footer.vue +3 -2
  41. package/src/layout/flex-header.vue +3 -2
  42. package/src/layout/flex-row.vue +35 -0
  43. package/src/layout/flex-spacer.vue +17 -0
  44. package/src/layout/panel-body.vue +13 -0
  45. package/src/layout/panel-footer.vue +20 -0
  46. package/src/layout/panel-header.vue +20 -0
  47. package/src/layout/panel.vue +23 -0
  48. package/src/modal/ConfirmModal.vue +50 -0
  49. package/src/modal/ContentModal.vue +99 -0
  50. package/src/modal/Modal.vue +85 -0
  51. package/src/modal/ModalMixin.js +21 -0
  52. package/src/modal/OptionsModal.vue +31 -0
  53. package/src/modal/PromptModal.vue +31 -0
  54. package/src/services/selection.js +140 -0
  55. package/src/table/Table.vue +269 -0
  56. package/src/table/TableCell.vue +64 -0
  57. package/src/table/TableRow.vue +94 -0
  58. package/src/table/cells/TableCellMixin.js +15 -0
  59. package/src/table/cells/Thumbnail.vue +38 -0
  60. package/src/ui/button.vue +254 -0
  61. package/src/ui/checkbox.vue +79 -0
  62. package/src/ui/icon.vue +57 -0
  63. package/src/ui/image.vue +158 -0
  64. package/src/ui/link.vue +62 -0
  65. package/src/ui/list-item.vue +16 -0
  66. package/src/ui/list.vue +26 -0
  67. package/src/ui/menu.vue +135 -0
  68. package/src/ui/progressbar.vue +77 -0
  69. package/src/ui/spinner.vue +26 -0
  70. package/src/ui/switch.vue +89 -0
  71. package/yarn-error.log +2923 -0
  72. package/index.js +0 -14
@@ -0,0 +1,423 @@
1
+ <template>
2
+ <div class="ux-field-render" v-if="visible" :class="classes">
3
+ <label class="ux-field-title">{{title}}</label>
4
+ <div class="ux-field-description">{{field.description}}</div>
5
+ <template v-if="type == 'reference'">
6
+ <template v-if="multiValue">
7
+ <item :key="item._id" :item="item" v-for="(item, index) in fieldModel" />
8
+ </template>
9
+ <template v-else>
10
+ <item :item="fieldModel" />
11
+ </template>
12
+ </template>
13
+ <template v-if="widget == 'group'">
14
+ <template v-if="asObject">
15
+ <field-group :field="field" :parentModel="parentModel" v-model="fieldModel" />
16
+ </template>
17
+ <template v-else>
18
+ <field-group :field="field" :parentModel="parentModel" v-model="sourceModel" />
19
+ </template>
20
+ </template>
21
+ <!-- <template v-if="type == 'group'">
22
+ <template v-if="multiValue">
23
+ <item :key="item._id" :item="item" v-for="(item, index) in fieldModel" />
24
+ </template>
25
+ <template v-else>
26
+ <item :item="fieldModel" />
27
+ </template>
28
+ </template> -->
29
+ <template v-if="type == 'string'">
30
+ <template v-if="multiValue">
31
+ <div v-for="(value, index) in fieldModel">
32
+ {{value}}
33
+ </div>
34
+ </template>
35
+ <template v-else>
36
+ <div>{{fieldModel}}</div>
37
+ </template>
38
+ </template>
39
+ <template v-if="type == 'date'">
40
+ <template v-if="multiValue">
41
+ <div v-for="(value, index) in fieldModel">
42
+ {{value}}
43
+ </div>
44
+ </template>
45
+ <template v-else>
46
+ <div>
47
+ {{fieldModel}}
48
+ </div>
49
+ </template>
50
+ </template>
51
+ <template v-if="type == 'email'">
52
+ <template v-if="multiValue">
53
+ <div v-for="(value, index) in fieldModel">
54
+ <a :href="`mailto:${value}`">{{value}}</a>
55
+ </div>
56
+ </template>
57
+ <template v-else>
58
+ <div>
59
+ <a :href="`mailto:${fieldModel}`">{{fieldModel}}</a>
60
+ </div>
61
+ </template>
62
+ </template>
63
+ <template v-if="type == 'url'">
64
+ <template v-if="multiValue">
65
+ <div v-for="(value, index) in fieldModel">
66
+ <a :href="value">{{value}}</a>
67
+ </div>
68
+ </template>
69
+ <template v-else>
70
+ <div>
71
+ <a :href="fieldModel">{{fieldModel}}</a>
72
+ </div>
73
+ </template>
74
+ </template>
75
+ <template v-if="isNumber">
76
+ <template v-if="multiValue">
77
+ <div v-for="(value, index) in fieldModel">
78
+ {{value}}
79
+ </div>
80
+ </template>
81
+ <template v-else>
82
+ <div>{{fieldModel}}</div>
83
+ </template>
84
+ </template>
85
+ <!-- <pre>{{fieldModel}}</pre> -->
86
+ <!-- <template v-if="widget == 'group'">
87
+ <template v-if="asObject">
88
+ <field-group :field="actualField" :parentModel="parentModel" v-model="fieldModel" />
89
+ </template>
90
+ <template v-else>
91
+ <field-group :field="actualField" :parentModel="parentModel" v-model="sourceModel" />
92
+ </template>
93
+ </template> -->
94
+ <!-- <template v-if="widget == 'checkbox'">
95
+ <checkbox @touched="touch" :field="actualField" v-model="fieldModel" />
96
+ </template>
97
+ <template v-if="widget == 'switch'">
98
+ <boolean-switch @touched="touch" :field="actualField" v-model="fieldModel" />
99
+ </template>
100
+ <template v-if="widget == 'upload'">
101
+ <upload @touched="touch" :field="actualField" v-model="fieldModel" />
102
+ </template>
103
+
104
+ <template v-if="widget == 'select'">
105
+ <native-select @touched="touch" :field="actualField" v-model="fieldModel" />
106
+ </template>
107
+ <template v-if="widget == 'buttons'">
108
+ <button-select @touched="touch" :field="actualField" v-model="fieldModel" />
109
+ </template>
110
+ <template v-if="widget == 'textfield'">
111
+ <text-field @touched="touch" :field="actualField" v-model="fieldModel" />
112
+ </template>
113
+ <template v-if="widget == 'currency'">
114
+ <currency-field @touched="touch" :field="actualField" v-model="fieldModel" />
115
+ </template>
116
+ <template v-if="widget == 'datefield'">
117
+ <date-field @touched="touch" :field="actualField" v-model="fieldModel" />
118
+ </template>
119
+ <template v-if="widget == 'content-select'">
120
+ <content-select @touched="touch" :field="actualField" v-model="fieldModel" />
121
+ </template>
122
+ <template v-if="widget == 'richtext'">
123
+ <text-area @touched="touch" :field="actualField" v-model="fieldModel" />
124
+ </template>
125
+ <template v-if="widget == 'longtext'">
126
+ <text-area @touched="touch" :field="actualField" v-model="fieldModel" />
127
+ </template>
128
+ <template v-if="widget == 'value'">
129
+ </template>
130
+ <div v-if="error && validateResults.message" class="ux-field-message">
131
+ {{validateResults.message}}
132
+ </div> -->
133
+ </div>
134
+ </template>
135
+ <script>
136
+ import Item from '../item.vue';
137
+
138
+ //Inputs
139
+ // import ContentSelect from './inputs/content-select.vue';
140
+ // import CurrencyField from './inputs/currency.vue';
141
+ // import TextField from './inputs/textfield.vue';
142
+ // import TextArea from './inputs/textarea.vue';
143
+ // import DateField from './inputs/datefield.vue';
144
+ // import Checkbox from './inputs/checkbox.vue';
145
+ // import Switch from './inputs/switch.vue';
146
+ // import Upload from './inputs/upload/upload.vue';
147
+ import FieldGroup from './group.vue';
148
+ // import NativeSelect from './inputs/select.vue';
149
+ // import ButtonSelect from './inputs/button-select.vue';
150
+
151
+ import Expressions from '../../form/expressions';
152
+
153
+ ////////////////////////////////////////
154
+
155
+ function computedExpression(key) {
156
+ return function() {
157
+ var self = this;
158
+ if (!self.expressions) {
159
+ return;
160
+ }
161
+
162
+ let expression = self.expressions[key];
163
+ if (!expression) {
164
+ return;
165
+ }
166
+
167
+ let context = self.expressionsContext;
168
+ return Expressions.evaluateExpression(expression, context);
169
+ }
170
+ }
171
+
172
+
173
+ export default {
174
+ components: {
175
+ Item,
176
+ FieldGroup,
177
+ // ButtonSelect,
178
+ // NativeSelect,
179
+ // DateField,
180
+ // TextField,
181
+ // CurrencyField,
182
+ // TextArea,
183
+ // Checkbox,
184
+ // BooleanSwitch: Switch,
185
+ // FieldGroup,
186
+ // ContentSelect,
187
+ // Upload,
188
+ },
189
+ props: {
190
+ field: {
191
+ type: Object,
192
+ required: true,
193
+ },
194
+ parentModel: {
195
+ type: Object,
196
+ },
197
+ modelValue: {
198
+ type: Object,
199
+ required: true,
200
+ },
201
+ },
202
+ data() {
203
+ return {
204
+ model: this.modelValue,
205
+ }
206
+ },
207
+ // created() {
208
+ // // if (this.visible) {
209
+ // // var currentValue = this.fieldModel;
210
+ // // var defaultValue = this.fieldModel || this.expressions && this.expressions.defaultValue ? this.getExpressionDefaultValue : getDefaultValue(this.actualField);
211
+ // // if (!currentValue) {
212
+ // // // console.log(this.actualField.key, this.actualField.title, defaultValue);
213
+ // // if (this.fieldModel != defaultValue) {
214
+ // // this.fieldModel = defaultValue;
215
+ // // }
216
+ // // }
217
+ // // }
218
+
219
+ // },
220
+ methods: {
221
+ cleanInput(val) {
222
+ return val;
223
+ },
224
+ cleanOutput(val) {
225
+ return val;
226
+ }
227
+ },
228
+ watch: {
229
+ modelValue(val, old) {
230
+ this.model = val;
231
+ },
232
+ },
233
+ computed: {
234
+ type() {
235
+ return this.field.type || 'string';
236
+ },
237
+ isGroup() {
238
+ return this.type === 'group'
239
+ },
240
+ asObject() {
241
+ return this.isGroup && this.field.asObject;
242
+ },
243
+ isNumber() {
244
+ switch (this.type) {
245
+ case 'integer':
246
+ case 'number':
247
+ case 'float':
248
+ case 'decimal':
249
+ return true;
250
+ break;
251
+ }
252
+ },
253
+ multiValue() {
254
+ return this.field.maximum != 1;
255
+ },
256
+ title() {
257
+ return this.field.title;
258
+ },
259
+ getExpressionHide() {
260
+ if (!this.expressions) {
261
+ return;
262
+ }
263
+
264
+ let showExpression = this.expressions.show;
265
+ let hideExpression = this.expressions.hide;
266
+ let context = this.expressionsContext;
267
+
268
+ if (showExpression) {
269
+ return !!!Expressions.evaluateExpression(showExpression, context);
270
+ } else if (hideExpression) {
271
+ return Expressions.evaluateExpression(hideExpression, context);
272
+ }
273
+ },
274
+ expressions() {
275
+ return this.field.expressions;
276
+ },
277
+ expressionsContext() {
278
+ return {
279
+ this: this.model,
280
+ model: this.model,
281
+ data: this.parentModel,
282
+ }
283
+ },
284
+ hidden() {
285
+ return this.getExpressionHide;
286
+ },
287
+ visible() {
288
+ return !this.hidden && this.fieldModel;
289
+ },
290
+ type() {
291
+ return this.field.type || 'string';
292
+ },
293
+ key() {
294
+ return this.field.key;
295
+ },
296
+ isGroup() {
297
+ return this.type === 'group'
298
+ },
299
+ asObject() {
300
+ return this.isGroup && this.field.asObject;
301
+ },
302
+ layoutGroup() {
303
+ return this.isGroup && !this.field.asObject;
304
+ },
305
+ fieldModel: {
306
+ get() {
307
+ return this.cleanOutput(this.model[this.key]);
308
+ },
309
+ set(value) {
310
+ // this.model[this.key] = this.cleanInput(value);
311
+ // this.$emit('update:modelValue', this.model);
312
+ }
313
+ },
314
+ sourceModel: {
315
+ get() {
316
+ return this.model;
317
+ },
318
+ set(value) {
319
+ // this.model = value;
320
+ // this.$emit('update:modelValue', this.model);
321
+ }
322
+ },
323
+ classes() {
324
+ var array = [];
325
+ array.push(`ux-field-render-${this.type}`)
326
+
327
+ if (this.layoutGroup) {
328
+ array.push('ux-layout-only');
329
+ }
330
+
331
+ return array;
332
+ },
333
+ widget() {
334
+
335
+ //We're a group
336
+ if (this.type == 'group') {
337
+ return this.type;
338
+ }
339
+
340
+ //Get the widget
341
+ var widget = this.field.widget;
342
+
343
+ ///////////////////////////////
344
+
345
+
346
+ ///////////////////////////////
347
+
348
+ switch (widget) {
349
+ case 'content-select':
350
+ case 'select':
351
+ case 'checkbox':
352
+ case 'datefield':
353
+ case 'richtext':
354
+ case 'longtext':
355
+ case 'buttons':
356
+ case 'switch':
357
+ case 'email':
358
+ case 'url':
359
+ case 'currency':
360
+ case 'timezone':
361
+ case 'country':
362
+ case 'typeselect':
363
+ case 'upload':
364
+ break;
365
+ default:
366
+ switch (this.type) {
367
+ case 'date':
368
+ widget = 'datefield';
369
+ break;
370
+ case 'reference':
371
+ widget = 'content-select';
372
+ break;
373
+ case 'boolean':
374
+ widget = 'checkbox';
375
+ break;
376
+ default:
377
+ case 'string':
378
+ widget = 'textfield';
379
+ break;
380
+ }
381
+ break;
382
+ }
383
+
384
+ return widget;
385
+
386
+ },
387
+ },
388
+
389
+ }
390
+ </script>
391
+ <style lang="scss" scoped>
392
+ .ux-field-render {
393
+ margin-bottom: 1.5em;
394
+
395
+ &.ux-layout-only {
396
+ margin-bottom: 0;
397
+ }
398
+ }
399
+
400
+
401
+
402
+ :deep(.ux-field-title) {
403
+ // .ux-field-title {
404
+ margin-top: 0.5em;
405
+ display: block;
406
+ margin-bottom: 0.2em;
407
+ font-size: 0.9em;
408
+ font-weight: bold;
409
+ }
410
+
411
+
412
+ :deep(.ux-field-description) {
413
+ // .ux-field-description {
414
+ font-size: 0.8em;
415
+ opacity: 0.5;
416
+ margin-bottom: 0.5em;
417
+
418
+ }
419
+
420
+ :deep(.ux-form-flex .ux-field-description) {
421
+ // min-height: 2.6em;
422
+ }
423
+ </style>
@@ -0,0 +1,65 @@
1
+ <template>
2
+ <div class="ux-multi-group" v-if="multiValue">
3
+ <panel ref="row" :key="entry" v-for="(entry, index) in model">
4
+ <panel-header>
5
+ <flex-row>
6
+ <flex-cell vcenter>
7
+ <div>
8
+ <strong>{{multiLabel(entry, index)}}</strong>
9
+ </div>
10
+ </flex-cell>
11
+ </flex-row>
12
+ </panel-header>
13
+ <panel-body>
14
+ <ux-render :fields="fields" :flex="sameLine" :parentModel="parentModel" v-model="model[index]" />
15
+ </panel-body>
16
+ </panel>
17
+ </div>
18
+ <template v-else>
19
+ <ux-render :fields="fields" :flex="sameLine" :parentModel="parentModel" v-model="model" />
20
+ <!-- <ux-form ref="form" @form:state="stateChange" :parentModel="parentModel" v-model="model" :flex="sameLine" :fields="field.fields" /> -->
21
+ </template>
22
+ </template>
23
+ <script>
24
+ import RenderMixin from './render-mixin.js';
25
+
26
+ export default {
27
+ mixins: [RenderMixin],
28
+ props: {
29
+ modelValue: {
30
+ type: [Object, Array],
31
+ },
32
+ },
33
+ // created() {
34
+ // // this.value = this.cleanInput(this.value, true);
35
+ // },
36
+ computed: {
37
+ sameLine() {
38
+ return this.field.sameLine;
39
+ }
40
+ },
41
+ methods: {
42
+ multiLabel(entry, index) {
43
+
44
+ if (entry.name) {
45
+ return entry.name;
46
+ }
47
+
48
+ if (entry.title) {
49
+ return entry.title;
50
+ }
51
+
52
+ if (entry.firstName) {
53
+ return entry.firstName;
54
+ }
55
+
56
+ return `${this.label} ${index+1}`
57
+ },
58
+ }
59
+ }
60
+ </script>
61
+ <style lang="scss" scoped>
62
+ .ux-multi-group {
63
+ margin-bottom: 1em;
64
+ }
65
+ </style>
@@ -0,0 +1,101 @@
1
+
2
+ export default {
3
+ props: {
4
+ field: {
5
+ type: Object,
6
+ default () {
7
+ return {}
8
+ },
9
+ },
10
+ parentModel: {
11
+ type: Object,
12
+ },
13
+ },
14
+ data() {
15
+ return {
16
+ model: this.modelValue,
17
+ }
18
+ },
19
+ methods: {
20
+ getValue(option) {
21
+ if (!option) {
22
+ return;
23
+ }
24
+
25
+ return option._id || option.value || option;
26
+ },
27
+ getLabel(option) {
28
+ if (!option) {
29
+ return;
30
+ }
31
+
32
+ return option.title || option.name || option.label || option;
33
+ },
34
+ },
35
+ computed:{
36
+ label() {
37
+ return this.field.title;
38
+ },
39
+ description() {
40
+ return this.field.description;
41
+ },
42
+ singleValue() {
43
+ return this.maximum == 1;
44
+ },
45
+ multiValue() {
46
+ return this.maximum != 1;
47
+ },
48
+ key() {
49
+ return this.field.key;
50
+ },
51
+ isGroup() {
52
+ return this.type === 'group'
53
+ },
54
+ asObject() {
55
+ return this.isGroup && !!this.field.asObject;
56
+ },
57
+ layoutGroup() {
58
+ return this.isGroup && !this.field.asObject;
59
+ },
60
+ numValues() {
61
+ if (!this.multiValue) {
62
+ return 1;
63
+ }
64
+
65
+ return (this.model || []).length;
66
+ },
67
+ fields() {
68
+ var subFields = this.field.fields;
69
+
70
+ if (subFields && subFields.length) {
71
+ return subFields;
72
+ }
73
+ },
74
+ minimum() {
75
+ if (this.layoutGroup) {
76
+ return 1;
77
+ }
78
+
79
+ var int = parseInt(this.field.minimum || 0);
80
+ if (isNaN(int)) {
81
+ int = 0;
82
+ }
83
+
84
+ int = Math.max(int, 0)
85
+ int = this.maximum ? Math.min(int, this.maximum) : int;
86
+ return parseInt(int);
87
+ },
88
+ maximum() {
89
+ if (this.layoutGroup) {
90
+ return 1;
91
+ }
92
+
93
+ var int = parseInt(this.field.maximum || 0);
94
+ if (isNaN(int)) {
95
+ int = 0;
96
+ }
97
+ int = Math.max(int, 0)
98
+ return parseInt(int);
99
+ },
100
+ }
101
+ }
@@ -0,0 +1,86 @@
1
+ <template>
2
+ <div class="ux-render" :class="renderClass">
3
+ <slot name="render" :fields="fields">
4
+ <ux-field-render :field="field" v-model="model" :parentModel="parentModel || model" :key="`ux-render-field-${field.key}-${index}`" :class="fieldClass" v-for="(field, index) in renderFields" />
5
+ </slot>
6
+ </div>
7
+ </template>
8
+ <script>
9
+ import UXFieldRender from './field.vue';
10
+
11
+ export default {
12
+ props: {
13
+ parentModel: {
14
+ type: Object,
15
+ },
16
+ fields: {
17
+ type: Array,
18
+ default () {
19
+ return []
20
+ }
21
+ },
22
+ modelValue: {
23
+ type: Object,
24
+ default () {
25
+ return {}
26
+ }
27
+ },
28
+ flex: {
29
+ type: Boolean,
30
+ default: false,
31
+ },
32
+ },
33
+ watch: {
34
+ modelValue(val, old) {
35
+ this.model = val;
36
+ },
37
+ },
38
+ data() {
39
+ return {
40
+ model: this.modelValue,
41
+ }
42
+ },
43
+ components: {
44
+ UxFieldRender: UXFieldRender,
45
+ },
46
+ computed: {
47
+ renderClass() {
48
+ var array = [];
49
+
50
+ if (this.flex) {
51
+ array.push('ux-render-flex');
52
+ }
53
+ return array;
54
+ },
55
+
56
+ fieldClass() {
57
+ var array = [];
58
+
59
+ if (this.flex) {
60
+ array.push('ux-field-render-flex');
61
+ }
62
+ return array;
63
+ },
64
+ renderFields() {
65
+ return this.fields;
66
+ }
67
+ }
68
+ }
69
+ </script>
70
+ <style lang="scss" scoped>
71
+ .ux-render-flex {
72
+ display: flex;
73
+ flex: 1;
74
+ gap: 2em;
75
+
76
+ .ux-field-render-flex {
77
+ flex: 1;
78
+ // display: flex;
79
+ // align-items: flex-end;
80
+
81
+ // & > .ux-field {
82
+ // flex:1;
83
+ // }
84
+ }
85
+ }
86
+ </style>