mirror of
https://github.com/emailerfacu-spec/minix-front.git
synced 2026-04-01 13:10:44 -03:00
el input de busqueda de usuarios
This commit is contained in:
10
bun.lock
10
bun.lock
@@ -8,13 +8,13 @@
|
|||||||
"mode-watcher": "^1.1.0",
|
"mode-watcher": "^1.1.0",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@internationalized/date": "^3.8.1",
|
"@internationalized/date": "^3.10.0",
|
||||||
"@lucide/svelte": "^0.544.0",
|
"@lucide/svelte": "^0.561.0",
|
||||||
"@sveltejs/adapter-vercel": "^6.0.0",
|
"@sveltejs/adapter-vercel": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.47.1",
|
"@sveltejs/kit": "^2.47.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"bits-ui": "^2.11.0",
|
"bits-ui": "^2.14.4",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"prettier": "^3.7.4",
|
"prettier": "^3.7.4",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "^3.4.0",
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
|
|
||||||
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
"@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="],
|
||||||
|
|
||||||
"@lucide/svelte": ["@lucide/svelte@0.544.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-9f9O6uxng2pLB01sxNySHduJN3HTl5p0HDu4H26VR51vhZfiMzyOMe9Mhof3XAk4l813eTtl+/DYRvGyoRR+yw=="],
|
"@lucide/svelte": ["@lucide/svelte@0.561.0", "", { "peerDependencies": { "svelte": "^5" } }, "sha512-vofKV2UFVrKE6I4ewKJ3dfCXSV6iP6nWVmiM83MLjsU91EeJcEg7LoWUABLp/aOTxj1HQNbJD1f3g3L0JQgH9A=="],
|
||||||
|
|
||||||
"@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg=="],
|
"@mapbox/node-pre-gyp": ["@mapbox/node-pre-gyp@2.0.0", "", { "dependencies": { "consola": "^3.2.3", "detect-libc": "^2.0.0", "https-proxy-agent": "^7.0.5", "node-fetch": "^2.6.7", "nopt": "^8.0.0", "semver": "^7.5.3", "tar": "^7.4.0" }, "bin": { "node-pre-gyp": "bin/node-pre-gyp" } }, "sha512-llMXd39jtP0HpQLVI37Bf1m2ADlEb35GYSh1SDSLsBhR+5iCxiNGlT31yqbNtVHygHAtMy6dWFERpU2JgufhPg=="],
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
|
|
||||||
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
"bindings": ["bindings@1.5.0", "", { "dependencies": { "file-uri-to-path": "1.0.0" } }, "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ=="],
|
||||||
|
|
||||||
"bits-ui": ["bits-ui@2.14.3", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-Dkpenu6F5WUfdDJn5D8ALkTaAM+7sUCszKjzav5TWAzsq1fj2tcqKYJcUm82OS+JlgcolI7LOkrqIXzKnt56RA=="],
|
"bits-ui": ["bits-ui@2.14.4", "", { "dependencies": { "@floating-ui/core": "^1.7.1", "@floating-ui/dom": "^1.7.1", "esm-env": "^1.1.2", "runed": "^0.35.1", "svelte-toolbelt": "^0.10.6", "tabbable": "^6.2.0" }, "peerDependencies": { "@internationalized/date": "^3.8.1", "svelte": "^5.33.0" } }, "sha512-W6kenhnbd/YVvur+DKkaVJ6GldE53eLewur5AhUCqslYQ0vjZr8eWlOfwZnMiPB+PF5HMVqf61vXBvmyrAmPWg=="],
|
||||||
|
|
||||||
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
"brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="],
|
||||||
|
|
||||||
|
|||||||
@@ -14,13 +14,13 @@
|
|||||||
"lint": "prettier --check ."
|
"lint": "prettier --check ."
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@internationalized/date": "^3.8.1",
|
"@internationalized/date": "^3.10.0",
|
||||||
"@lucide/svelte": "^0.544.0",
|
"@lucide/svelte": "^0.561.0",
|
||||||
"@sveltejs/adapter-vercel": "^6.0.0",
|
"@sveltejs/adapter-vercel": "^6.0.0",
|
||||||
"@sveltejs/kit": "^2.47.1",
|
"@sveltejs/kit": "^2.47.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
"@sveltejs/vite-plugin-svelte": "^6.2.1",
|
||||||
"@tailwindcss/vite": "^4.1.14",
|
"@tailwindcss/vite": "^4.1.14",
|
||||||
"bits-ui": "^2.11.0",
|
"bits-ui": "^2.14.4",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"prettier": "^3.7.4",
|
"prettier": "^3.7.4",
|
||||||
"prettier-plugin-svelte": "^3.4.0",
|
"prettier-plugin-svelte": "^3.4.0",
|
||||||
|
|||||||
40
src/lib/components/ui/command/command-dialog.svelte
Normal file
40
src/lib/components/ui/command/command-dialog.svelte
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import type { Command as CommandPrimitive, Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import type { Snippet } from "svelte";
|
||||||
|
import Command from "./command.svelte";
|
||||||
|
import * as Dialog from "$lib/components/ui/dialog/index.js";
|
||||||
|
import type { WithoutChildrenOrChild } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
open = $bindable(false),
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(""),
|
||||||
|
title = "Command Palette",
|
||||||
|
description = "Search for a command to run",
|
||||||
|
portalProps,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithoutChildrenOrChild<DialogPrimitive.RootProps> &
|
||||||
|
WithoutChildrenOrChild<CommandPrimitive.RootProps> & {
|
||||||
|
portalProps?: DialogPrimitive.PortalProps;
|
||||||
|
children: Snippet;
|
||||||
|
title?: string;
|
||||||
|
description?: string;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<Dialog.Root bind:open {...restProps}>
|
||||||
|
<Dialog.Header class="sr-only">
|
||||||
|
<Dialog.Title>{title}</Dialog.Title>
|
||||||
|
<Dialog.Description>{description}</Dialog.Description>
|
||||||
|
</Dialog.Header>
|
||||||
|
<Dialog.Content class="overflow-hidden p-0" {portalProps}>
|
||||||
|
<Command
|
||||||
|
class="**:data-[slot=command-input-wrapper]:h-12 [&_[data-command-group]]:px-2 [&_[data-command-group]:not([hidden])_~[data-command-group]]:pt-0 [&_[data-command-input-wrapper]_svg]:h-5 [&_[data-command-input-wrapper]_svg]:w-5 [&_[data-command-input]]:h-12 [&_[data-command-item]]:px-2 [&_[data-command-item]]:py-3 [&_[data-command-item]_svg]:h-5 [&_[data-command-item]_svg]:w-5"
|
||||||
|
{...restProps}
|
||||||
|
bind:value
|
||||||
|
bind:ref
|
||||||
|
{children}
|
||||||
|
/>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Root>
|
||||||
17
src/lib/components/ui/command/command-empty.svelte
Normal file
17
src/lib/components/ui/command/command-empty.svelte
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.EmptyProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Empty
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-empty"
|
||||||
|
class={cn("py-6 text-center text-sm", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
32
src/lib/components/ui/command/command-group.svelte
Normal file
32
src/lib/components/ui/command/command-group.svelte
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive, useId } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
heading,
|
||||||
|
value,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.GroupProps & {
|
||||||
|
heading?: string;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Group
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-group"
|
||||||
|
class={cn("text-foreground overflow-hidden p-1", className)}
|
||||||
|
value={value ?? heading ?? `----${useId()}`}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{#if heading}
|
||||||
|
<CommandPrimitive.GroupHeading
|
||||||
|
class="text-muted-foreground px-2 py-1.5 text-xs font-medium"
|
||||||
|
>
|
||||||
|
{heading}
|
||||||
|
</CommandPrimitive.GroupHeading>
|
||||||
|
{/if}
|
||||||
|
<CommandPrimitive.GroupItems {children} />
|
||||||
|
</CommandPrimitive.Group>
|
||||||
26
src/lib/components/ui/command/command-input.svelte
Normal file
26
src/lib/components/ui/command/command-input.svelte
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import SearchIcon from "@lucide/svelte/icons/search";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
value = $bindable(""),
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.InputProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex h-9 items-center gap-2 border-b ps-3 pe-8" data-slot="command-input-wrapper">
|
||||||
|
<SearchIcon class="size-4 shrink-0 opacity-50" />
|
||||||
|
<CommandPrimitive.Input
|
||||||
|
data-slot="command-input"
|
||||||
|
class={cn(
|
||||||
|
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
bind:ref
|
||||||
|
{...restProps}
|
||||||
|
bind:value
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
20
src/lib/components/ui/command/command-item.svelte
Normal file
20
src/lib/components/ui/command/command-item.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.ItemProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Item
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-item"
|
||||||
|
class={cn(
|
||||||
|
"aria-selected:bg-accent aria-selected:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
20
src/lib/components/ui/command/command-link-item.svelte
Normal file
20
src/lib/components/ui/command/command-link-item.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.LinkItemProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.LinkItem
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-item"
|
||||||
|
class={cn(
|
||||||
|
"aria-selected:bg-accent aria-selected:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
17
src/lib/components/ui/command/command-list.svelte
Normal file
17
src/lib/components/ui/command/command-list.svelte
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.ListProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.List
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-list"
|
||||||
|
class={cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
7
src/lib/components/ui/command/command-loading.svelte
Normal file
7
src/lib/components/ui/command/command-loading.svelte
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let { ref = $bindable(null), ...restProps }: CommandPrimitive.LoadingProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Loading bind:ref {...restProps} />
|
||||||
17
src/lib/components/ui/command/command-separator.svelte
Normal file
17
src/lib/components/ui/command/command-separator.svelte
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.SeparatorProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Separator
|
||||||
|
bind:ref
|
||||||
|
data-slot="command-separator"
|
||||||
|
class={cn("bg-border -mx-1 h-px", className)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
20
src/lib/components/ui/command/command-shortcut.svelte
Normal file
20
src/lib/components/ui/command/command-shortcut.svelte
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn, type WithElementRef } from "$lib/utils.js";
|
||||||
|
import type { HTMLAttributes } from "svelte/elements";
|
||||||
|
|
||||||
|
let {
|
||||||
|
ref = $bindable(null),
|
||||||
|
class: className,
|
||||||
|
children,
|
||||||
|
...restProps
|
||||||
|
}: WithElementRef<HTMLAttributes<HTMLSpanElement>> = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<span
|
||||||
|
bind:this={ref}
|
||||||
|
data-slot="command-shortcut"
|
||||||
|
class={cn("text-muted-foreground ms-auto text-xs tracking-widest", className)}
|
||||||
|
{...restProps}
|
||||||
|
>
|
||||||
|
{@render children?.()}
|
||||||
|
</span>
|
||||||
28
src/lib/components/ui/command/command.svelte
Normal file
28
src/lib/components/ui/command/command.svelte
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { cn } from "$lib/utils.js";
|
||||||
|
import { Command as CommandPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
export type CommandRootApi = CommandPrimitive.Root;
|
||||||
|
|
||||||
|
let {
|
||||||
|
api = $bindable(null),
|
||||||
|
ref = $bindable(null),
|
||||||
|
value = $bindable(""),
|
||||||
|
class: className,
|
||||||
|
...restProps
|
||||||
|
}: CommandPrimitive.RootProps & {
|
||||||
|
api?: CommandRootApi | null;
|
||||||
|
} = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<CommandPrimitive.Root
|
||||||
|
bind:this={api}
|
||||||
|
bind:value
|
||||||
|
bind:ref
|
||||||
|
data-slot="command"
|
||||||
|
class={cn(
|
||||||
|
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
37
src/lib/components/ui/command/index.ts
Normal file
37
src/lib/components/ui/command/index.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import Root from "./command.svelte";
|
||||||
|
import Loading from "./command-loading.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";
|
||||||
|
import LinkItem from "./command-link-item.svelte";
|
||||||
|
|
||||||
|
export {
|
||||||
|
Root,
|
||||||
|
Dialog,
|
||||||
|
Empty,
|
||||||
|
Group,
|
||||||
|
Item,
|
||||||
|
LinkItem,
|
||||||
|
Input,
|
||||||
|
List,
|
||||||
|
Separator,
|
||||||
|
Shortcut,
|
||||||
|
Loading,
|
||||||
|
//
|
||||||
|
Root as Command,
|
||||||
|
Dialog as CommandDialog,
|
||||||
|
Empty as CommandEmpty,
|
||||||
|
Group as CommandGroup,
|
||||||
|
Item as CommandItem,
|
||||||
|
LinkItem as CommandLinkItem,
|
||||||
|
Input as CommandInput,
|
||||||
|
List as CommandList,
|
||||||
|
Separator as CommandSeparator,
|
||||||
|
Shortcut as CommandShortcut,
|
||||||
|
Loading as CommandLoading,
|
||||||
|
};
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
import DialogPortal from "./dialog-portal.svelte";
|
||||||
import XIcon from "@lucide/svelte/icons/x";
|
import XIcon from "@lucide/svelte/icons/x";
|
||||||
import type { Snippet } from "svelte";
|
import type { Snippet } from "svelte";
|
||||||
import * as Dialog from "./index.js";
|
import * as Dialog from "./index.js";
|
||||||
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
import { cn, type WithoutChildrenOrChild } from "$lib/utils.js";
|
||||||
|
import type { ComponentProps } from "svelte";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
ref = $bindable(null),
|
ref = $bindable(null),
|
||||||
@@ -13,19 +15,19 @@
|
|||||||
showCloseButton = true,
|
showCloseButton = true,
|
||||||
...restProps
|
...restProps
|
||||||
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
|
||||||
portalProps?: DialogPrimitive.PortalProps;
|
portalProps?: WithoutChildrenOrChild<ComponentProps<typeof DialogPortal>>;
|
||||||
children: Snippet;
|
children: Snippet;
|
||||||
showCloseButton?: boolean;
|
showCloseButton?: boolean;
|
||||||
} = $props();
|
} = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Dialog.Portal {...portalProps}>
|
<DialogPortal {...portalProps}>
|
||||||
<Dialog.Overlay />
|
<Dialog.Overlay />
|
||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-content"
|
data-slot="dialog-content"
|
||||||
class={cn(
|
class={cn(
|
||||||
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed start-[50%] top-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
@@ -33,11 +35,11 @@
|
|||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
{#if showCloseButton}
|
{#if showCloseButton}
|
||||||
<DialogPrimitive.Close
|
<DialogPrimitive.Close
|
||||||
class="ring-offset-background focus:ring-ring rounded-xs focus:outline-hidden absolute end-4 top-4 opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0"
|
class="ring-offset-background focus:ring-ring absolute end-4 top-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
||||||
>
|
>
|
||||||
<XIcon />
|
<XIcon />
|
||||||
<span class="sr-only">Close</span>
|
<span class="sr-only">Close</span>
|
||||||
</DialogPrimitive.Close>
|
</DialogPrimitive.Close>
|
||||||
{/if}
|
{/if}
|
||||||
</DialogPrimitive.Content>
|
</DialogPrimitive.Content>
|
||||||
</Dialog.Portal>
|
</DialogPortal>
|
||||||
|
|||||||
7
src/lib/components/ui/dialog/dialog-portal.svelte
Normal file
7
src/lib/components/ui/dialog/dialog-portal.svelte
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let { ...restProps }: DialogPrimitive.PortalProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Portal {...restProps} />
|
||||||
@@ -12,6 +12,6 @@
|
|||||||
<DialogPrimitive.Title
|
<DialogPrimitive.Title
|
||||||
bind:ref
|
bind:ref
|
||||||
data-slot="dialog-title"
|
data-slot="dialog-title"
|
||||||
class={cn("text-lg font-semibold leading-none", className)}
|
class={cn("text-lg leading-none font-semibold", className)}
|
||||||
{...restProps}
|
{...restProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
7
src/lib/components/ui/dialog/dialog.svelte
Normal file
7
src/lib/components/ui/dialog/dialog.svelte
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { Dialog as DialogPrimitive } from "bits-ui";
|
||||||
|
|
||||||
|
let { open = $bindable(false), ...restProps }: DialogPrimitive.RootProps = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<DialogPrimitive.Root bind:open {...restProps} />
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Dialog as DialogPrimitive } from "bits-ui";
|
import Root from "./dialog.svelte";
|
||||||
|
import Portal from "./dialog-portal.svelte";
|
||||||
import Title from "./dialog-title.svelte";
|
import Title from "./dialog-title.svelte";
|
||||||
import Footer from "./dialog-footer.svelte";
|
import Footer from "./dialog-footer.svelte";
|
||||||
import Header from "./dialog-header.svelte";
|
import Header from "./dialog-header.svelte";
|
||||||
@@ -9,9 +9,6 @@ import Description from "./dialog-description.svelte";
|
|||||||
import Trigger from "./dialog-trigger.svelte";
|
import Trigger from "./dialog-trigger.svelte";
|
||||||
import Close from "./dialog-close.svelte";
|
import Close from "./dialog-close.svelte";
|
||||||
|
|
||||||
const Root = DialogPrimitive.Root;
|
|
||||||
const Portal = DialogPrimitive.Portal;
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
Title,
|
Title,
|
||||||
|
|||||||
112
src/lib/head/Busqueda.svelte
Normal file
112
src/lib/head/Busqueda.svelte
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import CommandDialog from '@/components/ui/command/command-dialog.svelte';
|
||||||
|
import CommandGroup from '@/components/ui/command/command-group.svelte';
|
||||||
|
import CommandInput from '@/components/ui/command/command-input.svelte';
|
||||||
|
import CommandItem from '@/components/ui/command/command-item.svelte';
|
||||||
|
import CommandList from '@/components/ui/command/command-list.svelte';
|
||||||
|
import InputGroupAddon from '@/components/ui/input-group/input-group-addon.svelte';
|
||||||
|
import InputGroupInput from '@/components/ui/input-group/input-group-input.svelte';
|
||||||
|
import InputGroup from '@/components/ui/input-group/input-group.svelte';
|
||||||
|
import Kbd from '@/components/ui/kbd/kbd.svelte';
|
||||||
|
import Search from '@lucide/svelte/icons/search';
|
||||||
|
import User from '@lucide/svelte/icons/user';
|
||||||
|
import Hash from '@lucide/svelte/icons/hash';
|
||||||
|
import Spinner from '@/components/ui/spinner/spinner.svelte';
|
||||||
|
import { busquedaUsuarios } from '@/hooks/busquedaUsuarios';
|
||||||
|
import type { UserResponseDto } from '../../types';
|
||||||
|
import Avatar from '@/components/ui/avatar/avatar.svelte';
|
||||||
|
import AvatarImage from '@/components/ui/avatar/avatar-image.svelte';
|
||||||
|
import Label from '@/components/ui/label/label.svelte';
|
||||||
|
import { resolve } from '$app/paths';
|
||||||
|
|
||||||
|
let search: string = $state('');
|
||||||
|
let open = $state(false);
|
||||||
|
|
||||||
|
let usuarios: UserResponseDto[] = $state([]);
|
||||||
|
let loading = $state(false);
|
||||||
|
|
||||||
|
let hashtags: Promise<any[]> | undefined = $state();
|
||||||
|
|
||||||
|
function handleKeydown(e: KeyboardEvent) {
|
||||||
|
if (e.key === 'k' && (e.metaKey || e.ctrlKey)) {
|
||||||
|
e.preventDefault();
|
||||||
|
open = !open;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$inspect(usuarios, loading);
|
||||||
|
|
||||||
|
let timeoutId: number | undefined;
|
||||||
|
function buscar() {
|
||||||
|
loading = true;
|
||||||
|
if (timeoutId) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutId = setTimeout(async () => {
|
||||||
|
usuarios = await busquedaUsuarios(search);
|
||||||
|
loading = false;
|
||||||
|
}, 200);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (timeoutId) clearTimeout(timeoutId);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:document onkeydown={handleKeydown} />
|
||||||
|
|
||||||
|
<InputGroup>
|
||||||
|
<InputGroupAddon align="inline-start"><Search /></InputGroupAddon>
|
||||||
|
<InputGroupInput
|
||||||
|
type="text"
|
||||||
|
placeholder="Buscar Usuario o Hashtag"
|
||||||
|
bind:value={search}
|
||||||
|
oninput={() => (open = true)}
|
||||||
|
/>
|
||||||
|
<InputGroupAddon align="inline-end" class="flex gap-0">
|
||||||
|
<Kbd>Ctrl</Kbd>+<Kbd>K</Kbd>
|
||||||
|
</InputGroupAddon>
|
||||||
|
</InputGroup>
|
||||||
|
<CommandDialog bind:open>
|
||||||
|
<CommandInput
|
||||||
|
type="text"
|
||||||
|
placeholder="Buscar Usuario o Hashtag"
|
||||||
|
bind:value={search}
|
||||||
|
oninput={buscar}
|
||||||
|
/>
|
||||||
|
{#if search}
|
||||||
|
<ul class="space-y-2">
|
||||||
|
<Label class="ms-3 text-sm font-medium text-muted-foreground">Usuarios</Label>
|
||||||
|
{#each usuarios as usuario}
|
||||||
|
<li class=" w-full cursor-pointer rounded-md hover:bg-accent">
|
||||||
|
<a
|
||||||
|
href={resolve('/[perfil]', { perfil: usuario.username })}
|
||||||
|
class="flex items-center gap-2 px-3 py-2"
|
||||||
|
>
|
||||||
|
{#if usuario.imageUrl}
|
||||||
|
<img src={usuario.imageUrl} alt={usuario.username} class="h-5 w-5 rounded-full" />
|
||||||
|
{:else}
|
||||||
|
<User class="h-5 w-5" />
|
||||||
|
{/if}
|
||||||
|
<span>{usuario.username}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
|
||||||
|
<Label class="ms-3 text-sm font-medium text-muted-foreground">Hashtag</Label>
|
||||||
|
{#await hashtags}
|
||||||
|
<li class="flex items-center gap-2 px-3 py-2 text-muted-foreground">
|
||||||
|
<Spinner class="h-5 w-5" />
|
||||||
|
<span>Cargando …</span>
|
||||||
|
</li>
|
||||||
|
{:then hashtagsResult}
|
||||||
|
{#each hashtagsResult as hashtag}
|
||||||
|
<li class="flex cursor-pointer items-center gap-2 rounded-md px-3 py-2 hover:bg-accent">
|
||||||
|
<Hash class="h-5 w-5" />
|
||||||
|
<span>{hashtag.name}</span>
|
||||||
|
</li>
|
||||||
|
{/each}
|
||||||
|
{/await}
|
||||||
|
</ul>
|
||||||
|
{/if}
|
||||||
|
</CommandDialog>
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
import { apiBase } from '@/stores/url';
|
import { apiBase } from '@/stores/url';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import AvatarButton from './AvatarButton.svelte';
|
import AvatarButton from './AvatarButton.svelte';
|
||||||
|
import Busqueda from './Busqueda.svelte';
|
||||||
|
|
||||||
let menuOpen = $state(false);
|
let menuOpen = $state(false);
|
||||||
const toggleMenu = () => (menuOpen = !menuOpen);
|
const toggleMenu = () => (menuOpen = !menuOpen);
|
||||||
@@ -56,7 +57,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Desktop menu -->
|
<!-- Desktop menu -->
|
||||||
<div class="flex items-center justify-end md:flex">
|
<div class="flex items-center justify-end gap-2 md:flex">
|
||||||
|
<Busqueda></Busqueda>
|
||||||
{#if showCerrarSesion}
|
{#if showCerrarSesion}
|
||||||
{#if $sesionStore !== null}
|
{#if $sesionStore !== null}
|
||||||
<AvatarButton></AvatarButton>
|
<AvatarButton></AvatarButton>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import type { UserResponseDto } from '../../../types.js';
|
|||||||
|
|
||||||
export const ssr = false;
|
export const ssr = false;
|
||||||
|
|
||||||
export async function load({ depends }) {
|
export async function load({ depends, fetch }) {
|
||||||
depends('admin:load');
|
depends('admin:load');
|
||||||
const response = await fetch(get(apiBase) + '/api/admin/users', {
|
const response = await fetch(get(apiBase) + '/api/admin/users', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
|
|||||||
Reference in New Issue
Block a user