@qikdev/vue-ui 0.0.2 → 0.0.5

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": "@qikdev/vue-ui",
3
- "version": "0.0.2",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "description": "Vue UI component library",
6
6
  "scripts": {
@@ -7,17 +7,23 @@
7
7
  <flex-cell flex>
8
8
  <native-table :total="totalItems" :selectAll="selectAll" :deselectAll="deselectAllFunction" :actions="false" :selection="manager.items" @click:row="rowClicked" @select:row:toggle="rowToggled" @select:multiple="selectMultiple" @deselect:multiple="deselectMultiple" :rows="items" :columns="columns" />
9
9
  </flex-cell>
10
- <flex-column style="max-width: 600px;">
11
- <flex-header>
12
- Filters
13
- </flex-header>
10
+ <flex-column class="filter-column" style="max-width: 600px;" v-if="showFilters">
11
+ <flex-body>
12
+ <search v-model="search" :loading="searching" :debounce="500" placeholder="Keyword Search" />
13
+
14
+
15
+ <p></p>
16
+
17
+
18
+
14
19
  <filter-builder :definition="definition" v-model="filter" />
20
+ </flex-body>
15
21
  </flex-column>
16
22
  </flex-row>
17
23
  </flex-column>
18
24
  <flex-footer>
19
25
  <div class="footer">
20
- <flex-row center>
26
+ <flex-row center gap >
21
27
  <flex-cell shrink class="text">
22
28
  <native-select v-model="perPage" :field="perPageField">
23
29
  Showing {{displayStartIndex}} to {{endIndex}} of {{totalItems}} total
@@ -25,8 +31,8 @@
25
31
  </flex-cell>
26
32
  <flex-cell>
27
33
  </flex-cell>
28
- <flex-cell shrink>
29
- <flex-row center>
34
+ <flex-cell shrink v-if="totalPages > 1">
35
+ <flex-row gap center>
30
36
  <flex-cell shrink class="text">
31
37
  <native-select v-model="currentPage" :field="pageField">
32
38
  Page {{currentPage}} of {{totalPages}}
@@ -56,6 +62,7 @@ import NativeTable from '../table/Table.vue';
56
62
 
57
63
  import FilterBuilder from '../filter/FilterBuilder.vue';
58
64
  import Selection from '../services/selection.js';
65
+ import Search from '../form/inputs/search.vue';
59
66
 
60
67
 
61
68
  // import FilterRule from '../filter/FilterRule.vue';
@@ -69,6 +76,9 @@ export default {
69
76
  type: String,
70
77
  required: true,
71
78
  },
79
+ showFilters:{
80
+ type:Boolean,
81
+ },
72
82
  search: {
73
83
  type: String,
74
84
  },
@@ -101,6 +111,7 @@ export default {
101
111
  NativeSelect,
102
112
  NativeTable,
103
113
  FilterBuilder,
114
+ Search,
104
115
  // FilterRule,
105
116
  },
106
117
  async created() {
@@ -464,6 +475,11 @@ export default {
464
475
  }
465
476
  }
466
477
 
478
+ .filter-column {
479
+ padding:1em;
480
+ background: rgba(#000, 0.1);
481
+ }
482
+
467
483
 
468
484
  .footer {
469
485
  padding: 1em;
@@ -2,7 +2,7 @@
2
2
  <flex-column class="filter-builder">
3
3
  <flex-body>
4
4
  <div class="filters">
5
- <div class="top">
5
+ <div class="top" v-if="model.filters.length">
6
6
  <div class="summary">
7
7
  Match <native-select v-model="model.operator" :field="operatorField">
8
8
  {{summary}}
@@ -10,7 +10,7 @@
10
10
  </div>
11
11
  </div>
12
12
  <filter-rule :enableRemove="model.filters.length > 1" :key="`rule-${index}`" @remove="removeRule(index)" :definition="definition" v-model="model.filters[index]" :index="index" v-for="(rule, index) in model.filters" />
13
- <ux-button @click="addRule()">Add Rule</ux-button>
13
+ <ux-button @click="addRule()">Add Filter Rule</ux-button>
14
14
  </div>
15
15
  </flex-body>
16
16
  </flex-column>
@@ -119,12 +119,9 @@ export default {
119
119
  </script>
120
120
  <style lang="scss" scoped>
121
121
  .filter-builder {
122
- background: rgba(#000, 0.1);
122
+
123
123
 
124
124
 
125
- .filters {
126
- padding:0.7em;
127
- }
128
125
 
129
126
  .summary {
130
127
  font-size: 0.8em;
@@ -35,6 +35,10 @@
35
35
  <template v-if="widget == 'content-select'">
36
36
  <content-select @touched="touch" :field="actualField" v-model="fieldModel" />
37
37
  </template>
38
+
39
+ <template v-if="widget == 'type-select'">
40
+ <type-select @touched="touch" :field="actualField" v-model="fieldModel" />
41
+ </template>
38
42
  <template v-if="widget == 'richtext'">
39
43
  <text-area @touched="touch" :field="actualField" v-model="fieldModel" />
40
44
  </template>
@@ -70,6 +74,7 @@
70
74
  import PhoneNumberInput from './inputs/phone-number-input.vue';
71
75
  import TimezoneSelect from './inputs/timezone.vue';
72
76
  import ContentSelect from './inputs/content-select.vue';
77
+ import TypeSelect from './inputs/type-select.vue';
73
78
  import CurrencyField from './inputs/currency.vue';
74
79
  import TextField from './inputs/textfield.vue';
75
80
  import TextArea from './inputs/textarea.vue';
@@ -137,6 +142,7 @@ export default {
137
142
  BooleanSwitch: Switch,
138
143
  FieldGroup,
139
144
  ContentSelect,
145
+ TypeSelect,
140
146
  TimezoneSelect,
141
147
  PhoneNumberInput,
142
148
  Upload,
@@ -529,6 +535,10 @@ export default {
529
535
  case 'upload':
530
536
  case 'options':
531
537
  case 'button':
538
+ case 'type-select':
539
+ break;
540
+ case 'password':
541
+ return 'textfield';
532
542
  break;
533
543
  case 'phone':
534
544
  case 'phonenumber':
@@ -5,7 +5,7 @@
5
5
  <div class="items" v-if="model && model.length">
6
6
  <item :key="item._id" :item="item" v-for="(item, index) in model">
7
7
  <template #actions>
8
- <ux-button icon @click="remove(item)">
8
+ <ux-button icon @click.stop.prevent="remove(item)">
9
9
  <ux-icon icon="fa-times" />
10
10
  </ux-button>
11
11
  </template>
@@ -16,7 +16,7 @@
16
16
  <div class="items">
17
17
  <item :item="model">
18
18
  <template #actions>
19
- <ux-button icon @click="clear">
19
+ <ux-button icon @click.stop.prevent="clear">
20
20
  <ux-icon icon="fa-times" />
21
21
  </ux-button>
22
22
  </template>
@@ -6,8 +6,8 @@
6
6
  <flex-cell>
7
7
  <div class="ux-text-wrap">
8
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]" />
9
+ <input :type="inputType" 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 :type="inputType" 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
11
  <span class="ux-text-suffix" v-if="suffix">{{suffix}}</span>
12
12
  </div>
13
13
  </flex-cell>
@@ -22,11 +22,12 @@
22
22
  <template v-else>
23
23
  <div class="ux-text-wrap">
24
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" />
25
+ <input :type="inputType" v-if="lazy" ref="input" class="ux-field-focus ux-text-input-single" :placeholder="actualPlaceholder" @focus="touch" v-model.lazy="model" />
26
+ <input :type="inputType" v-if="!lazy" ref="input" class="ux-field-focus ux-text-input-single" :placeholder="actualPlaceholder" @focus="touch" v-model="model" />
27
27
  <span class="ux-text-suffix" v-if="suffix">{{suffix}}</span>
28
28
  </div>
29
29
  </template>
30
+
30
31
  </template>
31
32
  <script>
32
33
  import InputMixin from './input-mixin';
@@ -42,6 +43,25 @@ export default {
42
43
  },
43
44
  mixins: [InputMixin],
44
45
  computed: {
46
+ inputType() {
47
+ switch(this.field.widget) {
48
+ case 'password':
49
+ case 'email':
50
+ return this.field.widget;
51
+ break;
52
+ default:
53
+
54
+ switch(this.field.type) {
55
+ case 'email':
56
+ return 'email';
57
+ break;
58
+ default:
59
+ return 'text';
60
+ break;
61
+ }
62
+ break;
63
+ }
64
+ },
45
65
  lazy() {
46
66
  switch (this.type) {
47
67
  case 'integer':
@@ -0,0 +1,247 @@
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
+ </div>
17
+ </template>
18
+ <script>
19
+ import InputMixin from './input-mixin';
20
+
21
+
22
+
23
+ function isUndefined(entry) {
24
+ return entry === undefined || typeof entry === 'undefined' || entry === null || String(entry) === 'null' || String(entry) === 'undefined';
25
+ }
26
+
27
+ //////////////////////////
28
+
29
+ export default {
30
+ props: {
31
+ title: {
32
+ type: String,
33
+ },
34
+ modelValue: {
35
+ // type: [Object, Array],
36
+ },
37
+ },
38
+ mixins: [InputMixin],
39
+ async created() {
40
+ this.model = this.model;
41
+
42
+ var glossary = await this.$qik.content.glossary();
43
+
44
+
45
+ var typeList = glossary;
46
+
47
+ if (this.field.basicTypes === false) {
48
+ typeList = typeList.filter(function(definition) {
49
+ return !!definition.definesType
50
+ })
51
+ }
52
+
53
+ if (this.field.definedTypes === false) {
54
+ typeList = typeList.filter(function(definition) {
55
+ return !definition.definesType
56
+ })
57
+ }
58
+
59
+ ////////////////////////////
60
+
61
+ typeList = typeList.map(function(definition) {
62
+ return {
63
+ title: definition.title,
64
+ value: definition.key,
65
+ }
66
+ })
67
+ .sort((a, b) => a.title > b.title ? 1 : -1);
68
+
69
+ ////////////////////////////
70
+
71
+ this.types = typeList;
72
+ },
73
+ data() {
74
+ return {
75
+ types: [],
76
+ }
77
+ },
78
+ methods: {
79
+ cleanOutput(val) {
80
+ var self = this;
81
+
82
+ if (isUndefined(val)) {
83
+ if (self.multiValue) {
84
+ val = [];
85
+ } else {
86
+ val = undefined;
87
+ }
88
+ } else {
89
+ if (self.multiValue) {
90
+ val = (val || []).filter(Boolean).map(function(i) {
91
+ return self.getValue(i);
92
+ })
93
+ } else {
94
+ val = self.getValue(val);
95
+ }
96
+ }
97
+
98
+ return val;
99
+ },
100
+ cleanInput(val) {
101
+
102
+ var self = this;
103
+
104
+ if (self.multiValue) {
105
+ if (!val) {
106
+ val = [];
107
+ }
108
+
109
+ if (!Array.isArray(val)) {
110
+ val = [val];
111
+ }
112
+
113
+ /////////////////////////////////
114
+
115
+ if (self.maximum) {
116
+ if (val.length > self.maximum) {
117
+ val.length = self.maximum;
118
+ }
119
+ }
120
+
121
+
122
+ val = val.filter(Boolean).map(function(v) {
123
+ var valueKey = self.getValue(v);
124
+ return self.returnObject ? self.optionLookup[valueKey] : valueKey;
125
+ })
126
+
127
+ } else {
128
+ var valueKey = self.getValue(val);
129
+ val = self.returnObject ? self.optionLookup[valueKey] : valueKey;
130
+ }
131
+
132
+ return val;
133
+ },
134
+ },
135
+ computed: {
136
+ returnObject() {
137
+ return false;
138
+ },
139
+ classes() {
140
+ var array = []
141
+
142
+ if (this.multiValue) {
143
+ array.push('multiple');
144
+ } else {
145
+ array.push('single');
146
+ }
147
+
148
+ return array;
149
+ },
150
+ // model: {
151
+ // get() {
152
+ // let val = this.cleanOutput(this.value);
153
+ // return val;
154
+ // },
155
+ // set(val) {
156
+ // val = this.cleanInput(val);
157
+ // // // var val = this.cleanOutput(newValue);
158
+ // // // var existing = this.cleanOutput(this.value);
159
+
160
+ // // if (newValue != existing) {
161
+ // // newValue = this.cleanInput(val);
162
+ // // this.value = newValue;
163
+ // // this.dispatch();
164
+ // // }
165
+
166
+ // this.value = val;
167
+ // this.dispatch();
168
+
169
+ // }
170
+ // },
171
+ optionLookup() {
172
+ var self = this;
173
+ return self.types.reduce(function(set, option) {
174
+ const key = self.getValue(option);
175
+ set[key] = option;
176
+ return set;
177
+ }, {})
178
+ },
179
+ summary() {
180
+ return this.model ? this.getLabel(this.optionLookup[this.model]) : this.title || 'Click to select';
181
+ },
182
+
183
+ selectableOptions() {
184
+
185
+ return this.types;
186
+ // return this.options
187
+ // .sort(function(option) {
188
+ // return option.title;
189
+ // });
190
+ // if(this.type == 'reference') {
191
+
192
+ // } else {
193
+
194
+ // }
195
+
196
+ },
197
+ }
198
+ }
199
+ </script>
200
+ <style lang="scss" scoped>
201
+ .native-select {
202
+
203
+ cursor: pointer;
204
+
205
+ &.multiple {
206
+ select {
207
+ width: 100%;
208
+ font-size: 1em;
209
+ border: 1px solid rgba(#000, 0.1);
210
+ appearance: none;
211
+
212
+ &:focus {
213
+ border: 1px solid $primary;
214
+ }
215
+ }
216
+ }
217
+
218
+ &.single {
219
+ position: relative;
220
+
221
+ .ui-select-button {
222
+ position: relative;
223
+ width: 100%;
224
+
225
+ &>.ux-btn {
226
+ display: block;
227
+ text-align: left;
228
+ }
229
+ }
230
+
231
+ select {
232
+ cursor: pointer;
233
+ opacity: 0;
234
+ appearance: none;
235
+ width: 100%;
236
+ height: 100%;
237
+ position: absolute;
238
+ top: 0;
239
+ left: 0;
240
+ bottom: 0;
241
+ right: 0;
242
+ }
243
+ }
244
+
245
+
246
+ }
247
+ </style>
@@ -20,6 +20,10 @@ export default {
20
20
  align-items: center;
21
21
  justify-content: center;
22
22
  }
23
+
24
+ &[shrink] {
25
+ flex:none;
26
+ }
23
27
  }
24
28
 
25
29
 
@@ -28,6 +28,10 @@ export default {
28
28
  &[wrap] {
29
29
  flex-wrap: wrap;
30
30
  }
31
+
32
+ &[gap] {
33
+ gap: 0.2em;
34
+ }
31
35
  }
32
36
 
33
37
 
@@ -27,7 +27,6 @@
27
27
  Loading
28
28
  </flex-column>
29
29
 
30
- <pre>{{model}}</pre>
31
30
  </flex-column>
32
31
  </template>
33
32
  <script>
package/src/ui/button.vue CHANGED
@@ -161,7 +161,8 @@ export default {
161
161
 
162
162
  &.ux-btn-block {
163
163
  display: block;
164
- width: 100%;
164
+ width:100%;
165
+ box-sizing:border-box;
165
166
  text-align: center;
166
167
  }
167
168
  }