feat: extract shop from mp/shop — initial libreshop/shop
Some checks failed
Build and publish / build (push) Failing after 19s
Some checks failed
Build and publish / build (push) Failing after 19s
Source moved verbatim from mp/shop/ on 2026-04-29; mp was the first concrete adapter consuming the libreshop toolkit. Builds and publishes git.librete.ch/libreshop/shop on every main / v* push via the standard .gitea/workflows/build.yml shared across libreshop components.
This commit is contained in:
84
components/Background.vue
Normal file
84
components/Background.vue
Normal file
@@ -0,0 +1,84 @@
|
||||
<template>
|
||||
<article :class="bgClassList" :style="styles">
|
||||
<slot></slot>
|
||||
</article>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { randomTailwindColor } from "~/utils/randomTailwindColor";
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
coverId?: number | string | null;
|
||||
patternId?: number | string | null;
|
||||
/** @deprecated Use coverId and patternId instead */
|
||||
colorId?: number | string | null;
|
||||
shade?: 50 | 100 | 150 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900;
|
||||
opacity?: number;
|
||||
gradient?: boolean;
|
||||
gradientDirection?: "to-t" | "to-tr" | "to-r" | "to-br" | "to-b" | "to-bl" | "to-l" | "to-tl";
|
||||
customStyles?: Record<string, string>;
|
||||
}>(),
|
||||
{
|
||||
coverId: null,
|
||||
patternId: null,
|
||||
colorId: null,
|
||||
shade: 50,
|
||||
opacity: 100,
|
||||
gradient: false,
|
||||
gradientDirection: "to-br",
|
||||
customStyles: () => ({})
|
||||
}
|
||||
);
|
||||
|
||||
const bgClassList = computed(() => {
|
||||
// Use new system if coverId/patternId provided, fallback to legacy colorId
|
||||
const hasCoverPattern = props.coverId !== null || props.patternId !== null;
|
||||
const legacyColorId = props.colorId;
|
||||
|
||||
if (!hasCoverPattern && !legacyColorId) return ["bg-black"];
|
||||
|
||||
const classList: string[] = [];
|
||||
const opacityValue = props.opacity > 0 ? Math.floor(props.opacity) : 0;
|
||||
const opacitySuffix = opacityValue < 100 ? `/${opacityValue}` : undefined;
|
||||
|
||||
if (props.gradient) {
|
||||
classList.push(`bg-gradient-${props.gradientDirection}`);
|
||||
|
||||
if (hasCoverPattern) {
|
||||
// New system: cover determines one color, pattern determines another
|
||||
// This creates visual consistency within categories while varying by pattern
|
||||
const coverNum = Number(props.coverId ?? 0);
|
||||
const patternNum = Number(props.patternId ?? 0);
|
||||
|
||||
// from (top-left): cover color - lighter shade
|
||||
classList.push(randomTailwindColor(coverNum, "from", 100, opacitySuffix));
|
||||
|
||||
// via (middle): blend of both - mix the IDs for variety
|
||||
classList.push(randomTailwindColor(coverNum + patternNum, "via", 100, opacitySuffix));
|
||||
|
||||
// to (bottom-right): pattern color - slightly darker shade
|
||||
classList.push(randomTailwindColor(patternNum, "to", 100, opacitySuffix));
|
||||
} else {
|
||||
// Legacy system for backward compatibility
|
||||
const colorNum = Number(legacyColorId);
|
||||
classList.push(randomTailwindColor(colorNum + colorNum, "from", 100, opacitySuffix));
|
||||
classList.push(randomTailwindColor(colorNum, "to", 100, opacitySuffix));
|
||||
classList.push(randomTailwindColor(colorNum + colorNum, "via", 100, opacitySuffix));
|
||||
}
|
||||
} else {
|
||||
// Non-gradient: use pattern color if available, else cover, else legacy
|
||||
const colorNum = Number(props.patternId ?? props.coverId ?? legacyColorId ?? 0);
|
||||
const colorClass = randomTailwindColor(colorNum, "bg", props.shade);
|
||||
if (props.opacity < 100) {
|
||||
classList.push(`${colorClass}/${props.opacity}`);
|
||||
} else {
|
||||
classList.push(colorClass);
|
||||
}
|
||||
}
|
||||
|
||||
return classList;
|
||||
});
|
||||
|
||||
const styles = computed(() => props.customStyles);
|
||||
</script>
|
||||
Reference in New Issue
Block a user