This commit is contained in:
2025-07-14 15:30:16 +00:00
parent c534d1d084
commit 1caeae9ec9
4 changed files with 59 additions and 27 deletions

View File

@@ -128,10 +128,13 @@ export class SioCombox extends DeesElement {
overflow: hidden; overflow: hidden;
font-family: ${unsafeCSS(fontFamilies.sans)}; font-family: ${unsafeCSS(fontFamilies.sans)};
position: relative; position: relative;
animation: scaleIn 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
transform-origin: bottom right; transform-origin: bottom right;
} }
:host(.animate-in) {
animation: scaleIn 300ms cubic-bezier(0.34, 1.56, 0.64, 1);
}
@keyframes scaleIn { @keyframes scaleIn {
from { from {
opacity: 0; opacity: 0;
@@ -152,6 +155,7 @@ export class SioCombox extends DeesElement {
background: linear-gradient(145deg, ${bdTheme('border')}, transparent 50%); background: linear-gradient(145deg, ${bdTheme('border')}, transparent 50%);
-webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
-webkit-mask-composite: exclude; -webkit-mask-composite: exclude;
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: exclude; mask-composite: exclude;
opacity: 0.5; opacity: 0.5;
pointer-events: none; pointer-events: none;

View File

@@ -305,6 +305,10 @@ export class SioConversationView extends DeesElement {
} }
/* File drop zone */ /* File drop zone */
.messages-container {
position: relative;
}
.drop-overlay { .drop-overlay {
position: absolute; position: absolute;
inset: 0; inset: 0;
@@ -497,19 +501,22 @@ export class SioConversationView extends DeesElement {
</div> </div>
</div> </div>
<div class="drop-overlay ${this.isDragging ? 'active' : ''}"> <div class="messages-container" id="messages"
@dragover=${this.handleDragOver}
@dragleave=${this.handleDragLeave}
@drop=${this.handleDrop}
@dragenter=${this.handleDragOver}
>
<div class="drop-overlay ${this.isDragging ? 'active' : ''}"
@drop=${this.handleDrop}
@dragover=${(e: DragEvent) => e.preventDefault()}
>
<div class="drop-zone"> <div class="drop-zone">
<sio-icon class="drop-icon" icon="upload-cloud"></sio-icon> <sio-icon class="drop-icon" icon="upload-cloud"></sio-icon>
<div class="drop-text">Drop files here</div> <div class="drop-text">Drop files here</div>
<div class="drop-hint">Images and documents up to 10MB</div> <div class="drop-hint">Images and documents up to 10MB</div>
</div> </div>
</div> </div>
<div class="messages-container" id="messages"
@dragover=${this.handleDragOver}
@dragleave=${this.handleDragLeave}
@drop=${this.handleDrop}
>
${this.conversation.messages.map((msg, index) => html` ${this.conversation.messages.map((msg, index) => html`
<div class="message ${msg.sender}" style="animation-delay: ${index * 50}ms"> <div class="message ${msg.sender}" style="animation-delay: ${index * 50}ms">
<div class="message-content"> <div class="message-content">
@@ -586,7 +593,11 @@ export class SioConversationView extends DeesElement {
accept="image/*,.pdf,.doc,.docx,.txt" accept="image/*,.pdf,.doc,.docx,.txt"
@change=${this.handleFileSelect} @change=${this.handleFileSelect}
/> />
<sio-button type="ghost" size="sm" @click=${this.openFileSelector}> <sio-button type="ghost" size="sm" @click=${(e: Event) => {
e.preventDefault();
e.stopPropagation();
this.openFileSelector();
}}>
<sio-icon icon="paperclip" size="16"></sio-icon> <sio-icon icon="paperclip" size="16"></sio-icon>
</sio-button> </sio-button>
<sio-button <sio-button
@@ -681,14 +692,11 @@ export class SioConversationView extends DeesElement {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
// Check if we're leaving the container entirely // Check if we're actually leaving the messages container
const rect = (e.currentTarget as HTMLElement).getBoundingClientRect(); const relatedTarget = e.relatedTarget as Node;
if ( const container = e.currentTarget as HTMLElement;
e.clientX <= rect.left ||
e.clientX >= rect.right || if (!container.contains(relatedTarget)) {
e.clientY <= rect.top ||
e.clientY >= rect.bottom
) {
this.isDragging = false; this.isDragging = false;
} }
} }
@@ -699,12 +707,16 @@ export class SioConversationView extends DeesElement {
this.isDragging = false; this.isDragging = false;
const files = Array.from(e.dataTransfer?.files || []); const files = Array.from(e.dataTransfer?.files || []);
if (files.length > 0) {
this.processFiles(files); this.processFiles(files);
} }
}
private openFileSelector() { private openFileSelector() {
const fileInput = this.shadowRoot?.querySelector('#fileInput') as HTMLInputElement; const fileInput = this.shadowRoot?.querySelector('#fileInput') as HTMLInputElement;
fileInput?.click(); if (fileInput) {
fileInput.click();
}
} }
private handleFileSelect(e: Event) { private handleFileSelect(e: Event) {

View File

@@ -11,6 +11,7 @@ import * as domtools from '@design.estate/dees-domtools';
import { SioCombox } from './sio-combox.js'; import { SioCombox } from './sio-combox.js';
import { SioIcon } from './sio-icon.js'; import { SioIcon } from './sio-icon.js';
import { state } from '@design.estate/dees-element';
SioCombox; SioCombox;
SioIcon; SioIcon;
@@ -30,6 +31,9 @@ export class SioFab extends DeesElement {
@property({ type: Boolean }) @property({ type: Boolean })
public showCombox = false; public showCombox = false;
@state()
private hasShownOnce = false;
public static demo = () => html` <sio-fab .showCombox=${true}></sio-fab> `; public static demo = () => html` <sio-fab .showCombox=${true}></sio-fab> `;
constructor() { constructor() {
@@ -190,8 +194,10 @@ export class SioFab extends DeesElement {
<sio-icon icon="x" size="22"></sio-icon> <sio-icon icon="x" size="22"></sio-icon>
</div> </div>
</div> </div>
<div id="comboxContainer" class="${this.showCombox ? 'show' : null}"> <div id="comboxContainer" class="${this.showCombox ? 'show' : ''}">
${this.showCombox || this.hasShownOnce ? html`
<sio-combox @close=${() => this.showCombox = false}></sio-combox> <sio-combox @close=${() => this.showCombox = false}></sio-combox>
` : ''}
</div> </div>
`; `;
} }
@@ -202,6 +208,9 @@ export class SioFab extends DeesElement {
public async toggleCombox() { public async toggleCombox() {
console.log('toggle combox'); console.log('toggle combox');
this.showCombox = !this.showCombox; this.showCombox = !this.showCombox;
if (this.showCombox) {
this.hasShownOnce = true;
}
} }
public async firstUpdated(args) { public async firstUpdated(args) {
@@ -214,7 +223,7 @@ export class SioFab extends DeesElement {
domtools.keyboard domtools.keyboard
.on([domtools.keyboard.keyEnum.Ctrl, domtools.keyboard.keyEnum.S]) .on([domtools.keyboard.keyEnum.Ctrl, domtools.keyboard.keyEnum.S])
.subscribe((event) => { .subscribe((event) => {
this.showCombox = !this.showCombox; this.toggleCombox();
}); });
} }
} }

View File

@@ -279,7 +279,9 @@ export class SioImageLightbox extends DeesElement {
: ''; : '';
return html` return html`
<div class="overlay ${this.isOpen ? 'open' : ''}" @click=${this.close}></div> <div class="overlay ${this.isOpen ? 'open' : ''}" @click=${(e: Event) => {
if (e.target === e.currentTarget) this.close(e);
}}></div>
<div class="container ${this.isOpen ? 'open' : ''}"> <div class="container ${this.isOpen ? 'open' : ''}">
${this.image ? html` ${this.image ? html`
<div class="controls"> <div class="controls">
@@ -292,7 +294,7 @@ export class SioImageLightbox extends DeesElement {
<div class="control-button" @click=${this.resetZoom}> <div class="control-button" @click=${this.resetZoom}>
<sio-icon icon="maximize-2" size="18"></sio-icon> <sio-icon icon="maximize-2" size="18"></sio-icon>
</div> </div>
<div class="control-button" @click=${this.close}> <div class="control-button" @click=${(e: Event) => this.close(e)}>
<sio-icon icon="x" size="18"></sio-icon> <sio-icon icon="x" size="18"></sio-icon>
</div> </div>
</div> </div>
@@ -350,12 +352,17 @@ export class SioImageLightbox extends DeesElement {
document.addEventListener('keydown', this.handleKeyDown); document.addEventListener('keydown', this.handleKeyDown);
} }
private close = () => { private close = (e?: Event) => {
if (e) {
e.preventDefault();
e.stopPropagation();
}
this.isOpen = false; this.isOpen = false;
document.removeEventListener('keydown', this.handleKeyDown); document.removeEventListener('keydown', this.handleKeyDown);
// Dispatch close event // Dispatch close event
this.dispatchEvent(new CustomEvent('close', { this.dispatchEvent(new CustomEvent('lightbox-close', {
bubbles: true, bubbles: true,
composed: true composed: true
})); }));