mirror of
https://github.com/pipipi-pikachu/PPTist.git
synced 2025-04-15 02:20:00 +08:00
feat: 幻灯片分节
This commit is contained in:
parent
c8547cc898
commit
074ca6745c
@ -54,6 +54,7 @@ npm run dev
|
|||||||
- Add/delete pages
|
- Add/delete pages
|
||||||
- Copy/paste pages
|
- Copy/paste pages
|
||||||
- Adjust page order
|
- Adjust page order
|
||||||
|
- Create sections
|
||||||
- Background settings (solid color, gradient, image)
|
- Background settings (solid color, gradient, image)
|
||||||
- Set canvas size
|
- Set canvas size
|
||||||
- Gridlines
|
- Gridlines
|
||||||
|
@ -40,6 +40,7 @@ npm run dev
|
|||||||
- 页面添加、删除
|
- 页面添加、删除
|
||||||
- 页面顺序调整
|
- 页面顺序调整
|
||||||
- 页面复制粘贴
|
- 页面复制粘贴
|
||||||
|
- 幻灯片分节
|
||||||
- 背景设置(纯色、渐变、图片)
|
- 背景设置(纯色、渐变、图片)
|
||||||
- 设置画布尺寸
|
- 设置画布尺寸
|
||||||
- 网格线
|
- 网格线
|
||||||
|
@ -142,7 +142,25 @@ export default () => {
|
|||||||
const sortSlides = (newIndex: number, oldIndex: number) => {
|
const sortSlides = (newIndex: number, oldIndex: number) => {
|
||||||
if (oldIndex === newIndex) return
|
if (oldIndex === newIndex) return
|
||||||
|
|
||||||
const _slides = JSON.parse(JSON.stringify(slides.value))
|
const _slides: Slide[] = JSON.parse(JSON.stringify(slides.value))
|
||||||
|
|
||||||
|
const movingSlide = _slides[oldIndex]
|
||||||
|
const movingSlideSection = movingSlide.sectionTag
|
||||||
|
if (movingSlideSection) {
|
||||||
|
const movingSlideSectionNext = _slides[oldIndex + 1]
|
||||||
|
delete movingSlide.sectionTag
|
||||||
|
if (movingSlideSectionNext && !movingSlideSectionNext.sectionTag) {
|
||||||
|
movingSlideSectionNext.sectionTag = movingSlideSection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newIndex === 0) {
|
||||||
|
const firstSection = _slides[0].sectionTag
|
||||||
|
if (firstSection) {
|
||||||
|
delete _slides[0].sectionTag
|
||||||
|
movingSlide.sectionTag = firstSection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const _slide = _slides[oldIndex]
|
const _slide = _slides[oldIndex]
|
||||||
_slides.splice(oldIndex, 1)
|
_slides.splice(oldIndex, 1)
|
||||||
_slides.splice(newIndex, 0, _slide)
|
_slides.splice(newIndex, 0, _slide)
|
||||||
@ -150,6 +168,77 @@ export default () => {
|
|||||||
slidesStore.updateSlideIndex(newIndex)
|
slidesStore.updateSlideIndex(newIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createSection = () => {
|
||||||
|
slidesStore.updateSlide({
|
||||||
|
sectionTag: {
|
||||||
|
id: nanoid(6),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeSection = (sectionId: string) => {
|
||||||
|
if (!sectionId) return
|
||||||
|
|
||||||
|
const slide = slides.value.find(slide => slide.sectionTag?.id === sectionId)!
|
||||||
|
slidesStore.removeSlideProps({
|
||||||
|
id: slide.id,
|
||||||
|
propName: 'sectionTag',
|
||||||
|
})
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeAllSection = () => {
|
||||||
|
const _slides = slides.value.map(slide => {
|
||||||
|
if (slide.sectionTag) delete slide.sectionTag
|
||||||
|
return slide
|
||||||
|
})
|
||||||
|
slidesStore.setSlides(_slides)
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeSectionSlides = (sectionId: string) => {
|
||||||
|
let startIndex = 0
|
||||||
|
if (sectionId) {
|
||||||
|
startIndex = slides.value.findIndex(slide => slide.sectionTag?.id === sectionId)
|
||||||
|
}
|
||||||
|
const ids: string[] = []
|
||||||
|
|
||||||
|
for (let i = startIndex; i < slides.value.length; i++) {
|
||||||
|
const slide = slides.value[i]
|
||||||
|
if(i !== startIndex && slide.sectionTag) break
|
||||||
|
|
||||||
|
ids.push(slide.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteSlide(ids)
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateSectionTitle = (sectionId: string, title: string) => {
|
||||||
|
if (!title) return
|
||||||
|
|
||||||
|
if (sectionId === 'default') {
|
||||||
|
slidesStore.updateSlide({
|
||||||
|
sectionTag: {
|
||||||
|
id: nanoid(6),
|
||||||
|
title,
|
||||||
|
},
|
||||||
|
}, slides.value[0].id)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const slide = slides.value.find(slide => slide.sectionTag?.id === sectionId)
|
||||||
|
if (!slide) return
|
||||||
|
|
||||||
|
slidesStore.updateSlide({
|
||||||
|
sectionTag: {
|
||||||
|
...slide.sectionTag!,
|
||||||
|
title,
|
||||||
|
},
|
||||||
|
}, slide.id)
|
||||||
|
}
|
||||||
|
addHistorySnapshot()
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
resetSlides,
|
resetSlides,
|
||||||
updateSlideIndex,
|
updateSlideIndex,
|
||||||
@ -162,5 +251,10 @@ export default () => {
|
|||||||
cutSlide,
|
cutSlide,
|
||||||
selectAllSlide,
|
selectAllSlide,
|
||||||
sortSlides,
|
sortSlides,
|
||||||
|
createSection,
|
||||||
|
removeSection,
|
||||||
|
removeAllSection,
|
||||||
|
removeSectionSlides,
|
||||||
|
updateSectionTitle,
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,7 +6,7 @@ import { slides } from '@/mocks/slides'
|
|||||||
import { theme } from '@/mocks/theme'
|
import { theme } from '@/mocks/theme'
|
||||||
import { layouts } from '@/mocks/layout'
|
import { layouts } from '@/mocks/layout'
|
||||||
|
|
||||||
interface RemoveElementPropData {
|
interface RemovePropData {
|
||||||
id: string
|
id: string
|
||||||
propName: string | string[]
|
propName: string | string[]
|
||||||
}
|
}
|
||||||
@ -126,31 +126,56 @@ export const useSlidesStore = defineStore('slides', {
|
|||||||
|
|
||||||
addSlide(slide: Slide | Slide[]) {
|
addSlide(slide: Slide | Slide[]) {
|
||||||
const slides = Array.isArray(slide) ? slide : [slide]
|
const slides = Array.isArray(slide) ? slide : [slide]
|
||||||
|
for (const slide of slides) {
|
||||||
|
if (slide.sectionTag) delete slide.sectionTag
|
||||||
|
}
|
||||||
|
|
||||||
const addIndex = this.slideIndex + 1
|
const addIndex = this.slideIndex + 1
|
||||||
this.slides.splice(addIndex, 0, ...slides)
|
this.slides.splice(addIndex, 0, ...slides)
|
||||||
this.slideIndex = addIndex
|
this.slideIndex = addIndex
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSlide(props: Partial<Slide>) {
|
updateSlide(props: Partial<Slide>, slideId?: string) {
|
||||||
const slideIndex = this.slideIndex
|
const slideIndex = slideId ? this.slides.findIndex(item => item.id === slideId) : this.slideIndex
|
||||||
this.slides[slideIndex] = { ...this.slides[slideIndex], ...props }
|
this.slides[slideIndex] = { ...this.slides[slideIndex], ...props }
|
||||||
},
|
},
|
||||||
|
|
||||||
|
removeSlideProps(data: RemovePropData) {
|
||||||
|
const { id, propName } = data
|
||||||
|
|
||||||
|
const slides = this.slides.map(slide => {
|
||||||
|
return slide.id === id ? omit(slide, propName) : slide
|
||||||
|
}) as Slide[]
|
||||||
|
this.slides = slides
|
||||||
|
},
|
||||||
|
|
||||||
deleteSlide(slideId: string | string[]) {
|
deleteSlide(slideId: string | string[]) {
|
||||||
const slidesId = Array.isArray(slideId) ? slideId : [slideId]
|
const slidesId = Array.isArray(slideId) ? slideId : [slideId]
|
||||||
|
const slides: Slide[] = JSON.parse(JSON.stringify(this.slides))
|
||||||
|
|
||||||
const deleteSlidesIndex = []
|
const deleteSlidesIndex = []
|
||||||
for (let i = 0; i < slidesId.length; i++) {
|
for (const deletedId of slidesId) {
|
||||||
const index = this.slides.findIndex(item => item.id === slidesId[i])
|
const index = slides.findIndex(item => item.id === deletedId)
|
||||||
deleteSlidesIndex.push(index)
|
deleteSlidesIndex.push(index)
|
||||||
|
|
||||||
|
const deletedSlideSection = slides[index].sectionTag
|
||||||
|
if(deletedSlideSection) {
|
||||||
|
const handleSlideNext = slides[index + 1]
|
||||||
|
if(handleSlideNext && !handleSlideNext.sectionTag) {
|
||||||
|
delete slides[index].sectionTag
|
||||||
|
slides[index + 1].sectionTag = deletedSlideSection
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
slides.splice(index, 1)
|
||||||
}
|
}
|
||||||
let newIndex = Math.min(...deleteSlidesIndex)
|
let newIndex = Math.min(...deleteSlidesIndex)
|
||||||
|
|
||||||
const maxIndex = this.slides.length - slidesId.length - 1
|
const maxIndex = slides.length - 1
|
||||||
if (newIndex > maxIndex) newIndex = maxIndex
|
if (newIndex > maxIndex) newIndex = maxIndex
|
||||||
|
|
||||||
this.slideIndex = newIndex
|
this.slideIndex = newIndex
|
||||||
this.slides = this.slides.filter(item => !slidesId.includes(item.id))
|
this.slides = slides
|
||||||
},
|
},
|
||||||
|
|
||||||
updateSlideIndex(index: number) {
|
updateSlideIndex(index: number) {
|
||||||
@ -183,7 +208,7 @@ export const useSlidesStore = defineStore('slides', {
|
|||||||
this.slides[slideIndex].elements = (elements as PPTElement[])
|
this.slides[slideIndex].elements = (elements as PPTElement[])
|
||||||
},
|
},
|
||||||
|
|
||||||
removeElementProps(data: RemoveElementPropData) {
|
removeElementProps(data: RemovePropData) {
|
||||||
const { id, propName } = data
|
const { id, propName } = data
|
||||||
const propsNames = typeof propName === 'string' ? [propName] : propName
|
const propsNames = typeof propName === 'string' ? [propName] : propName
|
||||||
|
|
||||||
|
@ -677,6 +677,11 @@ export interface Note {
|
|||||||
replies?: NoteReply[]
|
replies?: NoteReply[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SectionTag {
|
||||||
|
id: string
|
||||||
|
title?: string
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 幻灯片页面
|
* 幻灯片页面
|
||||||
*
|
*
|
||||||
@ -702,6 +707,7 @@ export interface Slide {
|
|||||||
background?: SlideBackground
|
background?: SlideBackground
|
||||||
animations?: PPTAnimation[]
|
animations?: PPTAnimation[]
|
||||||
turningMode?: TurningMode
|
turningMode?: TurningMode
|
||||||
|
sectionTag?: SectionTag
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
@dblclick="enterEdit(groupItem.id)"
|
@dblclick="enterEdit(groupItem.id)"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
:id="`input-${groupItem.id}`"
|
:id="`select-panel-input-${groupItem.id}`"
|
||||||
:value="groupItem.name || ELEMENT_TYPE_ZH[groupItem.type]"
|
:value="groupItem.name || ELEMENT_TYPE_ZH[groupItem.type]"
|
||||||
class="input"
|
class="input"
|
||||||
type="text"
|
type="text"
|
||||||
@ -145,7 +145,7 @@ const saveElementName = (e: FocusEvent | KeyboardEvent, id: string) => {
|
|||||||
const enterEdit = (id: string) => {
|
const enterEdit = (id: string) => {
|
||||||
editingElId.value = id
|
editingElId.value = id
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
const inputRef = document.querySelector(`#input-${id}`) as HTMLInputElement
|
const inputRef = document.querySelector(`#select-panel-input-${id}`) as HTMLInputElement
|
||||||
inputRef.focus()
|
inputRef.focus()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -26,20 +26,38 @@
|
|||||||
itemKey="id"
|
itemKey="id"
|
||||||
>
|
>
|
||||||
<template #item="{ element, index }">
|
<template #item="{ element, index }">
|
||||||
<div
|
<div class="thumbnail-container">
|
||||||
class="thumbnail-item"
|
<div class="section-title"
|
||||||
:class="{
|
:data-section-id="element?.sectionTag?.id || ''"
|
||||||
'active': slideIndex === index,
|
v-if="element.sectionTag || (hasSection && index === 0)"
|
||||||
'selected': selectedSlidesIndex.includes(index),
|
v-contextmenu="contextmenusSection"
|
||||||
}"
|
>
|
||||||
@mousedown="$event => handleClickSlideThumbnail($event, index)"
|
<input
|
||||||
@dblclick="enterScreening()"
|
:id="`section-title-input-${element?.sectionTag?.id || 'default'}`"
|
||||||
v-contextmenu="contextmenusThumbnailItem"
|
type="text"
|
||||||
>
|
:value="element?.sectionTag?.title || ''"
|
||||||
<div class="label" :class="{ 'offset-left': index >= 99 }">{{ fillDigit(index + 1, 2) }}</div>
|
placeholder="输入节名称"
|
||||||
<ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" />
|
@blur="$event => saveSection($event)"
|
||||||
|
@keydown.enter.stop="$event => saveSection($event)"
|
||||||
<div class="note-flag" v-if="element.notes && element.notes.length" @click="openNotesPanel()">{{ element.notes.length }}</div>
|
v-if="editingSectionId === element?.sectionTag?.id || (index === 0 && editingSectionId === 'default')"
|
||||||
|
>
|
||||||
|
<span class="text" v-else>{{ element?.sectionTag ? (element?.sectionTag?.title || '无标题节') : '默认节' }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="thumbnail-item"
|
||||||
|
:class="{
|
||||||
|
'active': slideIndex === index,
|
||||||
|
'selected': selectedSlidesIndex.includes(index),
|
||||||
|
}"
|
||||||
|
@mousedown="$event => handleClickSlideThumbnail($event, index)"
|
||||||
|
@dblclick="enterScreening()"
|
||||||
|
v-contextmenu="contextmenusThumbnailItem"
|
||||||
|
>
|
||||||
|
<div class="label" :class="{ 'offset-left': index >= 99 }">{{ fillDigit(index + 1, 2) }}</div>
|
||||||
|
<ThumbnailSlide class="thumbnail" :slide="element" :size="120" :visible="index < slidesLoadLimit" />
|
||||||
|
|
||||||
|
<div class="note-flag" v-if="element.notes && element.notes.length" @click="openNotesPanel()">{{ element.notes.length }}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</Draggable>
|
</Draggable>
|
||||||
@ -68,7 +86,7 @@ const mainStore = useMainStore()
|
|||||||
const slidesStore = useSlidesStore()
|
const slidesStore = useSlidesStore()
|
||||||
const keyboardStore = useKeyboardStore()
|
const keyboardStore = useKeyboardStore()
|
||||||
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
|
const { selectedSlidesIndex: _selectedSlidesIndex, thumbnailsFocus } = storeToRefs(mainStore)
|
||||||
const { slides, slideIndex } = storeToRefs(slidesStore)
|
const { slides, slideIndex, currentSlide } = storeToRefs(slidesStore)
|
||||||
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
|
const { ctrlKeyState, shiftKeyState } = storeToRefs(keyboardStore)
|
||||||
|
|
||||||
const { slidesLoadLimit } = useLoadSlides()
|
const { slidesLoadLimit } = useLoadSlides()
|
||||||
@ -77,6 +95,10 @@ const selectedSlidesIndex = computed(() => [..._selectedSlidesIndex.value, slide
|
|||||||
|
|
||||||
const presetLayoutPopoverVisible = ref(false)
|
const presetLayoutPopoverVisible = ref(false)
|
||||||
|
|
||||||
|
const hasSection = computed(() => {
|
||||||
|
return slides.value.some(item => item.sectionTag)
|
||||||
|
})
|
||||||
|
|
||||||
const {
|
const {
|
||||||
copySlide,
|
copySlide,
|
||||||
pasteSlide,
|
pasteSlide,
|
||||||
@ -87,6 +109,11 @@ const {
|
|||||||
cutSlide,
|
cutSlide,
|
||||||
selectAllSlide,
|
selectAllSlide,
|
||||||
sortSlides,
|
sortSlides,
|
||||||
|
createSection,
|
||||||
|
removeSection,
|
||||||
|
removeAllSection,
|
||||||
|
removeSectionSlides,
|
||||||
|
updateSectionTitle,
|
||||||
} = useSlideHandler()
|
} = useSlideHandler()
|
||||||
|
|
||||||
// 页面被切换时
|
// 页面被切换时
|
||||||
@ -187,6 +214,49 @@ const openNotesPanel = () => {
|
|||||||
mainStore.setNotesPanelState(true)
|
mainStore.setNotesPanelState(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editingSectionId = ref('')
|
||||||
|
|
||||||
|
const editSection = (id: string) => {
|
||||||
|
mainStore.setDisableHotkeysState(true)
|
||||||
|
editingSectionId.value = id || 'default'
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
const inputRef = document.querySelector(`#section-title-input-${id || 'default'}`) as HTMLInputElement
|
||||||
|
inputRef.focus()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const saveSection = (e: FocusEvent | KeyboardEvent) => {
|
||||||
|
const title = (e.target as HTMLInputElement).value
|
||||||
|
updateSectionTitle(editingSectionId.value, title)
|
||||||
|
|
||||||
|
editingSectionId.value = ''
|
||||||
|
mainStore.setDisableHotkeysState(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const contextmenusSection = (el: HTMLElement): ContextmenuItem[] => {
|
||||||
|
const sectionId = el.dataset.sectionId!
|
||||||
|
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
text: '删除节',
|
||||||
|
handler: () => removeSection(sectionId),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '删除节和幻灯片',
|
||||||
|
handler: () => removeSectionSlides(sectionId),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '删除所有节',
|
||||||
|
handler: removeAllSection,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: '重命名节',
|
||||||
|
handler: () => editSection(sectionId),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
const { enterScreening, enterScreeningFromStart } = useScreening()
|
const { enterScreening, enterScreeningFromStart } = useScreening()
|
||||||
|
|
||||||
const contextmenusThumbnails = (): ContextmenuItem[] => {
|
const contextmenusThumbnails = (): ContextmenuItem[] => {
|
||||||
@ -252,6 +322,11 @@ const contextmenusThumbnailItem = (): ContextmenuItem[] => {
|
|||||||
subText: 'Delete',
|
subText: 'Delete',
|
||||||
handler: () => deleteSlide(),
|
handler: () => deleteSlide(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
text: '增加节',
|
||||||
|
handler: createSection,
|
||||||
|
disable: !!currentSlide.value.sectionTag,
|
||||||
|
},
|
||||||
{ divider: true },
|
{ divider: true },
|
||||||
{
|
{
|
||||||
text: '从当前放映',
|
text: '从当前放映',
|
||||||
@ -334,20 +409,27 @@ const contextmenusThumbnailItem = (): ContextmenuItem[] => {
|
|||||||
.thumbnail {
|
.thumbnail {
|
||||||
outline-color: $themeColor;
|
outline-color: $themeColor;
|
||||||
}
|
}
|
||||||
|
.note-flag {
|
||||||
|
background-color: $themeColor;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
border-top-color: $themeColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-flag {
|
.note-flag {
|
||||||
width: 18px;
|
width: 16px;
|
||||||
height: 14px;
|
height: 12px;
|
||||||
border-radius: 2px;
|
border-radius: 1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 7px;
|
left: 8px;
|
||||||
top: 10px;
|
top: 13px;
|
||||||
font-size: 8px;
|
font-size: 8px;
|
||||||
background-color: $themeColor;
|
background-color: rgba($color: $themeColor, $alpha: .75);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
line-height: 14px;
|
line-height: 12px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@ -355,10 +437,10 @@ const contextmenusThumbnailItem = (): ContextmenuItem[] => {
|
|||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 13px;
|
top: 10px;
|
||||||
left: 5px;
|
left: 4px;
|
||||||
border: 4px solid transparent;
|
border: 4px solid transparent;
|
||||||
border-top-color: $themeColor;
|
border-top-color: rgba($color: $themeColor, $alpha: .75);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,4 +467,47 @@ const contextmenusThumbnailItem = (): ContextmenuItem[] => {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
color: #666;
|
color: #666;
|
||||||
}
|
}
|
||||||
|
.section-title {
|
||||||
|
height: 26px;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 6px 8px 2px 18px;
|
||||||
|
color: #555;
|
||||||
|
|
||||||
|
&.contextmenu-active {
|
||||||
|
color: $themeColor;
|
||||||
|
|
||||||
|
.text::before {
|
||||||
|
border-bottom-color: $themeColor;
|
||||||
|
border-right-color: $themeColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
width: 100%;
|
||||||
|
display: inline-block;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
|
@include ellipsis-oneline();
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-top: 3px solid transparent;
|
||||||
|
border-left: 3px solid transparent;
|
||||||
|
border-bottom: 3px solid #555;
|
||||||
|
border-right: 3px solid #555;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 100%;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user