bak
This commit is contained in:
1 parent
c6863f2bfc
commit
94e9846c13
11 files changed
+985
-136
No files matched your search
@@ -1,8 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import {
|
||||
PhCircle,
|
||||
PhImage,
|
||||
PhImageSquare,
|
||||
PhListBullets,
|
||||
PhPlus,
|
||||
PhSquare,
|
||||
PhTextT,
|
||||
@@ -17,6 +19,17 @@ const store = useSceneStore()
|
||||
const fileInput = ref<HTMLInputElement | null>(null)
|
||||
const uploadError = ref<string | null>(null)
|
||||
|
||||
const STORAGE_KEY = 'animatr.assetThumbs'
|
||||
const storedThumbs = typeof localStorage !== 'undefined' ? localStorage.getItem(STORAGE_KEY) : null
|
||||
const showThumbs = ref(storedThumbs !== 'false')
|
||||
watch(showThumbs, (v) => {
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, String(v))
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
function addSampleRect() {
|
||||
const asset = store.addAsset({
|
||||
kind: 'rect',
|
||||
@@ -99,6 +112,28 @@ const assetsWithUsage = computed(() =>
|
||||
inUse: store.scene.layers.some((l) => l.assetId === a.id),
|
||||
})),
|
||||
)
|
||||
|
||||
const THUMB_SIZE = 40
|
||||
|
||||
function rectPreviewStyle(asset: Extract<Asset, { kind: 'rect' }>) {
|
||||
const scale = Math.min(THUMB_SIZE / asset.width, THUMB_SIZE / asset.height) * 0.9
|
||||
return {
|
||||
width: `${Math.max(6, asset.width * scale)}px`,
|
||||
height: `${Math.max(6, asset.height * scale)}px`,
|
||||
background: asset.fill,
|
||||
borderRadius: '2px',
|
||||
} as const
|
||||
}
|
||||
|
||||
function circlePreviewStyle(asset: Extract<Asset, { kind: 'circle' }>) {
|
||||
const d = Math.min(THUMB_SIZE, asset.radius * 2) * 0.9
|
||||
return {
|
||||
width: `${d}px`,
|
||||
height: `${d}px`,
|
||||
background: asset.fill,
|
||||
borderRadius: '50%',
|
||||
} as const
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -131,11 +166,51 @@ const assetsWithUsage = computed(() =>
|
||||
/>
|
||||
<p v-if="uploadError" class="error">{{ uploadError }}</p>
|
||||
|
||||
<h4>Bibliothek</h4>
|
||||
<ul class="assets">
|
||||
<div class="lib-header">
|
||||
<h4>Bibliothek</h4>
|
||||
<button
|
||||
class="thumb-toggle"
|
||||
:title="showThumbs ? 'Thumbnails ausblenden' : 'Thumbnails anzeigen'"
|
||||
@click="showThumbs = !showThumbs"
|
||||
>
|
||||
<PhImageSquare v-if="showThumbs" :size="13" />
|
||||
<PhListBullets v-else :size="13" />
|
||||
</button>
|
||||
</div>
|
||||
<ul class="assets" :class="{ compact: !showThumbs }">
|
||||
<li v-for="item in assetsWithUsage" :key="item.asset.id" :class="{ unused: !item.inUse }">
|
||||
<component :is="assetIconMap[item.asset.kind]" :size="14" class="asset-icon" />
|
||||
<span class="name" :title="item.asset.name">{{ item.asset.name }}</span>
|
||||
<template v-if="showThumbs">
|
||||
<div class="thumb">
|
||||
<img
|
||||
v-if="item.asset.kind === 'image'"
|
||||
:src="item.asset.src"
|
||||
:alt="item.asset.name"
|
||||
draggable="false"
|
||||
/>
|
||||
<div
|
||||
v-else-if="item.asset.kind === 'rect'"
|
||||
class="shape-preview"
|
||||
:style="rectPreviewStyle(item.asset)"
|
||||
/>
|
||||
<div
|
||||
v-else-if="item.asset.kind === 'circle'"
|
||||
class="shape-preview"
|
||||
:style="circlePreviewStyle(item.asset)"
|
||||
/>
|
||||
<span
|
||||
v-else-if="item.asset.kind === 'text'"
|
||||
class="text-preview"
|
||||
:style="{ color: item.asset.fill }"
|
||||
>Aa</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<component :is="assetIconMap[item.asset.kind]" :size="14" class="asset-icon" />
|
||||
</template>
|
||||
<div class="meta">
|
||||
<span class="name" :title="item.asset.name">{{ item.asset.name }}</span>
|
||||
<span v-if="showThumbs" class="sub">{{ item.asset.kind }}</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="!item.inUse"
|
||||
class="add-layer"
|
||||
@@ -165,7 +240,7 @@ h3 {
|
||||
}
|
||||
|
||||
h4 {
|
||||
margin: 6px 0 4px;
|
||||
margin: 0;
|
||||
font-size: 10px;
|
||||
text-transform: uppercase;
|
||||
color: var(--text-dim);
|
||||
@@ -211,6 +286,29 @@ h4 {
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.lib-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.thumb-toggle {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-dim);
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
.thumb-toggle:hover:not(:disabled) {
|
||||
background: var(--panel-alt);
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.assets {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
@@ -223,7 +321,7 @@ h4 {
|
||||
.assets li {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
gap: 10px;
|
||||
padding: 6px 8px;
|
||||
border-radius: var(--radius-sm);
|
||||
background: var(--panel-alt);
|
||||
@@ -236,7 +334,43 @@ h4 {
|
||||
}
|
||||
|
||||
.assets li.unused {
|
||||
opacity: 0.85;
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.assets.compact li {
|
||||
gap: 8px;
|
||||
padding: 6px 8px;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius-sm);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.thumb img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.shape-preview {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.text-preview {
|
||||
font-weight: 600;
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.02em;
|
||||
}
|
||||
|
||||
.asset-icon {
|
||||
@@ -244,13 +378,27 @@ h4 {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
.meta {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.name {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.sub {
|
||||
font-size: 10px;
|
||||
color: var(--text-dim);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.add-layer {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
@@ -259,6 +407,7 @@ h4 {
|
||||
background: transparent;
|
||||
border: 1px solid var(--border);
|
||||
color: var(--text-dim);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.add-layer:hover:not(:disabled) {
|
||||
|
||||
Reference in new issue
Block a user