Skip to content

Commit 53d4227

Browse files
committed
add truncate directive, modularize slide toc buttons
1 parent cb26d3e commit 53d4227

File tree

6 files changed

+323
-262
lines changed

6 files changed

+323
-262
lines changed

src/app.vue

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ export default class App extends Vue {
2626
}
2727
}
2828
}
29-
30-
3129
</script>
3230

3331
<style lang="scss">
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<template>
2+
<button
3+
class="flex gap-2 px-2 rounded-md bg-transparent hover:bg-gray-200"
4+
:disabled="!element[lang]"
5+
:class="{
6+
'selected-toc-config-item': element[lang] === currentSlide,
7+
'py-1': !isMobileSidebar,
8+
'py-2': isMobileSidebar,
9+
'border-2 border-blue-500': isMobileSidebar && element[lang] === currentSlide,
10+
'cursor-not-allowed border-2 border-red-400': !element[lang]
11+
}"
12+
@click.stop="
13+
$emit('select-slide');
14+
isMobileSidebar && $emit('close-sidebar');
15+
"
16+
>
17+
<!-- ::lang:: text -->
18+
<p class="font-bold italic text-gray-500 select-none" :class="{ 'text-gray-700': isActiveSlide }">
19+
{{ lang === 'en' ? 'EN' : 'FR' }}
20+
</p>
21+
<!-- Config title -->
22+
<p
23+
class="text-left select-none truncate-multiline"
24+
:class="{
25+
italic: !element[lang]?.title
26+
}"
27+
v-truncate="{
28+
options: {
29+
delay: '200',
30+
placement: isMobileSidebar ? 'top' : 'right',
31+
content: content,
32+
animateFill: true,
33+
offset: [0, isMobileSidebar ? 0 : 50],
34+
touch: ['hold', 500]
35+
}
36+
}"
37+
>
38+
{{ content }}
39+
</p>
40+
<!-- Options for ::lang:: items with missing configs (e.g. one language has config, other doesn't) -->
41+
<div v-if="!element[lang]" class="ml-auto flex my-auto">
42+
<!-- Create a new blank config -->
43+
<button
44+
class="slide-toc-button"
45+
v-tippy="{
46+
delay: '200',
47+
placement: 'top-start',
48+
content: $t('editor.slides.toc.newBlankConfig'),
49+
animateFill: false,
50+
touch: ['hold', 500]
51+
}"
52+
@click="$emit('create-config')"
53+
>
54+
<svg
55+
xmlns="http://www.w3.org/2000/svg"
56+
shape-rendering="geometricPrecision"
57+
text-rendering="geometricPrecision"
58+
image-rendering="optimizeQuality"
59+
fill-rule="evenodd"
60+
clip-rule="evenodd"
61+
viewBox="0 0 399 511.66"
62+
width="14"
63+
height="14"
64+
class="mx-1"
65+
>
66+
<path
67+
fill-rule="nonzero"
68+
d="M71.1 0h190.92c5.22 0 9.85 2.5 12.77 6.38L394.7 136.11c2.81 3.05 4.21 6.92 4.21 10.78l.09 293.67c0 19.47-8.02 37.23-20.9 50.14l-.09.08c-12.9 12.87-30.66 20.88-50.11 20.88H71.1c-19.54 0-37.33-8.01-50.22-20.9C8.01 477.89 0 460.1 0 440.56V71.1c0-19.56 8-37.35 20.87-50.23C33.75 8 51.54 0 71.1 0zm45.78 254.04c-8.81 0-15.96-7.15-15.96-15.95 0-8.81 7.15-15.96 15.96-15.96h165.23c8.81 0 15.96 7.15 15.96 15.96 0 8.8-7.15 15.95-15.96 15.95H116.88zm0 79.38c-8.81 0-15.96-7.15-15.96-15.96 0-8.8 7.15-15.95 15.96-15.95h156.47c8.81 0 15.96 7.15 15.96 15.95 0 8.81-7.15 15.96-15.96 15.96H116.88zm0 79.39c-8.81 0-15.96-7.15-15.96-15.96s7.15-15.95 15.96-15.95h132.7c8.81 0 15.95 7.14 15.95 15.95 0 8.81-7.14 15.96-15.95 15.96h-132.7zm154.2-363.67v54.21c1.07 13.59 5.77 24.22 13.99 31.24 8.63 7.37 21.65 11.52 38.95 11.83l36.93-.05-89.87-97.23zm96.01 129.11-43.31-.05c-25.2-.4-45.08-7.2-59.39-19.43-14.91-12.76-23.34-30.81-25.07-53.11l-.15-2.22V31.91H71.1c-10.77 0-20.58 4.42-27.68 11.51-7.09 7.1-11.51 16.91-11.51 27.68v369.46c0 10.76 4.43 20.56 11.52 27.65 7.11 7.12 16.92 11.53 27.67 11.53h256.8c10.78 0 20.58-4.4 27.65-11.48 7.13-7.12 11.54-16.93 11.54-27.7V178.25z"
69+
/>
70+
</svg>
71+
</button>
72+
<!-- Button: Copy the ::oppositeLang:: config in the same slide, if it exists -->
73+
<!-- Only available if the slide's ::lang:: config is undefined -->
74+
<button
75+
v-if="element[oppositeLang]"
76+
class="slide-toc-button"
77+
v-tippy="{
78+
delay: '200',
79+
placement: 'top-start',
80+
content:
81+
lang === 'en'
82+
? $t('editor.slides.toc.newConfigFromFR')
83+
: $t('editor.slides.toc.newConfigFromEng'),
84+
animateFill: false,
85+
touch: ['hold', 500]
86+
}"
87+
@click="$emit('copy-config')"
88+
>
89+
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" viewBox="0 0 24 24" class="mx-1">
90+
<path
91+
d="M5 22q-.825 0-1.413-.587Q3 20.825 3 20V6h2v14h11v2Zm4-4q-.825 0-1.412-.587Q7 16.825 7 16V4q0-.825.588-1.413Q8.175 2 9 2h9q.825 0 1.413.587Q20 3.175 20 4v12q0 .825-.587 1.413Q18.825 18 18 18Zm0-2h9V4H9v12Zm0 0V4v12Z"
92+
/>
93+
</svg>
94+
</button>
95+
</div>
96+
<div v-else class="ml-auto flex my-auto">
97+
<!-- ::lang:: options dropdown menu -->
98+
<toc-options :copy-allowed="!!element[oppositeLang]" @copy="$emit('copy')" @clear="$emit('clear')" />
99+
</div>
100+
</button>
101+
</template>
102+
103+
<script lang="ts">
104+
import { Slide } from '@/definitions';
105+
import { Options, Prop, Vue } from 'vue-property-decorator';
106+
import TocOptions from '@/components/helpers/toc-options.vue';
107+
108+
@Options({
109+
components: {
110+
TocOptions
111+
}
112+
})
113+
export default class SlideTocV extends Vue {
114+
@Prop() lang!: string;
115+
@Prop() element: Slide;
116+
@Prop() currentSlide!: Slide | string;
117+
@Prop({ default: false }) isMobileSidebar!: boolean;
118+
@Prop() isActiveSlide: boolean;
119+
120+
oppositeLang = '';
121+
content = '';
122+
123+
updateContent(): void {
124+
if (this.element[this.lang]?.title) {
125+
this.content = this.element[this.lang]?.title;
126+
} else if (this.element[this.lang]?.title === '') {
127+
this.content =
128+
this.lang === 'en'
129+
? this.$t('editor.slides.toc.newENGSlideText')
130+
: this.$t('editor.slides.toc.newFRSlideText');
131+
} else {
132+
this.content =
133+
this.lang === 'en' ? this.$t('editor.slide.toc.noENGslide') : this.$t('editor.slide.toc.noFRSlide');
134+
}
135+
}
136+
137+
mounted(): void {
138+
this.oppositeLang = this.lang === 'en' ? 'fr' : 'en';
139+
this.updateContent();
140+
}
141+
142+
updated(): void {
143+
this.updateContent();
144+
}
145+
}
146+
</script>
147+
148+
<style lang="scss" scoped>
149+
.truncate-multiline {
150+
overflow: hidden;
151+
text-overflow: ellipsis;
152+
display: -webkit-box;
153+
-webkit-box-orient: vertical;
154+
-webkit-line-clamp: 2;
155+
}
156+
157+
.slide-toc-button {
158+
border-radius: 3px;
159+
padding: 2px;
160+
}
161+
.slide-toc-button:hover {
162+
background-color: rgb(209, 213, 219);
163+
}
164+
</style>

0 commit comments

Comments
 (0)