@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,211 @@
1
+ <template>
2
+ <div class="native-select" :class="classes">
3
+ <label class="ux-field-title" v-if="showLabel">{{label}} <span class="ux-required-marker" v-if="required">*</span></label>
4
+ <div class="ux-field-description" v-if="showDescription">{{description}}</div>
5
+ <div class="ui-select-button" v-if="singleValue">
6
+ <slot>
7
+ <ux-button tag="div">
8
+ {{summary}}
9
+ </ux-button>
10
+ </slot>
11
+ </div>
12
+ <select @focus="touch" :multiple="multiValue" v-model="model">
13
+ <option value="" v-if="singleValue && !minimum">None</option>
14
+ <option :value="option.value" v-for="option in selectableOptions">{{option.title}}</option>
15
+ </select>
16
+
17
+ </div>
18
+ </template>
19
+ <script>
20
+ import InputMixin from './input-mixin';
21
+
22
+
23
+
24
+ function isUndefined(entry) {
25
+ return entry === undefined || typeof entry === 'undefined' || entry === null || String(entry) === 'null' || String(entry) === 'undefined';
26
+ }
27
+
28
+ //////////////////////////
29
+
30
+ export default {
31
+ props: {
32
+ title:{
33
+ type:String,
34
+ },
35
+ modelValue: {
36
+ // type: [Object, Array],
37
+ },
38
+ },
39
+ mixins: [InputMixin],
40
+ created() {
41
+ this.model = this.model;
42
+ },
43
+ methods: {
44
+ cleanOutput(val) {
45
+ var self = this;
46
+
47
+ if (isUndefined(val)) {
48
+ if (self.multiValue) {
49
+ val = [];
50
+ } else {
51
+ val = undefined;
52
+ }
53
+ } else {
54
+ if (self.multiValue) {
55
+ val = (val || []).filter(Boolean).map(function(i) {
56
+ return self.getValue(i);
57
+ })
58
+ } else {
59
+ val = self.getValue(val);
60
+ }
61
+ }
62
+
63
+ return val;
64
+ },
65
+ cleanInput(val) {
66
+
67
+ var self = this;
68
+
69
+ if (self.multiValue) {
70
+ if (!val) {
71
+ val = [];
72
+ }
73
+
74
+ if (!Array.isArray(val)) {
75
+ val = [val];
76
+ }
77
+
78
+ /////////////////////////////////
79
+
80
+ if (self.maximum) {
81
+ if (val.length > self.maximum) {
82
+ val.length = self.maximum;
83
+ }
84
+ }
85
+
86
+
87
+ val = val.filter(Boolean).map(function(v) {
88
+ var valueKey = self.getValue(v);
89
+ return self.returnObject ? self.optionLookup[valueKey] : valueKey;
90
+ })
91
+
92
+ } else {
93
+ var valueKey = self.getValue(val);
94
+ val = self.returnObject ? self.optionLookup[valueKey] : valueKey;
95
+ }
96
+
97
+ return val;
98
+ },
99
+ },
100
+ computed: {
101
+ returnObject() {
102
+ return this.type == 'reference';
103
+ },
104
+ classes() {
105
+ var array = []
106
+
107
+ if (this.multiValue) {
108
+ array.push('multiple');
109
+ } else {
110
+ array.push('single');
111
+ }
112
+
113
+ return array;
114
+ },
115
+ // model: {
116
+ // get() {
117
+ // let val = this.cleanOutput(this.value);
118
+ // return val;
119
+ // },
120
+ // set(val) {
121
+ // val = this.cleanInput(val);
122
+ // // // var val = this.cleanOutput(newValue);
123
+ // // // var existing = this.cleanOutput(this.value);
124
+
125
+ // // if (newValue != existing) {
126
+ // // newValue = this.cleanInput(val);
127
+ // // this.value = newValue;
128
+ // // this.dispatch();
129
+ // // }
130
+
131
+ // this.value = val;
132
+ // this.dispatch();
133
+
134
+ // }
135
+ // },
136
+ optionLookup() {
137
+ var self = this;
138
+ return self.options.reduce(function(set, option) {
139
+ const key = self.getValue(option);
140
+ set[key] = option;
141
+ return set;
142
+ }, {})
143
+ },
144
+ summary() {
145
+ return this.model ? this.getLabel(this.optionLookup[this.model]) : this.title || 'Click to select';
146
+ },
147
+
148
+ selectableOptions() {
149
+ return this.options
150
+ // .sort(function(option) {
151
+ // return option.title;
152
+ // });
153
+ // if(this.type == 'reference') {
154
+
155
+ // } else {
156
+
157
+ // }
158
+
159
+ },
160
+ }
161
+ }
162
+ </script>
163
+ <style lang="scss" scoped>
164
+ .native-select {
165
+
166
+ cursor: pointer;
167
+
168
+ &.multiple {
169
+ select {
170
+ width: 100%;
171
+ font-size:1em;
172
+ border:1px solid rgba(#000, 0.1);
173
+ appearance:none;
174
+
175
+ &:focus {
176
+ border:1px solid $primary;
177
+ }
178
+ }
179
+ }
180
+
181
+ &.single {
182
+ position: relative;
183
+
184
+ .ui-select-button {
185
+ position: relative;
186
+ width:100%;
187
+
188
+ & > .ux-btn {
189
+ display: block;
190
+ text-align: left;
191
+ }
192
+ }
193
+
194
+ select {
195
+ cursor: pointer;
196
+ opacity: 0;
197
+ appearance: none;
198
+ width: 100%;
199
+ height: 100%;
200
+ position: absolute;
201
+ top: 0;
202
+ left: 0;
203
+ bottom: 0;
204
+ right: 0;
205
+ }
206
+ }
207
+
208
+
209
+ }
210
+
211
+ </style>
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <flex-row @click="touch()">
3
+ <flex-cell vcenter shrink>
4
+ <ux-switch :value="model" @click="model = !model" />
5
+ </flex-cell>
6
+ <flex-spacer />
7
+ <flex-cell vcenter>
8
+ <div>
9
+ <label class="ux-field-title" v-if="showLabel">
10
+ {{label}} <span class="ux-required-marker" v-if="required">*</span>
11
+ </label>
12
+ <div class="ux-field-description" v-if="showDescription">{{description}}</div>
13
+ </div>
14
+ </flex-cell>
15
+ </flex-row>
16
+ </template>
17
+ <script>
18
+ import InputMixin from './input-mixin';
19
+
20
+ export default {
21
+ mixins: [InputMixin],
22
+ props: {
23
+ modelValue: {
24
+ type: Boolean,
25
+ default () {
26
+ return false;
27
+ },
28
+ },
29
+ },
30
+ data() {
31
+ return {
32
+ value: this.modelValue,
33
+ }
34
+ },
35
+ watch: {
36
+ modelValue(val, old) {
37
+ this.value = val;
38
+ this.model = val;
39
+
40
+ }
41
+ },
42
+ computed: {
43
+ longDescription() {
44
+ return String(this.description).length > 2;
45
+ },
46
+ defaultValue() {
47
+ return false;
48
+ },
49
+ model: {
50
+ get() {
51
+ return !!this.value;
52
+ },
53
+ set(value) {
54
+ this.value = !!value;
55
+ this.$emit('update:modelValue', this.value);
56
+ }
57
+ }
58
+ }
59
+ }
60
+ </script>
61
+ <style lang="scss" scoped>
62
+ .ux-checkbox {
63
+ margin-right: 0.5em;
64
+ line-height: 1;
65
+ height: 1.5em;
66
+ width: 1.5em;
67
+ padding: 0;
68
+
69
+ &:hover {
70
+ border-color: $primary;
71
+ }
72
+
73
+ &.ux-checkbox-true {
74
+ background: $primary;
75
+ border-color: $primary;
76
+ color: #fff;
77
+ }
78
+ }
79
+
80
+ .ux-field-title {
81
+ margin: 0 !important;
82
+ }
83
+
84
+ .ux-field-description-long {
85
+ margin-top: 0.5em;
86
+ }
87
+ </style>
@@ -0,0 +1,80 @@
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 v-if="multiValue">
5
+ <flex-row class="ux-text-row" :key="index" v-for="(entry, index) in model">
6
+ <flex-cell>
7
+ <textarea contenteditable @focus="touch" ref="input" v-model="model[index]" class="ux-textarea ux-field-focus ux-text-area-multiple"/>
8
+ </flex-cell>
9
+ <flex-cell shrink vcenter>
10
+ <ux-button tag="a" icon v-if="canRemoveValue" @click="remove(entry)">
11
+ <ux-icon icon="fa-times" />
12
+ </ux-button>
13
+ </flex-cell>
14
+ </flex-row>
15
+ <ux-button v-if="canAddValue" @click="add()">{{addLabel}}</ux-button>
16
+ </div>
17
+ <template v-else>
18
+ <textarea class="ux-textarea ux-field-focus ux-text-area-single" @focus="touch" v-model="model" role="textbox" contenteditable/>
19
+
20
+ <!-- <textarea class="ux-field-focus ux-text-area-single" @focus="touch" v-model="model" /> -->
21
+ </template>
22
+ </template>
23
+ <script>
24
+ import InputMixin from './input-mixin';
25
+
26
+ export default {
27
+ props: {
28
+ modelValue: {
29
+ type: [String, Array],
30
+ },
31
+ },
32
+ mixins: [InputMixin],
33
+ methods: {
34
+ getNewDefaultEntry() {
35
+ return '';
36
+ },
37
+ },
38
+ }
39
+ </script>
40
+ <style lang="scss" scoped>
41
+ .ux-text-row {
42
+ margin-bottom: 0.5em;
43
+ }
44
+
45
+ .ux-textarea,
46
+ textarea {
47
+ border-radius: 0.1em;
48
+ padding: 0.5em;
49
+ box-sizing: border-box;
50
+ background: rgba(#000, 0.05);
51
+ border: 1px solid rgba(#000, 0.1);
52
+ font-size: inherit;
53
+ appearance: none;
54
+ line-height: 1;
55
+ min-height: 5em;
56
+ font-family: inherit;
57
+ resize: vertical;
58
+ overflow: hidden;
59
+
60
+ &:focus {
61
+ background: none;
62
+ border: 1px solid $primary;
63
+ outline: none;
64
+ }
65
+ }
66
+
67
+ .ux-text-row .ux-btn {
68
+ margin-left: 0.25em;
69
+ }
70
+
71
+ .ux-text-area-multiple {
72
+ width: 100%;
73
+ }
74
+
75
+ .ux-text-area-single {
76
+ width:100%;
77
+ // width: calc(100% - 0.5em);
78
+ // margin: 0 0.5em 0 0;
79
+ }
80
+ </style>
@@ -0,0 +1,165 @@
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 v-if="multiValue">
5
+ <flex-row class="ux-text-row" :key="index" v-for="(entry, index) in model">
6
+ <flex-cell>
7
+ <div class="ux-text-wrap">
8
+ <span class="ux-text-prefix" v-if="prefix">{{prefix}}</span>
9
+ <input v-if="lazy" class="ux-field-focus ux-text-input-multiple" :placeholder="actualPlaceholder" @focus="touch" ref="input" @keydown.enter.stop.prevent="add()" v-model.lazy="model[index]" />
10
+ <input v-if="!lazy" class="ux-field-focus ux-text-input-multiple" :placeholder="actualPlaceholder" @focus="touch" ref="input" @keydown.enter.stop.prevent="add()" v-model="model[index]" />
11
+ <span class="ux-text-suffix" v-if="suffix">{{suffix}}</span>
12
+ </div>
13
+ </flex-cell>
14
+ <flex-cell shrink vcenter>
15
+ <ux-button tag="a" icon v-if="canRemoveValue" @click="remove(entry)">
16
+ <ux-icon icon="fa-times" />
17
+ </ux-button>
18
+ </flex-cell>
19
+ </flex-row>
20
+ <ux-button v-if="canAddValue" @click="add()">{{addLabel}} <ux-icon icon="fa-plus" right/></ux-button>
21
+ </div>
22
+ <template v-else>
23
+ <div class="ux-text-wrap">
24
+ <span class="ux-text-prefix" v-if="prefix">{{prefix}}</span>
25
+ <input v-if="lazy" ref="input" class="ux-field-focus ux-text-input-single" :placeholder="actualPlaceholder" @focus="touch" v-model.lazy="model" />
26
+ <input v-if="!lazy" ref="input" class="ux-field-focus ux-text-input-single" :placeholder="actualPlaceholder" @focus="touch" v-model="model" />
27
+ <span class="ux-text-suffix" v-if="suffix">{{suffix}}</span>
28
+ </div>
29
+ </template>
30
+ </template>
31
+ <script>
32
+ import InputMixin from './input-mixin';
33
+
34
+
35
+
36
+
37
+ export default {
38
+ props: {
39
+ modelValue: {
40
+ type: [String, Array],
41
+ },
42
+ },
43
+ mixins: [InputMixin],
44
+ computed: {
45
+ lazy() {
46
+ switch (this.type) {
47
+ case 'integer':
48
+ case 'number':
49
+ case 'decimal':
50
+ case 'float':
51
+ case 'url':
52
+ case 'key':
53
+ return true;
54
+ break;
55
+ }
56
+ },
57
+ actualPlaceholder() {
58
+ if(this.field.placeholder) {
59
+ return this.field.placeholder;
60
+ }
61
+
62
+ switch(this.type) {
63
+ case 'integer':
64
+ case 'number':
65
+ case 'decimal':
66
+ case 'float':
67
+ return '0';
68
+ break;
69
+ case 'url':
70
+ return 'https://www.website.com'
71
+ break;
72
+ case 'email':
73
+ return 'you@youremail.com'
74
+ break;
75
+ }
76
+ }
77
+ },
78
+ methods: {
79
+ cleanOutputValue(v) {
80
+ var cleaned = this.cleanTextInput(v, this.type, this);
81
+ return cleaned ? String(cleaned) : '';
82
+ },
83
+ cleanInputValue(v) {
84
+ return this.cleanTextInput(v, this.type, this);
85
+ },
86
+ getNewDefaultEntry() {
87
+ return '';
88
+ },
89
+ },
90
+ }
91
+ </script>
92
+ <style lang="scss" scoped>
93
+ .ux-text-row {
94
+ margin-bottom: 0.5em;
95
+ }
96
+
97
+ input {
98
+ border-radius: 0.1em;
99
+ padding: 0.5em;
100
+ box-sizing: border-box;
101
+ background: rgba(#000, 0.05);
102
+ border: 1px solid rgba(#000, 0.1);
103
+ font-size: inherit;
104
+ appearance: none;
105
+ line-height: 1;
106
+ height: 2.5em;
107
+
108
+ &:focus {
109
+ background: none;
110
+ border: 1px solid $primary;
111
+ outline: none;
112
+ }
113
+ }
114
+
115
+
116
+ .ux-text-wrap {
117
+ position: relative;
118
+
119
+ &.prefixed {
120
+ input {
121
+ padding-left: 1.2em;
122
+ }
123
+ }
124
+
125
+ .ux-text-prefix {
126
+ position: absolute;
127
+ left: 0;
128
+ top: 0;
129
+ bottom: 0;
130
+ width: 1em;
131
+ pointer-events: none;
132
+ display: flex;
133
+ align-items: center;
134
+ padding: 0.5em 0;
135
+ justify-content: right;
136
+ opacity: 0.5;
137
+ }
138
+
139
+ .ux-text-suffix {
140
+ position: absolute;
141
+ top: 0;
142
+ bottom: 0;
143
+ right: 0;
144
+ pointer-events: none;
145
+ display: flex;
146
+ align-items: center;
147
+ padding: 0.5em;
148
+ opacity: 0.5;
149
+ }
150
+ }
151
+
152
+ .ux-text-row .ux-btn {
153
+ margin-left: 0.25em;
154
+ }
155
+
156
+ .ux-text-input-multiple {
157
+ width: 100%;
158
+ }
159
+
160
+ .ux-text-input-single {
161
+ width: 100%;
162
+ // width: calc(100% - 0.5em);
163
+ // margin: 0 0.5em 0 0;
164
+ }
165
+ </style>