forked from coracle/flotilla
Add a currency input
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import Modal from "@lib/components/Modal.svelte"
|
||||
import ModalBody from "@lib/components/ModalBody.svelte"
|
||||
import CurrencyInput from "@app/components/CurrencyInput.svelte"
|
||||
import EditorContent from "@app/editor/EditorContent.svelte"
|
||||
import {pushToast} from "@app/util/toast"
|
||||
import {PROTECTED} from "@app/core/state"
|
||||
@@ -75,7 +76,9 @@
|
||||
|
||||
const editor = makeEditor({url, submit, uploading, placeholder: "What's on your mind?"})
|
||||
|
||||
let title: string = $state("")
|
||||
let title = $state("")
|
||||
let currencyCode = $state("SAT")
|
||||
let currencyAmount = $state(0)
|
||||
</script>
|
||||
|
||||
<Modal tag="form" onsubmit={preventDefault(submit)}>
|
||||
@@ -116,7 +119,12 @@
|
||||
<p>Price*</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
todo: value and search select inline
|
||||
<div class="join grid grid-cols-2">
|
||||
<label class="join-item input input-bordered flex w-full items-center gap-2">
|
||||
<input bind:value={currencyAmount} class="grow w-32" type="number" />
|
||||
</label>
|
||||
<CurrencyInput class="join-item" bind:value={currencyCode} />
|
||||
</div>
|
||||
{/snippet}
|
||||
</Field>
|
||||
<Field>
|
||||
@@ -124,7 +132,7 @@
|
||||
<p>Images</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
todo: attach multiple images
|
||||
todo: attach multiple images
|
||||
{/snippet}
|
||||
</Field>
|
||||
<Button
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {writable} from "svelte/store"
|
||||
import type {Writable} from "svelte/store"
|
||||
import type {Instance} from "tippy.js"
|
||||
import {preventDefault} from '@lib/html'
|
||||
import {createSearch} from "@welshman/app"
|
||||
import {currencyOptions, displayCurrency} from "@lib/currency"
|
||||
import Suggestions from "@lib/components/Suggestions.svelte"
|
||||
import CurrencySuggestion from "@app/components/CurrencySuggestion.svelte"
|
||||
import AltArrowDown from "@assets/icons/alt-arrow-down.svg?dataurl"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Tippy from "@lib/components/Tippy.svelte"
|
||||
|
||||
interface Props {
|
||||
value: string
|
||||
autofocus?: boolean
|
||||
term?: Writable<string>
|
||||
class?: string
|
||||
}
|
||||
|
||||
let {value = $bindable(), term = writable(""), autofocus = false, ...props}: Props = $props()
|
||||
|
||||
const options = createSearch(currencyOptions, {
|
||||
getValue: item => item.code,
|
||||
fuseOptions: {
|
||||
keys: ["name", "code"],
|
||||
threshold: 0.4,
|
||||
},
|
||||
})
|
||||
|
||||
const search = (term: string) =>
|
||||
term ? options.searchValues(term) : ["BTC", "SAT", "USD", "GBP", "AUD", "CAD"]
|
||||
|
||||
const selectCurrency = (code: string) => {
|
||||
value = code
|
||||
term.set("")
|
||||
popover?.hide()
|
||||
}
|
||||
|
||||
const clearAndFocus = () => {
|
||||
value = ""
|
||||
term.set("")
|
||||
setTimeout(() => wrapper?.querySelector("input")?.focus())
|
||||
}
|
||||
|
||||
const onKeyDown = (e: Event) => {
|
||||
if (instance.onKeyDown(e)) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const currency = $derived(currencyOptions.find(c => c.code === value))
|
||||
|
||||
let wrapper: Element | undefined = $state()
|
||||
let popover: Instance | undefined = $state()
|
||||
let instance: any = $state()
|
||||
|
||||
$effect(() => {
|
||||
if ($term) {
|
||||
popover?.show()
|
||||
} else {
|
||||
popover?.hide()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<button
|
||||
class={cx(
|
||||
props.class,
|
||||
{"bg-base-200": currency},
|
||||
"input input-bordered flex items-center gap-2 cursor-pointer",
|
||||
)}
|
||||
bind:this={wrapper}
|
||||
onfocus={preventDefault(clearAndFocus)}
|
||||
onclick={preventDefault(clearAndFocus)}>
|
||||
<Icon icon={AltArrowDown} />
|
||||
{#if currency}
|
||||
<span class="text-sm ellipsize whitespace-nowrap">
|
||||
{displayCurrency(currency)}
|
||||
</span>
|
||||
{:else}
|
||||
<!-- svelte-ignore a11y_autofocus -->
|
||||
<input {autofocus} class="grow" type="text" bind:value={$term} onkeydown={onKeyDown} />
|
||||
{/if}
|
||||
<Tippy
|
||||
bind:popover
|
||||
bind:instance
|
||||
component={Suggestions}
|
||||
props={{
|
||||
term,
|
||||
search,
|
||||
select: selectCurrency,
|
||||
component: CurrencySuggestion,
|
||||
}}
|
||||
params={{
|
||||
trigger: "manual",
|
||||
interactive: true,
|
||||
getReferenceClientRect: () => wrapper!.getBoundingClientRect(),
|
||||
}} />
|
||||
</button>
|
||||
@@ -0,0 +1,11 @@
|
||||
<script lang="ts">
|
||||
import {displayCurrencyByCode} from "@lib/currency"
|
||||
|
||||
type Props = {
|
||||
value: string
|
||||
}
|
||||
|
||||
const {value}: Props = $props()
|
||||
</script>
|
||||
|
||||
{displayCurrencyByCode(value)}
|
||||
Reference in New Issue
Block a user