update links page to use combobox to filter shorteners

pull/3/head
TZGyn 2 years ago
parent d3b3f56e50
commit 22032dcff5
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

Binary file not shown.

@ -35,8 +35,9 @@
"@types/he": "^1.2.3",
"apexcharts": "^3.44.0",
"argon2": "^0.31.2",
"bits-ui": "^0.9.8",
"bits-ui": "^0.18.2",
"clsx": "^2.0.0",
"cmdk-sv": "^0.0.13",
"drizzle-orm": "^0.29.0",
"formsnap": "^0.4.1",
"he": "^1.2.0",

@ -0,0 +1,23 @@
<script lang="ts">
import Command from "./command.svelte";
import * as Dialog from "$lib/components/ui/dialog";
import type { Dialog as DialogPrimitive } from "bits-ui";
import type { Command as CommandPrimitive } from "cmdk-sv";
type $$Props = DialogPrimitive.Props & CommandPrimitive.CommandProps;
export let open: $$Props["open"] = false;
export let value: $$Props["value"] = undefined;
</script>
<Dialog.Root bind:open {...$$restProps}>
<Dialog.Content class="overflow-hidden p-0 shadow-lg">
<Command
class="[&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:font-medium [&_[data-cmdk-group-heading]]:text-muted-foreground [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 [&_[data-cmdk-group]]:px-2 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 [&_[data-cmdk-input]]:h-12 [&_[data-cmdk-item]]:px-2 [&_[data-cmdk-item]]:py-3 [&_[data-cmdk-item]_svg]:h-5 [&_[data-cmdk-item]_svg]:w-5"
{...$$restProps}
bind:value
>
<slot />
</Command>
</Dialog.Content>
</Dialog.Root>

@ -0,0 +1,12 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.EmptyProps;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.Empty class={cn("py-6 text-center text-sm", className)} {...$$restProps}>
<slot />
</CommandPrimitive.Empty>

@ -0,0 +1,18 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.GroupProps;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.Group
class={cn(
"overflow-hidden p-1 text-foreground [&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:py-1.5 [&_[data-cmdk-group-heading]]:text-xs [&_[data-cmdk-group-heading]]:font-medium [&_[data-cmdk-group-heading]]:text-muted-foreground",
className
)}
{...$$restProps}
>
<slot />
</CommandPrimitive.Group>

@ -0,0 +1,23 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import Search from "lucide-svelte/icons/search";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.InputProps;
let className: string | undefined | null = undefined;
export { className as class };
export let value: string = "";
</script>
<div class="flex items-center border-b px-2" data-cmdk-input-wrapper="">
<Search class="mr-2 h-4 w-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
class={cn(
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...$$restProps}
bind:value
/>
</div>

@ -0,0 +1,24 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.ItemProps;
export let asChild = false;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.Item
{asChild}
class={cn(
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
className
)}
{...$$restProps}
let:action
let:attrs
>
<slot {action} {attrs} />
</CommandPrimitive.Item>

@ -0,0 +1,15 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.ListProps;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.List
class={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
{...$$restProps}
>
<slot />
</CommandPrimitive.List>

@ -0,0 +1,10 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.SeparatorProps;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.Separator class={cn("-mx-1 h-px bg-border", className)} {...$$restProps} />

@ -0,0 +1,16 @@
<script lang="ts">
import { cn } from "$lib/utils";
import type { HTMLAttributes } from "svelte/elements";
type $$Props = HTMLAttributes<HTMLSpanElement>;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<span
class={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)}
{...$$restProps}
>
<slot />
</span>

@ -0,0 +1,22 @@
<script lang="ts">
import { Command as CommandPrimitive } from "cmdk-sv";
import { cn } from "$lib/utils";
type $$Props = CommandPrimitive.CommandProps;
export let value: $$Props["value"] = undefined;
let className: string | undefined | null = undefined;
export { className as class };
</script>
<CommandPrimitive.Root
class={cn(
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
className
)}
bind:value
{...$$restProps}
>
<slot />
</CommandPrimitive.Root>

@ -0,0 +1,37 @@
import { Command as CommandPrimitive } from "cmdk-sv";
import Root from "./command.svelte";
import Dialog from "./command-dialog.svelte";
import Empty from "./command-empty.svelte";
import Group from "./command-group.svelte";
import Item from "./command-item.svelte";
import Input from "./command-input.svelte";
import List from "./command-list.svelte";
import Separator from "./command-separator.svelte";
import Shortcut from "./command-shortcut.svelte";
const Loading = CommandPrimitive.Loading;
export {
Root,
Dialog,
Empty,
Group,
Item,
Input,
List,
Separator,
Shortcut,
Loading,
//
Root as Command,
Dialog as CommandDialog,
Empty as CommandEmpty,
Group as CommandGroup,
Item as CommandItem,
Input as CommandInput,
List as CommandList,
Separator as CommandSeparator,
Shortcut as CommandShortcut,
Loading as CommandLoading,
};

@ -0,0 +1,14 @@
import { Popover as PopoverPrimitive } from "bits-ui";
import Content from "./popover-content.svelte";
const Root = PopoverPrimitive.Root;
const Trigger = PopoverPrimitive.Trigger;
export {
Root,
Content,
Trigger,
//
Root as Popover,
Content as PopoverContent,
Trigger as PopoverTrigger,
};

@ -0,0 +1,22 @@
<script lang="ts">
import { Popover as PopoverPrimitive } from "bits-ui";
import { cn, flyAndScale } from "$lib/utils";
type $$Props = PopoverPrimitive.ContentProps;
let className: $$Props["class"] = undefined;
export let transition: $$Props["transition"] = flyAndScale;
export let transitionConfig: $$Props["transitionConfig"] = undefined;
export { className as class };
</script>
<PopoverPrimitive.Content
{transition}
{transitionConfig}
class={cn(
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
className
)}
{...$$restProps}
>
<slot />
</PopoverPrimitive.Content>

@ -9,7 +9,7 @@ export const load = (async (event) => {
let project_id: number | undefined
let selected_project: { value: null | string; label: string } = {
value: null,
label: 'None',
label: 'All',
}
if (project_uuid) {

@ -6,6 +6,8 @@
import * as Card from '$lib/components/ui/card'
import * as DropdownMenu from '$lib/components/ui/dropdown-menu'
import * as Select from '$lib/components/ui/select'
import * as Command from '$lib/components/ui/command'
import * as Popover from '$lib/components/ui/popover'
import { Input } from '$lib/components/ui/input'
import { Label } from '$lib/components/ui/label'
import { Badge } from '$lib/components/ui/badge'
@ -15,15 +17,16 @@
Loader2,
MoreVertical,
QrCode,
Check,
ChevronsUpDown,
} from 'lucide-svelte'
import { goto, invalidateAll } from '$app/navigation'
import { cn } from '$lib/utils'
import Qr from '$lib/components/QR.svelte'
import AddShortenerDialog from './(component)/AddShortenerDialog.svelte'
export let data: PageData
let selectedProject: any = data.selected_project
let dialogOpen = false
let editDialogOpen = false
@ -32,6 +35,11 @@
let editShortenerCategory: any = undefined
let isEditLoading = false
let open: boolean = false
let selectedProject: any = data.selected_project.label
$: selectedProject = data.selected_project.label
const openEditDialog = (code: string, link: string) => {
editDialogOpen = true
editShortenerCode = code
@ -82,26 +90,51 @@
<Separator />
<div class="p-4">
<Select.Root portal={null} bind:selected={selectedProject}>
<Select.Trigger class="w-[180px]">
<Select.Value placeholder="Select a project" />
</Select.Trigger>
<Select.Content>
<Select.Group>
<Select.Label>Project</Select.Label>
<a href={`/links`}>
<Select.Item value={null} label={'None'}>None</Select.Item>
</a>
{#each data.projects as project}
<a href={`/links?project=${project.uuid}`}>
<Select.Item value={project.uuid} label={project.name}
>{project.name}</Select.Item>
<Popover.Root bind:open>
<Popover.Trigger asChild let:builder>
<Button
builders={[builder]}
variant="outline"
role="combobox"
aria-expanded={open}
class="w-[200px] justify-between">
{selectedProject}
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
</Button>
</Popover.Trigger>
<Popover.Content class="w-[200px] p-0">
<Command.Root>
<Command.Input placeholder="Search project..." />
<Command.Empty>No project found.</Command.Empty>
<Command.Group>
<a href={`/links`}>
<Command.Item onSelect={() => (open = false)}>
<Check
class={cn(
'mr-2 h-4 w-4',
data.selected_project.value !== null &&
'text-transparent',
)} />
All
</Command.Item>
</a>
{/each}
</Select.Group>
</Select.Content>
<Select.Input name="favoriteFruit" />
</Select.Root>
{#each data.projects as project}
<a href={`/links?project=${project.uuid}`}>
<Command.Item onSelect={() => (open = false)}>
<Check
class={cn(
'mr-2 h-4 w-4',
data.selected_project.value !== project.uuid &&
'text-transparent',
)} />
{project.name}
</Command.Item>
</a>
{/each}
</Command.Group>
</Command.Root>
</Popover.Content>
</Popover.Root>
</div>
{#if data.shorteners.length > 0}

Loading…
Cancel
Save