@signal24/vue-foundation 3.3.2 → 3.6.0
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/.eslintrc.js +16 -0
- package/.prettierrc.json +7 -0
- package/CHANGES.md +6 -3
- package/package.json +26 -13
- package/postcss.config.js +1 -1
- package/src/app.js +2 -2
- package/src/components/ajax-select.vue +10 -6
- package/src/components/alert.vue +28 -28
- package/src/components/index.js +6 -11
- package/src/components/modal.vue +18 -10
- package/src/components/smart-select.vue +57 -34
- package/src/config.js +1 -1
- package/src/directives/autofocus.js +4 -3
- package/src/directives/confirm-button.js +2 -2
- package/src/directives/date-input.js +7 -9
- package/src/directives/datetime.js +11 -9
- package/src/directives/disabled.js +4 -5
- package/src/directives/duration.js +7 -8
- package/src/directives/index.js +1 -1
- package/src/directives/infinite-scroll.js +1 -1
- package/src/directives/readonly.js +5 -6
- package/src/directives/tooltip.js +58 -61
- package/src/directives/user-text.js +1 -1
- package/src/filters/index.js +9 -6
- package/src/helpers/array.js +13 -14
- package/src/helpers/context-menu.js +16 -18
- package/src/helpers/delay.js +1 -1
- package/src/helpers/error.js +6 -9
- package/src/helpers/http.js +27 -25
- package/src/helpers/index.js +1 -1
- package/src/helpers/mask.js +27 -20
- package/src/helpers/number.js +2 -2
- package/src/helpers/string.js +17 -17
- package/src/helpers/vue.js +2 -2
- package/src/index.js +5 -5
- package/src/plugins/index.js +6 -6
- package/src/plugins/infinite-scroll/hook.js +2 -2
- package/src/plugins/infinite-scroll.js +20 -10
- package/src/plugins/resize-watcher.js +2 -4
package/.eslintrc.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
root: true,
|
|
3
|
+
env: {
|
|
4
|
+
node: true
|
|
5
|
+
},
|
|
6
|
+
extends: ['plugin:vue/vue3-essential', 'eslint:recommended', '@vue/prettier'],
|
|
7
|
+
rules: {
|
|
8
|
+
'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
|
9
|
+
'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
|
|
10
|
+
'simple-import-sort/imports': 'error',
|
|
11
|
+
'simple-import-sort/exports': 'error',
|
|
12
|
+
'prettier/prettier': 'warn',
|
|
13
|
+
'no-unused-vars': 'warn'
|
|
14
|
+
},
|
|
15
|
+
plugins: ['simple-import-sort']
|
|
16
|
+
};
|
package/.prettierrc.json
ADDED
package/CHANGES.md
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
# Release notes
|
|
2
|
+
|
|
2
3
|
All notable changes to this project will be documented in this file.
|
|
3
4
|
This project adheres to [Semantic Versioning](http://semver.org/).
|
|
4
5
|
|
|
5
6
|
## 1.0.1
|
|
6
|
-
|
|
7
|
-
-
|
|
7
|
+
|
|
8
|
+
- Update dependencies
|
|
9
|
+
- Fix $confirmDestroy
|
|
8
10
|
|
|
9
11
|
## 1.0.0
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
- Initial public release
|
package/package.json
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
2
|
+
"name": "@signal24/vue-foundation",
|
|
3
|
+
"version": "3.6.0",
|
|
4
|
+
"description": "Common components, directives, and helpers for Vue 3 apps",
|
|
5
|
+
"main": "src/index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"format": "prettier --write . && eslint src --fix"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"axios": "^0.26.0",
|
|
12
|
+
"jquery": "^3.6.0",
|
|
13
|
+
"lodash": "^4.17.21",
|
|
14
|
+
"moment": "^2.29.1",
|
|
15
|
+
"vue-stash-nested": "fergusean/vue-stash-nested#vue-foundation-3"
|
|
16
|
+
},
|
|
17
|
+
"devDependencies": {
|
|
18
|
+
"@vue/eslint-config-prettier": "^7.0.0",
|
|
19
|
+
"eslint": "^8.10.0",
|
|
20
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
21
|
+
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
22
|
+
"eslint-plugin-vue": "^8.5.0",
|
|
23
|
+
"prettier": "^2.5.1",
|
|
24
|
+
"sass": "^1.49.9",
|
|
25
|
+
"sass-loader": "^12",
|
|
26
|
+
"vue": "^3.2.31"
|
|
27
|
+
}
|
|
15
28
|
}
|
package/postcss.config.js
CHANGED
package/src/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createApp, h } from 'vue'
|
|
1
|
+
import { createApp, h } from 'vue';
|
|
2
2
|
|
|
3
3
|
let rootComponent;
|
|
4
4
|
function setRootComponent(inComponent) {
|
|
@@ -17,7 +17,7 @@ const app = createApp({
|
|
|
17
17
|
},
|
|
18
18
|
|
|
19
19
|
render() {
|
|
20
|
-
return h(rootComponent)
|
|
20
|
+
return h(rootComponent);
|
|
21
21
|
}
|
|
22
22
|
});
|
|
23
23
|
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<select v-if="!options" disabled
|
|
2
|
+
<select v-if="!options" disabled>
|
|
3
|
+
<option>{{ loadingText || 'Loading...' }}</option>
|
|
4
|
+
</select>
|
|
3
5
|
<select v-else v-model="selectedItem">
|
|
4
6
|
<option v-if="nullText" :value="null">{{ nullText }}</option>
|
|
5
|
-
<option v-for="option in options" :key="option.id" :value="option">
|
|
7
|
+
<option v-for="option in options" :key="option.id" :value="option">
|
|
8
|
+
{{ textKey ? option[textKey] : option }}
|
|
9
|
+
</option>
|
|
6
10
|
</select>
|
|
7
11
|
</template>
|
|
8
12
|
|
|
@@ -14,7 +18,7 @@ export default {
|
|
|
14
18
|
return {
|
|
15
19
|
options: null,
|
|
16
20
|
selectedItem: null
|
|
17
|
-
}
|
|
21
|
+
};
|
|
18
22
|
},
|
|
19
23
|
|
|
20
24
|
watch: {
|
|
@@ -38,7 +42,7 @@ export default {
|
|
|
38
42
|
methods: {
|
|
39
43
|
async load() {
|
|
40
44
|
this.options = null;
|
|
41
|
-
let params = this.params ? { params: this.params } : undefined
|
|
45
|
+
let params = this.params ? { params: this.params } : undefined;
|
|
42
46
|
let result = await this.$http.get(this.url, params);
|
|
43
47
|
let options = this.itemsKey ? result.data[this.itemsKey] : result.data;
|
|
44
48
|
this.preprocessor && this.preprocessor(options);
|
|
@@ -46,5 +50,5 @@ export default {
|
|
|
46
50
|
this.selectedItem = this.modelValue;
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
|
-
}
|
|
50
|
-
</script>
|
|
53
|
+
};
|
|
54
|
+
</script>
|
package/src/components/alert.vue
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
<
|
|
2
|
+
<Modal class="vf-alert" :class="classes">
|
|
3
|
+
<template v-if="!this.isBare" v-slot:header>
|
|
4
|
+
<h1>{{ title }}</h1>
|
|
5
|
+
</template>
|
|
4
6
|
|
|
5
7
|
<div v-if="isHtml" v-html="message" class="user-message"></div>
|
|
6
8
|
<div v-else v-user-text="message"></div>
|
|
@@ -12,13 +14,18 @@
|
|
|
12
14
|
</template>
|
|
13
15
|
<button v-else class="default" @click="ok" v-autofocus>OK</button>
|
|
14
16
|
</template>
|
|
15
|
-
</
|
|
17
|
+
</Modal>
|
|
16
18
|
</template>
|
|
17
19
|
|
|
18
20
|
<script>
|
|
19
21
|
import app from '../app';
|
|
22
|
+
import Modal from './modal';
|
|
20
23
|
|
|
21
24
|
const classDef = {
|
|
25
|
+
components: {
|
|
26
|
+
Modal
|
|
27
|
+
},
|
|
28
|
+
|
|
22
29
|
data() {
|
|
23
30
|
return {
|
|
24
31
|
isBare: false,
|
|
@@ -27,17 +34,15 @@ const classDef = {
|
|
|
27
34
|
title: null,
|
|
28
35
|
message: null,
|
|
29
36
|
shouldConfirm: false
|
|
30
|
-
}
|
|
37
|
+
};
|
|
31
38
|
},
|
|
32
39
|
|
|
33
40
|
created() {
|
|
34
|
-
if (typeof
|
|
41
|
+
if (typeof this.message == 'object') {
|
|
35
42
|
if (this.message.html) {
|
|
36
43
|
this.isHtml = true;
|
|
37
44
|
this.message = this.message.html;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
else if (this.message instanceof Error) {
|
|
45
|
+
} else if (this.message instanceof Error) {
|
|
41
46
|
let err = this.message;
|
|
42
47
|
err.handle();
|
|
43
48
|
|
|
@@ -58,51 +63,46 @@ export default classDef;
|
|
|
58
63
|
async function launchModal(context, classDef, ...args) {
|
|
59
64
|
classDef = { ...classDef, __modalId: Math.random().toString(36).substring(2, 10) };
|
|
60
65
|
return await context.$modal.apply(context, [classDef, ...args]);
|
|
61
|
-
}
|
|
66
|
+
}
|
|
62
67
|
|
|
63
|
-
app.config.globalProperties.$alert = async function(title, message) {
|
|
68
|
+
app.config.globalProperties.$alert = async function (title, message) {
|
|
64
69
|
return await launchModal(this, classDef, { title, message });
|
|
65
|
-
}
|
|
70
|
+
};
|
|
66
71
|
|
|
67
|
-
app.config.globalProperties.$confirm = async function(title, message, options) {
|
|
72
|
+
app.config.globalProperties.$confirm = async function (title, message, options) {
|
|
68
73
|
options = options || {};
|
|
69
74
|
const result = await launchModal(this, classDef, { title, message, shouldConfirm: true, ...options });
|
|
70
75
|
return !!result;
|
|
71
|
-
}
|
|
76
|
+
};
|
|
72
77
|
|
|
73
|
-
app.config.globalProperties.$confirmDestroy = function(title, message, options) {
|
|
78
|
+
app.config.globalProperties.$confirmDestroy = function (title, message, options) {
|
|
74
79
|
options = options || {};
|
|
75
80
|
options.classes = options.classes || [];
|
|
76
81
|
options.classes.push('destructive');
|
|
77
82
|
return this.$confirm(title, message, options);
|
|
78
|
-
}
|
|
83
|
+
};
|
|
79
84
|
|
|
80
|
-
app.config.globalProperties.$wait = function(title, message) {
|
|
85
|
+
app.config.globalProperties.$wait = function (title, message) {
|
|
81
86
|
if (title && !message) {
|
|
82
87
|
message = title;
|
|
83
88
|
title = undefined;
|
|
84
|
-
}
|
|
85
|
-
else if (!title && !message) {
|
|
89
|
+
} else if (!title && !message) {
|
|
86
90
|
message = 'Please wait...';
|
|
87
91
|
}
|
|
88
92
|
|
|
89
93
|
let resolved = null;
|
|
90
94
|
let promise = new Promise((resolve, reject) => {
|
|
91
95
|
launchModal(this, classDef, { title, message, isBare: true, classes: ['wait'] }, resolve);
|
|
92
|
-
})
|
|
93
|
-
.then(inResolved => resolved = inResolved);
|
|
96
|
+
}).then(inResolved => (resolved = inResolved));
|
|
94
97
|
|
|
95
98
|
this.$endWait = async () => {
|
|
96
99
|
delete this.$endWait;
|
|
97
|
-
if (resolved)
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
await promise.then(() => resolved.$dismiss());
|
|
101
|
-
}
|
|
100
|
+
if (resolved) await resolved.$dismiss();
|
|
101
|
+
else await promise.then(() => resolved.$dismiss());
|
|
102
|
+
};
|
|
102
103
|
|
|
103
104
|
return this.$endWait;
|
|
104
|
-
}
|
|
105
|
-
|
|
105
|
+
};
|
|
106
106
|
</script>
|
|
107
107
|
|
|
108
108
|
<style lang="scss">
|
|
@@ -127,4 +127,4 @@ app.config.globalProperties.$wait = function(title, message) {
|
|
|
127
127
|
}
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
|
-
</style>
|
|
130
|
+
</style>
|
package/src/components/index.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import app from '../app';
|
|
2
|
-
|
|
3
|
-
import AjaxSelect from './ajax-select'
|
|
2
|
+
import AjaxSelect from './ajax-select';
|
|
4
3
|
app.component('AjaxSelect', AjaxSelect);
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
// the already-cached 'Alert' component instead of recompiling
|
|
9
|
-
// TODO: ^ is this for mutating Alert during dev, or...?
|
|
10
|
-
import Alert from './alert'
|
|
11
|
-
Alert;
|
|
5
|
+
import Alert from './alert';
|
|
6
|
+
app.component('Alert', Alert);
|
|
12
7
|
|
|
13
|
-
import Modal from './modal'
|
|
8
|
+
import Modal from './modal';
|
|
14
9
|
app.component('Modal', Modal);
|
|
15
10
|
|
|
16
|
-
import SmartSelect from './smart-select'
|
|
17
|
-
app.component('SmartSelect', SmartSelect);
|
|
11
|
+
import SmartSelect from './smart-select';
|
|
12
|
+
app.component('SmartSelect', SmartSelect);
|
package/src/components/modal.vue
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="vf-overlay vf-modal-wrap">
|
|
3
|
-
<form
|
|
3
|
+
<form
|
|
4
|
+
action="."
|
|
5
|
+
class="vf-modal"
|
|
6
|
+
:class="{ scrolls: $isPropTruthy(this.scrolls) }"
|
|
7
|
+
@submit.prevent="$emit('formSubmit')"
|
|
8
|
+
>
|
|
4
9
|
<div v-if="$slots.header" class="vf-modal-header">
|
|
5
10
|
<slot name="header" />
|
|
6
11
|
<i v-if="$isPropTruthy(this.closeX)" class="close" @click="$parent.$dismiss()"></i>
|
|
@@ -26,8 +31,7 @@ export default {
|
|
|
26
31
|
|
|
27
32
|
if (this.$isPropTruthy(this.closeOnMaskClick)) {
|
|
28
33
|
this.$el.addEventListener('click', e => {
|
|
29
|
-
if (e.target == this.$el)
|
|
30
|
-
this.$parent.$dismiss();
|
|
34
|
+
if (e.target == this.$el) this.$parent.$dismiss();
|
|
31
35
|
});
|
|
32
36
|
}
|
|
33
37
|
},
|
|
@@ -49,7 +53,7 @@ export default {
|
|
|
49
53
|
}
|
|
50
54
|
}
|
|
51
55
|
}
|
|
52
|
-
}
|
|
56
|
+
};
|
|
53
57
|
|
|
54
58
|
import app from '../app';
|
|
55
59
|
import { markRaw } from 'vue';
|
|
@@ -66,14 +70,18 @@ function bootModal(modalId) {
|
|
|
66
70
|
this.$options.storeParent = this.$modalOpener;
|
|
67
71
|
|
|
68
72
|
let originalDataFn = this.$options.data;
|
|
69
|
-
this.$options.data = function() {
|
|
73
|
+
this.$options.data = function () {
|
|
70
74
|
const injectedData = config.injectedData || {};
|
|
71
75
|
const keepOriginalKeys = this.$options.keepOriginal || [];
|
|
72
76
|
let data = originalDataFn ? originalDataFn.apply(this) : {};
|
|
73
77
|
|
|
74
78
|
for (let key in injectedData) {
|
|
75
79
|
if (!keepOriginalKeys.includes(key)) {
|
|
76
|
-
if (
|
|
80
|
+
if (
|
|
81
|
+
injectedData[key] !== null &&
|
|
82
|
+
typeof injectedData[key] == 'object' &&
|
|
83
|
+
injectedData[key].constructor === Object
|
|
84
|
+
) {
|
|
77
85
|
data[key] = cloneDeep(injectedData[key]);
|
|
78
86
|
} else {
|
|
79
87
|
data[key] = injectedData[key];
|
|
@@ -116,7 +124,7 @@ app.mixin({
|
|
|
116
124
|
}
|
|
117
125
|
});
|
|
118
126
|
|
|
119
|
-
app.config.globalProperties.$modal = function(classDef, injectedData, instanceCreationCallback) {
|
|
127
|
+
app.config.globalProperties.$modal = function (classDef, injectedData, instanceCreationCallback) {
|
|
120
128
|
return new Promise((resolve, reject) => {
|
|
121
129
|
const modalId = classDef.__modalId || classDef.__file || Math.random().toString(36).substring(2, 10);
|
|
122
130
|
classDef.__modalId = modalId;
|
|
@@ -132,7 +140,7 @@ app.config.globalProperties.$modal = function(classDef, injectedData, instanceCr
|
|
|
132
140
|
app.vm.store.rootInjections.push(markRaw(classDef));
|
|
133
141
|
});
|
|
134
142
|
});
|
|
135
|
-
}
|
|
143
|
+
};
|
|
136
144
|
|
|
137
145
|
// TODO: see about a injecting a root modal container & HMR inside it
|
|
138
146
|
// modals, on render, can hot move themselves to body end
|
|
@@ -163,7 +171,7 @@ app.config.globalProperties.$modal = function(classDef, injectedData, instanceCr
|
|
|
163
171
|
|
|
164
172
|
.vf-modal {
|
|
165
173
|
background: white;
|
|
166
|
-
box-shadow: 0px 3px 6px 0px rgba(0,0,0
|
|
174
|
+
box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.15);
|
|
167
175
|
min-width: 200px;
|
|
168
176
|
max-width: 95%;
|
|
169
177
|
max-height: 95%;
|
|
@@ -187,4 +195,4 @@ app.config.globalProperties.$modal = function(classDef, injectedData, instanceCr
|
|
|
187
195
|
flex-shrink: 1;
|
|
188
196
|
flex-basis: 0%;
|
|
189
197
|
}
|
|
190
|
-
</style>
|
|
198
|
+
</style>
|
|
@@ -41,10 +41,10 @@ import debounce from 'lodash/debounce';
|
|
|
41
41
|
const nullSymbol = Symbol(null);
|
|
42
42
|
const createSymbol = Symbol('create');
|
|
43
43
|
|
|
44
|
-
const VALID_KEYS = `\`1234567890-=[]
|
|
44
|
+
const VALID_KEYS = `\`1234567890-=[]\\;',./~!@#$%^&*()_+{}|:"<>?qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM`;
|
|
45
45
|
|
|
46
46
|
export default {
|
|
47
|
-
emits: ['optionsLoaded', 'createItem'],
|
|
47
|
+
emits: ['optionsLoaded', 'createItem', 'update:modelValue'],
|
|
48
48
|
|
|
49
49
|
props: [
|
|
50
50
|
'modelValue',
|
|
@@ -72,7 +72,6 @@ export default {
|
|
|
72
72
|
return {
|
|
73
73
|
isLoaded: false,
|
|
74
74
|
resolvedOptions: [],
|
|
75
|
-
decoratedOptions: [],
|
|
76
75
|
isSearching: false,
|
|
77
76
|
searchText: '',
|
|
78
77
|
selectedOption: null,
|
|
@@ -84,6 +83,10 @@ export default {
|
|
|
84
83
|
},
|
|
85
84
|
|
|
86
85
|
computed: {
|
|
86
|
+
hasManualOptionsObject() {
|
|
87
|
+
return this.options && typeof this.options === 'object' && !Array.isArray(this.options);
|
|
88
|
+
},
|
|
89
|
+
|
|
87
90
|
effectiveDisabled() {
|
|
88
91
|
return this.disabled || !this.resolvedOptions;
|
|
89
92
|
},
|
|
@@ -115,7 +118,8 @@ export default {
|
|
|
115
118
|
});
|
|
116
119
|
|
|
117
120
|
if (this.shouldShowCreateOption) {
|
|
118
|
-
const hasExactMatch =
|
|
121
|
+
const hasExactMatch =
|
|
122
|
+
options.find(option => option.searchContent === strippedSearchText) !== undefined;
|
|
119
123
|
if (!hasExactMatch) {
|
|
120
124
|
options.push({
|
|
121
125
|
key: createSymbol,
|
|
@@ -124,9 +128,7 @@ export default {
|
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
else if (this.nullTitle) {
|
|
131
|
+
} else if (this.nullTitle) {
|
|
130
132
|
options.unshift({
|
|
131
133
|
key: nullSymbol,
|
|
132
134
|
titleHtml: this.nullTitle
|
|
@@ -144,34 +146,27 @@ export default {
|
|
|
144
146
|
return this.titleKey || 'name';
|
|
145
147
|
},
|
|
146
148
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
watch: {
|
|
153
|
-
// props
|
|
154
|
-
|
|
155
|
-
modelValue() {
|
|
156
|
-
this.handleValueChanged();
|
|
157
|
-
},
|
|
158
|
-
|
|
159
|
-
options() {
|
|
160
|
-
this.resolvedOptions = this.options;
|
|
149
|
+
effectiveValueKey() {
|
|
150
|
+
if (this.valueKey) return this.valueKey;
|
|
151
|
+
if (this.hasManualOptionsObject) return this.effectiveIdKey;
|
|
152
|
+
return undefined;
|
|
161
153
|
},
|
|
162
154
|
|
|
163
|
-
|
|
164
|
-
this.
|
|
155
|
+
effectiveNoResultsText() {
|
|
156
|
+
return this.noResultsText || 'No options match your search.';
|
|
165
157
|
},
|
|
166
158
|
|
|
167
|
-
|
|
168
|
-
this.
|
|
159
|
+
resolvedOptionsArray() {
|
|
160
|
+
return this.hasManualOptionsObject
|
|
161
|
+
? Object.entries(this.resolvedOptions).map(entry => ({
|
|
162
|
+
[this.effectiveIdKey]: entry[0],
|
|
163
|
+
[this.effectiveTitleKey]: entry[1]
|
|
164
|
+
}))
|
|
165
|
+
: this.resolvedOptions;
|
|
169
166
|
},
|
|
170
167
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
resolvedOptions() {
|
|
174
|
-
this.decoratedOptions = this.resolvedOptions.map((option, index) => {
|
|
168
|
+
decoratedOptions() {
|
|
169
|
+
return this.resolvedOptionsArray.map((option, index) => {
|
|
175
170
|
const title = this.getOptionTitle(option);
|
|
176
171
|
const subtitle = this.getOptionSubtitle(option);
|
|
177
172
|
const strippedTitle = title ? title.text.trim().toLowerCase() : '';
|
|
@@ -195,7 +190,31 @@ export default {
|
|
|
195
190
|
ref: option
|
|
196
191
|
};
|
|
197
192
|
});
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
watch: {
|
|
197
|
+
// props
|
|
198
|
+
|
|
199
|
+
modelValue() {
|
|
200
|
+
this.handleValueChanged();
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
options() {
|
|
204
|
+
this.resolvedOptions = this.options;
|
|
205
|
+
},
|
|
206
|
+
|
|
207
|
+
url() {
|
|
208
|
+
this.handleSourceUpdate();
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
urlParams() {
|
|
212
|
+
this.handleSourceUpdate();
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
// data
|
|
198
216
|
|
|
217
|
+
decoratedOptions() {
|
|
199
218
|
this.shouldDisplayOptions && setTimeout(this.highlightInitialOption, 0);
|
|
200
219
|
},
|
|
201
220
|
|
|
@@ -227,6 +246,7 @@ export default {
|
|
|
227
246
|
|
|
228
247
|
if (this.options) {
|
|
229
248
|
this.resolvedOptions = this.options;
|
|
249
|
+
// this.buildDecoratedOptions();
|
|
230
250
|
this.isLoaded = true;
|
|
231
251
|
} else if (this.$isPropTruthy(this.preload)) {
|
|
232
252
|
this.performInitialLoad();
|
|
@@ -235,7 +255,8 @@ export default {
|
|
|
235
255
|
this.handleValueChanged();
|
|
236
256
|
|
|
237
257
|
this.$watch('selectedOption', () => {
|
|
238
|
-
const newValue =
|
|
258
|
+
const newValue =
|
|
259
|
+
this.selectedOption && this.effectiveValueKey ? this.selectedOption[this.effectiveValueKey] : this.selectedOption;
|
|
239
260
|
newValue === this.modelValue || this.$emit('update:modelValue', newValue);
|
|
240
261
|
});
|
|
241
262
|
},
|
|
@@ -429,10 +450,10 @@ export default {
|
|
|
429
450
|
this.selectedOptionTitle = null;
|
|
430
451
|
this.$emit('createItem', createText);
|
|
431
452
|
} else {
|
|
432
|
-
const
|
|
453
|
+
const selectedDecoratedOption = this.decoratedOptions.find(
|
|
433
454
|
decoratedOption => decoratedOption.key == option.key
|
|
434
455
|
);
|
|
435
|
-
const realOption =
|
|
456
|
+
const realOption = selectedDecoratedOption.ref;
|
|
436
457
|
this.selectedOption = realOption;
|
|
437
458
|
this.selectedOptionTitle = this.getOptionTitle(this.selectedOption).text;
|
|
438
459
|
this.searchText = this.selectedOptionTitle || '';
|
|
@@ -443,8 +464,10 @@ export default {
|
|
|
443
464
|
|
|
444
465
|
handleValueChanged() {
|
|
445
466
|
if (this.modelValue) {
|
|
446
|
-
if (this.
|
|
447
|
-
this.selectedOption = this.
|
|
467
|
+
if (this.effectiveValueKey) {
|
|
468
|
+
this.selectedOption = this.resolvedOptionsArray.find(
|
|
469
|
+
option => option[this.effectiveValueKey] === this.modelValue
|
|
470
|
+
);
|
|
448
471
|
} else {
|
|
449
472
|
this.selectedOption = this.modelValue;
|
|
450
473
|
}
|
package/src/config.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import app from '../app';
|
|
2
1
|
import $ from 'jquery';
|
|
3
2
|
|
|
3
|
+
import app from '../app';
|
|
4
|
+
|
|
4
5
|
app.directive('autofocus', {
|
|
5
6
|
mounted: fn,
|
|
6
7
|
updated: fn
|
|
@@ -11,6 +12,6 @@ function fn(el, binding) {
|
|
|
11
12
|
if (binding.value !== undefined && !binding.value) return;
|
|
12
13
|
if (binding.oldValue !== undefined && binding.value == binding.oldValue) return;
|
|
13
14
|
el.hasAutoFocused = true;
|
|
14
|
-
el = ['BUTTON','INPUT','TEXTAREA','SELECT'].indexOf(el.tagName) > -1 ? el : $(el).find('input:first')[0];
|
|
15
|
+
el = ['BUTTON', 'INPUT', 'TEXTAREA', 'SELECT'].indexOf(el.tagName) > -1 ? el : $(el).find('input:first')[0];
|
|
15
16
|
setTimeout(() => el.focus(), 10);
|
|
16
|
-
}
|
|
17
|
+
}
|
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
import app from '../app';
|
|
2
1
|
import moment from 'moment';
|
|
3
2
|
|
|
3
|
+
import app from '../app';
|
|
4
|
+
|
|
4
5
|
app.directive('date-input', {
|
|
5
6
|
beforeMount: fn
|
|
6
7
|
});
|
|
7
8
|
|
|
8
|
-
function fn(el
|
|
9
|
+
function fn(el) {
|
|
9
10
|
el.addEventListener('blur', () => {
|
|
10
11
|
let val = el.value;
|
|
11
|
-
if (/^[0-9]{1,2}\/[0-9]{1,2}$/.test(val))
|
|
12
|
-
val += '/' + moment().format('YY');
|
|
12
|
+
if (/^[0-9]{1,2}\/[0-9]{1,2}$/.test(val)) val += '/' + moment().format('YY');
|
|
13
13
|
let ts = Date.parse(val);
|
|
14
|
-
if (isNaN(ts))
|
|
15
|
-
|
|
16
|
-
else
|
|
17
|
-
el.value = moment(ts).format('MM/DD/YYYY');
|
|
14
|
+
if (isNaN(ts)) el.value = '';
|
|
15
|
+
else el.value = moment(ts).format('MM/DD/YYYY');
|
|
18
16
|
el.dispatchEvent(new Event('input'));
|
|
19
17
|
});
|
|
20
|
-
}
|
|
18
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import app from '../app';
|
|
2
1
|
import moment from 'moment';
|
|
3
2
|
|
|
3
|
+
import app from '../app';
|
|
4
|
+
|
|
4
5
|
app.directive('datetime', {
|
|
5
6
|
beforeMount: applyDateTime,
|
|
6
7
|
updated: applyDateTime
|
|
@@ -19,26 +20,27 @@ function getDateTimeValue(el, binding) {
|
|
|
19
20
|
let prefix = '';
|
|
20
21
|
let thatMoment = el.attributes.local ? moment(binding.value) : moment.utc(binding.value);
|
|
21
22
|
|
|
22
|
-
if (!el.attributes['display-utc'])
|
|
23
|
-
thatMoment.local();
|
|
23
|
+
if (!el.attributes['display-utc']) thatMoment.local();
|
|
24
24
|
|
|
25
25
|
let format = el.attributes.format ? el.attributes.format.value : null;
|
|
26
26
|
|
|
27
27
|
if (!format && el.attributes['relative-date']) {
|
|
28
28
|
let thisMoment = moment();
|
|
29
|
-
if (
|
|
29
|
+
if (
|
|
30
|
+
thisMoment.year() == thatMoment.year() &&
|
|
31
|
+
thisMoment.month() == thatMoment.month() &&
|
|
32
|
+
thisMoment.date() == thatMoment.date()
|
|
33
|
+
) {
|
|
30
34
|
prefix = 'at';
|
|
31
35
|
format = 'HH:mm';
|
|
32
36
|
}
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
if (!format)
|
|
36
|
-
format = 'MM/DD/YY HH:mm';
|
|
39
|
+
if (!format) format = 'MM/DD/YY HH:mm';
|
|
37
40
|
|
|
38
41
|
let result = thatMoment.format(format);
|
|
39
42
|
|
|
40
|
-
if (prefix)
|
|
41
|
-
result = prefix + ' ' + result;
|
|
43
|
+
if (prefix) result = prefix + ' ' + result;
|
|
42
44
|
|
|
43
45
|
return result;
|
|
44
|
-
}
|
|
46
|
+
}
|