import { DeesElement, customElement, html, property, css, cssManager, state, type TemplateResult, } from '@design.estate/dees-element'; import '../dees-icon.js'; import '../dees-button.js'; import '../dees-windowlayer.js'; import { ImageCropper } from './profilepicture.cropper.js'; import { zIndexRegistry } from '../00zindex.js'; import type { ProfileShape } from './dees-input-profilepicture.js'; @customElement('dees-profilepicture-modal') export class ProfilePictureModal extends DeesElement { @property({ type: String }) public initialImage: string = ''; @property({ type: String }) public shape: ProfileShape = 'round'; @state() private currentStep: 'crop' | 'preview' = 'crop'; @state() private croppedImage: string = ''; @state() private isProcessing: boolean = false; private cropper: ImageCropper | null = null; private windowLayer: any; private zIndex: number = 0; public static styles = [ cssManager.defaultStyles, css` :host { position: fixed; top: 0; left: 0; right: 0; bottom: 0; display: flex; align-items: center; justify-content: center; z-index: var(--z-index); } .modal-container { background: ${cssManager.bdTheme('hsl(0 0% 100%)', 'hsl(224 71.4% 4.1%)')}; border-radius: 16px; box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); width: 90%; max-width: 600px; max-height: 90vh; display: flex; flex-direction: column; overflow: hidden; animation: modalSlideIn 0.3s ease-out; } @keyframes modalSlideIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } } .modal-header { padding: 24px; border-bottom: 1px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(217.2 32.6% 17.5%)')}; display: flex; align-items: center; justify-content: space-between; } .modal-title { font-size: 20px; font-weight: 600; color: ${cssManager.bdTheme('hsl(224 71.4% 4.1%)', 'hsl(210 20% 98%)')}; } .close-button { width: 32px; height: 32px; border: none; background: transparent; cursor: pointer; border-radius: 8px; display: flex; align-items: center; justify-content: center; color: ${cssManager.bdTheme('hsl(220 8.9% 46.1%)', 'hsl(215 20.2% 65.1%)')}; transition: all 0.2s ease; } .close-button:hover { background: ${cssManager.bdTheme('hsl(210 20% 98%)', 'hsl(215 27.9% 16.9%)')}; color: ${cssManager.bdTheme('hsl(224 71.4% 4.1%)', 'hsl(210 20% 98%)')}; } .modal-body { flex: 1; padding: 24px; overflow-y: auto; display: flex; flex-direction: column; align-items: center; gap: 24px; } .cropper-container { width: 100%; max-width: 400px; aspect-ratio: 1; position: relative; } .preview-container { display: flex; flex-direction: column; align-items: center; gap: 24px; } .preview-image { width: 200px; height: 200px; object-fit: cover; border: 3px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(217.2 32.6% 17.5%)')}; } .preview-image.round { border-radius: 50%; } .preview-image.square { border-radius: 12px; } .success-message { display: flex; align-items: center; gap: 12px; padding: 12px 24px; background: ${cssManager.bdTheme('hsl(142 69% 45% / 0.1)', 'hsl(142 69% 55% / 0.1)')}; color: ${cssManager.bdTheme('hsl(142 69% 45%)', 'hsl(142 69% 55%)')}; border-radius: 8px; font-weight: 500; } .modal-footer { padding: 24px; border-top: 1px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(217.2 32.6% 17.5%)')}; display: flex; gap: 12px; justify-content: flex-end; } .instructions { text-align: center; color: ${cssManager.bdTheme('hsl(220 8.9% 46.1%)', 'hsl(215 20.2% 65.1%)')}; font-size: 14px; } .loading-spinner { width: 48px; height: 48px; border: 3px solid ${cssManager.bdTheme('hsl(214.3 31.8% 91.4%)', 'hsl(217.2 32.6% 17.5%)')}; border-top-color: ${cssManager.bdTheme('hsl(222.2 47.4% 11.2%)', 'hsl(210 20% 98%)')}; border-radius: 50%; animation: spin 0.8s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } } `, ]; async connectedCallback() { super.connectedCallback(); // Get z-index from registry this.zIndex = zIndexRegistry.getNextZIndex(); this.style.setProperty('--z-index', this.zIndex.toString()); // Add window layer this.windowLayer = document.createElement('dees-windowlayer'); this.windowLayer.addEventListener('click', () => this.close()); document.body.appendChild(this.windowLayer); // Register with z-index registry zIndexRegistry.register(this, this.zIndex); } async disconnectedCallback() { super.disconnectedCallback(); // Cleanup if (this.cropper) { this.cropper.destroy(); } if (this.windowLayer) { this.windowLayer.remove(); } // Unregister from z-index registry zIndexRegistry.unregister(this); } render(): TemplateResult { return html`