141 lines
5.2 KiB
Vue
Raw Permalink Normal View History

2026-05-31 13:21:13 +02:00
<script setup lang="ts">
import { Menu } from 'floating-vue'
import { useDrawings } from '../composables/useDrawings'
import Draggable from './Draggable.vue'
import IconButton from './IconButton.vue'
import VerticalDivider from './VerticalDivider.vue'
const {
brush,
canClear,
canRedo,
canUndo,
clear,
drauu,
drawingEnabled,
drawingMode,
drawingPinned,
brushColors,
} = useDrawings()
function undo() {
drauu.undo()
}
function redo() {
drauu.redo()
}
let lastDrawingMode: typeof drawingMode.value = 'stylus'
function setDrawingMode(mode: typeof drawingMode.value) {
drawingMode.value = mode
drawingEnabled.value = true
if (mode !== 'eraseLine')
lastDrawingMode = mode
}
function setBrushColor(color: typeof brush.color) {
brush.color = color
drawingEnabled.value = true
drawingMode.value = lastDrawingMode
}
</script>
<template>
<Draggable
v-if="drawingEnabled || drawingPinned"
class="flex flex-wrap text-xl p-2 gap-1 rounded-md bg-main shadow transition-opacity duration-200 z-nav border border-main"
:class="!drawingEnabled && drawingPinned ? 'opacity-40 hover:opacity-90' : ''"
storage-key="slidev-drawing-pos"
:initial-x="10"
:initial-y="10"
>
<IconButton title="Draw with stylus" :class="{ shallow: drawingMode !== 'stylus' }" @click="setDrawingMode('stylus')">
<div class="i-carbon:pen" />
</IconButton>
<IconButton title="Draw a line" :class="{ shallow: drawingMode !== 'line' }" @click="setDrawingMode('line')">
<svg width="1em" height="1em" class="-mt-0.5" preserveAspectRatio="xMidYMid meet" viewBox="0 0 24 24">
<path d="M21.71 3.29a1 1 0 0 0-1.42 0l-18 18a1 1 0 0 0 0 1.42a1 1 0 0 0 1.42 0l18-18a1 1 0 0 0 0-1.42z" fill="currentColor" />
</svg>
</IconButton>
<IconButton title="Draw an arrow" :class="{ shallow: drawingMode !== 'arrow' }" @click="setDrawingMode('arrow')">
<div class="i-carbon:arrow-up-right" />
</IconButton>
<IconButton title="Draw an ellipse" :class="{ shallow: drawingMode !== 'ellipse' }" @click="setDrawingMode('ellipse')">
<div class="i-carbon:radio-button" />
</IconButton>
<IconButton title="Draw a rectangle" :class="{ shallow: drawingMode !== 'rectangle' }" @click="setDrawingMode('rectangle')">
<div class="i-carbon:checkbox" />
</IconButton>
<IconButton title="Erase" :class="{ shallow: drawingMode !== 'eraseLine' }" @click="setDrawingMode('eraseLine')">
<div class="i-carbon:erase" />
</IconButton>
<VerticalDivider />
<Menu>
<IconButton title="Adjust stroke width" :class="{ shallow: drawingMode === 'eraseLine' }">
<svg viewBox="0 0 32 32" width="1.2em" height="1.2em">
<line x1="2" y1="15" x2="22" y2="4" stroke="currentColor" stroke-width="1" stroke-linecap="round" />
<line x1="2" y1="24" x2="28" y2="10" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<line x1="7" y1="31" x2="29" y2="19" stroke="currentColor" stroke-width="3" stroke-linecap="round" />
</svg>
</IconButton>
<template #popper>
<div class="flex bg-main p-2">
<div class="inline-block w-7 text-center">
{{ brush.size }}
</div>
<div class="pt-.5">
<input v-model="brush.size" type="range" min="1" max="15" @change="drawingMode = lastDrawingMode">
</div>
</div>
</template>
</Menu>
<IconButton
v-for="color of brushColors"
:key="color"
title="Set brush color"
:class="brush.color === color && drawingMode !== 'eraseLine' ? 'active' : 'shallow'"
@click="setBrushColor(color)"
>
<div
class="w-6 h-6 transition-all transform border"
:class="brush.color !== color ? 'rounded-1/2 scale-85 border-white' : 'rounded-md border-gray-300/50'"
:style="drawingEnabled ? { background: color } : { borderColor: color }"
/>
</IconButton>
<VerticalDivider />
<IconButton title="Undo" :class="{ disabled: !canUndo }" @click="undo()">
<div class="i-carbon:undo" />
</IconButton>
<IconButton title="Redo" :class="{ disabled: !canRedo }" @click="redo()">
<div class="i-carbon:redo" />
</IconButton>
<IconButton title="Delete" :class="{ disabled: !canClear }" @click="clear()">
<div class="i-carbon:trash-can" />
</IconButton>
<VerticalDivider />
<IconButton :title="drawingPinned ? 'Unpin drawing' : 'Pin drawing'" :class="{ shallow: !drawingPinned }" @click="drawingPinned = !drawingPinned">
<div v-show="drawingPinned" class="i-carbon:pin-filled transform -rotate-45" />
<div v-show="!drawingPinned" class="i-carbon:pin" />
</IconButton>
<IconButton
v-if="drawingEnabled"
:title="drawingPinned ? 'Drawing pinned' : 'Drawing unpinned'"
:class="{ shallow: !drawingEnabled }"
@click="drawingEnabled = !drawingEnabled"
>
<div v-show="drawingPinned" class="i-carbon:error" />
<div v-show="!drawingPinned" class="i-carbon:close-outline" />
</IconButton>
</Draggable>
</template>
<style>
.v-popper--theme-menu .v-popper__arrow-inner {
--uno: border-main;
}
</style>