forked from coracle/flotilla
Migrate more stuff
This commit is contained in:
@@ -2,13 +2,11 @@
|
||||
import {onMount} from "svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
export let src = ""
|
||||
export let size = 7
|
||||
export let icon = "user-rounded"
|
||||
let {src = "", size = 7, icon = "user-rounded", style = "", ...restProps} = $props()
|
||||
|
||||
let element: HTMLElement
|
||||
|
||||
$: rem = size * 4
|
||||
const rem = $derived(size * 4)
|
||||
|
||||
onMount(() => {
|
||||
if (src) {
|
||||
@@ -25,8 +23,7 @@
|
||||
|
||||
<div
|
||||
bind:this={element}
|
||||
class="{$$props.class} relative !flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-cover bg-center"
|
||||
style="width: {rem}px; height: {rem}px; min-width: {rem}px; background-image: url({src}); {$$props.style ||
|
||||
''}">
|
||||
class="{restProps.class} relative !flex shrink-0 items-center justify-center overflow-hidden rounded-full bg-cover bg-center"
|
||||
style="width: {rem}px; height: {rem}px; min-width: {rem}px; background-image: url({src}); {style}">
|
||||
<Icon {icon} class={src ? "hidden" : ""} size={Math.round(size * 0.8)} />
|
||||
</div>
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
<script lang="ts">
|
||||
export let type: "button" | "submit" = "button"
|
||||
interface Props {
|
||||
type?: "button" | "submit"
|
||||
}
|
||||
|
||||
$: className = `text-left ${$$props.class}`
|
||||
let {type = "button", ...restProps} = $props()
|
||||
|
||||
const className = $derived(`text-left ${restProps.class}`)
|
||||
</script>
|
||||
|
||||
{#if type === "submit"}
|
||||
<button {...$$props} {type} class={className}>
|
||||
<button {...restProps} {type} class={className}>
|
||||
<slot />
|
||||
</button>
|
||||
{:else}
|
||||
<button on:click|stopPropagation|preventDefault {...$$props} {type} class={className}>
|
||||
<button on:click|stopPropagation|preventDefault {...restProps} {type} class={className}>
|
||||
<slot />
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
@@ -1,18 +1,26 @@
|
||||
<script lang="ts">
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
interface Props {
|
||||
icon?: import("svelte").Snippet
|
||||
title?: import("svelte").Snippet
|
||||
info?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="btn btn-neutral flex h-[unset] w-full flex-nowrap py-4 text-left {$$props.class}">
|
||||
<div class="btn btn-neutral flex h-[unset] w-full flex-nowrap py-4 text-left {props.class}">
|
||||
<div class="flex flex-grow flex-row items-start gap-1 sm:pl-2">
|
||||
<div class="flex h-14 w-12 flex-shrink-0 items-center">
|
||||
<slot name="icon" />
|
||||
{@render props.icon?.()}
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
<p class="text-bold text-lg">
|
||||
<slot name="title" />
|
||||
{@render props.title?.()}
|
||||
</p>
|
||||
<p class="text-sm">
|
||||
<slot name="info" />
|
||||
{@render props.info?.()}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,27 +1,35 @@
|
||||
<script lang="ts">
|
||||
import {slide} from "@lib/transition"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
interface Props {
|
||||
title?: import("svelte").Snippet
|
||||
description?: import("svelte").Snippet
|
||||
children?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
|
||||
const toggle = () => {
|
||||
isOpen = !isOpen
|
||||
}
|
||||
|
||||
let isOpen = false
|
||||
let isOpen = $state(false)
|
||||
</script>
|
||||
|
||||
<div class="relative flex flex-col gap-4 {$$props.class}">
|
||||
<div class="relative flex flex-col gap-4 {props.class}">
|
||||
<button
|
||||
type="button"
|
||||
class="absolute right-8 top-8 h-4 w-4 cursor-pointer transition-all"
|
||||
class:rotate-90={!isOpen}
|
||||
on:click={toggle}>
|
||||
onclick={toggle}>
|
||||
<Icon icon="alt-arrow-down" />
|
||||
</button>
|
||||
<slot name="title" />
|
||||
<slot name="description" />
|
||||
{@render props.title?.()}
|
||||
{@render props.description?.()}
|
||||
{#if isOpen}
|
||||
<div transition:slide>
|
||||
<slot />
|
||||
{@render props.children?.()}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
<script lang="ts">
|
||||
import {preventDefault} from "svelte/legacy"
|
||||
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Spinner from "@lib/components/Spinner.svelte"
|
||||
import ModalHeader from "@lib/components/ModalHeader.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
|
||||
export let title = "Are you sure?"
|
||||
export let subtitle = ""
|
||||
export let message
|
||||
export let confirm
|
||||
interface Props {
|
||||
title?: string
|
||||
subtitle?: string
|
||||
message: any
|
||||
confirm: any
|
||||
}
|
||||
|
||||
let loading = false
|
||||
let {title = "Are you sure?", subtitle = "", message, confirm}: Props = $props()
|
||||
|
||||
let loading = $state(false)
|
||||
|
||||
const tryConfirm = async () => {
|
||||
loading = true
|
||||
@@ -25,10 +31,14 @@
|
||||
const back = () => history.back()
|
||||
</script>
|
||||
|
||||
<form class="column gap-4" on:submit|preventDefault={tryConfirm}>
|
||||
<form class="column gap-4" onsubmit={preventDefault(tryConfirm)}>
|
||||
<ModalHeader>
|
||||
<div slot="title">{title}</div>
|
||||
<div slot="info">{subtitle}</div>
|
||||
{#snippet title()}
|
||||
<div>{title}</div>
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
<div>{subtitle}</div>
|
||||
{/snippet}
|
||||
</ModalHeader>
|
||||
<p>{message}</p>
|
||||
<ModalFooter>
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
<div class="col-2 content-padding-t content-padding-x h-full {$$props.class}">
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
input?: import("svelte").Snippet
|
||||
content?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="col-2 content-padding-t content-padding-x h-full {props.class}">
|
||||
<div class="z-feature">
|
||||
<div class="content-sizing">
|
||||
<slot name="input" />
|
||||
{@render props.input?.()}
|
||||
</div>
|
||||
</div>
|
||||
<div class="scroll-container overflow-auto pt-2">
|
||||
<div class="content-sizing">
|
||||
<slot name="content" />
|
||||
{@render props.content?.()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,8 +3,13 @@
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
|
||||
export let initialValue: Date | undefined = undefined
|
||||
export let value: Date | undefined = initialValue
|
||||
interface Props {
|
||||
initialValue?: Date | undefined
|
||||
value?: Date | undefined
|
||||
}
|
||||
|
||||
let {initialValue = undefined, value = $bindable<Date | undefined>(initialValue)}: Props =
|
||||
$props()
|
||||
|
||||
const init = () => {
|
||||
if (!value) {
|
||||
|
||||
@@ -2,12 +2,18 @@
|
||||
import {noop} from "@welshman/lib"
|
||||
import {fade, fly} from "@lib/transition"
|
||||
|
||||
export let onClose: any = noop
|
||||
export let fullscreen = false
|
||||
interface Props {
|
||||
onClose?: any
|
||||
fullscreen?: boolean
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
$: extraClass =
|
||||
let {onClose = noop, fullscreen = false, children}: Props = $props()
|
||||
|
||||
let extraClass = $derived(
|
||||
!fullscreen &&
|
||||
"card2 bg-alt max-h-[90vh] w-[90vw] overflow-auto text-base-content sm:w-[520px] shadow-xl"
|
||||
"card2 bg-alt max-h-[90vh] w-[90vw] overflow-auto text-base-content sm:w-[520px] shadow-xl",
|
||||
)
|
||||
</script>
|
||||
|
||||
<div class="center fixed inset-0 z-modal">
|
||||
@@ -15,9 +21,9 @@
|
||||
aria-label="Close dialog"
|
||||
class="absolute inset-0 cursor-pointer bg-black opacity-75"
|
||||
transition:fade={{duration: 300}}
|
||||
on:click={onClose}>
|
||||
onclick={onClose}>
|
||||
</button>
|
||||
<div class="scroll-container relative {extraClass}" transition:fly={{duration: 300}}>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {children}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="flex items-center gap-2 p-2 text-xs uppercase opacity-50">
|
||||
<div class="h-px flex-grow bg-base-content opacity-25"></div>
|
||||
{#if $$slots.default}
|
||||
<p><slot /></p>
|
||||
{#if children}
|
||||
<p>{@render children?.()}</p>
|
||||
<div class="h-px flex-grow bg-base-content opacity-25"></div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {fade, translate} from "@lib/transition"
|
||||
|
||||
export let onClose
|
||||
let {onClose, children} = $props()
|
||||
</script>
|
||||
|
||||
<div class="drawer fixed inset-0 z-modal">
|
||||
@@ -9,11 +9,11 @@
|
||||
aria-label="Close drawer"
|
||||
class="absolute inset-0 cursor-pointer bg-black opacity-50"
|
||||
transition:fade
|
||||
on:click={onClose}>
|
||||
onclick={onClose}>
|
||||
</button>
|
||||
<div
|
||||
class="scroll-container saiy sair absolute bottom-0 right-0 top-0 w-80 overflow-auto bg-base-200 text-base-content lg:w-96"
|
||||
transition:translate={{axis: "x", duration: 300}}>
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
import Tippy from "@lib/components/Tippy.svelte"
|
||||
import EmojiPicker from "@lib/components/EmojiPicker.svelte"
|
||||
|
||||
export let onEmoji
|
||||
let {...props} = $props()
|
||||
|
||||
const open = () => popover.show()
|
||||
const open = () => popover?.show()
|
||||
|
||||
const onClick = (emoji: NativeEmoji) => {
|
||||
onEmoji(emoji)
|
||||
popover.hide()
|
||||
props.onEmoji(emoji)
|
||||
popover?.hide()
|
||||
}
|
||||
|
||||
const onMouseMove = throttle(300, ({clientX, clientY}: any) => {
|
||||
@@ -25,17 +25,17 @@
|
||||
}
|
||||
})
|
||||
|
||||
let popover: Instance
|
||||
let popover: Instance | undefined = $state()
|
||||
</script>
|
||||
|
||||
<svelte:document on:mousemove={onMouseMove} />
|
||||
<svelte:document onmousemove={onMouseMove} />
|
||||
|
||||
<Tippy
|
||||
bind:popover
|
||||
component={EmojiPicker}
|
||||
props={{onClick}}
|
||||
params={{trigger: "manual", interactive: true}}>
|
||||
<Button on:click={open} class={$$props.class}>
|
||||
<slot />
|
||||
<Button on:click={open} class={props.class}>
|
||||
{@render props.children?.()}
|
||||
</Button>
|
||||
</Tippy>
|
||||
|
||||
@@ -13,12 +13,16 @@
|
||||
import type {Emoji} from "emoji-picker-element/shared"
|
||||
import {onMount} from "svelte"
|
||||
|
||||
export let onClick: (emoji: Emoji) => void
|
||||
interface Props {
|
||||
onClick: (emoji: Emoji) => void
|
||||
}
|
||||
|
||||
let element: Element
|
||||
let {onClick}: Props = $props()
|
||||
|
||||
let element: Element | undefined = $state()
|
||||
|
||||
onMount(() => {
|
||||
element.addEventListener("emoji-click", (event: any) => onClick(event.detail as Emoji))
|
||||
element?.addEventListener("emoji-click", (event: any) => onClick(event.detail as Emoji))
|
||||
})
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
<div class="flex flex-col gap-2 {$$props.class}">
|
||||
{#if $$slots.label}
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
label?: import("svelte").Snippet
|
||||
input?: import("svelte").Snippet
|
||||
info?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-2 {props.class}">
|
||||
{#if props.label}
|
||||
<label class="flex items-center gap-2 font-bold">
|
||||
<slot name="label" />
|
||||
{@render props.label?.()}
|
||||
</label>
|
||||
{/if}
|
||||
<slot name="input" />
|
||||
{#if $$slots.info}
|
||||
{@render props.input?.()}
|
||||
{#if props.info}
|
||||
<p class="text-sm">
|
||||
<slot name="info" />
|
||||
{@render props.info?.()}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
@@ -1,13 +1,24 @@
|
||||
<div class="grid grid-cols-1 gap-2 md:grid-cols-3 {$$props.class}">
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
label?: import("svelte").Snippet
|
||||
input?: import("svelte").Snippet
|
||||
info?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="grid grid-cols-1 gap-2 md:grid-cols-3 {props.class}">
|
||||
<label class="flex items-center gap-2 font-bold">
|
||||
<slot name="label" />
|
||||
{@render props.label?.()}
|
||||
</label>
|
||||
<div class="col-span-2 flex items-center gap-2">
|
||||
<slot name="input" />
|
||||
{@render props.input?.()}
|
||||
</div>
|
||||
<p class="flex-end text-sm md:col-span-3">
|
||||
{#if $$slots.info}
|
||||
<slot name="info" />
|
||||
{#if props.info}
|
||||
{@render props.info?.()}
|
||||
{/if}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -84,8 +84,12 @@
|
||||
import WidgetAdd from "@assets/icons/Widget Add.svg?dataurl"
|
||||
import WiFiRouterRound from "@assets/icons/Wi-Fi Router Round.svg?dataurl"
|
||||
|
||||
export let icon
|
||||
export let size = 5
|
||||
interface Props {
|
||||
icon: string
|
||||
size: number
|
||||
}
|
||||
|
||||
let {icon, size = 5, ...restProps} = $props()
|
||||
|
||||
const px = size * 4
|
||||
|
||||
@@ -173,6 +177,6 @@
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={cx("inline-block", $$props.class)}
|
||||
class="inline-block {restProps.class}"
|
||||
style="mask-image: url({data}); width: {px}px; height: {px}px; min-width: {px}px; min-height: {px}px; background-color: currentcolor;">
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
<script lang="ts">
|
||||
import {run, preventDefault, stopPropagation} from "svelte/legacy"
|
||||
|
||||
import {randomId} from "@welshman/lib"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
export let file: File | null = null
|
||||
export let url: string | null = null
|
||||
interface Props {
|
||||
file?: File | null
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
let {file = $bindable(null), url = $bindable(null)}: Props = $props()
|
||||
|
||||
const id = randomId()
|
||||
|
||||
@@ -35,10 +41,10 @@
|
||||
url = null
|
||||
}
|
||||
|
||||
let active = false
|
||||
let initialUrl = url
|
||||
let active = $state(false)
|
||||
let initialUrl = $state(url)
|
||||
|
||||
$: {
|
||||
run(() => {
|
||||
if (file) {
|
||||
const reader = new FileReader()
|
||||
|
||||
@@ -53,21 +59,21 @@
|
||||
} else {
|
||||
url = initialUrl
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<form>
|
||||
<input {id} type="file" accept="image/*" on:change={onChange} class="hidden" />
|
||||
<input {id} type="file" accept="image/*" onchange={onChange} class="hidden" />
|
||||
<label
|
||||
for={id}
|
||||
aria-label="Drag and drop files here."
|
||||
style="background-image: url({url});"
|
||||
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-dashed border-base-content bg-base-300 bg-cover bg-center transition-all"
|
||||
class:border-primary={active}
|
||||
on:dragenter|preventDefault|stopPropagation={onDragEnter}
|
||||
on:dragover|preventDefault|stopPropagation={onDragOver}
|
||||
on:dragleave|preventDefault|stopPropagation={onDragLeave}
|
||||
on:drop|preventDefault|stopPropagation={onDrop}>
|
||||
ondragenter={stopPropagation(preventDefault(onDragEnter))}
|
||||
ondragover={stopPropagation(preventDefault(onDragOver))}
|
||||
ondragleave={stopPropagation(preventDefault(onDragLeave))}
|
||||
ondrop={stopPropagation(preventDefault(onDrop))}>
|
||||
<div
|
||||
class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full bg-primary"
|
||||
class:bg-error={file}
|
||||
@@ -76,8 +82,8 @@
|
||||
<span
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
on:mousedown|stopPropagation={onClear}
|
||||
on:touchstart|stopPropagation={onClear}>
|
||||
onmousedown={stopPropagation(onClear)}
|
||||
ontouchstart={stopPropagation(onClear)}>
|
||||
<Icon icon="close-circle" class="scale-150 !bg-base-300" />
|
||||
</span>
|
||||
{:else}
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
<script lang="ts">
|
||||
import {run, preventDefault, stopPropagation} from "svelte/legacy"
|
||||
|
||||
import {randomId} from "@welshman/lib"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
|
||||
export let file: File | null = null
|
||||
export let url: string | null = null
|
||||
interface Props {
|
||||
file?: File | null
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
let {file = $bindable(null), url = $bindable(null)}: Props = $props()
|
||||
|
||||
const id = randomId()
|
||||
|
||||
@@ -35,10 +41,10 @@
|
||||
url = null
|
||||
}
|
||||
|
||||
let active = false
|
||||
let initialUrl = url
|
||||
let active = $state(false)
|
||||
let initialUrl = $state(url)
|
||||
|
||||
$: {
|
||||
run(() => {
|
||||
if (file) {
|
||||
const reader = new FileReader()
|
||||
|
||||
@@ -53,11 +59,11 @@
|
||||
} else {
|
||||
url = initialUrl
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<form>
|
||||
<input {id} type="file" accept="image/*" on:change={onChange} class="hidden" />
|
||||
<input {id} type="file" accept="image/*" onchange={onChange} class="hidden" />
|
||||
<label
|
||||
for={id}
|
||||
aria-label="Drag and drop files here."
|
||||
@@ -65,10 +71,10 @@
|
||||
class="relative flex h-24 w-24 shrink-0 cursor-pointer items-center justify-center rounded-full border-2 border-solid border-base-content bg-base-300 bg-cover bg-center transition-all"
|
||||
class:transparent={!url}
|
||||
class:border-primary={active}
|
||||
on:dragenter|preventDefault|stopPropagation={onDragEnter}
|
||||
on:dragover|preventDefault|stopPropagation={onDragOver}
|
||||
on:dragleave|preventDefault|stopPropagation={onDragLeave}
|
||||
on:drop|preventDefault|stopPropagation={onDrop}>
|
||||
ondragenter={stopPropagation(preventDefault(onDragEnter))}
|
||||
ondragover={stopPropagation(preventDefault(onDragOver))}
|
||||
ondragleave={stopPropagation(preventDefault(onDragLeave))}
|
||||
ondrop={stopPropagation(preventDefault(onDrop))}>
|
||||
<div
|
||||
class="absolute right-0 top-0 h-5 w-5 overflow-hidden rounded-full bg-primary"
|
||||
class:bg-error={url}
|
||||
@@ -77,8 +83,8 @@
|
||||
<span
|
||||
role="button"
|
||||
tabindex="-1"
|
||||
on:mousedown|stopPropagation={onClear}
|
||||
on:touchstart|stopPropagation={onClear}>
|
||||
onmousedown={stopPropagation(onClear)}
|
||||
ontouchstart={stopPropagation(onClear)}>
|
||||
<Icon icon="close-circle" class="scale-150 !bg-base-300" />
|
||||
</span>
|
||||
{:else}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
<script lang="ts">
|
||||
import {goto} from "$app/navigation"
|
||||
|
||||
export let href
|
||||
export let external = false
|
||||
export let replaceState = false
|
||||
interface Props {
|
||||
href: string
|
||||
external: boolean
|
||||
replaceState: boolean
|
||||
}
|
||||
|
||||
let {href, external = false, replaceState = false, ...restProps} = $props()
|
||||
|
||||
const go = (e: Event) => {
|
||||
if (!external) {
|
||||
@@ -16,9 +20,9 @@
|
||||
|
||||
<a
|
||||
{href}
|
||||
{...$$props}
|
||||
{...restProps}
|
||||
on:click|stopPropagation={go}
|
||||
class="cursor-pointer {$$props.class}"
|
||||
class="cursor-pointer {restProps.class}"
|
||||
rel={external ? "noopener noreferer" : ""}
|
||||
target={external ? "_blank" : ""}>
|
||||
<slot />
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
<script lang="ts">
|
||||
export let onLongPress
|
||||
import {createBubbler} from "svelte/legacy"
|
||||
|
||||
const bubble = createBubbler()
|
||||
let {...props} = $props()
|
||||
|
||||
const onTouchStart = (event: any) => {
|
||||
touch = event.touches[0]
|
||||
timeout = setTimeout(onLongPress, 500)
|
||||
timeout = setTimeout(props.onLongPress, 500)
|
||||
}
|
||||
|
||||
const onTouchMove = (event: any) => {
|
||||
@@ -27,10 +30,10 @@
|
||||
<div
|
||||
role="button"
|
||||
tabindex="0"
|
||||
on:click
|
||||
on:touchstart={onTouchStart}
|
||||
on:touchmove={onTouchMove}
|
||||
on:touchend={onTouchEnd}
|
||||
{...$$props}>
|
||||
<slot />
|
||||
onclick={bubble("click")}
|
||||
ontouchstart={onTouchStart}
|
||||
ontouchmove={onTouchMove}
|
||||
ontouchend={onTouchEnd}
|
||||
{...props}>
|
||||
{@render props.children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {children}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="row-4 mt-4 items-center justify-between">
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
title?: import("svelte").Snippet
|
||||
info?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {title, info}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="column m-auto max-w-xs gap-2 py-4">
|
||||
<h1 class="heading"><slot name="title" /></h1>
|
||||
<p class="text-center"><slot name="info" /></p>
|
||||
<h1 class="heading">{@render title?.()}</h1>
|
||||
<p class="text-center">{@render info?.()}</p>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="sait saib sair scroll-container max-h-screen flex-grow overflow-auto bg-base-200 pb-14 md:pb-0 {$$props.class}">
|
||||
<slot />
|
||||
class="sait saib sair scroll-container max-h-screen flex-grow overflow-auto bg-base-200 pb-14 md:pb-0 {props.class}">
|
||||
{@render props.children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
<div class="relative z-feature mx-2 rounded-xl pt-4 {$$props.class}">
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
icon?: import("svelte").Snippet
|
||||
title?: import("svelte").Snippet
|
||||
action?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="relative z-feature mx-2 rounded-xl pt-4 {props.class}">
|
||||
<div
|
||||
class="flex min-h-12 items-center justify-between gap-4 rounded-xl bg-base-100 px-4 shadow-xl">
|
||||
<div class="flex items-center gap-4">
|
||||
<slot name="icon" />
|
||||
<slot name="title" />
|
||||
{@render props.icon?.()}
|
||||
{@render props.title?.()}
|
||||
</div>
|
||||
<slot name="action" />
|
||||
{@render props.action?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,13 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
title?: import("svelte").Snippet
|
||||
info?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {title, info}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="column gap-4 py-12">
|
||||
<h1 class="superheading"><slot name="title" /></h1>
|
||||
<p class="text-center"><slot name="info" /></p>
|
||||
<h1 class="superheading">{@render title?.()}</h1>
|
||||
<p class="text-center">{@render info?.()}</p>
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
<script lang="ts">
|
||||
import type {Snippet} from "svelte"
|
||||
import {fly} from "@lib/transition"
|
||||
|
||||
export let onClose
|
||||
export let hideOnClick = false
|
||||
interface Props {
|
||||
onClose: any
|
||||
hideOnClick?: boolean
|
||||
children?: Snippet
|
||||
}
|
||||
|
||||
let {onClose, hideOnClick = false, children}: Props = $props()
|
||||
|
||||
const onMouseUp = (e: any) => {
|
||||
if (hideOnClick || !element.contains(e.target)) {
|
||||
if (hideOnClick || !element?.contains(e.target)) {
|
||||
setTimeout(onClose)
|
||||
}
|
||||
}
|
||||
@@ -16,13 +22,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
let element: HTMLElement
|
||||
let element: HTMLElement | undefined = $state()
|
||||
</script>
|
||||
|
||||
<svelte:window on:mouseup={onMouseUp} on:keydown={onKeyDown} />
|
||||
<svelte:window onmouseup={onMouseUp} onkeydown={onKeyDown} />
|
||||
|
||||
<div class="relative w-full" bind:this={element}>
|
||||
<div transition:fly|local class="absolute z-popover w-full">
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,18 +2,15 @@
|
||||
import {page} from "$app/stores"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
|
||||
export let title = ""
|
||||
export let href = ""
|
||||
export let prefix = ""
|
||||
export let notification = false
|
||||
let {title = "", href = "", prefix = "", notification = false, ...restProps} = $props()
|
||||
|
||||
$: active = $page.url?.pathname?.startsWith(prefix || href || "bogus")
|
||||
const active = $derived($page.url?.pathname?.startsWith(prefix || href || "bogus"))
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a {href} class="relative z-nav-item flex h-14 w-14 items-center justify-center">
|
||||
<div
|
||||
class="avatar cursor-pointer rounded-full p-1 {$$props.class} transition-colors hover:bg-base-300"
|
||||
class="avatar cursor-pointer rounded-full p-1 {restProps.class} transition-colors hover:bg-base-300"
|
||||
class:bg-base-300={active}
|
||||
class:tooltip={title}
|
||||
data-tip={title}>
|
||||
@@ -26,7 +23,7 @@
|
||||
{:else}
|
||||
<Button on:click class="relative z-nav-item flex h-14 w-14 items-center justify-center">
|
||||
<div
|
||||
class="avatar cursor-pointer rounded-full p-1 {$$props.class} transition-colors hover:bg-base-300"
|
||||
class="avatar cursor-pointer rounded-full p-1 {restProps.class} transition-colors hover:bg-base-300"
|
||||
class:bg-base-300={active}
|
||||
class:tooltip={title}
|
||||
data-tip={title}>
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Tippy from "@lib/components/Tippy.svelte"
|
||||
|
||||
export let value: string
|
||||
export let options: string[] = []
|
||||
export let allowCreate = false
|
||||
interface Props {
|
||||
value: string
|
||||
options: string[]
|
||||
allowCreate?: boolean
|
||||
}
|
||||
|
||||
let input: Element
|
||||
let popover: Instance
|
||||
let instance: any
|
||||
let {value, options, allowCreate = false, ...restProps} = $props()
|
||||
let input: Element | undefined = $state()
|
||||
let popover: Instance | undefined = $state()
|
||||
let instance: any = $state()
|
||||
|
||||
const search = readable(
|
||||
createSearch(options, {
|
||||
@@ -23,26 +26,26 @@
|
||||
)
|
||||
|
||||
const select = (newValue: string) => {
|
||||
popover.hide()
|
||||
popover?.hide()
|
||||
value = newValue
|
||||
}
|
||||
|
||||
const onKeyDown = (e: Event) => {
|
||||
if (instance.onKeyDown(e)) {
|
||||
if (instance?.onKeyDown(e)) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
|
||||
const onFocus = () => {
|
||||
popover.show()
|
||||
popover?.show()
|
||||
}
|
||||
|
||||
const onBlur = () => {
|
||||
popover.hide()
|
||||
popover?.hide()
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class={$$props.class}>
|
||||
<div class={restProps.class}>
|
||||
<label class="input input-bordered flex w-full items-center gap-3" bind:this={input}>
|
||||
<slot name="before" />
|
||||
<input
|
||||
@@ -71,6 +74,6 @@
|
||||
trigger: "manual",
|
||||
interactive: true,
|
||||
maxWidth: "none",
|
||||
getReferenceClientRect: () => input.getBoundingClientRect(),
|
||||
getReferenceClientRect: () => input!.getBoundingClientRect(),
|
||||
}} />
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {children}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="sail sait saib hidden max-h-screen w-60 flex-shrink-0 flex-col gap-1 bg-base-300 md:flex">
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {children}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="flex items-center justify-between px-4 py-2 text-sm font-bold uppercase">
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</div>
|
||||
|
||||
@@ -21,25 +21,20 @@
|
||||
</style>
|
||||
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {fade} from "@lib/transition"
|
||||
import {page} from "$app/stores"
|
||||
|
||||
export let href: string = ""
|
||||
export let notification = false
|
||||
let {href = "", notification = "false", ...restProps} = $props()
|
||||
|
||||
$: active = $page.url.pathname === href
|
||||
const active = $derived($page.url.pathname === href)
|
||||
</script>
|
||||
|
||||
{#if href}
|
||||
<a
|
||||
{...$$props}
|
||||
{...restProps}
|
||||
{href}
|
||||
on:click
|
||||
class={cx(
|
||||
$$props.class,
|
||||
"relative flex items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content",
|
||||
)}
|
||||
class="{restProps.class} relative flex items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content"
|
||||
class:text-base-content={active}
|
||||
class:bg-base-100={active}>
|
||||
<slot />
|
||||
@@ -49,12 +44,9 @@
|
||||
</a>
|
||||
{:else}
|
||||
<button
|
||||
{...$$props}
|
||||
{...restProps}
|
||||
on:click
|
||||
class={cx(
|
||||
$$props.class,
|
||||
"relative flex w-full items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content",
|
||||
)}
|
||||
class="{restProps.class} relative flex w-full items-center gap-3 text-left transition-all hover:bg-base-100 hover:text-base-content"
|
||||
class:text-base-content={active}
|
||||
class:bg-base-100={active}>
|
||||
{#if !active && notification}
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
<div class="flex flex-col gap-1 px-2 py-4 {$$props.class}">
|
||||
<slot />
|
||||
<script lang="ts">
|
||||
interface Props {
|
||||
children?: import("svelte").Snippet
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
let {...props}: Props = $props()
|
||||
</script>
|
||||
|
||||
<div class="flex flex-col gap-1 px-2 py-4 {props.class}">
|
||||
{@render props.children?.()}
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
<script lang="ts">
|
||||
import {slide, fade} from "svelte/transition"
|
||||
|
||||
export let loading = false
|
||||
interface Props {
|
||||
loading?: boolean
|
||||
children?: import("svelte").Snippet
|
||||
}
|
||||
|
||||
let {loading = false, children}: Props = $props()
|
||||
</script>
|
||||
|
||||
<span class="flex min-h-10 items-center">
|
||||
@@ -10,5 +15,5 @@
|
||||
<span class="loading loading-spinner" transition:fade|local={{duration: 100}}></span>
|
||||
</span>
|
||||
{/if}
|
||||
<slot />
|
||||
{@render children?.()}
|
||||
</span>
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
return () => {
|
||||
popover?.destroy()
|
||||
unmount(instance)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
@@ -16,17 +16,21 @@
|
||||
<script lang="ts">
|
||||
import {clamp} from "@welshman/lib"
|
||||
|
||||
export let score
|
||||
export let max = 100
|
||||
export let active = false
|
||||
interface Props {
|
||||
score: any
|
||||
max?: number
|
||||
active?: boolean
|
||||
}
|
||||
|
||||
let {score, max = 100, active = false}: Props = $props()
|
||||
|
||||
const radius = 6
|
||||
const center = radius + 1
|
||||
|
||||
$: normalizedScore = clamp([0, max], score) / max
|
||||
$: dashOffset = 100 - 44 * normalizedScore
|
||||
$: style = `transform: rotate(${135 - normalizedScore * 180}deg)`
|
||||
$: stroke = active ? "var(--primary)" : "var(--base-content)"
|
||||
let normalizedScore = $derived(clamp([0, max], score) / max)
|
||||
let dashOffset = $derived(100 - 44 * normalizedScore)
|
||||
let style = $derived(`transform: rotate(${135 - normalizedScore * 180}deg)`)
|
||||
let stroke = $derived(active ? "var(--primary)" : "var(--base-content)")
|
||||
</script>
|
||||
|
||||
<div class="relative h-[14px] w-[14px]">
|
||||
|
||||
Reference in New Issue
Block a user