@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,280 @@
1
+ <template>
2
+ <div class="ux-form" :class="formClass">
3
+ <slot name="fields" :fields="renderFields" :hash="fieldHash">
4
+ <ux-field ref="field" @field:mount="fieldMounted" @field:unmount="fieldUnmounted" @field:dirty="fieldDirty" @field:invalid="fieldInvalid" @field:valid="fieldValid" @field:error="fieldError" @field:focus="fieldFocus" @field:blur="fieldBlur" @field:touched="fieldTouch" :field="field" v-model="formModel" :parentModel="parentModel || formModel" :class="fieldClass" :key="`ux-form-field-${field.key}-${index}`" v-for="(field, index) in renderFields" />
5
+ </slot>
6
+ </div>
7
+ </template>
8
+ <script>
9
+ import UXField from './field.vue';
10
+ import debounce from 'lodash/debounce';
11
+
12
+ export default {
13
+ props: {
14
+ parentModel: {
15
+ type: Object,
16
+ },
17
+ fields: {
18
+ type: Array,
19
+ default () {
20
+ return []
21
+ }
22
+ },
23
+ modelValue: {
24
+ type: Object,
25
+ default () {
26
+ return {}
27
+ }
28
+ },
29
+ flex: {
30
+ type: Boolean,
31
+ default: false,
32
+ },
33
+ },
34
+ watch: {
35
+ modelValue(val, old) {
36
+ this.model = val;
37
+ },
38
+ },
39
+ data() {
40
+
41
+ // console.log('start', JSON.parse(JSON.stringify(this.modelValue)));
42
+
43
+ return {
44
+ mounted: false,
45
+ model: this.modelValue,
46
+ touched: false,
47
+ invalid: false,
48
+ error: false,
49
+ dirty: false,
50
+ focussed: false,
51
+ }
52
+ },
53
+ mounted() {
54
+ this.mounted = true;
55
+ },
56
+ beforeUnmount() {
57
+ this.mounted = false;
58
+ },
59
+
60
+ methods: {
61
+ reset() {
62
+
63
+ },
64
+ fieldUnmounted(field) {
65
+ this.fieldStateChange(field, 'unmount');
66
+ this.$emit('field:unmount', this);
67
+ },
68
+ fieldMounted(field) {
69
+ this.fieldStateChange(field, 'unmount');
70
+ this.$emit('field:mount', this);
71
+ },
72
+ fieldDirty(field) {
73
+ this.fieldStateChange(field, 'dirty');
74
+ this.$emit('field:dirty', this);
75
+ },
76
+ fieldInvalid(field) {
77
+ this.fieldStateChange(field, 'invalid');
78
+ this.$emit('field:invalid', this);
79
+ },
80
+ fieldValid(field) {
81
+ this.fieldStateChange(field, 'valid');
82
+ this.$emit('field:valid', this);
83
+ },
84
+ fieldError(field) {
85
+ this.fieldStateChange(field, 'error');
86
+ this.$emit('field:error', this);
87
+ },
88
+ fieldFocus(field) {
89
+ this.fieldStateChange(field, 'focus');
90
+ this.$emit('field:focus', this);
91
+ },
92
+ fieldBlur(field) {
93
+ this.fieldStateChange(field, 'blur');
94
+ this.$emit('field:blur', this);
95
+ },
96
+ fieldTouch(field) {
97
+ this.fieldStateChange(field, 'touch');
98
+ this.$emit('field:touch', this);
99
+ },
100
+ fieldStateChange(triggerField, event) {
101
+ var self = this;
102
+
103
+
104
+ self.$nextTick(function() {
105
+ var dirty = false;
106
+ var invalid = false;
107
+ var error = false;
108
+ var touched = false;
109
+ var focussed = false;
110
+ var invalidFields = [];
111
+
112
+ //If we are actually on the screen
113
+
114
+ self.childFields.forEach(function(field) {
115
+
116
+ if (field.dirty) {
117
+ dirty = true;
118
+ }
119
+
120
+ if (field.invalid) {
121
+ invalid = true;
122
+ invalidFields.push({
123
+ title:field.field.title,
124
+ key:field.field.key,
125
+ });
126
+ }
127
+
128
+ if (field.error) {
129
+ error = true;
130
+ }
131
+
132
+ if (field.touched) {
133
+ touched = true;
134
+ }
135
+
136
+ if (field.focussed) {
137
+ focussed = true;
138
+ }
139
+
140
+ })
141
+
142
+
143
+
144
+ self.dirty = dirty;
145
+ self.error = error;
146
+ self.touched = touched;
147
+ self.focussed = focussed;
148
+ self.invalid = invalid;
149
+ self.$emit('form:state', {
150
+ dirty,
151
+ error,
152
+ focussed,
153
+ touched,
154
+ invalid,
155
+ valid: !invalid,
156
+ invalidFields,
157
+ });
158
+ })
159
+
160
+
161
+ },
162
+
163
+ },
164
+ components: {
165
+ UxField: UXField,
166
+ },
167
+ computed: {
168
+ fieldHash() {
169
+ return this.renderFields.reduce(function(set,field) {
170
+ set[field.key] = field;
171
+ return set;
172
+ }, {});
173
+ },
174
+ valid() {
175
+ return !this.invalid;
176
+ },
177
+ childFields() {
178
+ var self = this;
179
+
180
+ var directRefs = [];
181
+
182
+ if (!self.mounted) {
183
+ return [];
184
+ }
185
+
186
+ findRecursive(this.$refs, directRefs);
187
+
188
+ function findRecursive($refs, collection) {
189
+
190
+ var fields = $refs.field ? $refs.field : [];
191
+ var groups = $refs.group ? $refs.group : [];
192
+ var forms = $refs.form ? $refs.form : [];
193
+
194
+ ////////////////////////////////////////
195
+
196
+ if (fields && !Array.isArray(fields)) {
197
+ fields = [fields];
198
+ }
199
+
200
+ if (groups && !Array.isArray(groups)) {
201
+ groups = [groups];
202
+ }
203
+
204
+ if (forms && !Array.isArray(forms)) {
205
+ forms = [forms];
206
+ }
207
+
208
+ ////////////////////////////////////////
209
+
210
+ fields.forEach(function(field) {
211
+ if (field.visible) {
212
+ collection.push(field);
213
+ findRecursive(field.$refs, collection);
214
+ }
215
+ })
216
+
217
+ groups.forEach(function(group) {
218
+ findRecursive(group.$refs, collection);
219
+ })
220
+
221
+ forms.forEach(function(form) {
222
+ findRecursive(form.$refs, collection);
223
+ })
224
+ }
225
+
226
+ return directRefs;
227
+
228
+ },
229
+
230
+
231
+ formClass() {
232
+ var array = [];
233
+
234
+ if (this.flex) {
235
+ array.push('ux-form-flex');
236
+ }
237
+ return array;
238
+ },
239
+
240
+ fieldClass() {
241
+ var array = [];
242
+
243
+ if (this.flex) {
244
+ array.push('ux-field-flex');
245
+ }
246
+ return array;
247
+ },
248
+ formModel: {
249
+ get() {
250
+ return this.model;
251
+ },
252
+ set(value) {
253
+ this.model = value;
254
+ this.$emit('update:modelValue', this.model);
255
+
256
+ },
257
+ },
258
+ renderFields() {
259
+ return this.fields;
260
+ }
261
+ }
262
+ }
263
+ </script>
264
+ <style lang="scss" scoped>
265
+ .ux-form-flex {
266
+ display: flex;
267
+ flex: 1;
268
+ gap: 2em;
269
+
270
+ .ux-field-flex {
271
+ flex: 1;
272
+ // display: flex;
273
+ // align-items: flex-end;
274
+
275
+ // & > .ux-field {
276
+ // flex:1;
277
+ // }
278
+ }
279
+ }
280
+ </style>
@@ -0,0 +1,224 @@
1
+ import parseBoolean from './parseBoolean';
2
+
3
+
4
+ function ensureMinimum(field, array, min, ask, max, func) {
5
+
6
+ array = array || [];
7
+
8
+
9
+ min = Math.max(min, ask);
10
+
11
+ var length = array.length;
12
+ var meetsMinimum = length >= min;
13
+ var meetsMaximum = length <= max;
14
+
15
+ if (!meetsMinimum) {
16
+ if (field.key == 'multiNumber') {
17
+ console.log(field.key, min)
18
+ }
19
+ var difference = min - length;
20
+ var extras = Array(difference).fill().map(func);
21
+ return [...array, ...extras];
22
+ }
23
+
24
+ return array;
25
+
26
+ }
27
+
28
+ //////////////
29
+
30
+ export default function getDefaultValue(fieldData, currentValue) {
31
+
32
+ if (currentValue) {
33
+ return currentValue;
34
+ }
35
+
36
+ function isUndefined(entry) {
37
+ return entry === undefined || typeof entry === 'undefined' || entry === null;
38
+ }
39
+
40
+ /////////////////////////////////////
41
+
42
+ var minimum = parseInt(fieldData.minimum);
43
+ var maximum = parseInt(fieldData.maximum);
44
+ var ask = parseInt(fieldData.ask || 0);
45
+
46
+ //Ensure that the ask is always at least the minimum
47
+ ask = Math.max(ask, minimum);
48
+ //Ensure that if there is a maximum set it's never more than the maximum
49
+ ask = maximum ? Math.min(ask, maximum) : ask;
50
+
51
+ var singleValue = (maximum == 1);
52
+ var multiValue = !singleValue;
53
+ var defaultValues = (fieldData.type === 'reference' ? fieldData.defaultReferences : fieldData.defaultValues) || [];
54
+ var firstDefaultValue = defaultValues[0];
55
+
56
+ /////////////////////////////////////
57
+
58
+ var output;
59
+
60
+
61
+
62
+ switch (fieldData.type) {
63
+ case 'date':
64
+
65
+ function getDate(v) {
66
+
67
+ switch (String(v).toLowerCase()) {
68
+ case 'now':
69
+ return new Date();
70
+ break;
71
+ }
72
+
73
+ return new Date(v);
74
+ }
75
+
76
+ if (multiValue) {
77
+ if (defaultValues.length) {
78
+ if (maximum) {
79
+ output = defaultValues.slice(0, maximum).map(function(v) {
80
+ return getDate(v)
81
+ });
82
+ } else {
83
+ output = defaultValues.slice().map(function(v) {
84
+ return getDate(v)
85
+ });
86
+ }
87
+ }
88
+
89
+ output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
90
+ return getDate(new Date());
91
+ })
92
+ } else {
93
+ output = isUndefined(firstDefaultValue) ? undefined : getDate(firstDefaultValue);
94
+ }
95
+
96
+ break;
97
+ case 'integer':
98
+ // if (multiValue) {
99
+
100
+ // if (defaultValues.length) {
101
+ // if (maximum) {
102
+ // output = defaultValues.slice(0, maximum).map(function(val) {
103
+ // return parseInt(val);
104
+ // });
105
+
106
+ // } else {
107
+ // output = defaultValues.slice().map(function(val) {
108
+ // return parseInt(val);
109
+ // });
110
+ // }
111
+ // }
112
+
113
+ // output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
114
+ // return 0;
115
+ // })
116
+ // } else {
117
+ // output = isUndefined(firstDefaultValue) ? undefined : parseInt(firstDefaultValue);
118
+ // }
119
+ // break;
120
+ case 'decimal':
121
+ case 'number':
122
+ case 'float':
123
+ if (multiValue) {
124
+ if (defaultValues.length) {
125
+ if (maximum) {
126
+ output = defaultValues.slice(0, maximum).map(function(val) {
127
+ return Number(val);
128
+ });
129
+ } else {
130
+ output = defaultValues.slice().map(function(val) {
131
+ return Number(val);
132
+ });
133
+ }
134
+ }
135
+
136
+ output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
137
+ return '';
138
+ })
139
+ } else {
140
+ output = isUndefined(firstDefaultValue) ? undefined : Number(firstDefaultValue);
141
+ }
142
+ break;
143
+ case 'group':
144
+ if (fieldData.asObject) {
145
+ var number = ask;
146
+ if (multiValue) {
147
+ if (number > 0) {
148
+ output = Array(number).fill().map(function() {
149
+ return {}
150
+ });
151
+ } else {
152
+ output = [];
153
+ }
154
+
155
+ } else {
156
+ output = isUndefined(firstDefaultValue) ? {} : firstDefaultValue;
157
+ }
158
+ }
159
+ break;
160
+ case 'boolean':
161
+
162
+ if (multiValue) {
163
+ if (defaultValues.length) {
164
+ if (maximum) {
165
+ output = defaultValues.slice(0, maximum).map(function(val) {
166
+ return parseBoolean(val);
167
+ });
168
+ } else {
169
+ output = defaultValues.slice().map(function(val) {
170
+ return parseBoolean(val);
171
+ });
172
+ }
173
+ }
174
+
175
+ output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
176
+ return;
177
+ })
178
+ } else {
179
+ output = isUndefined(firstDefaultValue) ? false : parseBoolean(firstDefaultValue);
180
+ }
181
+
182
+ break;
183
+ case 'reference':
184
+ if (multiValue) {
185
+ if (defaultValues.length) {
186
+ output = defaultValues.slice(0, maximum);
187
+ } else {
188
+ output = [];
189
+ }
190
+ } else {
191
+ output = isUndefined(firstDefaultValue) ? undefined : firstDefaultValue;
192
+ }
193
+ break;
194
+ case 'string':
195
+ if (multiValue) {
196
+ if (defaultValues.length) {
197
+ output = defaultValues.slice(0, maximum);
198
+ }
199
+
200
+ output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
201
+ return '';
202
+ })
203
+ } else {
204
+ output = isUndefined(firstDefaultValue) ? '' : firstDefaultValue;
205
+ }
206
+ break;
207
+ default:
208
+ if (multiValue) {
209
+ if (defaultValues.length) {
210
+ output = defaultValues.slice(0, maximum);
211
+ }
212
+
213
+ output = ensureMinimum(fieldData, output, minimum, ask, maximum, function() {
214
+ return;
215
+ })
216
+ } else {
217
+ output = isUndefined(firstDefaultValue) ? '' : firstDefaultValue;
218
+ }
219
+ break;
220
+ }
221
+
222
+ return output;
223
+
224
+ }
@@ -0,0 +1,208 @@
1
+ <template>
2
+ <label class="ux-field-title" v-if="showLabel">{{label}} <span class="ux-required-marker" v-if="required">*</span></label>
3
+ <div class="ux-field-description" v-if="showDescription">{{description}}</div>
4
+ <div class="buttons">
5
+ <option-slot :option="option" v-slot="{plainValue}" v-for="option in selectableOptions">
6
+ <ux-button :class="{active:selectionHash[plainValue]}" @click="toggle(plainValue)">
7
+ {{getLabel(option)}}
8
+ <ux-icon icon="fa-check" right />
9
+ </ux-button>
10
+ </option-slot>
11
+ </div>
12
+ </template>
13
+ <script>
14
+ import InputMixin from './input-mixin';
15
+ import OptionSlot from './option.vue';
16
+
17
+
18
+ function isUndefined(entry) {
19
+ return entry === undefined || typeof entry === 'undefined' || entry === null || String(entry) === 'null' || String(entry) === 'undefined';
20
+ }
21
+
22
+ //////////////////////////
23
+
24
+ export default {
25
+ components: {
26
+ OptionSlot,
27
+ },
28
+ props: {
29
+ modelValue: {
30
+ // type: [Object, Array],
31
+ },
32
+ },
33
+ mixins: [InputMixin],
34
+ created() {
35
+ this.model = this.model;
36
+ },
37
+ methods: {
38
+ select(val) {
39
+
40
+ var self = this;
41
+ if (self.multiValue) {
42
+ self.model = [...self.model, val];
43
+ } else {
44
+ self.model = val;
45
+ }
46
+
47
+ },
48
+ deselect(val) {
49
+ var self = this;
50
+ // var val = self.getValue(option);
51
+
52
+ if (this.multiValue) {
53
+ var sliced = this.model.slice();
54
+ var index = sliced.indexOf(val)
55
+
56
+ if (index != -1) {
57
+ sliced.splice(index, 1);
58
+ this.model = sliced
59
+ }
60
+ } else {
61
+ if (self.getValue(this.model) == val) {
62
+ this.model = undefined;
63
+ } else {
64
+ this.model = val;
65
+ }
66
+ }
67
+
68
+ },
69
+ toggle(plainValue) {
70
+
71
+ if (this.selectionHash[plainValue]) {
72
+ this.deselect(plainValue);
73
+ } else {
74
+ this.select(plainValue);
75
+ }
76
+
77
+ this.touch();
78
+ },
79
+
80
+ model: {
81
+ get() {
82
+ return this.cleanOutput(this.value);
83
+ },
84
+ set(val) {
85
+ this.value = this.cleanInput(val);
86
+ this.dispatch();
87
+ }
88
+ },
89
+
90
+ cleanOutput(val) {
91
+ var self = this;
92
+
93
+ if (isUndefined(val)) {
94
+ if (self.multiValue) {
95
+ val = [];
96
+ } else {
97
+ val = undefined;
98
+ }
99
+ } else {
100
+ if (self.multiValue) {
101
+ val = (val || []).map(function(i) {
102
+ return self.getValue(i);
103
+ })
104
+ } else {
105
+ val = self.getValue(val);
106
+ }
107
+ }
108
+
109
+ return val;
110
+ },
111
+ cleanInput(val) {
112
+
113
+ var self = this;
114
+
115
+ if (self.multiValue) {
116
+ if (!val) {
117
+ val = [];
118
+ }
119
+
120
+ if (!Array.isArray(val)) {
121
+ val = [val];
122
+ }
123
+
124
+ /////////////////////////////////
125
+
126
+ if (self.maximum) {
127
+ if (val.length > self.maximum) {
128
+ val.length = self.maximum;
129
+ }
130
+ }
131
+
132
+
133
+ val = val.map(function(v) {
134
+ var valueKey = self.getValue(v);
135
+ return self.returnObject ? self.optionLookup[valueKey] : valueKey;
136
+ })
137
+
138
+ } else {
139
+ var valueKey = self.getValue(val);
140
+ val = self.returnObject ? self.optionLookup[valueKey] : valueKey;
141
+ }
142
+
143
+ return val;
144
+ },
145
+ },
146
+ computed: {
147
+ selectionHash() {
148
+
149
+ var hash = {};
150
+
151
+ if (this.model) {
152
+ if (this.multiValue) {
153
+ this.model.forEach(function(val) {
154
+ hash[val] = true;
155
+ })
156
+ } else {
157
+ hash[this.model] = true;
158
+ }
159
+ }
160
+
161
+ console.log('change hash')
162
+ return hash;
163
+ },
164
+ returnObject() {
165
+ return this.type == 'reference';
166
+ },
167
+ summary() {
168
+ return this.getLabel(this.optionLookup[this.model]) || 'Click to select';
169
+ },
170
+
171
+ }
172
+ }
173
+ </script>
174
+ <style lang="scss" scoped>
175
+ // :deep(.buttons) {
176
+ .buttons {
177
+ display: flex;
178
+ gap: 0.2em;
179
+ flex-wrap: wrap;
180
+
181
+
182
+
183
+ .ux-btn {
184
+
185
+ margin: 0;
186
+
187
+ .ux-icon {
188
+ opacity: 0;
189
+ }
190
+
191
+ &:hover {
192
+ .ux-icon {
193
+ opacity: 0.5;
194
+ }
195
+ }
196
+
197
+ &.active {
198
+ background: $primary;
199
+ color: #fff;
200
+
201
+ .ux-icon {
202
+ opacity: 1;
203
+ }
204
+ }
205
+ }
206
+
207
+ }
208
+ </style>