js-kompo-utils 1.0.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/README.md +1 -0
- package/app.js +22 -0
- package/components/VlApexChart.vue +89 -0
- package/components/VlCKEditorTemplate.vue +52 -0
- package/components/VlCKEditorWithVars.vue +80 -0
- package/components/VlCollapsible.vue +91 -0
- package/components/VlCopyBox.vue +61 -0
- package/components/VlCreditCardInput.vue +104 -0
- package/components/VlDateMonthDay.vue +327 -0
- package/components/VlDateTextInput.vue +151 -0
- package/components/VlInternationalPhoneInput.vue +902 -0
- package/components/VlPartialDate.vue +283 -0
- package/components/VlPasswordInput.vue +358 -0
- package/components/VlQrCodeScanner.vue +91 -0
- package/components/VlSwipeableTab.vue +35 -0
- package/components/VlSwipeableTabs.vue +325 -0
- package/components/VlText.vue +72 -0
- package/components/VlTutorialStepBuilder.vue +671 -0
- package/components/VlValidatedInput.vue +262 -0
- package/components/data/countries.js +253 -0
- package/components/getAllDefaultComponents.js +12 -0
- package/docs/architecture.md +71 -0
- package/docs/tutorials.md +247 -0
- package/docs/usage.md +128 -0
- package/functions/index.js +7 -0
- package/functions/inputs.js +64 -0
- package/functions/loading.js +20 -0
- package/kompo-ckeditor-1.0.17/index.js +5 -0
- package/kompo-ckeditor-1.0.17/komponents/CKEditor.vue +36 -0
- package/kompo-ckeditor-1.0.17/komponents/CKEditorExtended.vue +66 -0
- package/kompo-ckeditor-1.0.17/komponents/EditableCKEditor.vue +42 -0
- package/kompo-ckeditor-1.0.17/komponents/TranslatableEditor.vue +28 -0
- package/kompo-ckeditor-1.0.17/mixins/CKEditor.js +291 -0
- package/kompo-ckeditor-1.0.17/mixins/CKEditorUtilities.js +52 -0
- package/kompo-ckeditor-1.0.17/mixins/CkUploadAdapter.js +95 -0
- package/kompo-ckeditor-1.0.17/mixins/translations/en.js +1 -0
- package/kompo-ckeditor-1.0.17/mixins/translations/fr.js +1 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockCommand.js +100 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockEditing.js +225 -0
- package/kompo-ckeditor-1.0.17/plugins/JsonBlockUi.js +21 -0
- package/kompo-ckeditor-1.0.17/plugins/MentionPlugin.js +118 -0
- package/orchestrator/KompoJsBuilder.js +333 -0
- package/package.json +25 -0
- package/raw_animations/count-up-animation.js +220 -0
- package/raw_animations/magic-poof.js +210 -0
- package/tutorials/TutorialConfig.js +34 -0
- package/tutorials/TutorialEngine.js +448 -0
- package/tutorials/index.js +2 -0
- package/tutorials/modules/AutoNext.js +86 -0
- package/tutorials/modules/Avatar.js +94 -0
- package/tutorials/modules/Bubble.js +617 -0
- package/tutorials/modules/Cursor.js +315 -0
- package/tutorials/modules/Highlight.js +282 -0
- package/tutorials/modules/HoverForcer.js +250 -0
- package/tutorials/modules/Mobile.js +148 -0
- package/tutorials/modules/Options.js +98 -0
- package/tutorials/modules/Overlay.js +142 -0
- package/tutorials/modules/Scroll.js +37 -0
- package/tutorials/modules/Typewriter.js +132 -0
- package/tutorials/step-builder/step-builder-bridge.js +436 -0
- package/tutorials/step-builder/utils/bezier-editor.js +379 -0
- package/tutorials/step-builder/utils/code-generator.js +127 -0
- package/tutorials/step-builder/utils/element-picker.js +125 -0
- package/tutorials/tutorial.scss +816 -0
- package/tutorials/utils/selectors.js +225 -0
- package/tutorials/utils/stability.js +76 -0
- package/tutorials/utils/svg.js +46 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div v-if="isVisible">
|
|
3
|
+
|
|
4
|
+
<p class="px-4 py-2 rounded-xl my-4" :class="resultClass" v-html="result"/>
|
|
5
|
+
|
|
6
|
+
<qrcode-stream :camera="camera" @decode="onDecode" @init="onInit" />
|
|
7
|
+
|
|
8
|
+
<!--<p class="p-4 rounded-xl my-4" :class="resultClass" v-html="result"/>-->
|
|
9
|
+
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
|
|
15
|
+
import Trigger from 'vue-kompo/js/form/mixins/Trigger'
|
|
16
|
+
|
|
17
|
+
export default {
|
|
18
|
+
mixins: [Trigger],
|
|
19
|
+
|
|
20
|
+
data () {
|
|
21
|
+
return {
|
|
22
|
+
result: '',
|
|
23
|
+
resultClass: '',
|
|
24
|
+
error: '',
|
|
25
|
+
camera: 'auto',
|
|
26
|
+
isVisible: false,
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
mounted(){
|
|
31
|
+
setTimeout(() => {
|
|
32
|
+
this.isVisible = true
|
|
33
|
+
window.isCameraActive = true
|
|
34
|
+
setInterval(() => this.checkCameraActive(), 2000)
|
|
35
|
+
}, 1000)
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
methods: {
|
|
39
|
+
checkCameraActive(){
|
|
40
|
+
this.isVisible = window.isCameraActive
|
|
41
|
+
},
|
|
42
|
+
onDecode (qrCode) {
|
|
43
|
+
axios({
|
|
44
|
+
url: this.$_config('checkRoute')+'/'+qrCode,
|
|
45
|
+
method: 'POST',
|
|
46
|
+
}).then(r => {
|
|
47
|
+
this.$kompo.vlFillModal(r, 'some-kompo-id')
|
|
48
|
+
this.camera = 'off'
|
|
49
|
+
setTimeout(() => this.camera = 'auto', 1000)
|
|
50
|
+
})
|
|
51
|
+
},
|
|
52
|
+
|
|
53
|
+
async onInit (promise) {
|
|
54
|
+
try {
|
|
55
|
+
await promise
|
|
56
|
+
|
|
57
|
+
this.result = this.$_config('readyMsg');
|
|
58
|
+
this.resultClass = 'bg-level5 text-white';
|
|
59
|
+
|
|
60
|
+
} catch (error) {
|
|
61
|
+
if (error.name === 'NotAllowedError') {
|
|
62
|
+
this.error = "ERROR: you need to grant camera access permission"
|
|
63
|
+
} else if (error.name === 'NotFoundError') {
|
|
64
|
+
this.error = "ERROR: no camera on this device"
|
|
65
|
+
} else if (error.name === 'NotSupportedError') {
|
|
66
|
+
his.error = "ERROR: secure context required (HTTPS, localhost)"
|
|
67
|
+
} else if (error.name === 'NotReadableError') {
|
|
68
|
+
this.error = "ERROR: is the camera already in use?"
|
|
69
|
+
} else if (error.name === 'OverconstrainedError') {
|
|
70
|
+
this.error = "ERROR: installed cameras are not suitable"
|
|
71
|
+
} else if (error.name === 'StreamApiNotSupportedError') {
|
|
72
|
+
this.error = "ERROR: Stream API is not supported in this browser"
|
|
73
|
+
} else if (error.name === 'InsecureContextError') {
|
|
74
|
+
this.error = 'ERROR: Camera access is only permitted in secure context. Use HTTPS or localhost rather than HTTP.';
|
|
75
|
+
} else {
|
|
76
|
+
this.error = `ERROR: Camera error (${error.name})`;
|
|
77
|
+
}
|
|
78
|
+
this.resultClass = 'bg-danger text-white';
|
|
79
|
+
this.result = this.error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<style scoped>
|
|
87
|
+
.error {
|
|
88
|
+
font-weight: bold;
|
|
89
|
+
color: red;
|
|
90
|
+
}
|
|
91
|
+
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section
|
|
3
|
+
v-if="!isDisabled"
|
|
4
|
+
:aria-hidden="!activeTab"
|
|
5
|
+
v-show="swipeable || activeTab"
|
|
6
|
+
v-bind="$_layoutWrapperAttributes"
|
|
7
|
+
class="vlTab"
|
|
8
|
+
:class="{ 'vlTab--swipeable': swipeable, 'vlTab--active': activeTab, 'vlTab--collapsed': collapsed }"
|
|
9
|
+
role="tabpanel">
|
|
10
|
+
|
|
11
|
+
<component
|
|
12
|
+
v-bind="$_attributes(tab)"
|
|
13
|
+
v-for="(tab,index) in elements"
|
|
14
|
+
:key="index" />
|
|
15
|
+
|
|
16
|
+
</section>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script>
|
|
20
|
+
import Layout from 'vue-kompo/js/form/mixins/Layout'
|
|
21
|
+
|
|
22
|
+
export default {
|
|
23
|
+
mixins: [Layout],
|
|
24
|
+
props: {
|
|
25
|
+
activeTab: { type: Boolean, required: true },
|
|
26
|
+
swipeable: { type: Boolean, default: false },
|
|
27
|
+
collapsed: { type: Boolean, default: false },
|
|
28
|
+
},
|
|
29
|
+
computed: {
|
|
30
|
+
isDisabled(){
|
|
31
|
+
return this.$_config('tabDisabled')
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}
|
|
35
|
+
</script>
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="vlTabs"
|
|
3
|
+
v-bind="$_layoutWrapperAttributes"
|
|
4
|
+
v-show="!$_hidden">
|
|
5
|
+
<ul role="tablist" class="flex">
|
|
6
|
+
<li
|
|
7
|
+
v-for="(element, index) in elements"
|
|
8
|
+
:key="index"
|
|
9
|
+
role="presentation"
|
|
10
|
+
>
|
|
11
|
+
<vl-form-tab-label
|
|
12
|
+
:activeTab="tabActive(index)"
|
|
13
|
+
:selectedClass="$_selectedClass"
|
|
14
|
+
:unselectedClass="$_unselectedClass"
|
|
15
|
+
:commonClass="$_commonClass"
|
|
16
|
+
:disabledClass="disabledClass"
|
|
17
|
+
:vkompo="element"
|
|
18
|
+
@selectTab="selectTab(index)" />
|
|
19
|
+
</li>
|
|
20
|
+
</ul>
|
|
21
|
+
<div class="vlTabContent" :class="{ 'vlTabContent--swipeable': isSwipeable }">
|
|
22
|
+
<div v-if="isSwipeable"
|
|
23
|
+
class="vlTabSwipeContainer"
|
|
24
|
+
:style="swipeContainerStyle"
|
|
25
|
+
@touchstart="onTouchStart"
|
|
26
|
+
@touchmove="onTouchMove"
|
|
27
|
+
@touchend="onTouchEnd">
|
|
28
|
+
<component
|
|
29
|
+
v-for="(tab, index) in elements"
|
|
30
|
+
:key="index"
|
|
31
|
+
:activeTab="tabActive(index)"
|
|
32
|
+
:collapsed="!tabActive(index)"
|
|
33
|
+
:swipeable="true"
|
|
34
|
+
v-bind="$_attributes(tab)"/>
|
|
35
|
+
</div>
|
|
36
|
+
<template v-else>
|
|
37
|
+
<component
|
|
38
|
+
v-for="(tab,index) in elements"
|
|
39
|
+
:key="index"
|
|
40
|
+
:activeTab="tabActive(index)"
|
|
41
|
+
v-bind="$_attributes(tab)"/>
|
|
42
|
+
</template>
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
46
|
+
|
|
47
|
+
<script>
|
|
48
|
+
import Layout from 'vue-kompo/js/form/mixins/Layout'
|
|
49
|
+
import HasSelectedClass from 'vue-kompo/js/form/mixins/HasSelectedClass'
|
|
50
|
+
|
|
51
|
+
export default {
|
|
52
|
+
mixins: [Layout, HasSelectedClass],
|
|
53
|
+
data(){
|
|
54
|
+
return {
|
|
55
|
+
activeTab: 0,
|
|
56
|
+
// Swipe state
|
|
57
|
+
swipeOffset: 0,
|
|
58
|
+
isSwiping: false,
|
|
59
|
+
isAnimating: false,
|
|
60
|
+
startX: 0,
|
|
61
|
+
startY: 0,
|
|
62
|
+
directionLocked: false,
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
computed: {
|
|
66
|
+
defaultActiveTab(){
|
|
67
|
+
return this.$_config('activeTab')
|
|
68
|
+
},
|
|
69
|
+
tabParamKey(){
|
|
70
|
+
return 'tab_number'
|
|
71
|
+
},
|
|
72
|
+
selectId(){
|
|
73
|
+
return this.$_config('selectId')
|
|
74
|
+
},
|
|
75
|
+
disabledClass(){
|
|
76
|
+
return this.$_config('disabledClass')
|
|
77
|
+
},
|
|
78
|
+
isSwipeable(){
|
|
79
|
+
return !!this.$_config('swipeable')
|
|
80
|
+
},
|
|
81
|
+
isMobile(){
|
|
82
|
+
return typeof window !== 'undefined' && window.matchMedia('(max-width: 1023px)').matches
|
|
83
|
+
},
|
|
84
|
+
swipeContainerStyle(){
|
|
85
|
+
var baseOffset = -this.activeTab * 100
|
|
86
|
+
|
|
87
|
+
if (!this.isMobile) {
|
|
88
|
+
return {
|
|
89
|
+
transform: 'translateX(' + baseOffset + '%)',
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.isSwiping) {
|
|
94
|
+
return {
|
|
95
|
+
transform: 'translateX(calc(' + baseOffset + '% + ' + this.swipeOffset + 'px))',
|
|
96
|
+
transition: 'none',
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return {
|
|
101
|
+
transform: 'translateX(' + baseOffset + '%)',
|
|
102
|
+
transition: this.isAnimating ? 'transform 0.3s ease' : 'none',
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
methods:{
|
|
107
|
+
$_validate(errors) {
|
|
108
|
+
Layout.methods.$_validate.call(this, errors)
|
|
109
|
+
this.elements.forEach( (tab, index) => {
|
|
110
|
+
var errors = []
|
|
111
|
+
tab.$_getErrors(errors)
|
|
112
|
+
if(errors.length)
|
|
113
|
+
this.activeTab = index
|
|
114
|
+
})
|
|
115
|
+
},
|
|
116
|
+
selectTab(index) {
|
|
117
|
+
if (this.activeTab === index) return
|
|
118
|
+
|
|
119
|
+
if (this.isSwipeable) {
|
|
120
|
+
this.isAnimating = true
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.activeTab = index
|
|
124
|
+
this.persistActiveTab()
|
|
125
|
+
this.syncSelect()
|
|
126
|
+
|
|
127
|
+
this.$_runOwnInteractions('click')
|
|
128
|
+
|
|
129
|
+
if (this.isSwipeable) {
|
|
130
|
+
setTimeout(() => {
|
|
131
|
+
this.isAnimating = false
|
|
132
|
+
}, 300)
|
|
133
|
+
}
|
|
134
|
+
},
|
|
135
|
+
tabActive(index) {
|
|
136
|
+
return index == this.activeTab
|
|
137
|
+
},
|
|
138
|
+
tabCollapsed(index) {
|
|
139
|
+
if (!this.isMobile) return false
|
|
140
|
+
if (index === this.activeTab) return false
|
|
141
|
+
if (this.isSwiping || this.isAnimating) return false
|
|
142
|
+
return true
|
|
143
|
+
},
|
|
144
|
+
tabDisabled(index) {
|
|
145
|
+
return this.elements[index].isDisabled
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
// --- Swipe methods ---
|
|
149
|
+
|
|
150
|
+
beginSwipe(startX, startY) {
|
|
151
|
+
this.startX = startX
|
|
152
|
+
this.startY = startY
|
|
153
|
+
this.swipeOffset = 0
|
|
154
|
+
this.isSwiping = false
|
|
155
|
+
this.directionLocked = false
|
|
156
|
+
},
|
|
157
|
+
|
|
158
|
+
updateSwipe(clientX, clientY, preventDefault) {
|
|
159
|
+
if (this.isAnimating) return
|
|
160
|
+
|
|
161
|
+
var deltaX = clientX - this.startX
|
|
162
|
+
var deltaY = clientY - this.startY
|
|
163
|
+
|
|
164
|
+
// Lock direction on first significant movement
|
|
165
|
+
if (!this.directionLocked) {
|
|
166
|
+
if (Math.abs(deltaX) < 5 && Math.abs(deltaY) < 5) return
|
|
167
|
+
|
|
168
|
+
if (Math.abs(deltaY) > Math.abs(deltaX)) {
|
|
169
|
+
// Vertical scroll — do nothing, let browser handle it
|
|
170
|
+
this.directionLocked = true
|
|
171
|
+
this.isSwiping = false
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
this.directionLocked = true
|
|
176
|
+
this.isSwiping = true
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (!this.isSwiping) return
|
|
180
|
+
|
|
181
|
+
if (preventDefault)
|
|
182
|
+
preventDefault()
|
|
183
|
+
|
|
184
|
+
// Boundary resistance: dampen swipe at edges
|
|
185
|
+
if (this.activeTab === 0 && deltaX > 0) {
|
|
186
|
+
deltaX = deltaX * 0.3
|
|
187
|
+
} else if (this.activeTab === this.elements.length - 1 && deltaX < 0) {
|
|
188
|
+
deltaX = deltaX * 0.3
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
this.swipeOffset = deltaX
|
|
192
|
+
},
|
|
193
|
+
|
|
194
|
+
completeSwipe() {
|
|
195
|
+
if (!this.isSwiping) {
|
|
196
|
+
this.directionLocked = false
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
var container = this.$el.querySelector('.vlTabContent')
|
|
201
|
+
var containerWidth = container ? container.offsetWidth : 1
|
|
202
|
+
var swipePercent = Math.abs(this.swipeOffset) / containerWidth
|
|
203
|
+
var swipedLeft = this.swipeOffset < 0
|
|
204
|
+
var swipedRight = this.swipeOffset > 0
|
|
205
|
+
|
|
206
|
+
this.isSwiping = false
|
|
207
|
+
this.isAnimating = true
|
|
208
|
+
|
|
209
|
+
if (swipePercent >= 0.4) {
|
|
210
|
+
// Find next valid (non-disabled) tab
|
|
211
|
+
var nextIndex = this.activeTab
|
|
212
|
+
|
|
213
|
+
if (swipedLeft && this.activeTab < this.elements.length - 1) {
|
|
214
|
+
nextIndex = this.findNextEnabledTab(this.activeTab, 1)
|
|
215
|
+
} else if (swipedRight && this.activeTab > 0) {
|
|
216
|
+
nextIndex = this.findNextEnabledTab(this.activeTab, -1)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (nextIndex !== this.activeTab) {
|
|
220
|
+
this.activeTab = nextIndex
|
|
221
|
+
this.persistActiveTab()
|
|
222
|
+
this.syncSelect()
|
|
223
|
+
this.$_runOwnInteractions('click')
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// else: snap back (activeTab unchanged, animation brings it back)
|
|
227
|
+
|
|
228
|
+
this.swipeOffset = 0
|
|
229
|
+
|
|
230
|
+
setTimeout(() => {
|
|
231
|
+
this.isAnimating = false
|
|
232
|
+
}, 300)
|
|
233
|
+
},
|
|
234
|
+
|
|
235
|
+
onTouchStart(e) {
|
|
236
|
+
if (this.isAnimating) return
|
|
237
|
+
|
|
238
|
+
var touch = e.touches[0]
|
|
239
|
+
this.beginSwipe(touch.clientX, touch.clientY)
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
onTouchMove(e) {
|
|
243
|
+
var touch = e.touches[0]
|
|
244
|
+
this.updateSwipe(touch.clientX, touch.clientY, () => e.preventDefault())
|
|
245
|
+
},
|
|
246
|
+
|
|
247
|
+
onTouchEnd() {
|
|
248
|
+
this.completeSwipe()
|
|
249
|
+
},
|
|
250
|
+
|
|
251
|
+
findNextEnabledTab(fromIndex, direction) {
|
|
252
|
+
var nextIndex = fromIndex + direction
|
|
253
|
+
|
|
254
|
+
while (nextIndex >= 0 && nextIndex < this.elements.length) {
|
|
255
|
+
if (!this.elements[nextIndex].isDisabled) {
|
|
256
|
+
return nextIndex
|
|
257
|
+
}
|
|
258
|
+
nextIndex += direction
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
return fromIndex // No valid tab found, stay put
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
persistActiveTab() {
|
|
265
|
+
if (!this.tabParamKey || typeof window === 'undefined') return
|
|
266
|
+
|
|
267
|
+
var url = new URL(window.location.href)
|
|
268
|
+
url.searchParams.set(this.tabParamKey, this.activeTab)
|
|
269
|
+
window.history.replaceState({}, '', url.toString())
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
getPersistedTab() {
|
|
273
|
+
if (!this.tabParamKey || typeof window === 'undefined') return null
|
|
274
|
+
|
|
275
|
+
var params = new URLSearchParams(window.location.search)
|
|
276
|
+
var tabParam = params.get(this.tabParamKey)
|
|
277
|
+
|
|
278
|
+
if (tabParam === null) return null
|
|
279
|
+
|
|
280
|
+
var parsed = parseInt(tabParam, 10)
|
|
281
|
+
return isNaN(parsed) ? null : parsed
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
syncSelect() {
|
|
285
|
+
if (!this.selectId || typeof window === 'undefined') return
|
|
286
|
+
|
|
287
|
+
this.$nextTick(() => {
|
|
288
|
+
var inputEl = document.getElementById(this.selectId)
|
|
289
|
+
if (!inputEl) return
|
|
290
|
+
|
|
291
|
+
// id is on the <input>, walk up DOM to find a Vue component root
|
|
292
|
+
var el = inputEl.parentElement
|
|
293
|
+
while (el && !el.__vue__) {
|
|
294
|
+
el = el.parentElement
|
|
295
|
+
}
|
|
296
|
+
if (!el) return
|
|
297
|
+
|
|
298
|
+
// Walk up Vue component tree to find the Kompo Select
|
|
299
|
+
var vue = el.__vue__
|
|
300
|
+
while (vue && typeof vue.select !== 'function') {
|
|
301
|
+
vue = vue.$parent
|
|
302
|
+
}
|
|
303
|
+
if (!vue || !vue.component || !vue.component.options) return
|
|
304
|
+
|
|
305
|
+
var option = vue.component.options[this.activeTab]
|
|
306
|
+
if (option) {
|
|
307
|
+
vue.$set(vue.component, 'value', [option])
|
|
308
|
+
}
|
|
309
|
+
})
|
|
310
|
+
},
|
|
311
|
+
},
|
|
312
|
+
created(){
|
|
313
|
+
var persistedTab = this.getPersistedTab()
|
|
314
|
+
|
|
315
|
+
if(persistedTab !== null){
|
|
316
|
+
this.activeTab = persistedTab
|
|
317
|
+
}else if(this.defaultActiveTab !== undefined && this.defaultActiveTab !== null){
|
|
318
|
+
this.activeTab = this.defaultActiveTab
|
|
319
|
+
}
|
|
320
|
+
},
|
|
321
|
+
mounted(){
|
|
322
|
+
this.syncSelect()
|
|
323
|
+
},
|
|
324
|
+
}
|
|
325
|
+
</script>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div
|
|
4
|
+
v-if="!$_displayNone"
|
|
5
|
+
v-show="!$_hidden"
|
|
6
|
+
v-bind="$_attributes"
|
|
7
|
+
v-html="content"
|
|
8
|
+
/>
|
|
9
|
+
<button type="button" :style="buttonStyle" :class="buttonClass" v-if="showMoreBtn" @click.stop="toggleShowingMore">{{showingMore ? showLessText : showMoreText}}</button>
|
|
10
|
+
</div>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
import Other from 'vue-kompo/js/form/mixins/Other'
|
|
15
|
+
|
|
16
|
+
export default {
|
|
17
|
+
mixins: [Other],
|
|
18
|
+
methods: {
|
|
19
|
+
toggleShowingMore() {
|
|
20
|
+
this.showingMore = !this.showingMore;
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
computed: {
|
|
24
|
+
content() {
|
|
25
|
+
const originalContent = this.$_config('content');
|
|
26
|
+
let content = originalContent;
|
|
27
|
+
|
|
28
|
+
if (this.maxLines != null && !this.showingMore) {
|
|
29
|
+
content = content.split('\r\n').slice(0, this.maxLines).join('\r\n');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (this.maxChars != null && !this.showingMore) {
|
|
33
|
+
content = content.slice(0, this.maxChars);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (originalContent != content) {
|
|
37
|
+
content += '...';
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return content;
|
|
41
|
+
},
|
|
42
|
+
showMoreBtn() {
|
|
43
|
+
return (this.maxLines != null || this.maxChars != null) &&
|
|
44
|
+
(this.$_config('content').length != this.content.length || this.showingMore);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
data() {
|
|
48
|
+
return {
|
|
49
|
+
maxLines: null,
|
|
50
|
+
maxChars: null,
|
|
51
|
+
|
|
52
|
+
showMoreText: '',
|
|
53
|
+
showLessText: '',
|
|
54
|
+
|
|
55
|
+
buttonClass: '',
|
|
56
|
+
buttonStyle: '',
|
|
57
|
+
|
|
58
|
+
showingMore: false,
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
mounted() {
|
|
62
|
+
this.maxLines = this.$_config('maxLines') ?? this.maxLines;
|
|
63
|
+
this.maxChars = this.$_config('maxChars') ?? this.maxChars;
|
|
64
|
+
|
|
65
|
+
this.showMoreText = this.$_config('showMoreText') ?? this.showMoreText;
|
|
66
|
+
this.showLessText = this.$_config('showLessText') ?? this.showLessText;
|
|
67
|
+
|
|
68
|
+
this.buttonClass = this.$_config('buttonClass') ?? this.buttonClass;
|
|
69
|
+
this.buttonStyle = this.$_config('buttonStyle') ?? this.buttonStyle;
|
|
70
|
+
},
|
|
71
|
+
}
|
|
72
|
+
</script>
|