@jhits/plugin-images 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,111 @@
1
+ 'use client';
2
+
3
+ import React, { useState, useEffect } from 'react';
4
+ import { Image } from './Image';
5
+ import { Edit2, Loader2 } from 'lucide-react';
6
+
7
+ export interface BackgroundImageProps {
8
+ id: string;
9
+ className?: string;
10
+ style?: React.CSSProperties;
11
+ children?: React.ReactNode;
12
+ backgroundSize?: 'cover' | 'contain' | 'auto' | string;
13
+ backgroundPosition?: string;
14
+ backgroundRepeat?: 'repeat' | 'no-repeat' | 'repeat-x' | 'repeat-y';
15
+ }
16
+
17
+ /**
18
+ * BackgroundImage Component
19
+ * * A container that handles a background image with admin edit capabilities.
20
+ * The edit button appears on hover anywhere within the container.
21
+ */
22
+ export function BackgroundImage({
23
+ id,
24
+ className = '',
25
+ style = {},
26
+ children,
27
+ backgroundSize = 'cover',
28
+ backgroundPosition = 'center',
29
+ }: BackgroundImageProps) {
30
+ const [isAdmin, setIsAdmin] = useState(false);
31
+ const [isLoading, setIsLoading] = useState(true);
32
+
33
+ // Authentication check for Admin/Dev users
34
+ useEffect(() => {
35
+ const checkUser = async () => {
36
+ try {
37
+ const res = await fetch('/api/me');
38
+ const data = await res.json();
39
+ if (data.loggedIn && (data.user?.role === 'admin' || data.user?.role === 'dev')) {
40
+ setIsAdmin(true);
41
+ }
42
+ } catch (error) {
43
+ console.error('Failed to check user role:', error);
44
+ } finally {
45
+ setIsLoading(false);
46
+ }
47
+ };
48
+ checkUser();
49
+ }, []);
50
+
51
+ const handleEditClick = (e: React.MouseEvent) => {
52
+ e.preventDefault();
53
+ e.stopPropagation();
54
+ // Dispatch event to the GlobalImageEditor
55
+ window.dispatchEvent(new CustomEvent('open-image-editor', { detail: { id } }));
56
+ };
57
+
58
+ return (
59
+ <div
60
+ data-background-image-component="true"
61
+ data-background-image-id={id}
62
+ className={`group relative overflow-hidden w-full ${className}`}
63
+ style={style}
64
+ >
65
+ {/* 1. BACKGROUND IMAGE LAYER (z-0) */}
66
+ <div className="absolute inset-0 z-0 pointer-events-none">
67
+ <Image
68
+ id={id}
69
+ alt=""
70
+ fill
71
+ className="w-full h-full"
72
+ objectFit={backgroundSize === 'cover' ? 'cover' : 'contain'}
73
+ objectPosition={backgroundPosition}
74
+ editable={false} // We handle the button manually below
75
+ />
76
+ </div>
77
+
78
+ {/* 2. CONTENT LAYER (z-10) */}
79
+ <div className="relative z-10 w-full h-full">
80
+ {children}
81
+ </div>
82
+
83
+ {/* 3. ADMIN UI LAYER (z-50) - Dashboard Theme */}
84
+ {!isLoading && isAdmin && (
85
+ <div className="absolute inset-0 z-50 pointer-events-none">
86
+ <button
87
+ type="button"
88
+ onClick={handleEditClick}
89
+ className="
90
+ pointer-events-auto absolute bottom-8 left-8
91
+ flex items-center gap-3 px-6 py-3
92
+ bg-neutral-100 dark:bg-neutral-800
93
+ text-neutral-900 dark:text-neutral-100
94
+ rounded-full shadow-2xl
95
+ border border-neutral-300 dark:border-neutral-700
96
+ cursor-pointer hover:bg-neutral-200 dark:hover:bg-neutral-700
97
+ opacity-0 group-hover:opacity-100
98
+ translate-y-4 group-hover:translate-y-0
99
+ transition-all duration-500 ease-out
100
+ "
101
+ >
102
+ <Edit2 size={16} strokeWidth={2.5} className="text-primary" />
103
+ <span className="text-[11px] font-black uppercase tracking-[0.2em]">
104
+ Edit Background
105
+ </span>
106
+ </button>
107
+ </div>
108
+ )}
109
+ </div>
110
+ );
111
+ }