update
This commit is contained in:
@ -49,12 +49,21 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
@property({ type: Array })
|
||||
public acceptedFormats: string[] = ['image/jpeg', 'image/png', 'image/webp'];
|
||||
|
||||
@property({ type: Number })
|
||||
public outputSize: number = 800; // Output resolution in pixels
|
||||
|
||||
@property({ type: Number })
|
||||
public outputQuality: number = 0.95; // 0-1 quality for JPEG
|
||||
|
||||
@state()
|
||||
private isHovered: boolean = false;
|
||||
|
||||
@state()
|
||||
private isDragging: boolean = false;
|
||||
|
||||
@state()
|
||||
private isLoading: boolean = false;
|
||||
|
||||
private modalInstance: ProfilePictureModal | null = null;
|
||||
|
||||
public static styles = [
|
||||
@ -86,8 +95,8 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
.profile-picture {
|
||||
width: var(--size, 120px);
|
||||
height: var(--size, 120px);
|
||||
background: ${cssManager.bdTheme('hsl(210 20% 98%)', 'hsl(215 27.9% 16.9%)')};
|
||||
border: 3px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(217.2 32.6% 17.5%)')};
|
||||
background: ${cssManager.bdTheme('#f5f5f5', '#18181b')};
|
||||
border: 3px solid ${cssManager.bdTheme('#e5e7eb', '#27272a')};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@ -105,12 +114,12 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
}
|
||||
|
||||
.profile-picture.dragging {
|
||||
border-color: ${cssManager.bdTheme('hsl(222.2 47.4% 11.2%)', 'hsl(210 20% 98%)')};
|
||||
box-shadow: 0 0 0 4px ${cssManager.bdTheme('hsl(222.2 47.4% 11.2% / 0.1)', 'hsl(210 20% 98% / 0.1)')};
|
||||
border-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
|
||||
box-shadow: 0 0 0 4px ${cssManager.bdTheme('rgba(59, 130, 246, 0.15)', 'rgba(96, 165, 250, 0.15)')};
|
||||
}
|
||||
|
||||
.profile-picture:hover {
|
||||
border-color: ${cssManager.bdTheme('hsl(222.2 47.4% 11.2%)', 'hsl(210 20% 98%)')};
|
||||
border-color: ${cssManager.bdTheme('#d4d4d8', '#3f3f46')};
|
||||
}
|
||||
|
||||
.profile-picture:disabled {
|
||||
@ -125,7 +134,7 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
}
|
||||
|
||||
.placeholder-icon {
|
||||
color: ${cssManager.bdTheme('hsl(220 8.9% 46.1%)', 'hsl(215 20.2% 65.1%)')};
|
||||
color: ${cssManager.bdTheme('#71717a', '#a1a1aa')};
|
||||
}
|
||||
|
||||
.overlay {
|
||||
@ -156,28 +165,32 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border: none;
|
||||
background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.95)', 'rgba(39, 39, 42, 0.95)')};
|
||||
border: 1px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
|
||||
color: ${cssManager.bdTheme('#09090b', '#fafafa')};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
pointer-events: auto;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.overlay-button:hover {
|
||||
background: white;
|
||||
background: ${cssManager.bdTheme('#ffffff', '#3f3f46')};
|
||||
transform: scale(1.1);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.overlay-button.delete {
|
||||
background: rgba(239, 68, 68, 0.9);
|
||||
background: ${cssManager.bdTheme('rgba(239, 68, 68, 0.9)', 'rgba(220, 38, 38, 0.9)')};
|
||||
color: white;
|
||||
border-color: transparent;
|
||||
}
|
||||
|
||||
.overlay-button.delete:hover {
|
||||
background: rgb(239, 68, 68);
|
||||
background: ${cssManager.bdTheme('#ef4444', '#dc2626')};
|
||||
}
|
||||
|
||||
.drop-zone-text {
|
||||
@ -194,6 +207,62 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
.hidden-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Loading animation */
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: ${cssManager.bdTheme('rgba(255, 255, 255, 0.8)', 'rgba(0, 0, 0, 0.8)')};
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: inherit;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.loading-overlay.show {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.loading-spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid ${cssManager.bdTheme('rgba(0, 0, 0, 0.1)', 'rgba(255, 255, 255, 0.1)')};
|
||||
border-top-color: ${cssManager.bdTheme('#3b82f6', '#60a5fa')};
|
||||
border-radius: 50%;
|
||||
animation: spin 0.6s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.05);
|
||||
opacity: 0.8;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.profile-picture.clicking {
|
||||
animation: pulse 0.3s ease-out;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@ -210,7 +279,7 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
@drop=${this.handleDrop}
|
||||
style="--size: ${this.size}px"
|
||||
>
|
||||
<div class="profile-picture ${this.shape} ${this.isDragging ? 'dragging' : ''}">
|
||||
<div class="profile-picture ${this.shape} ${this.isDragging ? 'dragging' : ''} ${this.isLoading && !this.value ? 'clicking' : ''}">
|
||||
${this.value ? html`
|
||||
<img class="profile-image" src="${this.value}" alt="Profile picture" />
|
||||
` : html`
|
||||
@ -241,6 +310,12 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
${this.isLoading && !this.value ? html`
|
||||
<div class="loading-overlay show">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -259,7 +334,21 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
|
||||
if (!this.value) {
|
||||
// If no image, open file picker
|
||||
this.isLoading = true;
|
||||
const input = this.shadowRoot!.querySelector('.hidden-input') as HTMLInputElement;
|
||||
|
||||
// Set up a focus handler to detect when the dialog is closed without selection
|
||||
const handleFocus = () => {
|
||||
setTimeout(() => {
|
||||
// Check if no file was selected
|
||||
if (!input.files || input.files.length === 0) {
|
||||
this.isLoading = false;
|
||||
}
|
||||
window.removeEventListener('focus', handleFocus);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
window.addEventListener('focus', handleFocus);
|
||||
input.click();
|
||||
}
|
||||
}
|
||||
@ -268,6 +357,9 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
const input = event.target as HTMLInputElement;
|
||||
const file = input.files?.[0];
|
||||
|
||||
// Always reset loading state when file dialog interaction completes
|
||||
this.isLoading = false;
|
||||
|
||||
if (file) {
|
||||
this.processFile(file);
|
||||
}
|
||||
@ -337,6 +429,8 @@ export class DeesInputProfilePicture extends DeesInputBase<DeesInputProfilePictu
|
||||
this.modalInstance = new ProfilePictureModal();
|
||||
this.modalInstance.shape = this.shape;
|
||||
this.modalInstance.initialImage = imageToEdit;
|
||||
this.modalInstance.outputSize = this.outputSize;
|
||||
this.modalInstance.outputQuality = this.outputQuality;
|
||||
|
||||
this.modalInstance.addEventListener('save', (event: CustomEvent) => {
|
||||
this.value = event.detail.croppedImage;
|
||||
|
Reference in New Issue
Block a user