Replace the legacy mule-image backend with PhotoPrism plus a thin SvelteKit client and a Node sidecar for endpoints PhotoPrism doesn't expose (file rename), and add a two-phase migrator (metadata via PUT, heaps → albums) for the existing Postgres library. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57 lines
1.8 KiB
Svelte
57 lines
1.8 KiB
Svelte
<!--
|
|
Thin wrapper around bits-ui's DM. Provides:
|
|
- A round ⋯ trigger button styled like the rest of the sidebar's hover
|
|
affordances (muted, becomes accent on hover/open).
|
|
- A portal-positioned content container with shadcn-zinc styling.
|
|
- An `Item` re-export consumers compose into the menu body so we don't
|
|
also have to redeclare the item styling at every call site.
|
|
|
|
Items are passed as a snippet via `children` so callers can mix the
|
|
`Item` re-export, separators, or destructive variants freely.
|
|
-->
|
|
<script lang="ts" module>
|
|
import { DropdownMenu as DM } from 'bits-ui';
|
|
export const Item = DM.Item;
|
|
export const Separator = DM.Separator;
|
|
</script>
|
|
|
|
<script lang="ts">
|
|
import { MoreHorizontal } from 'lucide-svelte';
|
|
|
|
interface Props {
|
|
/** Tooltip + aria-label for the trigger button. */
|
|
label?: string;
|
|
/** Force the trigger visible regardless of hover state. Used when
|
|
* the menu is open so it doesn't disappear underneath a row hover
|
|
* transition while the user is interacting with it. */
|
|
alwaysVisible?: boolean;
|
|
children: import('svelte').Snippet;
|
|
}
|
|
|
|
let { label = 'More', alwaysVisible = false, children }: Props = $props();
|
|
let open = $state(false);
|
|
</script>
|
|
|
|
<DM.Root bind:open>
|
|
<DM.Trigger
|
|
class="rounded p-0.5 text-xs text-muted-foreground transition-opacity hover:bg-accent hover:text-foreground focus:outline-none {open ||
|
|
alwaysVisible
|
|
? 'opacity-100'
|
|
: 'opacity-0 group-hover:opacity-100'}"
|
|
title={label}
|
|
aria-label={label}
|
|
onclick={(e) => e.stopPropagation()}
|
|
>
|
|
<MoreHorizontal class="h-3.5 w-3.5" />
|
|
</DM.Trigger>
|
|
<DM.Portal>
|
|
<DM.Content
|
|
class="z-50 min-w-[180px] overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md outline-none"
|
|
sideOffset={4}
|
|
align="end"
|
|
>
|
|
{@render children()}
|
|
</DM.Content>
|
|
</DM.Portal>
|
|
</DM.Root>
|