Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114<script lang="ts"> import { page } from "$app/state"; import SmilePlus from "$icon/smile-plus"; import { createAction } from "#lib/action.svelte.ts"; import type { KnotOrigin } from "#lib/api/syntax.ts"; import { createBobbinClient } from "#lib/api/client.ts"; import { getAuth } from "#lib/auth.svelte.ts"; import Button from "#lib/components/ui/Button.svelte"; import { ORDERED_REACTION_KINDS, toggleReaction, type ReactionGroup, type ReactionKind } from "#lib/components/reaction/reactions.ts"; import Dropdown, { type DropdownVariants } from "#lib/components/ui/Dropdown.svelte"; import type { PopoverOrigin } from "#lib/components/ui/popover.svelte.ts"; import Tooltip from "#lib/components/ui/Tooltip.svelte"; import { resetFailureSoon } from "#lib/optimistic.svelte.ts";
interface Props { subjectUri: string; subjectCid?: string; knot?: KnotOrigin; groups: ReactionGroup[]; onchange: (next: ReactionGroup[]) => void; dropdownAlign?: DropdownVariants["align"]; dropdownOrigin?: PopoverOrigin; triggerClass?: string; }
let { subjectUri, subjectCid, knot, groups, onchange, dropdownAlign, dropdownOrigin, triggerClass }: Props = $props();
const auth = getAuth();
let dropdown = $state<ReturnType<typeof Dropdown>>(); let failed = $state(false);
resetFailureSoon( () => failed, () => (failed = false) );
const pick = createAction(async (kind: ReactionKind) => { const agent = auth?.agent; const viewer = auth?.currentUser; if (!agent || !viewer) return;
const bobbinUrl = page.data.publicConfig?.bobbinUrl; await toggleReaction({ agent, knot, subject: { uri: subjectUri, cid: subjectCid }, kind, viewer, bobbin: bobbinUrl ? createBobbinClient({ serviceUrl: bobbinUrl }) : null, groups: () => groups, commit: onchange }); });
const handlePick = async (kind: ReactionKind) => { if (pick.loading) return; dropdown?.hideMenu(); failed = false; await pick.run(kind); failed = pick.error !== undefined; };</script>
<Tooltip content="Something went wrong. Try again." disabled={!failed}> <Dropdown bind:this={dropdown} square variant="button" buttonVariant={failed ? "danger" : "ghost"} size="small" label="React" title="React" menuClass="w-fit" align={dropdownAlign} origin={dropdownOrigin} {triggerClass} > {#snippet trigger()} <SmilePlus class="size-3.5" /> {/snippet}
<div class="grid grid-cols-4"> {#each ORDERED_REACTION_KINDS as kind (kind)} <Button data-kind={kind} variant="ghost" class="[--btn-radius:0.25rem]" aria-label={`React with ${kind}`} aria-pressed={groups.some((g) => g.kind === kind && g.isReacted)} disabled={pick.loading} onclick={() => handlePick(kind)} > <span class="typography-paragraph-regular leading-none">{kind}</span> </Button> {/each} </div> </Dropdown></Tooltip>