@windward/core 0.12.0 → 0.12.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.
package/CHANGELOG.md
CHANGED
|
@@ -83,6 +83,9 @@ export default {
|
|
|
83
83
|
ImageAssetViewer,
|
|
84
84
|
},
|
|
85
85
|
extends: BaseContentBlock,
|
|
86
|
+
data() {
|
|
87
|
+
return {}
|
|
88
|
+
},
|
|
86
89
|
beforeMount() {
|
|
87
90
|
this.block.body = this.$t(
|
|
88
91
|
'windward.core.shared.content_blocks.title.tab'
|
|
@@ -117,9 +120,6 @@ export default {
|
|
|
117
120
|
this.block.metadata.config.currentTab = 0
|
|
118
121
|
}
|
|
119
122
|
},
|
|
120
|
-
data() {
|
|
121
|
-
return {}
|
|
122
|
-
},
|
|
123
123
|
methods: {
|
|
124
124
|
async onBeforeSave() {
|
|
125
125
|
this.block.metadata.config.items.forEach((element) => {
|
|
@@ -128,12 +128,15 @@ export default {
|
|
|
128
128
|
this.block.metadata.config.currentTab = null
|
|
129
129
|
},
|
|
130
130
|
getImageWidth(item) {
|
|
131
|
-
if (item
|
|
131
|
+
if (item?.imageAsset?.display) {
|
|
132
132
|
return String(item.imageAsset.display.width) + '%'
|
|
133
133
|
}
|
|
134
134
|
},
|
|
135
135
|
getTextImageContainerClass(item) {
|
|
136
|
-
const { margin, width } = item
|
|
136
|
+
const { margin, width } = item?.imageAsset?.display || {
|
|
137
|
+
margin: null,
|
|
138
|
+
width: null,
|
|
139
|
+
}
|
|
137
140
|
// if full width set container to column
|
|
138
141
|
if (width === 100) {
|
|
139
142
|
return margin === 'top'
|
|
@@ -160,7 +163,7 @@ export default {
|
|
|
160
163
|
}
|
|
161
164
|
},
|
|
162
165
|
getImageOrder(item) {
|
|
163
|
-
const margin = item
|
|
166
|
+
const margin = item?.imageAsset?.display?.margin
|
|
164
167
|
// filter out tab blocks that were created before custom
|
|
165
168
|
// spacing was added to image asset settings
|
|
166
169
|
if (margin) {
|
|
@@ -1,64 +1,65 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
3
|
-
v-
|
|
4
|
-
class="glossary-word"
|
|
5
|
-
:class="{ active: show }"
|
|
6
|
-
@click="show = !show"
|
|
7
|
-
>
|
|
8
|
-
<v-tooltip
|
|
2
|
+
<div class="glossary-word" :class="{ active: show }">
|
|
3
|
+
<v-menu
|
|
9
4
|
v-model="show"
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
color="primary"
|
|
5
|
+
:close-on-content-click="false"
|
|
6
|
+
offset-y
|
|
13
7
|
max-width="768px"
|
|
14
|
-
z-index="
|
|
8
|
+
:z-index="20"
|
|
15
9
|
>
|
|
16
10
|
<template #activator="{ on }">
|
|
17
|
-
<span
|
|
11
|
+
<span
|
|
12
|
+
tabindex="0"
|
|
13
|
+
v-on="on"
|
|
14
|
+
@click.stop="show = !show"
|
|
15
|
+
>
|
|
18
16
|
<slot name="term"></slot>
|
|
19
17
|
</span>
|
|
20
18
|
</template>
|
|
21
|
-
<div>
|
|
22
|
-
<div v-if="$slots['definition']">
|
|
23
|
-
<h6 class="text-capitalize">
|
|
24
|
-
<slot name="term"></slot>
|
|
25
|
-
{{
|
|
26
|
-
$t(
|
|
27
|
-
'windward.core.components.utils.tiny_mce_wrapper.definition'
|
|
28
|
-
)
|
|
29
|
-
}}
|
|
30
|
-
:
|
|
31
|
-
</h6>
|
|
32
|
-
<p>
|
|
33
|
-
<slot name="definition"></slot>
|
|
34
|
-
</p>
|
|
35
|
-
</div>
|
|
36
|
-
<div v-if="$slots['alternate_forms']">
|
|
37
|
-
<h4 class="text-capitalize">
|
|
38
|
-
<slot name="term"></slot>
|
|
39
|
-
{{
|
|
40
|
-
$t(
|
|
41
|
-
'windward.core.components.utils.tiny_mce_wrapper.alternate_forms'
|
|
42
|
-
)
|
|
43
|
-
}}
|
|
44
|
-
:
|
|
45
|
-
</h4>
|
|
46
|
-
<p><slot name="alternate_forms"></slot></p>
|
|
47
|
-
</div>
|
|
48
19
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
20
|
+
<v-card>
|
|
21
|
+
<v-card-text>
|
|
22
|
+
<div v-if="$slots['definition']">
|
|
23
|
+
<h6 class="text-capitalize">
|
|
24
|
+
<slot name="term"></slot>
|
|
25
|
+
{{
|
|
26
|
+
$t(
|
|
27
|
+
'windward.core.components.utils.tiny_mce_wrapper.definition'
|
|
28
|
+
)
|
|
29
|
+
}}
|
|
30
|
+
:
|
|
31
|
+
</h6>
|
|
32
|
+
<p>
|
|
33
|
+
<slot name="definition"></slot>
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
<div v-if="$slots['alternate_forms']">
|
|
37
|
+
<h4 class="text-capitalize">
|
|
38
|
+
<slot name="term"></slot>
|
|
39
|
+
{{
|
|
40
|
+
$t(
|
|
41
|
+
'windward.core.components.utils.tiny_mce_wrapper.alternate_forms'
|
|
42
|
+
)
|
|
43
|
+
}}
|
|
44
|
+
:
|
|
45
|
+
</h4>
|
|
46
|
+
<p><slot name="alternate_forms"></slot></p>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div v-if="$slots['related_terms']">
|
|
50
|
+
<h4 class="text-capitalize">
|
|
51
|
+
{{
|
|
52
|
+
$t(
|
|
53
|
+
'windward.core.components.utils.tiny_mce_wrapper.related_terms'
|
|
54
|
+
)
|
|
55
|
+
}}
|
|
56
|
+
:
|
|
57
|
+
</h4>
|
|
58
|
+
<p><slot name="related_terms"></slot></p>
|
|
59
|
+
</div>
|
|
60
|
+
</v-card-text>
|
|
61
|
+
</v-card>
|
|
62
|
+
</v-menu>
|
|
62
63
|
</div>
|
|
63
64
|
</template>
|
|
64
65
|
|
|
@@ -67,14 +68,12 @@ export default {
|
|
|
67
68
|
name: 'GlossaryToolTip',
|
|
68
69
|
data() {
|
|
69
70
|
return {
|
|
70
|
-
show: false
|
|
71
|
+
show: false
|
|
71
72
|
}
|
|
72
73
|
},
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
},
|
|
74
|
+
beforeDestroy() {
|
|
75
|
+
this.show = false
|
|
76
|
+
}
|
|
78
77
|
}
|
|
79
78
|
</script>
|
|
80
79
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { mount, createLocalVue } from '@vue/test-utils'
|
|
2
|
+
import Vue from 'vue'
|
|
3
|
+
import Vuetify from 'vuetify'
|
|
4
|
+
import VueI18n from 'vue-i18n'
|
|
5
|
+
import GlossaryToolTip from '../../../../components/utils/glossary/GlossaryToolTip.vue'
|
|
6
|
+
|
|
7
|
+
Vue.use(Vuetify)
|
|
8
|
+
Vue.use(VueI18n)
|
|
9
|
+
|
|
10
|
+
describe('GlossaryToolTip', () => {
|
|
11
|
+
const localVue = createLocalVue()
|
|
12
|
+
let vuetify
|
|
13
|
+
let i18n
|
|
14
|
+
let wrapper
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vuetify = new Vuetify()
|
|
18
|
+
i18n = new VueI18n({
|
|
19
|
+
locale: 'en',
|
|
20
|
+
messages: {
|
|
21
|
+
en: {
|
|
22
|
+
'windward.core.components.utils.tiny_mce_wrapper.definition': 'Definition',
|
|
23
|
+
'windward.core.components.utils.tiny_mce_wrapper.alternate_forms': 'Alternate Forms',
|
|
24
|
+
'windward.core.components.utils.tiny_mce_wrapper.related_terms': 'Related Terms'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
// Create data-app element for Vuetify
|
|
30
|
+
const app = document.createElement('div')
|
|
31
|
+
app.setAttribute('data-app', 'true')
|
|
32
|
+
document.body.appendChild(app)
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
afterEach(() => {
|
|
36
|
+
wrapper.destroy()
|
|
37
|
+
// Clean up data-app element
|
|
38
|
+
const app = document.querySelector('[data-app=true]')
|
|
39
|
+
if (app) {
|
|
40
|
+
document.body.removeChild(app)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
const mountComponent = (options = {}) => {
|
|
45
|
+
return mount(GlossaryToolTip, {
|
|
46
|
+
localVue,
|
|
47
|
+
vuetify,
|
|
48
|
+
i18n,
|
|
49
|
+
attachTo: document.body,
|
|
50
|
+
slots: {
|
|
51
|
+
term: '<span>Test Term</span>',
|
|
52
|
+
definition: '<span>Test Definition</span>'
|
|
53
|
+
},
|
|
54
|
+
...options
|
|
55
|
+
})
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const waitForMenuTransition = async () => {
|
|
59
|
+
await new Promise(resolve => setTimeout(resolve, 300))
|
|
60
|
+
await Vue.nextTick()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
it('renders the term in the activator slot', () => {
|
|
64
|
+
wrapper = mountComponent()
|
|
65
|
+
expect(wrapper.find('.glossary-word').text()).toContain('Test Term')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('starts with menu closed', () => {
|
|
69
|
+
wrapper = mountComponent()
|
|
70
|
+
expect(wrapper.vm.show).toBe(false)
|
|
71
|
+
expect(wrapper.find('.v-menu__content').exists()).toBe(false)
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
it('opens menu on click', async () => {
|
|
75
|
+
wrapper = mountComponent()
|
|
76
|
+
const activator = wrapper.find('.glossary-word span')
|
|
77
|
+
|
|
78
|
+
await activator.trigger('click')
|
|
79
|
+
await waitForMenuTransition()
|
|
80
|
+
|
|
81
|
+
expect(wrapper.vm.show).toBe(true)
|
|
82
|
+
const menu = document.querySelector('.v-menu__content')
|
|
83
|
+
expect(menu).toBeTruthy()
|
|
84
|
+
expect(getComputedStyle(menu).display).not.toBe('none')
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
it('closes menu when clicking outside', async () => {
|
|
88
|
+
wrapper = mountComponent()
|
|
89
|
+
const activator = wrapper.find('.glossary-word span')
|
|
90
|
+
|
|
91
|
+
// Open menu
|
|
92
|
+
await activator.trigger('click')
|
|
93
|
+
await waitForMenuTransition()
|
|
94
|
+
expect(wrapper.vm.show).toBe(true)
|
|
95
|
+
|
|
96
|
+
// Click outside
|
|
97
|
+
document.body.click()
|
|
98
|
+
await waitForMenuTransition()
|
|
99
|
+
|
|
100
|
+
expect(wrapper.vm.show).toBe(false)
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
it('renders definition content when menu is open', async () => {
|
|
104
|
+
wrapper = mountComponent()
|
|
105
|
+
const activator = wrapper.find('.glossary-word span')
|
|
106
|
+
|
|
107
|
+
await activator.trigger('click')
|
|
108
|
+
await waitForMenuTransition()
|
|
109
|
+
|
|
110
|
+
expect(document.body.textContent).toContain('Test Definition')
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('applies active class when menu is open', async () => {
|
|
114
|
+
wrapper = mountComponent()
|
|
115
|
+
const activator = wrapper.find('.glossary-word span')
|
|
116
|
+
|
|
117
|
+
await activator.trigger('click')
|
|
118
|
+
await waitForMenuTransition()
|
|
119
|
+
|
|
120
|
+
expect(wrapper.find('.glossary-word').classes()).toContain('active')
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('removes active class when menu is closed', async () => {
|
|
124
|
+
wrapper = mountComponent()
|
|
125
|
+
const activator = wrapper.find('.glossary-word span')
|
|
126
|
+
|
|
127
|
+
// Open then close
|
|
128
|
+
await activator.trigger('click')
|
|
129
|
+
await waitForMenuTransition()
|
|
130
|
+
|
|
131
|
+
document.body.click()
|
|
132
|
+
await waitForMenuTransition()
|
|
133
|
+
|
|
134
|
+
expect(wrapper.find('.glossary-word').classes()).not.toContain('active')
|
|
135
|
+
})
|
|
136
|
+
})
|