@m5kdev/web-ui 0.9.1 → 0.9.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/components/AvatarUpload.js +2 -2
- package/dist/src/components/AvatarUpload.mjs +3 -3
- package/dist/src/components/AvatarUpload.mjs.map +1 -1
- package/dist/src/components/Calendar.d.mts +1 -1
- package/dist/src/components/CardsSelect.js +2 -2
- package/dist/src/components/CardsSelect.mjs +2 -2
- package/dist/src/components/CollapsibleSidebarMenuItem.d.mts +1 -1
- package/dist/src/components/CollapsibleSidebarMenuItem.js +1 -1
- package/dist/src/components/CollapsibleSidebarMenuItem.mjs +1 -1
- package/dist/src/components/ColorPicker.js +2 -2
- package/dist/src/components/ColorPicker.mjs +2 -2
- package/dist/src/components/CopyButton.js +3 -3
- package/dist/src/components/CopyButton.mjs +4 -4
- package/dist/src/components/CopyButton.mjs.map +1 -1
- package/dist/src/components/CropDialog.js +2 -2
- package/dist/src/components/CropDialog.mjs +2 -2
- package/dist/src/components/DialogProvider.js +1 -1
- package/dist/src/components/DialogProvider.mjs +2 -2
- package/dist/src/components/DialogProvider.mjs.map +1 -1
- package/dist/src/components/FileDropzone.js +2 -2
- package/dist/src/components/FileDropzone.mjs +4 -4
- package/dist/src/components/FileDropzone.mjs.map +1 -1
- package/dist/src/components/MultiSelectDropdown.js +2 -2
- package/dist/src/components/MultiSelectDropdown.mjs +8 -8
- package/dist/src/components/MultiSelectDropdown.mjs.map +1 -1
- package/dist/src/components/Orb.js +1 -1
- package/dist/src/components/Orb.mjs +1 -1
- package/dist/src/components/PageAlert.d.mts +1 -1
- package/dist/src/components/PageAlert.d.ts +1 -1
- package/dist/src/components/PageAlert.js +4 -3
- package/dist/src/components/PageAlert.js.map +1 -1
- package/dist/src/components/PageAlert.mjs +2 -2
- package/dist/src/components/SidebarItem.d.mts +1 -1
- package/dist/src/components/Steps.js +1 -1
- package/dist/src/components/Steps.mjs +1 -1
- package/dist/src/components/app-header.js +1 -1
- package/dist/src/components/app-header.mjs +2 -2
- package/dist/src/components/app-header.mjs.map +1 -1
- package/dist/src/components/blur-card.d.mts +1 -1
- package/dist/src/components/blur-card.js +1 -1
- package/dist/src/components/blur-card.mjs +1 -1
- package/dist/src/components/features-section-demo-1.js +1 -1
- package/dist/src/components/features-section-demo-1.mjs +1 -1
- package/dist/src/components/features-section-demo-3.js +1 -1
- package/dist/src/components/features-section-demo-3.mjs +1 -1
- package/dist/src/components/mode-toggle.js +1 -1
- package/dist/src/components/mode-toggle.mjs +1 -1
- package/dist/src/components/nav-main.d.mts +1 -1
- package/dist/src/components/nav-main.js +1 -1
- package/dist/src/components/nav-main.mjs +1 -1
- package/dist/src/components/pricing-cards.js +1 -1
- package/dist/src/components/pricing-cards.mjs +1 -1
- package/dist/src/components/shared/ButtonCopy.js +2 -2
- package/dist/src/components/shared/ButtonCopy.mjs +3 -3
- package/dist/src/components/shared/ButtonCopy.mjs.map +1 -1
- package/dist/src/components/team-switcher.d.mts +1 -1
- package/dist/src/components/team-switcher.js +2 -2
- package/dist/src/components/team-switcher.mjs +2 -2
- package/dist/src/components/theme-provider.js +1 -1
- package/dist/src/components/theme-provider.mjs +1 -1
- package/dist/src/components/typewriter.js +1 -1
- package/dist/src/components/typewriter.mjs +1 -1
- package/dist/src/components/ui/alert-dialog.d.mts +1 -1
- package/dist/src/components/ui/alert.d.mts +1 -1
- package/dist/src/components/ui/alert.js +2 -1
- package/dist/src/components/ui/alert.js.map +1 -1
- package/dist/src/components/ui/alert.mjs +1 -1
- package/dist/src/components/ui/avatar.js +1 -1
- package/dist/src/components/ui/avatar.mjs +1 -1
- package/dist/src/components/ui/badge.d.mts +1 -1
- package/dist/src/components/ui/badge.js +2 -1
- package/dist/src/components/ui/badge.js.map +1 -1
- package/dist/src/components/ui/badge.mjs +1 -1
- package/dist/src/components/ui/bento-grid2.d.mts +1 -1
- package/dist/src/components/ui/breadcrumb.d.mts +1 -1
- package/dist/src/components/ui/breadcrumb.js +2 -2
- package/dist/src/components/ui/breadcrumb.mjs +2 -2
- package/dist/src/components/ui/button.js +3 -2
- package/dist/src/components/ui/button.js.map +1 -1
- package/dist/src/components/ui/button.mjs +1 -1
- package/dist/src/components/ui/card.js +1 -1
- package/dist/src/components/ui/card.mjs +1 -1
- package/dist/src/components/ui/checkbox.js +2 -2
- package/dist/src/components/ui/checkbox.mjs +2 -2
- package/dist/src/components/ui/dialog.d.mts +1 -1
- package/dist/src/components/ui/dialog.js +1 -1
- package/dist/src/components/ui/dialog.mjs +1 -1
- package/dist/src/components/ui/dropdown-menu.d.mts +1 -1
- package/dist/src/components/ui/dropdown-menu.js +2 -2
- package/dist/src/components/ui/dropdown-menu.mjs +2 -2
- package/dist/src/components/ui/floating-navbar.d.mts +1 -1
- package/dist/src/components/ui/floating-navbar.js +1 -1
- package/dist/src/components/ui/floating-navbar.mjs +1 -1
- package/dist/src/components/ui/form.d.mts +1 -1
- package/dist/src/components/ui/form.js +1 -1
- package/dist/src/components/ui/form.mjs +1 -1
- package/dist/src/components/ui/image.js +1 -1
- package/dist/src/components/ui/image.mjs +1 -1
- package/dist/src/components/ui/input.js +1 -1
- package/dist/src/components/ui/input.mjs +1 -1
- package/dist/src/components/ui/label.js +1 -1
- package/dist/src/components/ui/label.mjs +1 -1
- package/dist/src/components/ui/pagination.d.mts +1 -1
- package/dist/src/components/ui/pagination.js +1 -1
- package/dist/src/components/ui/pagination.mjs +1 -1
- package/dist/src/components/ui/progress.js +1 -1
- package/dist/src/components/ui/progress.mjs +1 -1
- package/dist/src/components/ui/resizable-navbar.d.mts +1 -1
- package/dist/src/components/ui/resizable-navbar.js +2 -2
- package/dist/src/components/ui/resizable-navbar.mjs +2 -2
- package/dist/src/components/ui/segment-control.js +1 -1
- package/dist/src/components/ui/segment-control.mjs +3 -3
- package/dist/src/components/ui/segment-control.mjs.map +1 -1
- package/dist/src/components/ui/select.js +2 -2
- package/dist/src/components/ui/select.mjs +2 -2
- package/dist/src/components/ui/separator.js +1 -1
- package/dist/src/components/ui/separator.mjs +1 -1
- package/dist/src/components/ui/sheet.d.mts +1 -1
- package/dist/src/components/ui/sheet.js +2 -2
- package/dist/src/components/ui/sheet.mjs +2 -2
- package/dist/src/components/ui/sidebar.js +3 -3
- package/dist/src/components/ui/sidebar.mjs +3 -3
- package/dist/src/components/ui/slider.js +1 -1
- package/dist/src/components/ui/slider.mjs +1 -1
- package/dist/src/components/ui/spinner.d.mts +1 -1
- package/dist/src/components/ui/spinner.js +1 -1
- package/dist/src/components/ui/spinner.mjs +1 -1
- package/dist/src/components/ui/switch.js +1 -1
- package/dist/src/components/ui/switch.mjs +1 -1
- package/dist/src/components/ui/table.d.mts +1 -1
- package/dist/src/components/ui/tabs.d.mts +1 -1
- package/dist/src/components/ui/textarea.d.mts +1 -1
- package/dist/src/components/ui/timeline.d.mts +1 -1
- package/dist/src/components/ui/timeline.js +1 -1
- package/dist/src/components/ui/timeline.mjs +1 -1
- package/dist/src/components/ui/toast.js +2 -2
- package/dist/src/components/ui/toast.mjs +2 -2
- package/dist/src/components/ui/tooltip.d.mts +1 -1
- package/dist/src/components/ui/typewriter-effect.js +1 -1
- package/dist/src/components/ui/typewriter-effect.mjs +1 -1
- package/dist/src/icons/GoogleIcon.d.mts +1 -1
- package/dist/src/icons/LinkedInIcon.d.mts +1 -1
- package/dist/src/icons/MicrosoftIcon.d.mts +1 -1
- package/dist/src/modules/app/components/AppShell.d.mts +1 -1
- package/dist/src/modules/app/components/AppSidebar.d.mts +1 -1
- package/dist/src/modules/app/components/AppSidebarHeader.js +2 -2
- package/dist/src/modules/app/components/AppSidebarHeader.mjs +3 -3
- package/dist/src/modules/app/components/AppSidebarHeader.mjs.map +1 -1
- package/dist/src/modules/app/components/AppSidebarInvites.js +2 -2
- package/dist/src/modules/app/components/AppSidebarInvites.mjs +4 -4
- package/dist/src/modules/app/components/AppSidebarInvites.mjs.map +1 -1
- package/dist/src/modules/app/components/AppSidebarUser.js +1 -1
- package/dist/src/modules/app/components/AppSidebarUser.mjs +1 -1
- package/dist/src/modules/auth/components/AdminUserManagement.js +4 -4
- package/dist/src/modules/auth/components/AdminUserManagement.mjs +8 -8
- package/dist/src/modules/auth/components/AdminUserManagement.mjs.map +1 -1
- package/dist/src/modules/auth/components/AdminWaitlist.js +2 -2
- package/dist/src/modules/auth/components/AdminWaitlist.mjs +4 -4
- package/dist/src/modules/auth/components/AdminWaitlist.mjs.map +1 -1
- package/dist/src/modules/auth/components/AuthLayout.d.mts +1 -1
- package/dist/src/modules/auth/components/AuthProviders.js +1 -1
- package/dist/src/modules/auth/components/AuthProviders.mjs +1 -1
- package/dist/src/modules/auth/components/AuthRouter.d.mts +1 -1
- package/dist/src/modules/auth/components/ClaimAccountRoute.js +2 -2
- package/dist/src/modules/auth/components/ClaimAccountRoute.mjs +2 -2
- package/dist/src/modules/auth/components/ErrorAuthRoute.js +2 -2
- package/dist/src/modules/auth/components/ErrorAuthRoute.mjs +5 -5
- package/dist/src/modules/auth/components/ErrorAuthRoute.mjs.map +1 -1
- package/dist/src/modules/auth/components/ForgotPasswordForm.js +2 -2
- package/dist/src/modules/auth/components/ForgotPasswordForm.mjs +2 -2
- package/dist/src/modules/auth/components/ForgotPasswordRoute.js +2 -2
- package/dist/src/modules/auth/components/ForgotPasswordRoute.mjs +3 -3
- package/dist/src/modules/auth/components/ForgotPasswordRoute.mjs.map +1 -1
- package/dist/src/modules/auth/components/InviteFriends.js +2 -2
- package/dist/src/modules/auth/components/InviteFriends.mjs +2 -2
- package/dist/src/modules/auth/components/LastUsedBadge.d.mts +1 -1
- package/dist/src/modules/auth/components/LastUsedBadge.js +1 -1
- package/dist/src/modules/auth/components/LastUsedBadge.mjs +1 -1
- package/dist/src/modules/auth/components/LoginForm.js +2 -2
- package/dist/src/modules/auth/components/LoginForm.mjs +4 -4
- package/dist/src/modules/auth/components/LoginForm.mjs.map +1 -1
- package/dist/src/modules/auth/components/LoginRoute.js +2 -2
- package/dist/src/modules/auth/components/LoginRoute.mjs +4 -4
- package/dist/src/modules/auth/components/LoginRoute.mjs.map +1 -1
- package/dist/src/modules/auth/components/LogoutRoute.js +2 -2
- package/dist/src/modules/auth/components/LogoutRoute.mjs +2 -2
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.js +2 -2
- package/dist/src/modules/auth/components/OrganizationAcceptInvitationRoute.mjs +2 -2
- package/dist/src/modules/auth/components/OrganizationMembersRoute.js +4 -4
- package/dist/src/modules/auth/components/OrganizationMembersRoute.mjs +4 -4
- package/dist/src/modules/auth/components/OrganizationPreferences.js +2 -2
- package/dist/src/modules/auth/components/OrganizationPreferences.mjs +2 -2
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.js +3 -3
- package/dist/src/modules/auth/components/OrganizationSettingsRoute.mjs +3 -3
- package/dist/src/modules/auth/components/OrganizationSwitcher.js +4 -4
- package/dist/src/modules/auth/components/OrganizationSwitcher.mjs +6 -6
- package/dist/src/modules/auth/components/OrganizationSwitcher.mjs.map +1 -1
- package/dist/src/modules/auth/components/ProfileRoute.js +1 -1
- package/dist/src/modules/auth/components/ProfileRoute.mjs +1 -1
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.js +2 -2
- package/dist/src/modules/auth/components/RangeNuqsDatePicker.mjs +2 -2
- package/dist/src/modules/auth/components/ResetPasswordForm.js +2 -2
- package/dist/src/modules/auth/components/ResetPasswordForm.mjs +3 -3
- package/dist/src/modules/auth/components/ResetPasswordForm.mjs.map +1 -1
- package/dist/src/modules/auth/components/ResetPasswordRoute.js +2 -2
- package/dist/src/modules/auth/components/ResetPasswordRoute.mjs +3 -3
- package/dist/src/modules/auth/components/ResetPasswordRoute.mjs.map +1 -1
- package/dist/src/modules/auth/components/SignupFormRoute.js +2 -2
- package/dist/src/modules/auth/components/SignupFormRoute.mjs +2 -2
- package/dist/src/modules/auth/components/SignupRoute.js +2 -2
- package/dist/src/modules/auth/components/SignupRoute.mjs +3 -3
- package/dist/src/modules/auth/components/SignupRoute.mjs.map +1 -1
- package/dist/src/modules/auth/components/UserPreferences.js +1 -1
- package/dist/src/modules/auth/components/UserPreferences.mjs +1 -1
- package/dist/src/modules/auth/components/WaitlistCard.js +2 -2
- package/dist/src/modules/auth/components/WaitlistCard.mjs +2 -2
- package/dist/src/modules/auth/components/WaitlistCodeValidation.js +1 -1
- package/dist/src/modules/auth/components/WaitlistCodeValidation.mjs +1 -1
- package/dist/src/modules/billing/components/BillingBetaPage.d.mts +1 -1
- package/dist/src/modules/billing/components/BillingBetaPage.js +1 -1
- package/dist/src/modules/billing/components/BillingBetaPage.mjs +1 -1
- package/dist/src/modules/billing/components/BillingInvoicePage.js +2 -2
- package/dist/src/modules/billing/components/BillingInvoicePage.mjs +2 -2
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.js +3 -3
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.mjs +5 -5
- package/dist/src/modules/billing/components/BillingSinglePlanSelect.mjs.map +1 -1
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.js +2 -2
- package/dist/src/modules/table/components/ColumnOrderAndVisibility.mjs +2 -2
- package/dist/src/modules/table/components/NuqsTable.js +2 -2
- package/dist/src/modules/table/components/NuqsTable.mjs +4 -4
- package/dist/src/modules/table/components/NuqsTable.mjs.map +1 -1
- package/dist/src/modules/table/components/TableFiltering.js +2 -2
- package/dist/src/modules/table/components/TableFiltering.mjs +2 -2
- package/dist/src/modules/table/components/TableGroupBy.js +1 -1
- package/dist/src/modules/table/components/TableGroupBy.mjs +1 -1
- package/dist/src/modules/table/components/TablePagination.js +1 -1
- package/dist/src/modules/table/components/TablePagination.mjs +1 -1
- package/package.json +5 -5
|
@@ -4,11 +4,11 @@ const require_src_lib_utils = require("../lib/utils.js");
|
|
|
4
4
|
const require_src_components_CropDialog = require("./CropDialog.js");
|
|
5
5
|
const require_src_components_ui_avatar = require("./ui/avatar.js");
|
|
6
6
|
const require_src_components_ui_progress = require("./ui/progress.js");
|
|
7
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
8
|
-
let react = require("react");
|
|
9
7
|
let _m5kdev_frontend_modules_file_hooks_useUpload = require("@m5kdev/frontend/modules/file/hooks/useUpload");
|
|
10
8
|
let lucide_react = require("lucide-react");
|
|
9
|
+
let react = require("react");
|
|
11
10
|
let react_i18next = require("react-i18next");
|
|
11
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
12
|
//#region src/components/AvatarUpload.tsx
|
|
13
13
|
function AvatarUpload({ currentAvatarUrl, onUploadComplete, className }) {
|
|
14
14
|
const { t } = (0, react_i18next.useTranslation)();
|
|
@@ -2,11 +2,11 @@ import { cn } from "../lib/utils.mjs";
|
|
|
2
2
|
import { CropDialog } from "./CropDialog.mjs";
|
|
3
3
|
import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar.mjs";
|
|
4
4
|
import { Progress } from "./ui/progress.mjs";
|
|
5
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
|
-
import { useRef, useState } from "react";
|
|
7
5
|
import { useFileUpload } from "@m5kdev/frontend/modules/file/hooks/useUpload";
|
|
8
6
|
import { Edit2, User } from "lucide-react";
|
|
7
|
+
import { useRef, useState } from "react";
|
|
9
8
|
import { useTranslation } from "react-i18next";
|
|
9
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
10
10
|
//#region src/components/AvatarUpload.tsx
|
|
11
11
|
function AvatarUpload({ currentAvatarUrl, onUploadComplete, className }) {
|
|
12
12
|
const { t } = useTranslation();
|
|
@@ -58,7 +58,7 @@ function AvatarUpload({ currentAvatarUrl, onUploadComplete, className }) {
|
|
|
58
58
|
reset();
|
|
59
59
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
60
60
|
};
|
|
61
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsxs("div", {
|
|
61
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsxs("div", {
|
|
62
62
|
role: "dialog",
|
|
63
63
|
className: cn("relative inline-block", className),
|
|
64
64
|
onMouseEnter: () => setIsHovered(true),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AvatarUpload.mjs","names":[],"sources":["../../../src/components/AvatarUpload.tsx"],"sourcesContent":["import { useFileUpload } from \"@m5kdev/frontend/modules/file/hooks/useUpload\";\r\nimport { Edit2, User } from \"lucide-react\";\r\nimport { type ChangeEvent, useRef, useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { CropDialog } from \"./CropDialog\";\r\nimport { Avatar, AvatarFallback, AvatarImage } from \"./ui/avatar\";\r\nimport { Progress } from \"./ui/progress\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface AvatarUploadProps {\r\n currentAvatarUrl?: string | null;\r\n onUploadComplete?: (avatarUrl: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function AvatarUpload({ currentAvatarUrl, onUploadComplete, className }: AvatarUploadProps) {\r\n const { t } = useTranslation();\r\n const [isHovered, setIsHovered] = useState(false);\r\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\r\n const [previewUrl, setPreviewUrl] = useState<string | null>(currentAvatarUrl || null);\r\n const [showCropDialog, setShowCropDialog] = useState(false);\r\n\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const { upload, status, progress, errorMessage, reset } = useFileUpload();\r\n\r\n const handleFileSelect = (event: ChangeEvent<HTMLInputElement>) => {\r\n const file = event.target.files?.[0];\r\n if (file) {\r\n // Validate file type\r\n if (![\"image/jpeg\", \"image/png\", \"image/webp\", \"image/jpg\"].includes(file.type)) {\r\n alert(t(\"web-ui:upload.errors.invalidType\"));\r\n return;\r\n }\r\n // Validate file size (5MB)\r\n if (file.size > 5 * 1024 * 1024) {\r\n alert(t(\"web-ui:upload.errors.tooLarge\"));\r\n return;\r\n }\r\n setSelectedFile(file);\r\n const objectUrl = URL.createObjectURL(file);\r\n setPreviewUrl(objectUrl);\r\n setShowCropDialog(true);\r\n }\r\n };\r\n\r\n const handleCropComplete = async (croppedBlob: Blob) => {\r\n const croppedFile = new File([croppedBlob], selectedFile?.name || \"cropped-image.jpg\", {\r\n type: \"image/jpeg\",\r\n });\r\n\r\n setSelectedFile(croppedFile);\r\n const croppedObjectUrl = URL.createObjectURL(croppedFile);\r\n setPreviewUrl(croppedObjectUrl);\r\n setShowCropDialog(false);\r\n\r\n try {\r\n const res = await upload<{\r\n url: string;\r\n minetype: string;\r\n size: number;\r\n }>(\"image\", croppedFile);\r\n console.log({ res });\r\n onUploadComplete?.(res.url);\r\n } catch (error) {\r\n console.error(\"Error uploading image:\", error);\r\n }\r\n };\r\n\r\n const removeFile = () => {\r\n if (previewUrl && previewUrl !== currentAvatarUrl) {\r\n URL.revokeObjectURL(previewUrl);\r\n }\r\n setSelectedFile(null);\r\n setPreviewUrl(currentAvatarUrl || null);\r\n setShowCropDialog(false);\r\n reset();\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = \"\";\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n role=\"dialog\"\r\n className={cn(\"relative inline-block\", className)}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => setIsHovered(false)}\r\n >\r\n <Avatar className=\"h-24 w-24 cursor-pointer\" onClick={() => fileInputRef.current?.click()}>\r\n {previewUrl ? (\r\n <AvatarImage src={previewUrl} alt={t(\"web-ui:avatar.preview.alt\")} />\r\n ) : (\r\n <AvatarFallback>\r\n <User className=\"h-12 w-12\" />\r\n </AvatarFallback>\r\n )}\r\n {isHovered && (\r\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 rounded-full\">\r\n <Edit2 className=\"h-6 w-6 text-white\" />\r\n </div>\r\n )}\r\n </Avatar>\r\n\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n className=\"hidden\"\r\n accept=\"image/jpeg,image/png,image/webp\"\r\n onChange={handleFileSelect}\r\n />\r\n\r\n {status === \"uploading\" && (\r\n <div className=\"mt-2 w-full\">\r\n <Progress value={progress} className=\"h-2\" />\r\n </div>\r\n )}\r\n {status === \"error\" && <p className=\"mt-2 text-sm text-red-500\">{errorMessage}</p>}\r\n </div>\r\n\r\n {previewUrl && (\r\n <CropDialog\r\n open={showCropDialog}\r\n onOpenChange={setShowCropDialog}\r\n imageUrl={previewUrl}\r\n onCropComplete={handleCropComplete}\r\n onCancel={removeFile}\r\n isLoading={status === \"uploading\"}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,aAAa,EAAE,kBAAkB,kBAAkB,aAAgC;CACjG,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,cAAc,mBAAmB,SAAsB,KAAK;CACnE,MAAM,CAAC,YAAY,iBAAiB,SAAwB,oBAAoB,KAAK;CACrF,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,MAAM;CAE3D,MAAM,eAAe,OAAyB,KAAK;CACnD,MAAM,EAAE,QAAQ,QAAQ,UAAU,cAAc,UAAU,eAAe;CAEzE,MAAM,oBAAoB,UAAyC;EACjE,MAAM,OAAO,MAAM,OAAO,QAAQ;AAClC,MAAI,MAAM;AAER,OAAI,CAAC;IAAC;IAAc;IAAa;IAAc;IAAY,CAAC,SAAS,KAAK,KAAK,EAAE;AAC/E,UAAM,EAAE,mCAAmC,CAAC;AAC5C;;AAGF,OAAI,KAAK,OAAO,IAAI,OAAO,MAAM;AAC/B,UAAM,EAAE,gCAAgC,CAAC;AACzC;;AAEF,mBAAgB,KAAK;AAErB,iBADkB,IAAI,gBAAgB,KAAK,CACnB;AACxB,qBAAkB,KAAK;;;CAI3B,MAAM,qBAAqB,OAAO,gBAAsB;EACtD,MAAM,cAAc,IAAI,KAAK,CAAC,YAAY,EAAE,cAAc,QAAQ,qBAAqB,EACrF,MAAM,cACP,CAAC;AAEF,kBAAgB,YAAY;AAE5B,gBADyB,IAAI,gBAAgB,YAAY,CAC1B;AAC/B,oBAAkB,MAAM;AAExB,MAAI;GACF,MAAM,MAAM,MAAM,OAIf,SAAS,YAAY;AACxB,WAAQ,IAAI,EAAE,KAAK,CAAC;AACpB,sBAAmB,IAAI,IAAI;WACpB,OAAO;AACd,WAAQ,MAAM,0BAA0B,MAAM;;;CAIlD,MAAM,mBAAmB;AACvB,MAAI,cAAc,eAAe,iBAC/B,KAAI,gBAAgB,WAAW;AAEjC,kBAAgB,KAAK;AACrB,gBAAc,oBAAoB,KAAK;AACvC,oBAAkB,MAAM;AACxB,SAAO;AACP,MAAI,aAAa,QACf,cAAa,QAAQ,QAAQ;;AAIjC,QACE,qBAAA,
|
|
1
|
+
{"version":3,"file":"AvatarUpload.mjs","names":[],"sources":["../../../src/components/AvatarUpload.tsx"],"sourcesContent":["import { useFileUpload } from \"@m5kdev/frontend/modules/file/hooks/useUpload\";\r\nimport { Edit2, User } from \"lucide-react\";\r\nimport { type ChangeEvent, useRef, useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { CropDialog } from \"./CropDialog\";\r\nimport { Avatar, AvatarFallback, AvatarImage } from \"./ui/avatar\";\r\nimport { Progress } from \"./ui/progress\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface AvatarUploadProps {\r\n currentAvatarUrl?: string | null;\r\n onUploadComplete?: (avatarUrl: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function AvatarUpload({ currentAvatarUrl, onUploadComplete, className }: AvatarUploadProps) {\r\n const { t } = useTranslation();\r\n const [isHovered, setIsHovered] = useState(false);\r\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\r\n const [previewUrl, setPreviewUrl] = useState<string | null>(currentAvatarUrl || null);\r\n const [showCropDialog, setShowCropDialog] = useState(false);\r\n\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n const { upload, status, progress, errorMessage, reset } = useFileUpload();\r\n\r\n const handleFileSelect = (event: ChangeEvent<HTMLInputElement>) => {\r\n const file = event.target.files?.[0];\r\n if (file) {\r\n // Validate file type\r\n if (![\"image/jpeg\", \"image/png\", \"image/webp\", \"image/jpg\"].includes(file.type)) {\r\n alert(t(\"web-ui:upload.errors.invalidType\"));\r\n return;\r\n }\r\n // Validate file size (5MB)\r\n if (file.size > 5 * 1024 * 1024) {\r\n alert(t(\"web-ui:upload.errors.tooLarge\"));\r\n return;\r\n }\r\n setSelectedFile(file);\r\n const objectUrl = URL.createObjectURL(file);\r\n setPreviewUrl(objectUrl);\r\n setShowCropDialog(true);\r\n }\r\n };\r\n\r\n const handleCropComplete = async (croppedBlob: Blob) => {\r\n const croppedFile = new File([croppedBlob], selectedFile?.name || \"cropped-image.jpg\", {\r\n type: \"image/jpeg\",\r\n });\r\n\r\n setSelectedFile(croppedFile);\r\n const croppedObjectUrl = URL.createObjectURL(croppedFile);\r\n setPreviewUrl(croppedObjectUrl);\r\n setShowCropDialog(false);\r\n\r\n try {\r\n const res = await upload<{\r\n url: string;\r\n minetype: string;\r\n size: number;\r\n }>(\"image\", croppedFile);\r\n console.log({ res });\r\n onUploadComplete?.(res.url);\r\n } catch (error) {\r\n console.error(\"Error uploading image:\", error);\r\n }\r\n };\r\n\r\n const removeFile = () => {\r\n if (previewUrl && previewUrl !== currentAvatarUrl) {\r\n URL.revokeObjectURL(previewUrl);\r\n }\r\n setSelectedFile(null);\r\n setPreviewUrl(currentAvatarUrl || null);\r\n setShowCropDialog(false);\r\n reset();\r\n if (fileInputRef.current) {\r\n fileInputRef.current.value = \"\";\r\n }\r\n };\r\n\r\n return (\r\n <>\r\n <div\r\n role=\"dialog\"\r\n className={cn(\"relative inline-block\", className)}\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => setIsHovered(false)}\r\n >\r\n <Avatar className=\"h-24 w-24 cursor-pointer\" onClick={() => fileInputRef.current?.click()}>\r\n {previewUrl ? (\r\n <AvatarImage src={previewUrl} alt={t(\"web-ui:avatar.preview.alt\")} />\r\n ) : (\r\n <AvatarFallback>\r\n <User className=\"h-12 w-12\" />\r\n </AvatarFallback>\r\n )}\r\n {isHovered && (\r\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/50 rounded-full\">\r\n <Edit2 className=\"h-6 w-6 text-white\" />\r\n </div>\r\n )}\r\n </Avatar>\r\n\r\n <input\r\n ref={fileInputRef}\r\n type=\"file\"\r\n className=\"hidden\"\r\n accept=\"image/jpeg,image/png,image/webp\"\r\n onChange={handleFileSelect}\r\n />\r\n\r\n {status === \"uploading\" && (\r\n <div className=\"mt-2 w-full\">\r\n <Progress value={progress} className=\"h-2\" />\r\n </div>\r\n )}\r\n {status === \"error\" && <p className=\"mt-2 text-sm text-red-500\">{errorMessage}</p>}\r\n </div>\r\n\r\n {previewUrl && (\r\n <CropDialog\r\n open={showCropDialog}\r\n onOpenChange={setShowCropDialog}\r\n imageUrl={previewUrl}\r\n onCropComplete={handleCropComplete}\r\n onCancel={removeFile}\r\n isLoading={status === \"uploading\"}\r\n />\r\n )}\r\n </>\r\n );\r\n}\r\n"],"mappings":";;;;;;;;;;AAeA,SAAgB,aAAa,EAAE,kBAAkB,kBAAkB,aAAgC;CACjG,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,CAAC,WAAW,gBAAgB,SAAS,MAAM;CACjD,MAAM,CAAC,cAAc,mBAAmB,SAAsB,KAAK;CACnE,MAAM,CAAC,YAAY,iBAAiB,SAAwB,oBAAoB,KAAK;CACrF,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,MAAM;CAE3D,MAAM,eAAe,OAAyB,KAAK;CACnD,MAAM,EAAE,QAAQ,QAAQ,UAAU,cAAc,UAAU,eAAe;CAEzE,MAAM,oBAAoB,UAAyC;EACjE,MAAM,OAAO,MAAM,OAAO,QAAQ;AAClC,MAAI,MAAM;AAER,OAAI,CAAC;IAAC;IAAc;IAAa;IAAc;IAAY,CAAC,SAAS,KAAK,KAAK,EAAE;AAC/E,UAAM,EAAE,mCAAmC,CAAC;AAC5C;;AAGF,OAAI,KAAK,OAAO,IAAI,OAAO,MAAM;AAC/B,UAAM,EAAE,gCAAgC,CAAC;AACzC;;AAEF,mBAAgB,KAAK;AAErB,iBADkB,IAAI,gBAAgB,KAAK,CACnB;AACxB,qBAAkB,KAAK;;;CAI3B,MAAM,qBAAqB,OAAO,gBAAsB;EACtD,MAAM,cAAc,IAAI,KAAK,CAAC,YAAY,EAAE,cAAc,QAAQ,qBAAqB,EACrF,MAAM,cACP,CAAC;AAEF,kBAAgB,YAAY;AAE5B,gBADyB,IAAI,gBAAgB,YAAY,CAC1B;AAC/B,oBAAkB,MAAM;AAExB,MAAI;GACF,MAAM,MAAM,MAAM,OAIf,SAAS,YAAY;AACxB,WAAQ,IAAI,EAAE,KAAK,CAAC;AACpB,sBAAmB,IAAI,IAAI;WACpB,OAAO;AACd,WAAQ,MAAM,0BAA0B,MAAM;;;CAIlD,MAAM,mBAAmB;AACvB,MAAI,cAAc,eAAe,iBAC/B,KAAI,gBAAgB,WAAW;AAEjC,kBAAgB,KAAK;AACrB,gBAAc,oBAAoB,KAAK;AACvC,oBAAkB,MAAM;AACxB,SAAO;AACP,MAAI,aAAa,QACf,cAAa,QAAQ,QAAQ;;AAIjC,QACE,qBAAA,YAAA,EAAA,UAAA,CACE,qBAAC,OAAD;EACE,MAAK;EACL,WAAW,GAAG,yBAAyB,UAAU;EACjD,oBAAoB,aAAa,KAAK;EACtC,oBAAoB,aAAa,MAAM;YAJzC;GAME,qBAAC,QAAD;IAAQ,WAAU;IAA2B,eAAe,aAAa,SAAS,OAAO;cAAzF,CACG,aACC,oBAAC,aAAD;KAAa,KAAK;KAAY,KAAK,EAAE,4BAA4B;KAAI,CAAA,GAErE,oBAAC,gBAAD,EAAA,UACE,oBAAC,MAAD,EAAM,WAAU,aAAc,CAAA,EACf,CAAA,EAElB,aACC,oBAAC,OAAD;KAAK,WAAU;eACb,oBAAC,OAAD,EAAO,WAAU,sBAAuB,CAAA;KACpC,CAAA,CAED;;GAET,oBAAC,SAAD;IACE,KAAK;IACL,MAAK;IACL,WAAU;IACV,QAAO;IACP,UAAU;IACV,CAAA;GAED,WAAW,eACV,oBAAC,OAAD;IAAK,WAAU;cACb,oBAAC,UAAD;KAAU,OAAO;KAAU,WAAU;KAAQ,CAAA;IACzC,CAAA;GAEP,WAAW,WAAW,oBAAC,KAAD;IAAG,WAAU;cAA6B;IAAiB,CAAA;GAC9E;KAEL,cACC,oBAAC,YAAD;EACE,MAAM;EACN,cAAc;EACd,UAAU;EACV,gBAAgB;EAChB,UAAU;EACV,WAAW,WAAW;EACtB,CAAA,CAEH,EAAA,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import React from "react";
|
|
2
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import { CalendarProps } from "react-big-calendar";
|
|
4
4
|
//#region src/components/Calendar.d.ts
|
|
5
5
|
type CalendarComponents = NonNullable<CalendarProps["components"]>;
|
|
@@ -2,10 +2,10 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
3
3
|
const require_src_lib_utils = require("../lib/utils.js");
|
|
4
4
|
const require_src_components_ui_card = require("./ui/card.js");
|
|
5
|
-
let
|
|
5
|
+
let lucide_react = require("lucide-react");
|
|
6
6
|
let react = require("react");
|
|
7
7
|
react = require_runtime.__toESM(react);
|
|
8
|
-
let
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
//#region src/components/CardsSelect.tsx
|
|
10
10
|
const CardsSelect = react.forwardRef(({ items, selectedIds, onSelectionChange, maxSelections, className, cardClassName, showCheckbox = true, disabled = false, reversed = false, ...props }, ref) => {
|
|
11
11
|
const handleCardClick = (itemId) => {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.mjs";
|
|
2
2
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card.mjs";
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
import * as React$1 from "react";
|
|
5
3
|
import { Check, Edit } from "lucide-react";
|
|
4
|
+
import * as React$1 from "react";
|
|
5
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
6
6
|
//#region src/components/CardsSelect.tsx
|
|
7
7
|
const CardsSelect = React$1.forwardRef(({ items, selectedIds, onSelectionChange, maxSelections, className, cardClassName, showCheckbox = true, disabled = false, reversed = false, ...props }, ref) => {
|
|
8
8
|
const handleCardClick = (itemId) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
2
1
|
import { ReactNode } from "react";
|
|
2
|
+
import * as _$react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import { CollapsibleProps } from "@radix-ui/react-collapsible";
|
|
4
4
|
|
|
5
5
|
//#region src/components/CollapsibleSidebarMenuItem.d.ts
|
|
@@ -2,8 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
2
2
|
require("../../_virtual/_rolldown/runtime.js");
|
|
3
3
|
const require_src_components_ui_collapsible = require("./ui/collapsible.js");
|
|
4
4
|
const require_src_components_ui_sidebar = require("./ui/sidebar.js");
|
|
5
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
5
|
let lucide_react = require("lucide-react");
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
7
|
let react_router = require("react-router");
|
|
8
8
|
//#region src/components/CollapsibleSidebarMenuItem.tsx
|
|
9
9
|
function CollapsibleSidebarMenuItem({ children, label, icon, link, badge, ...props }) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./ui/collapsible.mjs";
|
|
2
2
|
import { SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, useSidebar } from "./ui/sidebar.mjs";
|
|
3
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
3
|
import { ChevronRight } from "lucide-react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { Link } from "react-router";
|
|
6
6
|
//#region src/components/CollapsibleSidebarMenuItem.tsx
|
|
7
7
|
function CollapsibleSidebarMenuItem({ children, label, icon, link, badge, ...props }) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
3
|
-
let
|
|
3
|
+
let lucide_react = require("lucide-react");
|
|
4
4
|
let react = require("react");
|
|
5
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
6
|
let _heroui_react = require("@heroui/react");
|
|
6
|
-
let lucide_react = require("lucide-react");
|
|
7
7
|
let _uiw_color_convert = require("@uiw/color-convert");
|
|
8
8
|
let _uiw_react_color_colorful = require("@uiw/react-color-colorful");
|
|
9
9
|
_uiw_react_color_colorful = require_runtime.__toESM(_uiw_react_color_colorful);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PipetteIcon } from "lucide-react";
|
|
2
2
|
import { useState } from "react";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
4
|
import { Button, Input, Popover, PopoverContent, PopoverTrigger } from "@heroui/react";
|
|
4
|
-
import { PipetteIcon } from "lucide-react";
|
|
5
5
|
import { hexToHsva } from "@uiw/color-convert";
|
|
6
6
|
import Colorful from "@uiw/react-color-colorful";
|
|
7
7
|
//#region src/components/ColorPicker.tsx
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../_virtual/_rolldown/runtime.js");
|
|
3
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
|
-
let react = require("react");
|
|
5
|
-
let _heroui_react = require("@heroui/react");
|
|
6
3
|
let lucide_react = require("lucide-react");
|
|
4
|
+
let react = require("react");
|
|
7
5
|
let react_i18next = require("react-i18next");
|
|
6
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
+
let _heroui_react = require("@heroui/react");
|
|
8
8
|
let sonner = require("sonner");
|
|
9
9
|
//#region src/components/CopyButton.tsx
|
|
10
10
|
function CopyButton({ text, notificationTimeout = 1e3, isIconOnly, onCopy, ...props }) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
3
|
-
import { Button } from "@heroui/react";
|
|
4
1
|
import { CheckCircle, Copy } from "lucide-react";
|
|
2
|
+
import { useState } from "react";
|
|
5
3
|
import { useTranslation } from "react-i18next";
|
|
4
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Button } from "@heroui/react";
|
|
6
6
|
import { toast } from "sonner";
|
|
7
7
|
//#region src/components/CopyButton.tsx
|
|
8
8
|
function CopyButton({ text, notificationTimeout = 1e3, isIconOnly, onCopy, ...props }) {
|
|
@@ -24,7 +24,7 @@ function CopyButton({ text, notificationTimeout = 1e3, isIconOnly, onCopy, ...pr
|
|
|
24
24
|
isIconOnly,
|
|
25
25
|
onPress: () => handleCopy(text),
|
|
26
26
|
...props,
|
|
27
|
-
children: isCopied ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4" }), !isIconOnly && t("web-ui:common.copied")] }) : /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }), !isIconOnly && t("web-ui:common.copy")] })
|
|
27
|
+
children: isCopied ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(CheckCircle, { className: "h-4 w-4" }), !isIconOnly && t("web-ui:common.copied")] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Copy, { className: "h-4 w-4" }), !isIconOnly && t("web-ui:common.copy")] })
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
30
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyButton.mjs","names":[],"sources":["../../../src/components/CopyButton.tsx"],"sourcesContent":["import { Button, type ButtonProps } from \"@heroui/react\";\r\nimport { CheckCircle, Copy } from \"lucide-react\";\r\nimport { useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { toast } from \"sonner\";\r\n\r\nexport function CopyButton({\r\n text,\r\n notificationTimeout = 1000,\r\n isIconOnly,\r\n onCopy,\r\n ...props\r\n}: ButtonProps & { text: string; notificationTimeout?: number; onCopy?: () => void }) {\r\n const { t } = useTranslation();\r\n const [isCopied, setIsCopied] = useState(false);\r\n\r\n const handleCopy = async (text: string) => {\r\n try {\r\n await window.navigator.clipboard.writeText(text);\r\n setIsCopied(true);\r\n onCopy?.();\r\n toast.success(t(\"web-ui:common.copySuccess\"));\r\n setTimeout(() => setIsCopied(false), notificationTimeout);\r\n } catch (error) {\r\n toast.error(t(\"web-ui:common.copyError\"));\r\n console.error(error);\r\n }\r\n };\r\n\r\n return (\r\n <Button isIconOnly={isIconOnly} onPress={() => handleCopy(text)} {...props}>\r\n {isCopied ? (\r\n <>\r\n <CheckCircle className=\"h-4 w-4\" />\r\n {!isIconOnly && t(\"web-ui:common.copied\")}\r\n </>\r\n ) : (\r\n <>\r\n <Copy className=\"h-4 w-4\" />\r\n {!isIconOnly && t(\"web-ui:common.copy\")}\r\n </>\r\n )}\r\n </Button>\r\n );\r\n}\r\n"],"mappings":";;;;;;;AAMA,SAAgB,WAAW,EACzB,MACA,sBAAsB,KACtB,YACA,QACA,GAAG,SACiF;CACpF,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAE/C,MAAM,aAAa,OAAO,SAAiB;AACzC,MAAI;AACF,SAAM,OAAO,UAAU,UAAU,UAAU,KAAK;AAChD,eAAY,KAAK;AACjB,aAAU;AACV,SAAM,QAAQ,EAAE,4BAA4B,CAAC;AAC7C,oBAAiB,YAAY,MAAM,EAAE,oBAAoB;WAClD,OAAO;AACd,SAAM,MAAM,EAAE,0BAA0B,CAAC;AACzC,WAAQ,MAAM,MAAM;;;AAIxB,QACE,oBAAC,QAAD;EAAoB;EAAY,eAAe,WAAW,KAAK;EAAE,GAAI;YAClE,WACC,qBAAA,
|
|
1
|
+
{"version":3,"file":"CopyButton.mjs","names":[],"sources":["../../../src/components/CopyButton.tsx"],"sourcesContent":["import { Button, type ButtonProps } from \"@heroui/react\";\r\nimport { CheckCircle, Copy } from \"lucide-react\";\r\nimport { useState } from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\nimport { toast } from \"sonner\";\r\n\r\nexport function CopyButton({\r\n text,\r\n notificationTimeout = 1000,\r\n isIconOnly,\r\n onCopy,\r\n ...props\r\n}: ButtonProps & { text: string; notificationTimeout?: number; onCopy?: () => void }) {\r\n const { t } = useTranslation();\r\n const [isCopied, setIsCopied] = useState(false);\r\n\r\n const handleCopy = async (text: string) => {\r\n try {\r\n await window.navigator.clipboard.writeText(text);\r\n setIsCopied(true);\r\n onCopy?.();\r\n toast.success(t(\"web-ui:common.copySuccess\"));\r\n setTimeout(() => setIsCopied(false), notificationTimeout);\r\n } catch (error) {\r\n toast.error(t(\"web-ui:common.copyError\"));\r\n console.error(error);\r\n }\r\n };\r\n\r\n return (\r\n <Button isIconOnly={isIconOnly} onPress={() => handleCopy(text)} {...props}>\r\n {isCopied ? (\r\n <>\r\n <CheckCircle className=\"h-4 w-4\" />\r\n {!isIconOnly && t(\"web-ui:common.copied\")}\r\n </>\r\n ) : (\r\n <>\r\n <Copy className=\"h-4 w-4\" />\r\n {!isIconOnly && t(\"web-ui:common.copy\")}\r\n </>\r\n )}\r\n </Button>\r\n );\r\n}\r\n"],"mappings":";;;;;;;AAMA,SAAgB,WAAW,EACzB,MACA,sBAAsB,KACtB,YACA,QACA,GAAG,SACiF;CACpF,MAAM,EAAE,MAAM,gBAAgB;CAC9B,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAE/C,MAAM,aAAa,OAAO,SAAiB;AACzC,MAAI;AACF,SAAM,OAAO,UAAU,UAAU,UAAU,KAAK;AAChD,eAAY,KAAK;AACjB,aAAU;AACV,SAAM,QAAQ,EAAE,4BAA4B,CAAC;AAC7C,oBAAiB,YAAY,MAAM,EAAE,oBAAoB;WAClD,OAAO;AACd,SAAM,MAAM,EAAE,0BAA0B,CAAC;AACzC,WAAQ,MAAM,MAAM;;;AAIxB,QACE,oBAAC,QAAD;EAAoB;EAAY,eAAe,WAAW,KAAK;EAAE,GAAI;YAClE,WACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,aAAD,EAAa,WAAU,WAAY,CAAA,EAClC,CAAC,cAAc,EAAE,uBAAuB,CACxC,EAAA,CAAA,GAEH,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,MAAD,EAAM,WAAU,WAAY,CAAA,EAC3B,CAAC,cAAc,EAAE,qBAAqB,CACtC,EAAA,CAAA;EAEE,CAAA"}
|
|
@@ -3,12 +3,12 @@ const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
|
3
3
|
const require_src_components_ui_button = require("./ui/button.js");
|
|
4
4
|
const require_src_components_ui_dialog = require("./ui/dialog.js");
|
|
5
5
|
const require_src_components_ui_slider = require("./ui/slider.js");
|
|
6
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let react = require("react");
|
|
8
6
|
let lucide_react = require("lucide-react");
|
|
7
|
+
let react = require("react");
|
|
9
8
|
let react_i18next = require("react-i18next");
|
|
10
9
|
let react_easy_crop = require("react-easy-crop");
|
|
11
10
|
react_easy_crop = require_runtime.__toESM(react_easy_crop);
|
|
11
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
12
12
|
//#region src/components/CropDialog.tsx
|
|
13
13
|
async function getCroppedImg(imageSrc, pixelCrop, t) {
|
|
14
14
|
const image = new Image();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { Button } from "./ui/button.mjs";
|
|
2
2
|
import { Dialog, DialogContent, DialogHeader, DialogTitle } from "./ui/dialog.mjs";
|
|
3
3
|
import { Slider } from "./ui/slider.mjs";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { useState } from "react";
|
|
6
4
|
import { ZoomIn, ZoomOut } from "lucide-react";
|
|
5
|
+
import { useState } from "react";
|
|
7
6
|
import { useTranslation } from "react-i18next";
|
|
8
7
|
import Cropper from "react-easy-crop";
|
|
8
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region src/components/CropDialog.tsx
|
|
10
10
|
async function getCroppedImg(imageSrc, pixelCrop, t) {
|
|
11
11
|
const image = new Image();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
require("../../_virtual/_rolldown/runtime.js");
|
|
3
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
3
|
let react = require("react");
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
5
|
let _heroui_react = require("@heroui/react");
|
|
6
6
|
let _heroui_theme = require("@heroui/theme");
|
|
7
7
|
//#region src/components/DialogProvider.tsx
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
2
1
|
import { createContext, useContext, useRef, useState } from "react";
|
|
2
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { Button, Modal, ModalBody, ModalContent, ModalFooter, ModalHeader } from "@heroui/react";
|
|
4
4
|
import { semanticColors } from "@heroui/theme";
|
|
5
5
|
//#region src/components/DialogProvider.tsx
|
|
@@ -43,7 +43,7 @@ function DialogProvider({ children }) {
|
|
|
43
43
|
};
|
|
44
44
|
return /* @__PURE__ */ jsx(DialogContext.Provider, {
|
|
45
45
|
value: handleSetDialog,
|
|
46
|
-
children: /* @__PURE__ */ jsxs(Fragment, { children: [children, dialog && /* @__PURE__ */ jsx(Modal, {
|
|
46
|
+
children: /* @__PURE__ */ jsxs(Fragment$1, { children: [children, dialog && /* @__PURE__ */ jsx(Modal, {
|
|
47
47
|
isOpen,
|
|
48
48
|
onOpenChange: handleUnsetDialog,
|
|
49
49
|
style: { borderColor: semanticColors.light[dialog.color || "danger"][600] },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DialogProvider.mjs","names":[],"sources":["../../../src/components/DialogProvider.tsx"],"sourcesContent":["import {\r\n Button,\r\n type ButtonProps,\r\n Modal,\r\n ModalBody,\r\n ModalContent,\r\n ModalFooter,\r\n ModalHeader,\r\n} from \"@heroui/react\";\r\nimport { semanticColors } from \"@heroui/theme\";\r\nimport { createContext, useContext, useRef, useState } from \"react\";\r\n\r\nexport type DialogProps = {\r\n title: React.ReactNode;\r\n description: React.ReactNode;\r\n color?: ButtonProps[\"color\"];\r\n cancelable?: boolean;\r\n onCancel?: () => void;\r\n onConfirm?: () => void;\r\n cancelLabel?: string;\r\n confirmLabel?: string;\r\n};\r\n\r\nconst DialogContext = createContext<(dialog: DialogProps) => void>(() => {\r\n console.warn(\"DialogProvider is not initialized\");\r\n});\r\n\r\nexport function useDialog() {\r\n const context = useContext(DialogContext);\r\n if (!context) {\r\n throw new Error(\"useDialog must be used within a DialogProvider\");\r\n }\r\n return context;\r\n}\r\n\r\nexport function DialogProvider({ children }: { children: React.ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [dialog, setDialog] = useState<DialogProps | null>(null);\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n const handleSetDialog = (dialog: DialogProps) => {\r\n if (timeoutRef.current) {\r\n clearTimeout(timeoutRef.current);\r\n timeoutRef.current = null;\r\n }\r\n setDialog(dialog);\r\n setIsOpen(true);\r\n };\r\n\r\n const handleUnsetDialog = () => {\r\n setIsOpen(false);\r\n if (timeoutRef.current) {\r\n clearTimeout(timeoutRef.current);\r\n timeoutRef.current = null;\r\n }\r\n timeoutRef.current = setTimeout(() => {\r\n setDialog(null);\r\n }, 500);\r\n };\r\n\r\n const handleCancel = () => {\r\n dialog?.onCancel?.();\r\n handleUnsetDialog();\r\n };\r\n\r\n const handleConfirm = () => {\r\n dialog?.onConfirm?.();\r\n handleUnsetDialog();\r\n };\r\n\r\n return (\r\n <DialogContext.Provider value={handleSetDialog}>\r\n <>\r\n {children}\r\n {dialog && (\r\n <Modal\r\n isOpen={isOpen}\r\n onOpenChange={handleUnsetDialog}\r\n style={{\r\n borderColor: semanticColors.light[dialog.color || \"danger\"][600],\r\n }}\r\n classNames={{\r\n base: \"border-1\",\r\n }}\r\n >\r\n <ModalContent>\r\n <ModalHeader>{dialog.title}</ModalHeader>\r\n <ModalBody>{dialog.description}</ModalBody>\r\n <ModalFooter>\r\n <div className=\"flex flex-row gap-2\">\r\n {(dialog.cancelable || dialog.onCancel) && (\r\n <Button onPress={handleCancel}>{dialog.cancelLabel ?? \"Cancel\"}</Button>\r\n )}\r\n <Button color={dialog.color} onPress={handleConfirm}>\r\n {dialog.confirmLabel ?? \"Confirm\"}\r\n </Button>\r\n </div>\r\n </ModalFooter>\r\n </ModalContent>\r\n </Modal>\r\n )}\r\n </>\r\n </DialogContext.Provider>\r\n );\r\n}\r\n"],"mappings":";;;;;AAuBA,MAAM,gBAAgB,oBAAmD;AACvE,SAAQ,KAAK,oCAAoC;EACjD;AAEF,SAAgB,YAAY;CAC1B,MAAM,UAAU,WAAW,cAAc;AACzC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,iDAAiD;AAEnE,QAAO;;AAGT,SAAgB,eAAe,EAAE,YAA2C;CAC1E,MAAM,CAAC,QAAQ,aAAa,SAAS,MAAM;CAC3C,MAAM,CAAC,QAAQ,aAAa,SAA6B,KAAK;CAC9D,MAAM,aAAa,OAA6C,KAAK;CAErE,MAAM,mBAAmB,WAAwB;AAC/C,MAAI,WAAW,SAAS;AACtB,gBAAa,WAAW,QAAQ;AAChC,cAAW,UAAU;;AAEvB,YAAU,OAAO;AACjB,YAAU,KAAK;;CAGjB,MAAM,0BAA0B;AAC9B,YAAU,MAAM;AAChB,MAAI,WAAW,SAAS;AACtB,gBAAa,WAAW,QAAQ;AAChC,cAAW,UAAU;;AAEvB,aAAW,UAAU,iBAAiB;AACpC,aAAU,KAAK;KACd,IAAI;;CAGT,MAAM,qBAAqB;AACzB,UAAQ,YAAY;AACpB,qBAAmB;;CAGrB,MAAM,sBAAsB;AAC1B,UAAQ,aAAa;AACrB,qBAAmB;;AAGrB,QACE,oBAAC,cAAc,UAAf;EAAwB,OAAO;YAC7B,qBAAA,
|
|
1
|
+
{"version":3,"file":"DialogProvider.mjs","names":[],"sources":["../../../src/components/DialogProvider.tsx"],"sourcesContent":["import {\r\n Button,\r\n type ButtonProps,\r\n Modal,\r\n ModalBody,\r\n ModalContent,\r\n ModalFooter,\r\n ModalHeader,\r\n} from \"@heroui/react\";\r\nimport { semanticColors } from \"@heroui/theme\";\r\nimport { createContext, useContext, useRef, useState } from \"react\";\r\n\r\nexport type DialogProps = {\r\n title: React.ReactNode;\r\n description: React.ReactNode;\r\n color?: ButtonProps[\"color\"];\r\n cancelable?: boolean;\r\n onCancel?: () => void;\r\n onConfirm?: () => void;\r\n cancelLabel?: string;\r\n confirmLabel?: string;\r\n};\r\n\r\nconst DialogContext = createContext<(dialog: DialogProps) => void>(() => {\r\n console.warn(\"DialogProvider is not initialized\");\r\n});\r\n\r\nexport function useDialog() {\r\n const context = useContext(DialogContext);\r\n if (!context) {\r\n throw new Error(\"useDialog must be used within a DialogProvider\");\r\n }\r\n return context;\r\n}\r\n\r\nexport function DialogProvider({ children }: { children: React.ReactNode }) {\r\n const [isOpen, setIsOpen] = useState(false);\r\n const [dialog, setDialog] = useState<DialogProps | null>(null);\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n const handleSetDialog = (dialog: DialogProps) => {\r\n if (timeoutRef.current) {\r\n clearTimeout(timeoutRef.current);\r\n timeoutRef.current = null;\r\n }\r\n setDialog(dialog);\r\n setIsOpen(true);\r\n };\r\n\r\n const handleUnsetDialog = () => {\r\n setIsOpen(false);\r\n if (timeoutRef.current) {\r\n clearTimeout(timeoutRef.current);\r\n timeoutRef.current = null;\r\n }\r\n timeoutRef.current = setTimeout(() => {\r\n setDialog(null);\r\n }, 500);\r\n };\r\n\r\n const handleCancel = () => {\r\n dialog?.onCancel?.();\r\n handleUnsetDialog();\r\n };\r\n\r\n const handleConfirm = () => {\r\n dialog?.onConfirm?.();\r\n handleUnsetDialog();\r\n };\r\n\r\n return (\r\n <DialogContext.Provider value={handleSetDialog}>\r\n <>\r\n {children}\r\n {dialog && (\r\n <Modal\r\n isOpen={isOpen}\r\n onOpenChange={handleUnsetDialog}\r\n style={{\r\n borderColor: semanticColors.light[dialog.color || \"danger\"][600],\r\n }}\r\n classNames={{\r\n base: \"border-1\",\r\n }}\r\n >\r\n <ModalContent>\r\n <ModalHeader>{dialog.title}</ModalHeader>\r\n <ModalBody>{dialog.description}</ModalBody>\r\n <ModalFooter>\r\n <div className=\"flex flex-row gap-2\">\r\n {(dialog.cancelable || dialog.onCancel) && (\r\n <Button onPress={handleCancel}>{dialog.cancelLabel ?? \"Cancel\"}</Button>\r\n )}\r\n <Button color={dialog.color} onPress={handleConfirm}>\r\n {dialog.confirmLabel ?? \"Confirm\"}\r\n </Button>\r\n </div>\r\n </ModalFooter>\r\n </ModalContent>\r\n </Modal>\r\n )}\r\n </>\r\n </DialogContext.Provider>\r\n );\r\n}\r\n"],"mappings":";;;;;AAuBA,MAAM,gBAAgB,oBAAmD;AACvE,SAAQ,KAAK,oCAAoC;EACjD;AAEF,SAAgB,YAAY;CAC1B,MAAM,UAAU,WAAW,cAAc;AACzC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,iDAAiD;AAEnE,QAAO;;AAGT,SAAgB,eAAe,EAAE,YAA2C;CAC1E,MAAM,CAAC,QAAQ,aAAa,SAAS,MAAM;CAC3C,MAAM,CAAC,QAAQ,aAAa,SAA6B,KAAK;CAC9D,MAAM,aAAa,OAA6C,KAAK;CAErE,MAAM,mBAAmB,WAAwB;AAC/C,MAAI,WAAW,SAAS;AACtB,gBAAa,WAAW,QAAQ;AAChC,cAAW,UAAU;;AAEvB,YAAU,OAAO;AACjB,YAAU,KAAK;;CAGjB,MAAM,0BAA0B;AAC9B,YAAU,MAAM;AAChB,MAAI,WAAW,SAAS;AACtB,gBAAa,WAAW,QAAQ;AAChC,cAAW,UAAU;;AAEvB,aAAW,UAAU,iBAAiB;AACpC,aAAU,KAAK;KACd,IAAI;;CAGT,MAAM,qBAAqB;AACzB,UAAQ,YAAY;AACpB,qBAAmB;;CAGrB,MAAM,sBAAsB;AAC1B,UAAQ,aAAa;AACrB,qBAAmB;;AAGrB,QACE,oBAAC,cAAc,UAAf;EAAwB,OAAO;YAC7B,qBAAA,YAAA,EAAA,UAAA,CACG,UACA,UACC,oBAAC,OAAD;GACU;GACR,cAAc;GACd,OAAO,EACL,aAAa,eAAe,MAAM,OAAO,SAAS,UAAU,MAC7D;GACD,YAAY,EACV,MAAM,YACP;aAED,qBAAC,cAAD,EAAA,UAAA;IACE,oBAAC,aAAD,EAAA,UAAc,OAAO,OAAoB,CAAA;IACzC,oBAAC,WAAD,EAAA,UAAY,OAAO,aAAwB,CAAA;IAC3C,oBAAC,aAAD,EAAA,UACE,qBAAC,OAAD;KAAK,WAAU;eAAf,EACI,OAAO,cAAc,OAAO,aAC5B,oBAAC,QAAD;MAAQ,SAAS;gBAAe,OAAO,eAAe;MAAkB,CAAA,EAE1E,oBAAC,QAAD;MAAQ,OAAO,OAAO;MAAO,SAAS;gBACnC,OAAO,gBAAgB;MACjB,CAAA,CACL;QACM,CAAA;IACD,EAAA,CAAA;GACT,CAAA,CAET,EAAA,CAAA;EACoB,CAAA"}
|
|
@@ -3,9 +3,9 @@ require("../../_virtual/_rolldown/runtime.js");
|
|
|
3
3
|
const require_src_lib_utils = require("../lib/utils.js");
|
|
4
4
|
const require_src_components_ui_button = require("./ui/button.js");
|
|
5
5
|
const require_src_components_ui_progress = require("./ui/progress.js");
|
|
6
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
7
|
-
let react = require("react");
|
|
8
6
|
let lucide_react = require("lucide-react");
|
|
7
|
+
let react = require("react");
|
|
8
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
9
|
let react_dropzone = require("react-dropzone");
|
|
10
10
|
//#region src/components/FileDropzone.tsx
|
|
11
11
|
function FileDropzone({ onUploadComplete, className }) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.mjs";
|
|
2
2
|
import { Button } from "./ui/button.mjs";
|
|
3
3
|
import { Progress } from "./ui/progress.mjs";
|
|
4
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { useCallback, useState } from "react";
|
|
6
4
|
import { File, Upload, X } from "lucide-react";
|
|
5
|
+
import { useCallback, useState } from "react";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
import { useDropzone } from "react-dropzone";
|
|
8
8
|
//#region src/components/FileDropzone.tsx
|
|
9
9
|
function FileDropzone({ onUploadComplete, className }) {
|
|
@@ -55,7 +55,7 @@ function FileDropzone({ onUploadComplete, className }) {
|
|
|
55
55
|
className: cn("border-2 border-dashed rounded-lg p-6 cursor-pointer transition-colors", isDragActive ? "border-primary bg-primary/5" : "border-gray-300 hover:border-primary", selectedFile && "border-primary"),
|
|
56
56
|
children: [/* @__PURE__ */ jsx("input", { ...getInputProps() }), /* @__PURE__ */ jsx("div", {
|
|
57
57
|
className: "flex flex-col items-center justify-center space-y-2 text-center",
|
|
58
|
-
children: selectedFile ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(File, { className: "h-8 w-8 text-primary" }), /* @__PURE__ */ jsxs("div", {
|
|
58
|
+
children: selectedFile ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(File, { className: "h-8 w-8 text-primary" }), /* @__PURE__ */ jsxs("div", {
|
|
59
59
|
className: "flex items-center gap-2",
|
|
60
60
|
children: [/* @__PURE__ */ jsx("span", {
|
|
61
61
|
className: "text-sm text-gray-600",
|
|
@@ -69,7 +69,7 @@ function FileDropzone({ onUploadComplete, className }) {
|
|
|
69
69
|
className: "p-1 hover:bg-gray-100 rounded-full",
|
|
70
70
|
children: /* @__PURE__ */ jsx(X, { className: "h-4 w-4 text-gray-500" })
|
|
71
71
|
})]
|
|
72
|
-
})] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72
|
+
})] }) : /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
73
73
|
/* @__PURE__ */ jsx(Upload, { className: "h-8 w-8 text-gray-400" }),
|
|
74
74
|
/* @__PURE__ */ jsx("p", {
|
|
75
75
|
className: "text-sm text-gray-600",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileDropzone.mjs","names":[],"sources":["../../../src/components/FileDropzone.tsx"],"sourcesContent":["import { File, Upload, X } from \"lucide-react\";\r\nimport { useCallback, useState } from \"react\";\r\nimport { useDropzone } from \"react-dropzone\";\r\nimport { Button } from \"./ui/button\";\r\nimport { Progress } from \"./ui/progress\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface FileDropzoneProps {\r\n onUploadComplete?: (filePath: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function FileDropzone({ onUploadComplete, className }: FileDropzoneProps) {\r\n const [uploadProgress, setUploadProgress] = useState(0);\r\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\r\n const [isUploading, setIsUploading] = useState(false);\r\n\r\n const onDrop = useCallback((acceptedFiles: File[]) => {\r\n if (acceptedFiles.length > 0) {\r\n setSelectedFile(acceptedFiles[0]);\r\n }\r\n }, []);\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n onDrop,\r\n accept: {\r\n \"image/jpeg\": [],\r\n \"image/png\": [],\r\n \"image/webp\": [],\r\n \"image/jpg\": [],\r\n },\r\n maxFiles: 1,\r\n });\r\n\r\n const uploadFile = async () => {\r\n if (!selectedFile) return;\r\n\r\n setIsUploading(true);\r\n setUploadProgress(0);\r\n\r\n const formData = new FormData();\r\n formData.append(\"file\", selectedFile);\r\n\r\n try {\r\n const response = await fetch(\"/api/upload/image\", {\r\n method: \"POST\",\r\n body: formData,\r\n // Note: Content-Type is automatically set for FormData\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n onUploadComplete?.(data.filePath);\r\n setSelectedFile(null);\r\n setUploadProgress(0);\r\n } catch (error) {\r\n console.error(\"Upload error:\", error);\r\n } finally {\r\n setIsUploading(false);\r\n }\r\n };\r\n\r\n const removeFile = () => {\r\n setSelectedFile(null);\r\n setUploadProgress(0);\r\n };\r\n\r\n return (\r\n <div className={cn(\"w-full max-w-xl\", className)}>\r\n <div\r\n {...getRootProps()}\r\n className={cn(\r\n \"border-2 border-dashed rounded-lg p-6 cursor-pointer transition-colors\",\r\n isDragActive ? \"border-primary bg-primary/5\" : \"border-gray-300 hover:border-primary\",\r\n selectedFile && \"border-primary\"\r\n )}\r\n >\r\n <input {...getInputProps()} />\r\n <div className=\"flex flex-col items-center justify-center space-y-2 text-center\">\r\n {selectedFile ? (\r\n <>\r\n <File className=\"h-8 w-8 text-primary\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-gray-600\">{selectedFile.name}</span>\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n removeFile();\r\n }}\r\n className=\"p-1 hover:bg-gray-100 rounded-full\"\r\n >\r\n <X className=\"h-4 w-4 text-gray-500\" />\r\n </button>\r\n </div>\r\n </>\r\n ) : (\r\n <>\r\n <Upload className=\"h-8 w-8 text-gray-400\" />\r\n <p className=\"text-sm text-gray-600\">Drag & drop an image here, or click to select</p>\r\n <p className=\"text-xs text-gray-500\">Supports JPG, PNG, and WebP</p>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {selectedFile && (\r\n <div className=\"mt-4 space-y-4\">\r\n {isUploading && <Progress value={uploadProgress} className=\"h-2 w-full\" />}\r\n <Button onClick={uploadFile} disabled={isUploading} className=\"w-full\">\r\n {isUploading ? \"Uploading...\" : \"Upload File\"}\r\n </Button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"mappings":";;;;;;;;AAYA,SAAgB,aAAa,EAAE,kBAAkB,aAAgC;CAC/E,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,EAAE;CACvD,MAAM,CAAC,cAAc,mBAAmB,SAAsB,KAAK;CACnE,MAAM,CAAC,aAAa,kBAAkB,SAAS,MAAM;CAQrD,MAAM,EAAE,cAAc,eAAe,iBAAiB,YAAY;EAChE,QAPa,aAAa,kBAA0B;AACpD,OAAI,cAAc,SAAS,EACzB,iBAAgB,cAAc,GAAG;KAElC,EAAE,CAAC;EAIJ,QAAQ;GACN,cAAc,EAAE;GAChB,aAAa,EAAE;GACf,cAAc,EAAE;GAChB,aAAa,EAAE;GAChB;EACD,UAAU;EACX,CAAC;CAEF,MAAM,aAAa,YAAY;AAC7B,MAAI,CAAC,aAAc;AAEnB,iBAAe,KAAK;AACpB,oBAAkB,EAAE;EAEpB,MAAM,WAAW,IAAI,UAAU;AAC/B,WAAS,OAAO,QAAQ,aAAa;AAErC,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,qBAAqB;IAChD,QAAQ;IACR,MAAM;IAEP,CAAC;AAEF,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,uBAAuB,SAAS,SAAS;GAG3D,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,sBAAmB,KAAK,SAAS;AACjC,mBAAgB,KAAK;AACrB,qBAAkB,EAAE;WACb,OAAO;AACd,WAAQ,MAAM,iBAAiB,MAAM;YAC7B;AACR,kBAAe,MAAM;;;CAIzB,MAAM,mBAAmB;AACvB,kBAAgB,KAAK;AACrB,oBAAkB,EAAE;;AAGtB,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,mBAAmB,UAAU;YAAhD,CACE,qBAAC,OAAD;GACE,GAAI,cAAc;GAClB,WAAW,GACT,0EACA,eAAe,gCAAgC,wCAC/C,gBAAgB,iBACjB;aANH,CAQE,oBAAC,SAAD,EAAO,GAAI,eAAe,EAAI,CAAA,EAC9B,oBAAC,OAAD;IAAK,WAAU;cACZ,eACC,qBAAA,
|
|
1
|
+
{"version":3,"file":"FileDropzone.mjs","names":[],"sources":["../../../src/components/FileDropzone.tsx"],"sourcesContent":["import { File, Upload, X } from \"lucide-react\";\r\nimport { useCallback, useState } from \"react\";\r\nimport { useDropzone } from \"react-dropzone\";\r\nimport { Button } from \"./ui/button\";\r\nimport { Progress } from \"./ui/progress\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface FileDropzoneProps {\r\n onUploadComplete?: (filePath: string) => void;\r\n className?: string;\r\n}\r\n\r\nexport function FileDropzone({ onUploadComplete, className }: FileDropzoneProps) {\r\n const [uploadProgress, setUploadProgress] = useState(0);\r\n const [selectedFile, setSelectedFile] = useState<File | null>(null);\r\n const [isUploading, setIsUploading] = useState(false);\r\n\r\n const onDrop = useCallback((acceptedFiles: File[]) => {\r\n if (acceptedFiles.length > 0) {\r\n setSelectedFile(acceptedFiles[0]);\r\n }\r\n }, []);\r\n\r\n const { getRootProps, getInputProps, isDragActive } = useDropzone({\r\n onDrop,\r\n accept: {\r\n \"image/jpeg\": [],\r\n \"image/png\": [],\r\n \"image/webp\": [],\r\n \"image/jpg\": [],\r\n },\r\n maxFiles: 1,\r\n });\r\n\r\n const uploadFile = async () => {\r\n if (!selectedFile) return;\r\n\r\n setIsUploading(true);\r\n setUploadProgress(0);\r\n\r\n const formData = new FormData();\r\n formData.append(\"file\", selectedFile);\r\n\r\n try {\r\n const response = await fetch(\"/api/upload/image\", {\r\n method: \"POST\",\r\n body: formData,\r\n // Note: Content-Type is automatically set for FormData\r\n });\r\n\r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`);\r\n }\r\n\r\n const data = await response.json();\r\n onUploadComplete?.(data.filePath);\r\n setSelectedFile(null);\r\n setUploadProgress(0);\r\n } catch (error) {\r\n console.error(\"Upload error:\", error);\r\n } finally {\r\n setIsUploading(false);\r\n }\r\n };\r\n\r\n const removeFile = () => {\r\n setSelectedFile(null);\r\n setUploadProgress(0);\r\n };\r\n\r\n return (\r\n <div className={cn(\"w-full max-w-xl\", className)}>\r\n <div\r\n {...getRootProps()}\r\n className={cn(\r\n \"border-2 border-dashed rounded-lg p-6 cursor-pointer transition-colors\",\r\n isDragActive ? \"border-primary bg-primary/5\" : \"border-gray-300 hover:border-primary\",\r\n selectedFile && \"border-primary\"\r\n )}\r\n >\r\n <input {...getInputProps()} />\r\n <div className=\"flex flex-col items-center justify-center space-y-2 text-center\">\r\n {selectedFile ? (\r\n <>\r\n <File className=\"h-8 w-8 text-primary\" />\r\n <div className=\"flex items-center gap-2\">\r\n <span className=\"text-sm text-gray-600\">{selectedFile.name}</span>\r\n <button\r\n type=\"button\"\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n removeFile();\r\n }}\r\n className=\"p-1 hover:bg-gray-100 rounded-full\"\r\n >\r\n <X className=\"h-4 w-4 text-gray-500\" />\r\n </button>\r\n </div>\r\n </>\r\n ) : (\r\n <>\r\n <Upload className=\"h-8 w-8 text-gray-400\" />\r\n <p className=\"text-sm text-gray-600\">Drag & drop an image here, or click to select</p>\r\n <p className=\"text-xs text-gray-500\">Supports JPG, PNG, and WebP</p>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {selectedFile && (\r\n <div className=\"mt-4 space-y-4\">\r\n {isUploading && <Progress value={uploadProgress} className=\"h-2 w-full\" />}\r\n <Button onClick={uploadFile} disabled={isUploading} className=\"w-full\">\r\n {isUploading ? \"Uploading...\" : \"Upload File\"}\r\n </Button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"mappings":";;;;;;;;AAYA,SAAgB,aAAa,EAAE,kBAAkB,aAAgC;CAC/E,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,EAAE;CACvD,MAAM,CAAC,cAAc,mBAAmB,SAAsB,KAAK;CACnE,MAAM,CAAC,aAAa,kBAAkB,SAAS,MAAM;CAQrD,MAAM,EAAE,cAAc,eAAe,iBAAiB,YAAY;EAChE,QAPa,aAAa,kBAA0B;AACpD,OAAI,cAAc,SAAS,EACzB,iBAAgB,cAAc,GAAG;KAElC,EAAE,CAAC;EAIJ,QAAQ;GACN,cAAc,EAAE;GAChB,aAAa,EAAE;GACf,cAAc,EAAE;GAChB,aAAa,EAAE;GAChB;EACD,UAAU;EACX,CAAC;CAEF,MAAM,aAAa,YAAY;AAC7B,MAAI,CAAC,aAAc;AAEnB,iBAAe,KAAK;AACpB,oBAAkB,EAAE;EAEpB,MAAM,WAAW,IAAI,UAAU;AAC/B,WAAS,OAAO,QAAQ,aAAa;AAErC,MAAI;GACF,MAAM,WAAW,MAAM,MAAM,qBAAqB;IAChD,QAAQ;IACR,MAAM;IAEP,CAAC;AAEF,OAAI,CAAC,SAAS,GACZ,OAAM,IAAI,MAAM,uBAAuB,SAAS,SAAS;GAG3D,MAAM,OAAO,MAAM,SAAS,MAAM;AAClC,sBAAmB,KAAK,SAAS;AACjC,mBAAgB,KAAK;AACrB,qBAAkB,EAAE;WACb,OAAO;AACd,WAAQ,MAAM,iBAAiB,MAAM;YAC7B;AACR,kBAAe,MAAM;;;CAIzB,MAAM,mBAAmB;AACvB,kBAAgB,KAAK;AACrB,oBAAkB,EAAE;;AAGtB,QACE,qBAAC,OAAD;EAAK,WAAW,GAAG,mBAAmB,UAAU;YAAhD,CACE,qBAAC,OAAD;GACE,GAAI,cAAc;GAClB,WAAW,GACT,0EACA,eAAe,gCAAgC,wCAC/C,gBAAgB,iBACjB;aANH,CAQE,oBAAC,SAAD,EAAO,GAAI,eAAe,EAAI,CAAA,EAC9B,oBAAC,OAAD;IAAK,WAAU;cACZ,eACC,qBAAA,YAAA,EAAA,UAAA,CACE,oBAAC,MAAD,EAAM,WAAU,wBAAyB,CAAA,EACzC,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,oBAAC,QAAD;MAAM,WAAU;gBAAyB,aAAa;MAAY,CAAA,EAClE,oBAAC,UAAD;MACE,MAAK;MACL,UAAU,MAAM;AACd,SAAE,iBAAiB;AACnB,mBAAY;;MAEd,WAAU;gBAEV,oBAAC,GAAD,EAAG,WAAU,yBAA0B,CAAA;MAChC,CAAA,CACL;OACL,EAAA,CAAA,GAEH,qBAAA,YAAA,EAAA,UAAA;KACE,oBAAC,QAAD,EAAQ,WAAU,yBAA0B,CAAA;KAC5C,oBAAC,KAAD;MAAG,WAAU;gBAAwB;MAAiD,CAAA;KACtF,oBAAC,KAAD;MAAG,WAAU;gBAAwB;MAA+B,CAAA;KACnE,EAAA,CAAA;IAED,CAAA,CACF;MAEL,gBACC,qBAAC,OAAD;GAAK,WAAU;aAAf,CACG,eAAe,oBAAC,UAAD;IAAU,OAAO;IAAgB,WAAU;IAAe,CAAA,EAC1E,oBAAC,QAAD;IAAQ,SAAS;IAAY,UAAU;IAAa,WAAU;cAC3D,cAAc,iBAAiB;IACzB,CAAA,CACL;KAEJ"}
|
|
@@ -3,10 +3,10 @@ const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
|
3
3
|
const require_src_lib_utils = require("../lib/utils.js");
|
|
4
4
|
const require_src_components_ui_button = require("./ui/button.js");
|
|
5
5
|
const require_src_components_ui_dropdown_menu = require("./ui/dropdown-menu.js");
|
|
6
|
-
let
|
|
6
|
+
let lucide_react = require("lucide-react");
|
|
7
7
|
let react = require("react");
|
|
8
8
|
react = require_runtime.__toESM(react);
|
|
9
|
-
let
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
10
10
|
//#region src/components/MultiSelectDropdown.tsx
|
|
11
11
|
const MultiSelectDropdown = react.forwardRef(({ options, selectedValues, onValueChange, placeholder = "Select items...", label, className, triggerClassName, trigger, multiSelectLabel, disabled = false, maxDisplayCount = 3, resetButton = "bottom", resetLabel = "Reset", separateGroups = false, ...props }, ref) => {
|
|
12
12
|
const handleValueChange = (value, checked) => {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { cn } from "../lib/utils.mjs";
|
|
2
2
|
import { Button } from "./ui/button.mjs";
|
|
3
3
|
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from "./ui/dropdown-menu.mjs";
|
|
4
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import * as React$1 from "react";
|
|
6
4
|
import { ChevronDown, RotateCcw } from "lucide-react";
|
|
5
|
+
import * as React$1 from "react";
|
|
6
|
+
import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
|
|
7
7
|
//#region src/components/MultiSelectDropdown.tsx
|
|
8
8
|
const MultiSelectDropdown = React$1.forwardRef(({ options, selectedValues, onValueChange, placeholder = "Select items...", label, className, triggerClassName, trigger, multiSelectLabel, disabled = false, maxDisplayCount = 3, resetButton = "bottom", resetLabel = "Reset", separateGroups = false, ...props }, ref) => {
|
|
9
9
|
const handleValueChange = (value, checked) => {
|
|
@@ -44,7 +44,7 @@ const MultiSelectDropdown = React$1.forwardRef(({ options, selectedValues, onVal
|
|
|
44
44
|
className: cn("w-full justify-between text-left font-normal", selectedValues.length === 0 && "text-muted-foreground", triggerClassName),
|
|
45
45
|
disabled,
|
|
46
46
|
...props,
|
|
47
|
-
children: trigger || /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
|
|
47
|
+
children: trigger || /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
48
48
|
className: "truncate",
|
|
49
49
|
children: getDisplayText()
|
|
50
50
|
}), /* @__PURE__ */ jsx(ChevronDown, { className: "ml-2 h-4 w-4 shrink-0 opacity-50" })] })
|
|
@@ -53,14 +53,14 @@ const MultiSelectDropdown = React$1.forwardRef(({ options, selectedValues, onVal
|
|
|
53
53
|
className: "w-full min-w-[var(--radix-dropdown-menu-trigger-width)]",
|
|
54
54
|
align: "start",
|
|
55
55
|
children: [
|
|
56
|
-
resetButton && resetButton === "top" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
56
|
+
resetButton && resetButton === "top" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
57
57
|
onClick: handleReset,
|
|
58
58
|
disabled: selectedValues.length === 0,
|
|
59
59
|
onSelect: (event) => event.preventDefault(),
|
|
60
60
|
className: "cursor-pointer text-muted-foreground hover:text-foreground",
|
|
61
|
-
children: resetLabel || /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), "Reset"] })
|
|
61
|
+
children: resetLabel || /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), "Reset"] })
|
|
62
62
|
}), /* @__PURE__ */ jsx(DropdownMenuSeparator, {})] }),
|
|
63
|
-
label && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: label }), /* @__PURE__ */ jsx(DropdownMenuSeparator, {})] }),
|
|
63
|
+
label && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuLabel, { children: label }), /* @__PURE__ */ jsx(DropdownMenuSeparator, {})] }),
|
|
64
64
|
Object.entries(groupedOptions.groups).map(([groupName, groupOptions], groupIndex) => /* @__PURE__ */ jsxs(DropdownMenuGroup, { children: [
|
|
65
65
|
groupIndex > 0 && separateGroups && /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
|
|
66
66
|
/* @__PURE__ */ jsx(DropdownMenuLabel, {
|
|
@@ -85,12 +85,12 @@ const MultiSelectDropdown = React$1.forwardRef(({ options, selectedValues, onVal
|
|
|
85
85
|
className: "cursor-pointer",
|
|
86
86
|
children: option.label
|
|
87
87
|
}, option.value))] }),
|
|
88
|
-
resetButton && resetButton === "bottom" && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), /* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
88
|
+
resetButton && resetButton === "bottom" && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), /* @__PURE__ */ jsx(DropdownMenuItem, {
|
|
89
89
|
onClick: handleReset,
|
|
90
90
|
disabled: selectedValues.length === 0,
|
|
91
91
|
onSelect: (event) => event.preventDefault(),
|
|
92
92
|
className: "cursor-pointer text-muted-foreground hover:text-foreground",
|
|
93
|
-
children: resetLabel || /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), "Reset"] })
|
|
93
|
+
children: resetLabel || /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(RotateCcw, { className: "mr-2 h-4 w-4" }), "Reset"] })
|
|
94
94
|
})] })
|
|
95
95
|
]
|
|
96
96
|
})] })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MultiSelectDropdown.mjs","names":["React"],"sources":["../../../src/components/MultiSelectDropdown.tsx"],"sourcesContent":["import { ChevronDown, RotateCcw } from \"lucide-react\";\r\nimport * as React from \"react\";\r\n\r\nimport { Button } from \"./ui/button\";\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuCheckboxItem,\r\n DropdownMenuContent,\r\n DropdownMenuGroup,\r\n DropdownMenuItem,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from \"./ui/dropdown-menu\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface MultiSelectOption {\r\n label: string;\r\n icon?: React.ReactNode;\r\n value: string;\r\n group?: string;\r\n}\r\n\r\ninterface MultiSelectDropdownProps {\r\n options: MultiSelectOption[];\r\n selectedValues: string[];\r\n onValueChange: (selectedValues: string[]) => void;\r\n placeholder?: React.ReactNode;\r\n label?: string;\r\n className?: string;\r\n triggerClassName?: string;\r\n disabled?: boolean;\r\n maxDisplayCount?: number;\r\n multiSelectLabel?: string;\r\n trigger?: React.ReactNode;\r\n resetButton?: \"bottom\" | \"top\";\r\n resetLabel?: React.ReactNode;\r\n separateGroups?: boolean;\r\n}\r\n\r\nconst MultiSelectDropdown = React.forwardRef<\r\n React.ElementRef<typeof DropdownMenuTrigger>,\r\n MultiSelectDropdownProps\r\n>(\r\n (\r\n {\r\n options,\r\n selectedValues,\r\n onValueChange,\r\n placeholder = \"Select items...\",\r\n label,\r\n className,\r\n triggerClassName,\r\n trigger,\r\n multiSelectLabel,\r\n disabled = false,\r\n maxDisplayCount = 3,\r\n resetButton = \"bottom\",\r\n resetLabel = \"Reset\",\r\n separateGroups = false,\r\n ...props\r\n },\r\n ref\r\n ) => {\r\n const handleValueChange = (value: string, checked: boolean) => {\r\n if (checked) {\r\n onValueChange([...selectedValues, value]);\r\n } else {\r\n onValueChange(selectedValues.filter((v) => v !== value));\r\n }\r\n };\r\n\r\n const handleReset = () => {\r\n onValueChange([]);\r\n };\r\n\r\n const getDisplayText = () => {\r\n if (selectedValues.length === 0) {\r\n return placeholder;\r\n }\r\n\r\n const selectedLabels = options\r\n .filter((option) => selectedValues.includes(option.value))\r\n .map((option) => option.label);\r\n\r\n if (multiSelectLabel && selectedLabels.length > 1) {\r\n return multiSelectLabel;\r\n }\r\n\r\n if (selectedLabels.length <= maxDisplayCount) {\r\n return selectedLabels.join(\", \");\r\n }\r\n\r\n return `${selectedLabels.slice(0, maxDisplayCount).join(\", \")} (+${\r\n selectedLabels.length - maxDisplayCount\r\n } more)`;\r\n };\r\n\r\n const groupedOptions = React.useMemo(() => {\r\n const groups: Record<string, MultiSelectOption[]> = {};\r\n const ungrouped: MultiSelectOption[] = [];\r\n\r\n options.forEach((option) => {\r\n if (option.group) {\r\n if (!groups[option.group]) {\r\n groups[option.group] = [];\r\n }\r\n groups[option.group].push(option);\r\n } else {\r\n ungrouped.push(option);\r\n }\r\n });\r\n\r\n return { groups, ungrouped };\r\n }, [options]);\r\n\r\n return (\r\n <div className={cn(\"w-full\", className)}>\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n ref={ref}\r\n variant=\"outline\"\r\n className={cn(\r\n \"w-full justify-between text-left font-normal\",\r\n selectedValues.length === 0 && \"text-muted-foreground\",\r\n triggerClassName\r\n )}\r\n disabled={disabled}\r\n {...props}\r\n >\r\n {trigger || (\r\n <>\r\n <span className=\"truncate\">{getDisplayText()}</span>\r\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\r\n </>\r\n )}\r\n </Button>\r\n </DropdownMenuTrigger>\r\n\r\n <DropdownMenuContent\r\n className=\"w-full min-w-[var(--radix-dropdown-menu-trigger-width)]\"\r\n align=\"start\"\r\n >\r\n {resetButton && resetButton === \"top\" && (\r\n <>\r\n <DropdownMenuItem\r\n onClick={handleReset}\r\n disabled={selectedValues.length === 0}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer text-muted-foreground hover:text-foreground\"\r\n >\r\n {resetLabel || (\r\n <>\r\n <RotateCcw className=\"mr-2 h-4 w-4\" />\r\n Reset\r\n </>\r\n )}\r\n </DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n </>\r\n )}\r\n {label && (\r\n <>\r\n <DropdownMenuLabel>{label}</DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n </>\r\n )}\r\n {Object.entries(groupedOptions.groups).map(([groupName, groupOptions], groupIndex) => (\r\n <DropdownMenuGroup key={groupName}>\r\n {groupIndex > 0 && separateGroups && <DropdownMenuSeparator />}\r\n <DropdownMenuLabel className=\"text-xs font-semibold text-muted-foreground px-2 py-1.5\">\r\n {groupName}\r\n </DropdownMenuLabel>\r\n {groupOptions.map((option) => (\r\n <DropdownMenuCheckboxItem\r\n key={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onCheckedChange={(checked) => handleValueChange(option.value, checked)}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer\"\r\n >\r\n {option.icon && <span className=\"mr-2\">{option.icon}</span>}\r\n {option.label}\r\n </DropdownMenuCheckboxItem>\r\n ))}\r\n </DropdownMenuGroup>\r\n ))}\r\n {groupedOptions.ungrouped.length > 0 && (\r\n <DropdownMenuGroup>\r\n {Object.keys(groupedOptions.groups).length > 0 && <DropdownMenuSeparator />}\r\n {groupedOptions.ungrouped.map((option) => (\r\n <DropdownMenuCheckboxItem\r\n key={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onCheckedChange={(checked) => handleValueChange(option.value, checked)}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer\"\r\n >\r\n {option.label}\r\n </DropdownMenuCheckboxItem>\r\n ))}\r\n </DropdownMenuGroup>\r\n )}\r\n {resetButton && resetButton === \"bottom\" && (\r\n <>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={handleReset}\r\n disabled={selectedValues.length === 0}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer text-muted-foreground hover:text-foreground\"\r\n >\r\n {resetLabel || (\r\n <>\r\n <RotateCcw className=\"mr-2 h-4 w-4\" />\r\n Reset\r\n </>\r\n )}\r\n </DropdownMenuItem>\r\n </>\r\n )}\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nMultiSelectDropdown.displayName = \"MultiSelectDropdown\";\r\n\r\nexport { MultiSelectDropdown };\r\nexport type { MultiSelectOption, MultiSelectDropdownProps };\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MultiSelectDropdown.mjs","names":["React"],"sources":["../../../src/components/MultiSelectDropdown.tsx"],"sourcesContent":["import { ChevronDown, RotateCcw } from \"lucide-react\";\r\nimport * as React from \"react\";\r\n\r\nimport { Button } from \"./ui/button\";\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuCheckboxItem,\r\n DropdownMenuContent,\r\n DropdownMenuGroup,\r\n DropdownMenuItem,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuTrigger,\r\n} from \"./ui/dropdown-menu\";\r\nimport { cn } from \"../lib/utils\";\r\n\r\ninterface MultiSelectOption {\r\n label: string;\r\n icon?: React.ReactNode;\r\n value: string;\r\n group?: string;\r\n}\r\n\r\ninterface MultiSelectDropdownProps {\r\n options: MultiSelectOption[];\r\n selectedValues: string[];\r\n onValueChange: (selectedValues: string[]) => void;\r\n placeholder?: React.ReactNode;\r\n label?: string;\r\n className?: string;\r\n triggerClassName?: string;\r\n disabled?: boolean;\r\n maxDisplayCount?: number;\r\n multiSelectLabel?: string;\r\n trigger?: React.ReactNode;\r\n resetButton?: \"bottom\" | \"top\";\r\n resetLabel?: React.ReactNode;\r\n separateGroups?: boolean;\r\n}\r\n\r\nconst MultiSelectDropdown = React.forwardRef<\r\n React.ElementRef<typeof DropdownMenuTrigger>,\r\n MultiSelectDropdownProps\r\n>(\r\n (\r\n {\r\n options,\r\n selectedValues,\r\n onValueChange,\r\n placeholder = \"Select items...\",\r\n label,\r\n className,\r\n triggerClassName,\r\n trigger,\r\n multiSelectLabel,\r\n disabled = false,\r\n maxDisplayCount = 3,\r\n resetButton = \"bottom\",\r\n resetLabel = \"Reset\",\r\n separateGroups = false,\r\n ...props\r\n },\r\n ref\r\n ) => {\r\n const handleValueChange = (value: string, checked: boolean) => {\r\n if (checked) {\r\n onValueChange([...selectedValues, value]);\r\n } else {\r\n onValueChange(selectedValues.filter((v) => v !== value));\r\n }\r\n };\r\n\r\n const handleReset = () => {\r\n onValueChange([]);\r\n };\r\n\r\n const getDisplayText = () => {\r\n if (selectedValues.length === 0) {\r\n return placeholder;\r\n }\r\n\r\n const selectedLabels = options\r\n .filter((option) => selectedValues.includes(option.value))\r\n .map((option) => option.label);\r\n\r\n if (multiSelectLabel && selectedLabels.length > 1) {\r\n return multiSelectLabel;\r\n }\r\n\r\n if (selectedLabels.length <= maxDisplayCount) {\r\n return selectedLabels.join(\", \");\r\n }\r\n\r\n return `${selectedLabels.slice(0, maxDisplayCount).join(\", \")} (+${\r\n selectedLabels.length - maxDisplayCount\r\n } more)`;\r\n };\r\n\r\n const groupedOptions = React.useMemo(() => {\r\n const groups: Record<string, MultiSelectOption[]> = {};\r\n const ungrouped: MultiSelectOption[] = [];\r\n\r\n options.forEach((option) => {\r\n if (option.group) {\r\n if (!groups[option.group]) {\r\n groups[option.group] = [];\r\n }\r\n groups[option.group].push(option);\r\n } else {\r\n ungrouped.push(option);\r\n }\r\n });\r\n\r\n return { groups, ungrouped };\r\n }, [options]);\r\n\r\n return (\r\n <div className={cn(\"w-full\", className)}>\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button\r\n ref={ref}\r\n variant=\"outline\"\r\n className={cn(\r\n \"w-full justify-between text-left font-normal\",\r\n selectedValues.length === 0 && \"text-muted-foreground\",\r\n triggerClassName\r\n )}\r\n disabled={disabled}\r\n {...props}\r\n >\r\n {trigger || (\r\n <>\r\n <span className=\"truncate\">{getDisplayText()}</span>\r\n <ChevronDown className=\"ml-2 h-4 w-4 shrink-0 opacity-50\" />\r\n </>\r\n )}\r\n </Button>\r\n </DropdownMenuTrigger>\r\n\r\n <DropdownMenuContent\r\n className=\"w-full min-w-[var(--radix-dropdown-menu-trigger-width)]\"\r\n align=\"start\"\r\n >\r\n {resetButton && resetButton === \"top\" && (\r\n <>\r\n <DropdownMenuItem\r\n onClick={handleReset}\r\n disabled={selectedValues.length === 0}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer text-muted-foreground hover:text-foreground\"\r\n >\r\n {resetLabel || (\r\n <>\r\n <RotateCcw className=\"mr-2 h-4 w-4\" />\r\n Reset\r\n </>\r\n )}\r\n </DropdownMenuItem>\r\n <DropdownMenuSeparator />\r\n </>\r\n )}\r\n {label && (\r\n <>\r\n <DropdownMenuLabel>{label}</DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n </>\r\n )}\r\n {Object.entries(groupedOptions.groups).map(([groupName, groupOptions], groupIndex) => (\r\n <DropdownMenuGroup key={groupName}>\r\n {groupIndex > 0 && separateGroups && <DropdownMenuSeparator />}\r\n <DropdownMenuLabel className=\"text-xs font-semibold text-muted-foreground px-2 py-1.5\">\r\n {groupName}\r\n </DropdownMenuLabel>\r\n {groupOptions.map((option) => (\r\n <DropdownMenuCheckboxItem\r\n key={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onCheckedChange={(checked) => handleValueChange(option.value, checked)}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer\"\r\n >\r\n {option.icon && <span className=\"mr-2\">{option.icon}</span>}\r\n {option.label}\r\n </DropdownMenuCheckboxItem>\r\n ))}\r\n </DropdownMenuGroup>\r\n ))}\r\n {groupedOptions.ungrouped.length > 0 && (\r\n <DropdownMenuGroup>\r\n {Object.keys(groupedOptions.groups).length > 0 && <DropdownMenuSeparator />}\r\n {groupedOptions.ungrouped.map((option) => (\r\n <DropdownMenuCheckboxItem\r\n key={option.value}\r\n checked={selectedValues.includes(option.value)}\r\n onCheckedChange={(checked) => handleValueChange(option.value, checked)}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer\"\r\n >\r\n {option.label}\r\n </DropdownMenuCheckboxItem>\r\n ))}\r\n </DropdownMenuGroup>\r\n )}\r\n {resetButton && resetButton === \"bottom\" && (\r\n <>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuItem\r\n onClick={handleReset}\r\n disabled={selectedValues.length === 0}\r\n onSelect={(event) => event.preventDefault()}\r\n className=\"cursor-pointer text-muted-foreground hover:text-foreground\"\r\n >\r\n {resetLabel || (\r\n <>\r\n <RotateCcw className=\"mr-2 h-4 w-4\" />\r\n Reset\r\n </>\r\n )}\r\n </DropdownMenuItem>\r\n </>\r\n )}\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </div>\r\n );\r\n }\r\n);\r\n\r\nMultiSelectDropdown.displayName = \"MultiSelectDropdown\";\r\n\r\nexport { MultiSelectDropdown };\r\nexport type { MultiSelectOption, MultiSelectDropdownProps };\r\n"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
require("../../_virtual/_rolldown/runtime.js");
|
|
2
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
3
2
|
let react = require("react");
|
|
3
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
4
|
let ogl = require("ogl");
|
|
5
5
|
//#region src/components/Orb.tsx
|
|
6
6
|
function Orb({ hue = 0, hoverIntensity = .2, rotateOnHover = true, forceHoverState = false }) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
1
|
import { useEffect, useRef } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
3
|
import { Mesh, Program, Renderer, Triangle, Vec3 } from "ogl";
|
|
4
4
|
//#region src/components/Orb.tsx
|
|
5
5
|
function Orb({ hue = 0, hoverIntensity = .2, rotateOnHover = true, forceHoverState = false }) {
|
|
@@ -4,7 +4,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
|
|
|
4
4
|
|
|
5
5
|
//#region src/components/PageAlert.d.ts
|
|
6
6
|
declare const pageAlertVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "
|
|
7
|
+
variant?: "default" | "info" | "success" | "warning" | "destructive" | null | undefined;
|
|
8
8
|
} & _$class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
9
9
|
interface PageAlertProps extends React$1.ComponentProps<"div">, VariantProps<typeof pageAlertVariants> {
|
|
10
10
|
title?: string;
|
|
@@ -4,7 +4,7 @@ import * as React$1 from "react";
|
|
|
4
4
|
|
|
5
5
|
//#region src/components/PageAlert.d.ts
|
|
6
6
|
declare const pageAlertVariants: (props?: ({
|
|
7
|
-
variant?: "default" | "
|
|
7
|
+
variant?: "default" | "info" | "success" | "warning" | "destructive" | null | undefined;
|
|
8
8
|
} & _$class_variance_authority_types0.ClassProp) | undefined) => string;
|
|
9
9
|
interface PageAlertProps extends React$1.ComponentProps<"div">, VariantProps<typeof pageAlertVariants> {
|
|
10
10
|
title?: string;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_runtime = require("../../_virtual/_rolldown/runtime.js");
|
|
3
3
|
const require_src_lib_utils = require("../lib/utils.js");
|
|
4
|
-
let
|
|
4
|
+
let lucide_react = require("lucide-react");
|
|
5
5
|
let react = require("react");
|
|
6
6
|
react = require_runtime.__toESM(react);
|
|
7
|
-
let lucide_react = require("lucide-react");
|
|
8
7
|
let react_i18next = require("react-i18next");
|
|
8
|
+
let class_variance_authority = require("class-variance-authority");
|
|
9
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
10
|
//#region src/components/PageAlert.tsx
|
|
10
|
-
const pageAlertVariants = (0,
|
|
11
|
+
const pageAlertVariants = (0, class_variance_authority.cva)("relative w-full border-b px-4 py-3 text-sm transition-all duration-300 ease-in-out", {
|
|
11
12
|
variants: { variant: {
|
|
12
13
|
default: "bg-background border-border text-foreground",
|
|
13
14
|
info: "bg-blue-50 border-blue-200 text-blue-900 dark:bg-blue-950/50 dark:border-blue-800 dark:text-blue-100",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PageAlert.js","names":["Info","CheckCircle","AlertTriangle","AlertCircle","React","cn","X"],"sources":["../../../src/components/PageAlert.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { AlertCircle, AlertTriangle, CheckCircle, Info, X } from \"lucide-react\";\r\nimport * as React from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\nimport { cn } from \"../lib/utils\";\r\n\r\nconst pageAlertVariants = cva(\r\n \"relative w-full border-b px-4 py-3 text-sm transition-all duration-300 ease-in-out\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-background border-border text-foreground\",\r\n info: \"bg-blue-50 border-blue-200 text-blue-900 dark:bg-blue-950/50 dark:border-blue-800 dark:text-blue-100\",\r\n success:\r\n \"bg-green-50 border-green-200 text-green-900 dark:bg-green-950/50 dark:border-green-800 dark:text-green-100\",\r\n warning:\r\n \"bg-yellow-50 border-yellow-200 text-yellow-900 dark:bg-yellow-950/50 dark:border-yellow-800 dark:text-yellow-100\",\r\n destructive:\r\n \"bg-red-50 border-red-200 text-red-900 dark:bg-red-950/50 dark:border-red-800 dark:text-red-100\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n);\r\n\r\nconst iconMap = {\r\n default: Info,\r\n info: Info,\r\n success: CheckCircle,\r\n warning: AlertTriangle,\r\n destructive: AlertCircle,\r\n} as const;\r\n\r\ninterface PageAlertProps\r\n extends React.ComponentProps<\"div\">,\r\n VariantProps<typeof pageAlertVariants> {\r\n title?: string;\r\n description?: React.ReactNode;\r\n icon?: React.ComponentType<{ className?: string }>;\r\n dismissible?: boolean;\r\n defaultOpen?: boolean;\r\n onDismiss?: () => void;\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst PageAlert = React.forwardRef<HTMLDivElement, PageAlertProps>(\r\n (\r\n {\r\n className,\r\n variant = \"default\",\r\n title,\r\n description,\r\n icon,\r\n dismissible = true,\r\n defaultOpen = true,\r\n onDismiss,\r\n children,\r\n ...props\r\n },\r\n ref\r\n ) => {\r\n const { t } = useTranslation();\r\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\r\n const [isAnimatingOut, setIsAnimatingOut] = React.useState(false);\r\n const IconComponent = icon || iconMap[variant || \"default\"];\r\n\r\n const handleDismiss = React.useCallback(() => {\r\n setIsAnimatingOut(true);\r\n // Wait for animation to complete before removing from DOM\r\n setTimeout(() => {\r\n setIsOpen(false);\r\n onDismiss?.();\r\n }, 300); // Match the animation duration\r\n }, [onDismiss]);\r\n\r\n if (!isOpen) {\r\n return null;\r\n }\r\n\r\n const content = (\r\n <div\r\n ref={ref}\r\n role=\"alert\"\r\n className={cn(\r\n pageAlertVariants({ variant }),\r\n isAnimatingOut && \"transform -translate-y-full opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div className=\"flex items-start gap-3\">\r\n {IconComponent && <IconComponent className=\"h-4 w-4 mt-0.5 flex-shrink-0\" />}\r\n <div className=\"flex-1 min-w-0\">\r\n {title && <div className=\"font-medium leading-none tracking-tight mb-1\">{title}</div>}\r\n {description && <div className=\"text-sm opacity-90 leading-relaxed\">{description}</div>}\r\n {children}\r\n </div>\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n onClick={handleDismiss}\r\n className=\"flex-shrink-0 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\r\n aria-label={t(\"web-ui:alert.dismissLabel\")}\r\n >\r\n <X className=\"h-4 w-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n\r\n return content;\r\n }\r\n);\r\n\r\nPageAlert.displayName = \"PageAlert\";\r\n\r\nexport { PageAlert, type PageAlertProps };\r\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"PageAlert.js","names":["Info","CheckCircle","AlertTriangle","AlertCircle","React","cn","X"],"sources":["../../../src/components/PageAlert.tsx"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\r\nimport { AlertCircle, AlertTriangle, CheckCircle, Info, X } from \"lucide-react\";\r\nimport * as React from \"react\";\r\nimport { useTranslation } from \"react-i18next\";\r\n\r\nimport { cn } from \"../lib/utils\";\r\n\r\nconst pageAlertVariants = cva(\r\n \"relative w-full border-b px-4 py-3 text-sm transition-all duration-300 ease-in-out\",\r\n {\r\n variants: {\r\n variant: {\r\n default: \"bg-background border-border text-foreground\",\r\n info: \"bg-blue-50 border-blue-200 text-blue-900 dark:bg-blue-950/50 dark:border-blue-800 dark:text-blue-100\",\r\n success:\r\n \"bg-green-50 border-green-200 text-green-900 dark:bg-green-950/50 dark:border-green-800 dark:text-green-100\",\r\n warning:\r\n \"bg-yellow-50 border-yellow-200 text-yellow-900 dark:bg-yellow-950/50 dark:border-yellow-800 dark:text-yellow-100\",\r\n destructive:\r\n \"bg-red-50 border-red-200 text-red-900 dark:bg-red-950/50 dark:border-red-800 dark:text-red-100\",\r\n },\r\n },\r\n defaultVariants: {\r\n variant: \"default\",\r\n },\r\n }\r\n);\r\n\r\nconst iconMap = {\r\n default: Info,\r\n info: Info,\r\n success: CheckCircle,\r\n warning: AlertTriangle,\r\n destructive: AlertCircle,\r\n} as const;\r\n\r\ninterface PageAlertProps\r\n extends React.ComponentProps<\"div\">,\r\n VariantProps<typeof pageAlertVariants> {\r\n title?: string;\r\n description?: React.ReactNode;\r\n icon?: React.ComponentType<{ className?: string }>;\r\n dismissible?: boolean;\r\n defaultOpen?: boolean;\r\n onDismiss?: () => void;\r\n children?: React.ReactNode;\r\n}\r\n\r\nconst PageAlert = React.forwardRef<HTMLDivElement, PageAlertProps>(\r\n (\r\n {\r\n className,\r\n variant = \"default\",\r\n title,\r\n description,\r\n icon,\r\n dismissible = true,\r\n defaultOpen = true,\r\n onDismiss,\r\n children,\r\n ...props\r\n },\r\n ref\r\n ) => {\r\n const { t } = useTranslation();\r\n const [isOpen, setIsOpen] = React.useState(defaultOpen);\r\n const [isAnimatingOut, setIsAnimatingOut] = React.useState(false);\r\n const IconComponent = icon || iconMap[variant || \"default\"];\r\n\r\n const handleDismiss = React.useCallback(() => {\r\n setIsAnimatingOut(true);\r\n // Wait for animation to complete before removing from DOM\r\n setTimeout(() => {\r\n setIsOpen(false);\r\n onDismiss?.();\r\n }, 300); // Match the animation duration\r\n }, [onDismiss]);\r\n\r\n if (!isOpen) {\r\n return null;\r\n }\r\n\r\n const content = (\r\n <div\r\n ref={ref}\r\n role=\"alert\"\r\n className={cn(\r\n pageAlertVariants({ variant }),\r\n isAnimatingOut && \"transform -translate-y-full opacity-0\",\r\n className\r\n )}\r\n {...props}\r\n >\r\n <div className=\"flex items-start gap-3\">\r\n {IconComponent && <IconComponent className=\"h-4 w-4 mt-0.5 flex-shrink-0\" />}\r\n <div className=\"flex-1 min-w-0\">\r\n {title && <div className=\"font-medium leading-none tracking-tight mb-1\">{title}</div>}\r\n {description && <div className=\"text-sm opacity-90 leading-relaxed\">{description}</div>}\r\n {children}\r\n </div>\r\n {dismissible && (\r\n <button\r\n type=\"button\"\r\n onClick={handleDismiss}\r\n className=\"flex-shrink-0 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\r\n aria-label={t(\"web-ui:alert.dismissLabel\")}\r\n >\r\n <X className=\"h-4 w-4\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n\r\n return content;\r\n }\r\n);\r\n\r\nPageAlert.displayName = \"PageAlert\";\r\n\r\nexport { PageAlert, type PageAlertProps };\r\n"],"mappings":";;;;;;;;;;AAOA,MAAM,qBAAA,GAAA,yBAAA,KACJ,sFACA;CACE,UAAU,EACR,SAAS;EACP,SAAS;EACT,MAAM;EACN,SACE;EACF,SACE;EACF,aACE;EACH,EACF;CACD,iBAAiB,EACf,SAAS,WACV;CACF,CACF;AAED,MAAM,UAAU;CACd,SAASA,aAAAA;CACT,MAAMA,aAAAA;CACN,SAASC,aAAAA;CACT,SAASC,aAAAA;CACT,aAAaC,aAAAA;CACd;AAcD,MAAM,YAAYC,MAAM,YAEpB,EACE,WACA,UAAU,WACV,OACA,aACA,MACA,cAAc,MACd,cAAc,MACd,WACA,UACA,GAAG,SAEL,QACG;CACH,MAAM,EAAE,OAAA,GAAA,cAAA,iBAAsB;CAC9B,MAAM,CAAC,QAAQ,aAAaA,MAAM,SAAS,YAAY;CACvD,MAAM,CAAC,gBAAgB,qBAAqBA,MAAM,SAAS,MAAM;CACjE,MAAM,gBAAgB,QAAQ,QAAQ,WAAW;CAEjD,MAAM,gBAAgBA,MAAM,kBAAkB;AAC5C,oBAAkB,KAAK;AAEvB,mBAAiB;AACf,aAAU,MAAM;AAChB,gBAAa;KACZ,IAAI;IACN,CAAC,UAAU,CAAC;AAEf,KAAI,CAAC,OACH,QAAO;AAmCT,QA/BE,iBAAA,GAAA,kBAAA,KAAC,OAAD;EACO;EACL,MAAK;EACL,WAAWC,sBAAAA,GACT,kBAAkB,EAAE,SAAS,CAAC,EAC9B,kBAAkB,yCAClB,UACD;EACD,GAAI;YAEJ,iBAAA,GAAA,kBAAA,MAAC,OAAD;GAAK,WAAU;aAAf;IACG,iBAAiB,iBAAA,GAAA,kBAAA,KAAC,eAAD,EAAe,WAAU,gCAAiC,CAAA;IAC5E,iBAAA,GAAA,kBAAA,MAAC,OAAD;KAAK,WAAU;eAAf;MACG,SAAS,iBAAA,GAAA,kBAAA,KAAC,OAAD;OAAK,WAAU;iBAAgD;OAAY,CAAA;MACpF,eAAe,iBAAA,GAAA,kBAAA,KAAC,OAAD;OAAK,WAAU;iBAAsC;OAAkB,CAAA;MACtF;MACG;;IACL,eACC,iBAAA,GAAA,kBAAA,KAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;KACV,cAAY,EAAE,4BAA4B;eAE1C,iBAAA,GAAA,kBAAA,KAACC,aAAAA,GAAD,EAAG,WAAU,WAAY,CAAA;KAClB,CAAA;IAEP;;EACF,CAAA;EAKX;AAED,UAAU,cAAc"}
|