dialog thingy yay
This commit is contained in:
parent
9bc1b3766c
commit
fff9f56fea
7 changed files with 115 additions and 15 deletions
|
|
@ -315,16 +315,15 @@
|
|||
}
|
||||
|
||||
.modal-box {
|
||||
@apply col-start-1 row-start-1 max-h-screen w-11/12 max-w-[32rem] bg-neutral-100 p-6;
|
||||
@apply bg-background border-border col-start-1 row-start-1 max-h-screen w-11/12 max-w-[32rem] p-6;
|
||||
transition:
|
||||
translate 0.3s ease-out,
|
||||
scale 0.3s ease-out,
|
||||
opacity 0.2s ease-out 0.05s,
|
||||
box-shadow 0.3s ease-out;
|
||||
border-top-left-radius: var(--modal-tl, var(--radius-box));
|
||||
border-top-right-radius: var(--modal-tr, var(--radius-box));
|
||||
border-bottom-left-radius: var(--modal-bl, var(--radius-box));
|
||||
border-bottom-right-radius: var(--modal-br, var(--radius-box));
|
||||
|
||||
border-radius: var(--radius);
|
||||
|
||||
scale: 95%;
|
||||
opacity: 0;
|
||||
box-shadow: oklch(0% 0 0/ 0.25) 0px 25px 50px -12px;
|
||||
|
|
|
|||
56
src/lib/components/ui/modal/global-modal.svelte
Normal file
56
src/lib/components/ui/modal/global-modal.svelte
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<script lang="ts" module>
|
||||
import type { ButtonVariant } from '../button';
|
||||
|
||||
// We can extend the generics to include form fields if needed
|
||||
type CallModalArgs<Action extends string> = {
|
||||
title: string;
|
||||
description: string;
|
||||
actions?: Record<Action, ButtonVariant>;
|
||||
};
|
||||
|
||||
let modalArgs = $state(null) as null | CallModalArgs<string>;
|
||||
let resolve: (v: string | null) => void;
|
||||
|
||||
export function callModal<Action extends string>(
|
||||
args: CallModalArgs<Action>
|
||||
): Promise<Action | null> {
|
||||
modalArgs = args;
|
||||
|
||||
return new Promise<Action | null>((res) => {
|
||||
resolve = res as (v: string | null) => void;
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import Button from '../button/button.svelte';
|
||||
import Modal from './modal.svelte';
|
||||
|
||||
let open = $derived(!!modalArgs);
|
||||
</script>
|
||||
|
||||
<Modal
|
||||
bind:open={
|
||||
() => open,
|
||||
(v) => {
|
||||
if (v) return;
|
||||
open = false;
|
||||
setTimeout(() => (modalArgs = null), 200);
|
||||
resolve?.(null);
|
||||
}
|
||||
}
|
||||
>
|
||||
<h3 class="text-lg font-bold">{modalArgs?.title}</h3>
|
||||
<p class="py-4">{modalArgs?.description}</p>
|
||||
{#if modalArgs?.actions}
|
||||
<div class="modal-action">
|
||||
{#each Object.entries(modalArgs.actions) as [action, variant] (action)}
|
||||
<form method="dialog" onsubmit={() => resolve(action)}>
|
||||
<Button {variant} type="submit" class="capitalize">
|
||||
{action}
|
||||
</Button>
|
||||
</form>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</Modal>
|
||||
|
|
@ -21,15 +21,12 @@
|
|||
</script>
|
||||
|
||||
<dialog class="modal" bind:this={dialog} onclose={() => (open = false)}>
|
||||
<div class="modal-body" {@attach clickOutside(() => (open = false))}>
|
||||
<h3 class="text-lg font-bold">Hello!</h3>
|
||||
<p class="py-4">Press ESC key or click the button below to close</p>
|
||||
<div
|
||||
class="modal-box"
|
||||
{@attach clickOutside(() => {
|
||||
if (open) open = false;
|
||||
})}
|
||||
>
|
||||
{@render children()}
|
||||
<div class="modal-action">
|
||||
<form method="dialog">
|
||||
<!-- if there is a button in form, it will close the modal -->
|
||||
<button class="btn">Close</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
|
|
|
|||
|
|
@ -20,3 +20,39 @@ export function pick<T extends object, K extends keyof T>(obj: T, keys: K[]): Pi
|
|||
K
|
||||
>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an object into a new object by applying a mapping function
|
||||
* to each of its key-value pairs.
|
||||
*
|
||||
* @template KIn The type of the keys in the input object.
|
||||
* @template VIn The type of the values in the input object.
|
||||
* @template KOut The type of the keys in the output object.
|
||||
* @template VOut The type of the values in the output object.
|
||||
*
|
||||
* @param obj The input object to transform.
|
||||
* @param mapper A function that takes a key and its value from the input object
|
||||
* and returns a tuple `[KOut, VOut]` representing the new key
|
||||
* and new value for the output object.
|
||||
* @returns A new object with the transformed keys and values.
|
||||
*/
|
||||
export function objectMap<
|
||||
KIn extends string | number | symbol,
|
||||
VIn,
|
||||
KOut extends string | number | symbol,
|
||||
VOut,
|
||||
>(obj: Record<KIn, VIn>, mapper: (key: KIn, value: VIn) => [KOut, VOut]): Record<KOut, VOut> {
|
||||
const result: Record<KOut, VOut> = {} as Record<KOut, VOut>;
|
||||
|
||||
for (const rawKey in obj) {
|
||||
// Ensure we only process own properties (not inherited ones)
|
||||
if (Object.prototype.hasOwnProperty.call(obj, rawKey)) {
|
||||
const key = rawKey as KIn; // Cast to KIn as rawKey is initially string
|
||||
const value = obj[key];
|
||||
const [newKey, newValue] = mapper(key, value);
|
||||
result[newKey] = newValue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
import { ModeWatcher } from 'mode-watcher';
|
||||
import { PUBLIC_CONVEX_URL } from '$env/static/public';
|
||||
import { models } from '$lib/state/models.svelte';
|
||||
import GlobalModal from '$lib/components/ui/modal/global-modal.svelte';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
|
|
@ -13,3 +14,5 @@
|
|||
|
||||
<ModeWatcher />
|
||||
{@render children()}
|
||||
|
||||
<GlobalModal />
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
import { LocalToasts } from '$lib/builders/local-toasts.svelte';
|
||||
import { ResultAsync } from 'neverthrow';
|
||||
import TrashIcon from '~icons/lucide/trash';
|
||||
import { callModal } from '$lib/components/ui/modal/global-modal.svelte';
|
||||
|
||||
type Props = {
|
||||
rule: Doc<'user_rules'>;
|
||||
|
|
@ -57,6 +58,15 @@
|
|||
}
|
||||
|
||||
async function deleteRule() {
|
||||
const action = await callModal({
|
||||
title: 'Delete Rule',
|
||||
description: 'Are you sure you want to delete this rule?',
|
||||
actions: {
|
||||
delete: 'destructive',
|
||||
},
|
||||
});
|
||||
if (action !== 'delete') return;
|
||||
|
||||
deleting = true;
|
||||
|
||||
await client.mutation(api.user_rules.remove, {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
|
||||
async function toggleEnabled(v: boolean) {
|
||||
enabled = v; // Optimistic!
|
||||
console.log('hi');
|
||||
if (!session.current?.user.id) return;
|
||||
|
||||
const res = await ResultAsync.fromPromise(
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue