Maybe get dialogs behaving properly

This commit is contained in:
Jon Staab
2024-10-15 15:52:30 -07:00
parent 4decb2f4d9
commit 9c300d40f6
22 changed files with 169 additions and 189 deletions
-4
View File
@@ -140,10 +140,6 @@
@apply shadow-[0_20px_25px_-5px_rgb(0,0,0,0.1)_0_8px_10px_-6px_rgb(0,0,0,0.1)]; @apply shadow-[0_20px_25px_-5px_rgb(0,0,0,0.1)_0_8px_10px_-6px_rgb(0,0,0,0.1)];
} }
.modal-box .z-feature {
@apply z-modal-feature;
}
/* tiptap */ /* tiptap */
.input-editor, .input-editor,
+7 -7
View File
@@ -1,17 +1,17 @@
<script lang="ts"> <script lang="ts">
import {pubkey} from '@welshman/app' import {pubkey} from "@welshman/app"
import Landing from "@app/components/Landing.svelte" import Landing from "@app/components/Landing.svelte"
import Toast from "@app/components/Toast.svelte" import Toast from "@app/components/Toast.svelte"
import PrimaryNav from "@app/components/PrimaryNav.svelte" import PrimaryNav from "@app/components/PrimaryNav.svelte"
</script> </script>
<div class="flex h-screen overflow-hidden"> <div class="flex h-screen overflow-hidden">
<PrimaryNav> {#if $pubkey}
{#if $pubkey} <PrimaryNav>
<slot /> <slot />
{:else} </PrimaryNav>
<Landing /> {:else}
{/if} <Landing />
</PrimaryNav> {/if}
</div> </div>
<Toast /> <Toast />
+7 -5
View File
@@ -14,7 +14,6 @@
import type {PublishStatusData} from "@welshman/app" import type {PublishStatusData} from "@welshman/app"
import {REACTION, ZAP_RESPONSE, displayRelayUrl} from "@welshman/util" import {REACTION, ZAP_RESPONSE, displayRelayUrl} from "@welshman/util"
import {repository} from "@welshman/app" import {repository} from "@welshman/app"
import {slideAndFade} from '@lib/transition'
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Avatar from "@lib/components/Avatar.svelte" import Avatar from "@lib/components/Avatar.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
@@ -41,7 +40,10 @@
const rootHints = [rootTag?.[2]].filter(Boolean) as string[] const rootHints = [rootTag?.[2]].filter(Boolean) as string[]
const rootEvent = rootId ? deriveEvent(rootId, rootHints) : readable(null) const rootEvent = rootId ? deriveEvent(rootId, rootHints) : readable(null)
const [colorName, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length] const [colorName, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length]
const ps = throttled(300, derived(publishStatusData, $m => Object.values($m[event.id] || {}))) const ps = throttled(
300,
derived(publishStatusData, $m => Object.values($m[event.id] || {})),
)
const showInfo = () => pushModal(EventInfo, {event}) const showInfo = () => pushModal(EventInfo, {event})
@@ -94,7 +96,7 @@
</p> </p>
</div> </div>
{/if} {/if}
<div class="flex gap-2 w-full"> <div class="flex w-full gap-2">
{#if showPubkey} {#if showPubkey}
<Avatar src={$profile?.picture} class="border border-solid border-base-content" size={10} /> <Avatar src={$profile?.picture} class="border border-solid border-base-content" size={10} />
{:else} {:else}
@@ -128,7 +130,7 @@
</div> </div>
{#if $reactions.length > 0 || $zaps.length > 0} {#if $reactions.length > 0 || $zaps.length > 0}
<div class="ml-12 text-xs"> <div class="ml-12 text-xs">
{#each groupBy(e => e.content, uniqBy(e => e.pubkey + e.content, $reactions)).entries() as [content, events]} {#each groupBy( e => e.content, uniqBy(e => e.pubkey + e.content, $reactions), ).entries() as [content, events]}
{@const isOwn = events.some(e => e.pubkey === $pubkey)} {@const isOwn = events.some(e => e.pubkey === $pubkey)}
{@const onClick = () => onReactionClick(content, events)} {@const onClick = () => onReactionClick(content, events)}
<button <button
@@ -147,7 +149,7 @@
</div> </div>
{/if} {/if}
<button <button
class="join absolute top-1 right-1 border border-solid border-neutral text-xs opacity-0 transition-all group-hover:opacity-100" class="join absolute right-1 top-1 border border-solid border-neutral text-xs opacity-0 transition-all group-hover:opacity-100"
on:click|stopPropagation> on:click|stopPropagation>
<ChannelMessageEmojiButton {url} {room} {event} /> <ChannelMessageEmojiButton {url} {room} {event} />
<Button class="btn join-item btn-xs" on:click={showInfo}> <Button class="btn join-item btn-xs" on:click={showInfo}>
+1 -1
View File
@@ -43,7 +43,7 @@
} }
</script> </script>
<div class="fixed flex max-h-screen w-full flex-col gap-2"> <div class="col-2">
<div class="overflow-auto pt-3"> <div class="overflow-auto pt-3">
<ChannelMessage {url} {room} {event} showPubkey /> <ChannelMessage {url} {room} {event} showPubkey />
{#each sortBy(e => e.created_at, $replies) as reply (reply.id)} {#each sortBy(e => e.created_at, $replies) as reply (reply.id)}
+8 -5
View File
@@ -35,7 +35,10 @@
const reactions = deriveEvents(repository, {filters: [{kinds: [REACTION], "#e": [event.id]}]}) const reactions = deriveEvents(repository, {filters: [{kinds: [REACTION], "#e": [event.id]}]})
const zaps = deriveEvents(repository, {filters: [{kinds: [ZAP_RESPONSE], "#e": [event.id]}]}) const zaps = deriveEvents(repository, {filters: [{kinds: [ZAP_RESPONSE], "#e": [event.id]}]})
const [_, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length] const [_, colorValue] = colors[parseInt(hash(event.pubkey)) % colors.length]
const ps = throttled(300, derived(publishStatusData, $m => Object.values($m[event.wrap!.id] || {}))) const ps = throttled(
300,
derived(publishStatusData, $m => Object.values($m[event.wrap!.id] || {})),
)
const showProfile = () => pushDrawer(ProfileDetail, {pubkey: event.pubkey}) const showProfile = () => pushDrawer(ProfileDetail, {pubkey: event.pubkey})
@@ -67,7 +70,7 @@
</script> </script>
<div <div
class="chat flex gap-1 items-center group justify-end" class="group chat flex items-center justify-end gap-1"
class:chat-start={event.pubkey !== $pubkey} class:chat-start={event.pubkey !== $pubkey}
class:flex-row-reverse={event.pubkey !== $pubkey} class:flex-row-reverse={event.pubkey !== $pubkey}
class:chat-end={event.pubkey === $pubkey}> class:chat-end={event.pubkey === $pubkey}>
@@ -85,13 +88,13 @@
popoverIsVisible = false popoverIsVisible = false
}, },
}}> }}>
<Button class="group-hover:opacity-100 opacity-0 transition-all" on:click={togglePopover}> <Button class="opacity-0 transition-all group-hover:opacity-100" on:click={togglePopover}>
<Icon icon="menu-dots" size={4} /> <Icon icon="menu-dots" size={4} />
</Button> </Button>
</Tippy> </Tippy>
<div class="flex flex-col"> <div class="flex flex-col">
<div class="chat-bubble mx-1 max-w-sm"> <div class="chat-bubble mx-1 max-w-sm">
<div class="flex items-start gap-2 w-full"> <div class="flex w-full items-start gap-2">
{#if showPubkey} {#if showPubkey}
<Button on:click={showProfile}> <Button on:click={showProfile}>
<Avatar <Avatar
@@ -129,7 +132,7 @@
</div> </div>
</div> </div>
{#if $reactions.length > 0 || $zaps.length > 0} {#if $reactions.length > 0 || $zaps.length > 0}
<div class="-mt-4 text-xs z-feature relative flex justify-end"> <div class="relative z-feature -mt-4 flex justify-end text-xs">
{#each groupBy( e => e.content, uniqBy(e => e.pubkey + e.content, $reactions), ).entries() as [content, events]} {#each groupBy( e => e.content, uniqBy(e => e.pubkey + e.content, $reactions), ).entries() as [content, events]}
{@const isOwn = events.some(e => e.pubkey === $pubkey)} {@const isOwn = events.some(e => e.pubkey === $pubkey)}
{@const onClick = () => onReactionClick(content, events)} {@const onClick = () => onReactionClick(content, events)}
+4 -4
View File
@@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import Icon from '@lib/components/Icon.svelte' import Icon from "@lib/components/Icon.svelte"
import Button from '@lib/components/Button.svelte' import Button from "@lib/components/Button.svelte"
import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte" import ChatMessageEmojiButton from "@app/components/ChatMessageEmojiButton.svelte"
import EventInfo from '@app/components/EventInfo.svelte' import EventInfo from "@app/components/EventInfo.svelte"
import {pushModal} from '@app/modal' import {pushModal} from "@app/modal"
export let event export let event
export let pubkeys export let pubkeys
+1 -2
View File
@@ -14,7 +14,6 @@
import DateTimeInput from "@lib/components/DateTimeInput.svelte" import DateTimeInput from "@lib/components/DateTimeInput.svelte"
import {getPubkeyHints} from "@app/commands" import {getPubkeyHints} from "@app/commands"
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor" import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
import {clearModal} from "@app/modal"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
export let url export let url
@@ -54,7 +53,7 @@
}) })
publishThunk({event, relays: [url]}) publishThunk({event, relays: [url]})
clearModal() history.back()
} }
let editor: Readable<Editor> let editor: Readable<Editor>
+2 -4
View File
@@ -1,5 +1,5 @@
<script lang="ts"> <script lang="ts">
import Button from '@lib/components/Button.svelte' import Button from "@lib/components/Button.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
export let event export let event
@@ -8,9 +8,7 @@
<div class="column gap-4"> <div class="column gap-4">
<ModalHeader> <ModalHeader>
<div slot="title">Event Details</div> <div slot="title">Event Details</div>
<div slot="info"> <div slot="info">The full details of this event are shown below.</div>
The full details of this event are shown below.
</div>
</ModalHeader> </ModalHeader>
<pre class="overflow-auto"><code>{JSON.stringify(event, null, 2)}</code></pre> <pre class="overflow-auto"><code>{JSON.stringify(event, null, 2)}</code></pre>
<Button class="btn btn-primary" on:click={() => history.back()}>Got it</Button> <Button class="btn btn-primary" on:click={() => history.back()}>Got it</Button>
+22 -19
View File
@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import Button from "@lib/components/Button.svelte" import Button from "@lib/components/Button.svelte"
import Dialog from "@lib/components/Dialog.svelte"
import CardButton from "@lib/components/CardButton.svelte" import CardButton from "@lib/components/CardButton.svelte"
import LogIn from "@app/components/LogIn.svelte" import LogIn from "@app/components/LogIn.svelte"
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
@@ -11,23 +12,25 @@
const signUp = () => pushModal(SignUp) const signUp = () => pushModal(SignUp)
</script> </script>
<div class="column gap-4"> <Dialog>
<div class="py-2"> <div class="column gap-4">
<h1 class="heading">Welcome to Flotilla!</h1> <div class="py-2">
<p class="text-center">The chat app built for sovereign communities.</p> <h1 class="heading">Welcome to Flotilla!</h1>
<p class="text-center">The chat app built for sovereign communities.</p>
</div>
<Button on:click={logIn}>
<CardButton>
<div slot="icon"><Icon icon="login-2" size={7} /></div>
<div slot="title">Log in</div>
<div slot="info">If you've been here before, you know the drill.</div>
</CardButton>
</Button>
<Button on:click={signUp}>
<CardButton>
<div slot="icon"><Icon icon="add-circle" size={7} /></div>
<div slot="title">Create an account</div>
<div slot="info">Just a few questions and you'll be on your way.</div>
</CardButton>
</Button>
</div> </div>
<Button on:click={logIn}> </Dialog>
<CardButton>
<div slot="icon"><Icon icon="login-2" size={7} /></div>
<div slot="title">Log in</div>
<div slot="info">If you've been here before, you know the drill.</div>
</CardButton>
</Button>
<Button on:click={signUp}>
<CardButton>
<div slot="icon"><Icon icon="add-circle" size={7} /></div>
<div slot="title">Create an account</div>
<div slot="info">Just a few questions and you'll be on your way.</div>
</CardButton>
</Button>
</div>
+2 -2
View File
@@ -9,7 +9,7 @@
import SignUp from "@app/components/SignUp.svelte" import SignUp from "@app/components/SignUp.svelte"
import InfoNostr from "@app/components/InfoNostr.svelte" import InfoNostr from "@app/components/InfoNostr.svelte"
import LogInInfoRemoteSigner from "@app/components/LogInInfoRemoteSigner.svelte" import LogInInfoRemoteSigner from "@app/components/LogInInfoRemoteSigner.svelte"
import {pushModal, clearModal} from "@app/modal" import {pushModal, clearModals} from "@app/modal"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
import {loadUserData} from "@app/commands" import {loadUserData} from "@app/commands"
@@ -31,7 +31,7 @@
await loadUserData(session.pubkey, {relays}) await loadUserData(session.pubkey, {relays})
pushToast({message: "Successfully logged in!"}) pushToast({message: "Successfully logged in!"})
clearModal() clearModals()
} }
const loginWithNip46 = withLoading(async () => { const loginWithNip46 = withLoading(async () => {
+23 -45
View File
@@ -1,56 +1,34 @@
<script lang="ts"> <script lang="ts">
import {onMount} from 'svelte'
import type {SvelteComponent} from "svelte"
import {page} from "$app/stores" import {page} from "$app/stores"
import {fly} from "@lib/transition"
import Drawer from "@lib/components/Drawer.svelte" import Drawer from "@lib/components/Drawer.svelte"
import {modals} from "@app/modal" import Dialog from "@lib/components/Dialog.svelte"
import Toast from "@app/components/Toast.svelte" import {modals, clearModals} from "@app/modal"
let prev: any const onKeyDown = (e: any) => {
let mounted = false if (e.code === "Escape" && e.target === document.body) {
let dialog: HTMLDialogElement clearModals()
let drawer: SvelteComponent
$: hash = $page.url.hash.slice(1)
$: modal = modals.get(hash)
$: prev = modal || prev
$: {
if (mounted) {
if (modal?.options?.drawer) {
drawer.open()
} else if (modal) {
dialog.showModal()
} else {
drawer.close()
dialog.close()
}
} }
} }
onMount(() => { let modal: any
mounted = true
}) $: hash = $page.url.hash.slice(1)
$: hashIsValid = Boolean($modals[hash])
$: modal = $modals[hash] || modal
</script> </script>
<dialog bind:this={dialog} class="modal modal-bottom !z-modal sm:modal-middle"> <svelte:window on:keydown={onKeyDown} />
{#if modal && !modal.options?.drawer}
{#key hash} {#if hashIsValid && modal?.options?.drawer}
<div class="bg-alt modal-box overflow-visible overflow-y-auto" transition:fly={{duration: 100}}> <Drawer onClose={clearModals}>
<svelte:component this={modal.component} {...modal.props} /> {#key modal.id}
</div>
{/key}
<Toast />
{/if}
<form method="dialog" class="modal-backdrop">
<button />
</form>
</dialog>
<Drawer bind:this={drawer}>
{#if modal && modal.options?.drawer}
{#key hash}
<svelte:component this={modal.component} {...modal.props} /> <svelte:component this={modal.component} {...modal.props} />
{/key} {/key}
{/if} </Drawer>
</Drawer> {:else if hashIsValid && modal}
<Dialog onClose={clearModals}>
{#key modal.id}
<svelte:component this={modal.component} {...modal.props} />
{/key}
</Dialog>
{/if}
+2 -2
View File
@@ -54,9 +54,9 @@
{@const following = getPubkeyTagValues(getListTags($userFollows)).includes(pubkey)} {@const following = getPubkeyTagValues(getListTags($userFollows)).includes(pubkey)}
<div class="divider" /> <div class="divider" />
<button type="button" class="chat chat-start cursor-default" on:click|stopPropagation> <button type="button" class="chat chat-start cursor-default" on:click|stopPropagation>
<div class="bg-alt chat-bubble text-left col-4"> <div class="bg-alt col-4 chat-bubble text-left">
<Content hideMedia={!following} {event} /> <Content hideMedia={!following} {event} />
<Link external href={entityLink(nevent)} class="row-2 justify-end group whitespace-nowrap"> <Link external href={entityLink(nevent)} class="row-2 group justify-end whitespace-nowrap">
<Icon icon="link-round" size={3} /> <Icon icon="link-round" size={3} />
<p class="text-xs">{formatTimestamp(event.created_at)}</p> <p class="text-xs">{formatTimestamp(event.created_at)}</p>
</Link> </Link>
+2 -2
View File
@@ -7,7 +7,7 @@
import Spinner from "@lib/components/Spinner.svelte" import Spinner from "@lib/components/Spinner.svelte"
import LogIn from "@app/components/LogIn.svelte" import LogIn from "@app/components/LogIn.svelte"
import InfoNostr from "@app/components/LogIn.svelte" import InfoNostr from "@app/components/LogIn.svelte"
import {pushModal, clearModal} from "@app/modal" import {pushModal, clearModals} from "@app/modal"
import {pushToast} from "@app/toast" import {pushToast} from "@app/toast"
const login = () => pushModal(LogIn) const login = () => pushModal(LogIn)
@@ -38,7 +38,7 @@
if (await loginBroker.connect("", nip46Perms)) { if (await loginBroker.connect("", nip46Perms)) {
addSession({method: "nip46", pubkey, secret, handler}) addSession({method: "nip46", pubkey, secret, handler})
pushToast({message: "Successfully logged in!"}) pushToast({message: "Successfully logged in!"})
clearModal() clearModals()
} else { } else {
pushToast({ pushToast({
theme: "error", theme: "error",
+2 -2
View File
@@ -5,7 +5,7 @@
import Icon from "@lib/components/Icon.svelte" import Icon from "@lib/components/Icon.svelte"
import ModalHeader from "@lib/components/ModalHeader.svelte" import ModalHeader from "@lib/components/ModalHeader.svelte"
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {clearModal} from "@app/modal" import {clearModals} from "@app/modal"
import {addSpaceMembership} from "@app/commands" import {addSpaceMembership} from "@app/commands"
export let url export let url
@@ -15,7 +15,7 @@
const tryJoin = async () => { const tryJoin = async () => {
await addSpaceMembership(url) await addSpaceMembership(url)
clearModal() clearModals()
} }
const join = async () => { const join = async () => {
+1 -2
View File
@@ -11,7 +11,6 @@
import ModalFooter from "@lib/components/ModalFooter.svelte" import ModalFooter from "@lib/components/ModalFooter.svelte"
import {getPubkeyHints} from "@app/commands" import {getPubkeyHints} from "@app/commands"
import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor" import {getEditorOptions, addFile, uploadFiles, getEditorTags} from "@lib/editor"
import {clearModal} from "@app/modal"
export let url export let url
@@ -25,7 +24,7 @@
const event = createEvent(NOTE, {content: $editor.getText(), tags: getEditorTags($editor)}) const event = createEvent(NOTE, {content: $editor.getText(), tags: getEditorTags($editor)})
publishThunk({event, relays: [url]}) publishThunk({event, relays: [url]})
clearModal() history.back()
} }
let editor: Readable<Editor> let editor: Readable<Editor>
+16 -9
View File
@@ -1,15 +1,23 @@
import type {ComponentType} from "svelte" import type {ComponentType} from "svelte"
import {randomId, Emitter} from "@welshman/lib" import {writable} from "svelte/store"
import {randomId, always, assoc, Emitter} from "@welshman/lib"
import {goto} from "$app/navigation" import {goto} from "$app/navigation"
export const emitter = new Emitter()
export const modals = new Map()
export type ModalOptions = { export type ModalOptions = {
drawer?: boolean drawer?: boolean
} }
export type Modal = {
id: string
component: ComponentType
props: Record<string, any>
options: ModalOptions
}
export const emitter = new Emitter()
export const modals = writable<Record<string, Modal>>({})
export const pushModal = ( export const pushModal = (
component: ComponentType, component: ComponentType,
props: Record<string, any> = {}, props: Record<string, any> = {},
@@ -17,7 +25,7 @@ export const pushModal = (
) => { ) => {
const id = randomId() const id = randomId()
modals.set(id, {component, props, options}) modals.update(assoc(id, {id, component, props, options}))
goto("#" + id) goto("#" + id)
@@ -30,8 +38,7 @@ export const pushDrawer = (
options: ModalOptions = {}, options: ModalOptions = {},
) => pushModal(component, props, {...options, drawer: true}) ) => pushModal(component, props, {...options, drawer: true})
export const clearModal = () => { export const clearModals = () => {
goto("#") modals.update(always({}))
modals.clear()
emitter.emit("close") emitter.emit("close")
} }
+2 -2
View File
@@ -187,7 +187,7 @@ setContext({
return false return false
} }
const roomTags = event.tags.filter(nthEq(0, '~')) const roomTags = event.tags.filter(nthEq(0, "~"))
if (roomTags.length > 0 && !roomTags.some(nthEq(2, url))) { if (roomTags.length > 0 && !roomTags.some(nthEq(2, url))) {
return false return false
@@ -268,7 +268,7 @@ export const {
// Messages // Messages
export type ChannelMessage = { export type ChannelMessage = {
url: string, url: string
room: string room: string
event: TrustedEvent event: TrustedEvent
} }
+18
View File
@@ -0,0 +1,18 @@
<script lang="ts">
import {noop} from '@welshman/lib'
import {fade, fly} from "@lib/transition"
export let onClose: any = noop
</script>
<div class="center fixed inset-0 z-modal">
<button
class="absolute inset-0 cursor-pointer bg-black opacity-50"
transition:fade
on:click={onClose} />
<div
class="card2 bg-alt absolute max-h-[90vh] w-[90vw] overflow-auto text-base-content sm:w-[520px]"
transition:fly={{duration: 300}}>
<slot />
</div>
</div>
+11 -31
View File
@@ -1,37 +1,17 @@
<script lang="ts"> <script lang="ts">
import {randomId} from "@welshman/lib" import {fade, slide} from "@lib/transition"
const id = randomId() export let onClose
let input: any
let label: any
export const open = () => {
if (!input.checked) {
label.click()
}
}
export const close = () => {
if (input.checked) {
label.click()
}
}
export const toggle = () => {
label.click()
}
</script> </script>
<div class="drawer drawer-end"> <div class="fixed inset-0 z-modal">
<input {id} type="checkbox" class="drawer-toggle" bind:this={input} on:change /> <button
<div class="drawer-content"> class="absolute inset-0 cursor-pointer bg-black opacity-50"
<label for={id} bind:this={label} /> transition:fade
</div> on:click={onClose} />
<div class="drawer-side z-modal"> <div
<label for={id} aria-label="close sidebar" class="drawer-overlay"></label> class="menu absolute bottom-0 right-0 top-0 w-80 overflow-auto bg-base-200 text-base-content lg:w-96"
<div class="menu h-full w-80 overflow-auto bg-base-200 p-0 text-base-content lg:w-96"> transition:slide={{axis: "x", duration: 300}}>
<slot /> <slot />
</div>
</div> </div>
</div> </div>
+1 -1
View File
@@ -1,3 +1,3 @@
<div class="mt-4 flex flex-row items-center justify-between gap-4"> <div class="row-4 mt-4 items-center justify-between">
<slot /> <slot />
</div> </div>
+37 -35
View File
@@ -1,5 +1,5 @@
// @ts-nocheck // @ts-nocheck
import {cubicOut} from 'svelte/easing' import {cubicOut} from "svelte/easing"
import type {FlyParams} from "svelte/transition" import type {FlyParams} from "svelte/transition"
import {fly as baseFly} from "svelte/transition" import {fly as baseFly} from "svelte/transition"
@@ -9,38 +9,40 @@ export const fly = (node: Element, params?: FlyParams | undefined) =>
baseFly(node, {y: 20, ...params}) baseFly(node, {y: 20, ...params})
// Copy-pasted and tweaked from slide source code // Copy-pasted and tweaked from slide source code
export function slideAndFade(node: any, { delay = 0, duration = 400, easing = cubicOut, axis = 'y' } = {}) { export function slideAndFade(
const style = getComputedStyle(node) node: any,
const opacity = +style.opacity {delay = 0, duration = 400, easing = cubicOut, axis = "y"} = {},
const primary_property = axis === 'y' ? 'height' : 'width' ) {
const primary_property_value = parseFloat(style[primary_property]) const style = getComputedStyle(node)
const secondary_properties = axis === 'y' ? ['top', 'bottom'] : ['left', 'right'] const primary_property = axis === "y" ? "height" : "width"
const capitalized_secondary_properties = secondary_properties.map( const primary_property_value = parseFloat(style[primary_property])
(e: string) => `${e[0].toUpperCase()}${e.slice(1)}` const secondary_properties = axis === "y" ? ["top", "bottom"] : ["left", "right"]
) const capitalized_secondary_properties = secondary_properties.map(
const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`]) (e: string) => `${e[0].toUpperCase()}${e.slice(1)}`,
const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`]) )
const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`]) const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`])
const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`]) const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`])
const border_width_start_value = parseFloat( const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`])
style[`border${capitalized_secondary_properties[0]}Width`] const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`])
) const border_width_start_value = parseFloat(
const border_width_end_value = parseFloat( style[`border${capitalized_secondary_properties[0]}Width`],
style[`border${capitalized_secondary_properties[1]}Width`] )
) const border_width_end_value = parseFloat(
return { style[`border${capitalized_secondary_properties[1]}Width`],
delay, )
duration, return {
easing, delay,
css: (t: number) => duration,
'overflow: hidden;' + easing,
`opacity: ${t};` + css: (t: number) =>
`${primary_property}: ${t * primary_property_value}px;` + "overflow: hidden;" +
`padding-${secondary_properties[0]}: ${t * padding_start_value}px;` + `opacity: ${t};` +
`padding-${secondary_properties[1]}: ${t * padding_end_value}px;` + `${primary_property}: ${t * primary_property_value}px;` +
`margin-${secondary_properties[0]}: ${t * margin_start_value}px;` + `padding-${secondary_properties[0]}: ${t * padding_start_value}px;` +
`margin-${secondary_properties[1]}: ${t * margin_end_value}px;` + `padding-${secondary_properties[1]}: ${t * padding_end_value}px;` +
`border-${secondary_properties[0]}-width: ${t * border_width_start_value}px;` + `margin-${secondary_properties[0]}: ${t * margin_start_value}px;` +
`border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;` `margin-${secondary_properties[1]}: ${t * margin_end_value}px;` +
} `border-${secondary_properties[0]}-width: ${t * border_width_start_value}px;` +
`border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;`,
}
} }
-5
View File
@@ -2,9 +2,6 @@
import "@src/app.css" import "@src/app.css"
import {onMount} from "svelte" import {onMount} from "svelte"
import {get} from "svelte/store" import {get} from "svelte/store"
import {page} from "$app/stores"
import {goto} from "$app/navigation"
import {browser} from "$app/environment"
import {sleep, take, sortBy, ago, now, HOUR} from "@welshman/lib" import {sleep, take, sortBy, ago, now, HOUR} from "@welshman/lib"
import type {TrustedEvent} from "@welshman/util" import type {TrustedEvent} from "@welshman/util"
import { import {
@@ -26,7 +23,6 @@
db, db,
initStorage, initStorage,
repository, repository,
session,
pubkey, pubkey,
publishStatusData, publishStatusData,
plaintext, plaintext,
@@ -39,7 +35,6 @@
import * as app from "@welshman/app" import * as app from "@welshman/app"
import AppContainer from "@app/components/AppContainer.svelte" import AppContainer from "@app/components/AppContainer.svelte"
import ModalContainer from "@app/components/ModalContainer.svelte" import ModalContainer from "@app/components/ModalContainer.svelte"
import {modals, clearModal} from "@app/modal"
import {theme} from "@app/theme" import {theme} from "@app/theme"
import {INDEXER_RELAYS} from "@app/state" import {INDEXER_RELAYS} from "@app/state"
import {loadUserData} from "@app/commands" import {loadUserData} from "@app/commands"