Clicking outside popover dismisses it
This commit is contained in:
parent
9a09dde557
commit
2a6291a547
7 changed files with 49 additions and 22 deletions
|
|
@ -6,13 +6,15 @@
|
||||||
triggerElement: HTMLElement
|
triggerElement: HTMLElement
|
||||||
onUpdate: (key: string, value: any) => void
|
onUpdate: (key: string, value: any) => void
|
||||||
onDelete: () => void
|
onDelete: () => void
|
||||||
|
onClose?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
album = $bindable(),
|
album = $bindable(),
|
||||||
triggerElement,
|
triggerElement,
|
||||||
onUpdate,
|
onUpdate,
|
||||||
onDelete
|
onDelete,
|
||||||
|
onClose = () => {}
|
||||||
}: Props = $props()
|
}: Props = $props()
|
||||||
|
|
||||||
// Convert album date to YYYY-MM-DD format for date input
|
// Convert album date to YYYY-MM-DD format for date input
|
||||||
|
|
@ -98,4 +100,5 @@
|
||||||
bind:data={popoverData}
|
bind:data={popoverData}
|
||||||
{triggerElement}
|
{triggerElement}
|
||||||
onUpdate={handleDateChange}
|
onUpdate={handleDateChange}
|
||||||
|
{onClose}
|
||||||
/>
|
/>
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
onUpdate?: (key: string, value: any) => void
|
onUpdate?: (key: string, value: any) => void
|
||||||
onAddTag?: () => void
|
onAddTag?: () => void
|
||||||
onRemoveTag?: (tag: string) => void
|
onRemoveTag?: (tag: string) => void
|
||||||
|
onClose?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
|
@ -39,7 +40,8 @@
|
||||||
triggerElement,
|
triggerElement,
|
||||||
onUpdate = () => {},
|
onUpdate = () => {},
|
||||||
onAddTag = () => {},
|
onAddTag = () => {},
|
||||||
onRemoveTag = () => {}
|
onRemoveTag = () => {},
|
||||||
|
onClose = () => {}
|
||||||
}: Props = $props()
|
}: Props = $props()
|
||||||
|
|
||||||
let popoverElement: HTMLDivElement
|
let popoverElement: HTMLDivElement
|
||||||
|
|
@ -129,9 +131,26 @@
|
||||||
window.addEventListener('scroll', handleUpdate, true)
|
window.addEventListener('scroll', handleUpdate, true)
|
||||||
window.addEventListener('resize', handleUpdate)
|
window.addEventListener('resize', handleUpdate)
|
||||||
|
|
||||||
|
// Click outside handler
|
||||||
|
const handleClickOutside = (event: MouseEvent) => {
|
||||||
|
const target = event.target as Node
|
||||||
|
// Don't close if clicking inside the trigger button or the popover itself
|
||||||
|
if (
|
||||||
|
triggerElement?.contains(target) ||
|
||||||
|
popoverElement?.contains(target)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add click outside listener
|
||||||
|
document.addEventListener('click', handleClickOutside)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('scroll', handleUpdate, true)
|
window.removeEventListener('scroll', handleUpdate, true)
|
||||||
window.removeEventListener('resize', handleUpdate)
|
window.removeEventListener('resize', handleUpdate)
|
||||||
|
document.removeEventListener('click', handleClickOutside)
|
||||||
if (portalTarget) {
|
if (portalTarget) {
|
||||||
document.body.removeChild(portalTarget)
|
document.body.removeChild(portalTarget)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
onAddTag: () => void
|
onAddTag: () => void
|
||||||
onRemoveTag: (tag: string) => void
|
onRemoveTag: (tag: string) => void
|
||||||
onDelete: () => void
|
onDelete: () => void
|
||||||
|
onClose?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
let {
|
let {
|
||||||
|
|
@ -24,7 +25,8 @@
|
||||||
triggerElement,
|
triggerElement,
|
||||||
onAddTag,
|
onAddTag,
|
||||||
onRemoveTag,
|
onRemoveTag,
|
||||||
onDelete
|
onDelete,
|
||||||
|
onClose = () => {}
|
||||||
}: Props = $props()
|
}: Props = $props()
|
||||||
|
|
||||||
function handleFieldUpdate(key: string, value: any) {
|
function handleFieldUpdate(key: string, value: any) {
|
||||||
|
|
@ -102,4 +104,5 @@
|
||||||
onUpdate={handleFieldUpdate}
|
onUpdate={handleFieldUpdate}
|
||||||
{onAddTag}
|
{onAddTag}
|
||||||
{onRemoveTag}
|
{onRemoveTag}
|
||||||
|
{onClose}
|
||||||
/>
|
/>
|
||||||
|
|
@ -577,6 +577,7 @@
|
||||||
triggerElement={metadataButtonElement}
|
triggerElement={metadataButtonElement}
|
||||||
onUpdate={handleMetadataUpdate}
|
onUpdate={handleMetadataUpdate}
|
||||||
onDelete={handleMetadataDelete}
|
onDelete={handleMetadataDelete}
|
||||||
|
onClose={() => isMetadataOpen = false}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -258,6 +258,7 @@
|
||||||
triggerElement={metadataButtonElement}
|
triggerElement={metadataButtonElement}
|
||||||
onUpdate={handleMetadataUpdate}
|
onUpdate={handleMetadataUpdate}
|
||||||
onDelete={() => {}}
|
onDelete={() => {}}
|
||||||
|
onClose={() => isMetadataOpen = false}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -394,6 +395,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
padding: $unit-2x $unit-3x;
|
||||||
|
border: none;
|
||||||
|
border-radius: 50px;
|
||||||
|
font-size: 0.925rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $unit;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.6;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.metadata-popover-container {
|
.metadata-popover-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,7 @@
|
||||||
onAddTag={addTag}
|
onAddTag={addTag}
|
||||||
onRemoveTag={removeTag}
|
onRemoveTag={removeTag}
|
||||||
onDelete={openDeleteConfirmation}
|
onDelete={openDeleteConfirmation}
|
||||||
|
onClose={() => showMetadata = false}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -115,25 +115,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleMetadataPopover(event: MouseEvent) {
|
|
||||||
const target = event.target as Node
|
|
||||||
// Don't close if clicking inside the metadata button or anywhere in a metadata popover
|
|
||||||
if (
|
|
||||||
metadataButtonRef?.contains(target) ||
|
|
||||||
document.querySelector('.metadata-popover')?.contains(target)
|
|
||||||
) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
showMetadata = false
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
$effect(() => {
|
|
||||||
if (showMetadata) {
|
|
||||||
document.addEventListener('click', handleMetadataPopover)
|
|
||||||
return () => document.removeEventListener('click', handleMetadataPopover)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Mock post object for metadata popover
|
// Mock post object for metadata popover
|
||||||
const mockPost = $derived({
|
const mockPost = $derived({
|
||||||
|
|
@ -190,6 +171,7 @@
|
||||||
onAddTag={addTag}
|
onAddTag={addTag}
|
||||||
onRemoveTag={removeTag}
|
onRemoveTag={removeTag}
|
||||||
onDelete={() => {}}
|
onDelete={() => {}}
|
||||||
|
onClose={() => showMetadata = false}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue