feat : update
CI / Verify (push) Successful in 1m45s
CI / Build immutable images and deploy (push) Successful in 2m26s

This commit is contained in:
2026-10-07 19:01:45 +07:00 Unverified
parent 26660aaa49
commit 6d0feb11ca
25 changed files with 87 additions and 32 deletions
@@ -33,7 +33,7 @@ import {
EmptyTitle,
} from "@/components/ui/empty";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import { Switch } from "@/components/ui/switch";
import { Textarea } from "@/components/ui/textarea";
import { isValidPercent } from "@/lib/guides/percent-input";
+2 -1
View File
@@ -14,7 +14,8 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
import { Field, FieldDescription, FieldGroup, FieldLabel } from "@/components/ui/field";
import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group";
import { InputGroup, InputGroupAddon } from "@/components/ui/input-group";
import { ClearableInputGroupInput as InputGroupInput } from "@/components/admin/ui/clearable-input";
import { Spinner } from "@/components/ui/spinner";
import { Textarea } from "@/components/ui/textarea";
import { characterRarityGradientClass } from "@/lib/catalog/rarity";
+1 -1
View File
@@ -82,7 +82,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import {
InputGroup,
InputGroupAddon,
+1 -1
View File
@@ -14,7 +14,7 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from "@/components/ui/pagination";
import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Spinner } from "@/components/ui/spinner";
+1 -1
View File
@@ -35,7 +35,7 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import { Spinner } from "@/components/ui/spinner";
import { cn } from "@/lib/utils";
+1 -1
View File
@@ -27,7 +27,7 @@ import {
FieldGroup,
FieldLabel,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import {
Combobox,
ComboboxContent,
+1 -1
View File
@@ -119,7 +119,7 @@ import {
FieldLegend,
FieldSet,
} from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import {
Select,
@@ -81,7 +81,7 @@ import {
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import {
Popover,
PopoverContent,
+1 -1
View File
@@ -47,8 +47,8 @@ import {
import {
InputGroup,
InputGroupAddon,
InputGroupInput,
} from "@/components/ui/input-group";
import { ClearableInputGroupInput as InputGroupInput } from "@/components/admin/ui/clearable-input";
import { Spinner } from "@/components/ui/spinner";
import { useAdminPresence } from "@/hooks/use-presence";
import type { CatalogSyncJob } from "@/lib/catalog/sync";
+1 -1
View File
@@ -13,7 +13,7 @@ import { Button } from "@/components/ui/button";
import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from "@/components/ui/empty";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import { Textarea } from "@/components/ui/textarea";
import { supportsWeaponType } from "@/lib/catalog/lunaris";
+55
View File
@@ -0,0 +1,55 @@
"use client";
import { useRef, useState, type ComponentProps } from "react";
import { XIcon } from "lucide-react";
import { Input } from "@/components/ui/input";
import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from "@/components/ui/input-group";
export function ClearableInput({ className, ...props }: ComponentProps<typeof Input>) {
const editableText = ["text", "search", "email", "url", "tel"].includes(props.type ?? "text");
if (!editableText) return <Input className={className} {...props} />;
return <InputGroup className={className}><ClearableInputGroupInput {...props} /></InputGroup>;
}
export function ClearableInputGroupInput({ ref, onChange, onValueChange, ...props }: ComponentProps<typeof Input>) {
const inputRef = useRef<HTMLInputElement | null>(null);
const [uncontrolledValue, setUncontrolledValue] = useState(props.defaultValue ?? "");
const value = props.value ?? uncontrolledValue;
return (
<>
<InputGroupInput
{...props}
ref={(node) => {
inputRef.current = node;
if (typeof ref === "function") return ref(node);
if (ref) ref.current = node;
}}
onChange={(event) => {
setUncontrolledValue(event.target.value);
onValueChange?.(event.target.value);
onChange?.(event);
}}
/>
{String(value).length > 0 && !props.disabled && !props.readOnly ? (
<InputGroupAddon align="inline-end">
<InputGroupButton
size="icon-xs"
aria-label={`ล้าง${props["aria-label"] ?? props.placeholder ?? "ข้อความ"}`}
onClick={() => {
const input = inputRef.current;
if (!input) return;
// Use the native setter so React receives the same change as typing.
Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, "value")?.set?.call(input, "");
input.dispatchEvent(new Event("input", { bubbles: true }));
input.focus();
}}
>
<XIcon />
</InputGroupButton>
</InputGroupAddon>
) : null}
</>
);
}
+1 -1
View File
@@ -36,7 +36,7 @@ import {
EmptyTitle,
} from "@/components/ui/empty";
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { ClearableInput as Input } from "@/components/admin/ui/clearable-input";
import {
Select,
SelectContent,