From 7e3e6857638d701fbf01739edf2e39cc1c6a0f15 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sat, 12 Apr 2025 00:48:19 +0800 Subject: [PATCH 01/22] feat(graph): Add editing function for entity and relationship attributes --- lightrag/api/routers/graph_routes.py | 62 ++++- lightrag_webui/src/api/lightrag.ts | 55 ++++ .../components/graph/EditablePropertyRow.tsx | 245 ++++++++++++++++++ .../src/components/graph/PropertiesView.tsx | 57 +++- lightrag_webui/src/lib/constants.ts | 2 +- lightrag_webui/src/stores/graph.ts | 8 + 6 files changed, 421 insertions(+), 8 deletions(-) create mode 100644 lightrag_webui/src/components/graph/EditablePropertyRow.tsx diff --git a/lightrag/api/routers/graph_routes.py b/lightrag/api/routers/graph_routes.py index 381df90b..97a397d4 100644 --- a/lightrag/api/routers/graph_routes.py +++ b/lightrag/api/routers/graph_routes.py @@ -2,14 +2,21 @@ This module contains all graph-related routes for the LightRAG API. """ -from typing import Optional -from fastapi import APIRouter, Depends, Query +from typing import Optional, Dict, Any +from fastapi import APIRouter, Depends, Query, HTTPException +from pydantic import BaseModel from ..utils_api import get_combined_auth_dependency router = APIRouter(tags=["graph"]) +class EntityUpdateRequest(BaseModel): + entity_name: str + updated_data: Dict[str, Any] + allow_rename: bool = False + + def create_graph_routes(rag, api_key: Optional[str] = None): combined_auth = get_combined_auth_dependency(api_key) @@ -49,4 +56,55 @@ def create_graph_routes(rag, api_key: Optional[str] = None): max_nodes=max_nodes, ) + @router.get("/graph/entity/exists", dependencies=[Depends(combined_auth)]) + async def check_entity_exists( + name: str = Query(..., description="Entity name to check"), + ): + """ + Check if an entity with the given name exists in the knowledge graph + + Args: + name (str): Name of the entity to check + + Returns: + Dict[str, bool]: Dictionary with 'exists' key indicating if entity exists + """ + try: + exists = await rag.chunk_entity_relation_graph.has_node(name) + return {"exists": exists} + except Exception as e: + raise HTTPException( + status_code=500, detail=f"Error checking entity existence: {str(e)}" + ) + + @router.post("/graph/entity/edit", dependencies=[Depends(combined_auth)]) + async def update_entity(request: EntityUpdateRequest): + """ + Update an entity's properties in the knowledge graph + + Args: + request (EntityUpdateRequest): Request containing entity name, updated data, and rename flag + + Returns: + Dict: Updated entity information + """ + try: + print(request.entity_name, request.updated_data, request.allow_rename) + result = await rag.aedit_entity( + entity_name=request.entity_name, + updated_data=request.updated_data, + allow_rename=request.allow_rename, + ) + return { + "status": "success", + "message": "Entity updated successfully", + "data": result, + } + except ValueError as ve: + raise HTTPException(status_code=400, detail=str(ve)) + except Exception as e: + raise HTTPException( + status_code=500, detail=f"Error updating entity: {str(e)}" + ) + return router diff --git a/lightrag_webui/src/api/lightrag.ts b/lightrag_webui/src/api/lightrag.ts index fbe00d23..63f4e2f6 100644 --- a/lightrag_webui/src/api/lightrag.ts +++ b/lightrag_webui/src/api/lightrag.ts @@ -506,3 +506,58 @@ export const loginToServer = async (username: string, password: string): Promise return response.data; } + +/** + * Updates an entity's properties in the knowledge graph + * @param entityName The name of the entity to update + * @param updatedData Dictionary containing updated attributes + * @param allowRename Whether to allow renaming the entity (default: false) + * @returns Promise with the updated entity information + */ +export const updateEntity = async ( + entityName: string, + updatedData: Record, + allowRename: boolean = false +): Promise => { + const response = await axiosInstance.post('/graph/entity/edit', { + entity_name: entityName, + updated_data: updatedData, + allow_rename: allowRename + }) + return response.data +} + +/** + * Updates a relation's properties in the knowledge graph + * @param sourceEntity The source entity name + * @param targetEntity The target entity name + * @param updatedData Dictionary containing updated attributes + * @returns Promise with the updated relation information + */ +export const updateRelation = async ( + sourceEntity: string, + targetEntity: string, + updatedData: Record +): Promise => { + const response = await axiosInstance.post('/graph/relation/edit', { + source_entity: sourceEntity, + target_entity: targetEntity, + updated_data: updatedData + }) + return response.data +} + +/** + * Checks if an entity name already exists in the knowledge graph + * @param entityName The entity name to check + * @returns Promise with boolean indicating if the entity exists + */ +export const checkEntityNameExists = async (entityName: string): Promise => { + try { + const response = await axiosInstance.get(`/graph/entity/exists?name=${encodeURIComponent(entityName)}`) + return response.data.exists + } catch (error) { + console.error('Error checking entity name:', error) + return false + } +} diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx new file mode 100644 index 00000000..dfd94e49 --- /dev/null +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -0,0 +1,245 @@ +import { useState, useEffect, useRef } from 'react' +import { useTranslation } from 'react-i18next' +import Text from '@/components/ui/Text' +import Input from '@/components/ui/Input' +import { toast } from 'sonner' +import { updateEntity, updateRelation, checkEntityNameExists } from '@/api/lightrag' +import { useGraphStore } from '@/stores/graph' +import { useSettingsStore } from '@/stores/settings' + +interface EditablePropertyRowProps { + name: string + value: any + onClick?: () => void + tooltip?: string + entityId?: string + entityType?: 'node' | 'edge' + sourceId?: string + targetId?: string + onValueChange?: (newValue: any) => void + isEditable?: boolean +} + +/** + * EditablePropertyRow component that supports double-click to edit property values + * Specifically designed for editing 'description' and entity name fields + */ +const EditablePropertyRow = ({ + name, + value, + onClick, + tooltip, + entityId, + entityType, + sourceId, + targetId, + onValueChange, + isEditable = false +}: EditablePropertyRowProps) => { + const { t } = useTranslation() + const [isEditing, setIsEditing] = useState(false) + const [editValue, setEditValue] = useState('') + const [isSubmitting, setIsSubmitting] = useState(false) + const inputRef = useRef(null) + + // Initialize edit value when entering edit mode + useEffect(() => { + if (isEditing) { + setEditValue(String(value)) + // Focus the input element when entering edit mode + setTimeout(() => { + if (inputRef.current) { + inputRef.current.focus() + inputRef.current.select() + } + }, 50) + } + }, [isEditing, value]) + + const getPropertyNameTranslation = (propName: string) => { + const translationKey = `graphPanel.propertiesView.node.propertyNames.${propName}` + const translation = t(translationKey) + return translation === translationKey ? propName : translation + } + + const handleDoubleClick = () => { + if (isEditable && !isEditing) { + setIsEditing(true) + } + } + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handleSave() + } else if (e.key === 'Escape') { + setIsEditing(false) + } + } + + const handleSave = async () => { + if (isSubmitting) return + + // Don't save if value hasn't changed + if (editValue === String(value)) { + setIsEditing(false) + return + } + + setIsSubmitting(true) + + try { + // Special handling for entity_id (name) field to check for duplicates + if (name === 'entity_id' && entityType === 'node') { + // Ensure we are not checking the original name against itself if it's protected + if (editValue !== String(value)) { + const exists = await checkEntityNameExists(editValue); + if (exists) { + toast.error(t('graphPanel.propertiesView.errors.duplicateName')); + setIsSubmitting(false); + return; + } + } + } + + // Update the entity or relation in the database + if (entityType === 'node' && entityId) { + // For nodes, we need to determine if we're updating the name or description + const updatedData: Record = {} + + if (name === 'entity_id') { + // For entity name updates + updatedData['entity_name'] = editValue + await updateEntity(String(value), updatedData, true) // Pass original name (value) as identifier + + // Update node label in the graph directly instead of reloading the entire graph + const sigmaInstance = useGraphStore.getState().sigmaInstance + const sigmaGraph = useGraphStore.getState().sigmaGraph + const rawGraph = useGraphStore.getState().rawGraph + + if (sigmaInstance && sigmaGraph && rawGraph) { + // Update the node in sigma graph + if (sigmaGraph.hasNode(String(value))) { + // Update the node label in the sigma graph + sigmaGraph.setNodeAttribute(String(value), 'label', editValue) + + // Also update the node in the raw graph + const nodeIndex = rawGraph.nodeIdMap[String(value)] + if (nodeIndex !== undefined) { + rawGraph.nodes[nodeIndex].id = editValue + // Update the node ID map + delete rawGraph.nodeIdMap[String(value)] + rawGraph.nodeIdMap[editValue] = nodeIndex + } + + // Refresh the sigma instance to reflect changes + sigmaInstance.refresh() + + // Update selected node ID if it was the edited node + const selectedNode = useGraphStore.getState().selectedNode + if (selectedNode === String(value)) { + useGraphStore.getState().setSelectedNode(editValue) + } + } + } else { + // Fallback to full graph reload if direct update is not possible + useGraphStore.getState().setGraphDataFetchAttempted(false) + useGraphStore.getState().setLabelsFetchAttempted(false) + + // Get current label to trigger reload + const currentLabel = useSettingsStore.getState().queryLabel + if (currentLabel) { + // Trigger data reload by temporarily clearing and resetting the label + useSettingsStore.getState().setQueryLabel('') + setTimeout(() => { + useSettingsStore.getState().setQueryLabel(currentLabel) + }, 0) + } + } + } else if (name === 'description') { + // For description updates + updatedData['description'] = editValue + await updateEntity(entityId, updatedData) // Pass entityId as identifier + } else { + // For other property updates + updatedData[name] = editValue + await updateEntity(entityId, updatedData) // Pass entityId as identifier + } + + toast.success(t('graphPanel.propertiesView.success.entityUpdated')) + } else if (entityType === 'edge' && sourceId && targetId) { + // For edges, update the relation + const updatedData: Record = {} + updatedData[name] = editValue + await updateRelation(sourceId, targetId, updatedData) + toast.success(t('graphPanel.propertiesView.success.relationUpdated')) + } + + // Notify parent component about the value change + if (onValueChange) { + onValueChange(editValue) + } + } catch (error: any) { // Keep type as any to access potential response properties + console.error('Error updating property:', error); + + // Attempt to extract a more specific error message + let detailMessage = t('graphPanel.propertiesView.errors.updateFailed'); // Default message + if (error.response?.data?.detail) { + // Use the detailed message from the backend response if available + detailMessage = error.response.data.detail; + } else if (error.message) { + // Use the error object's message if no backend detail + detailMessage = error.message; + } + + toast.error(detailMessage); // Show the determined error message + + } finally { + setIsSubmitting(false) + setIsEditing(false) + } + } + + // Determine if this property should be editable + // Currently only 'description' and 'entity_id' fields are editable + const isEditableField = isEditable && (name === 'description' || name === 'entity_id') + + return ( +
+ + {getPropertyNameTranslation(name)} + : + {isEditing ? ( +
+ setEditValue(e.target.value)} + onBlur={handleSave} + onKeyDown={handleKeyDown} + disabled={isSubmitting} + /> +
+ ) : ( + // Wrap Text component in a div to handle onDoubleClick +
+ +
+ )} +
+ ) +} + +export default EditablePropertyRow diff --git a/lightrag_webui/src/components/graph/PropertiesView.tsx b/lightrag_webui/src/components/graph/PropertiesView.tsx index 3aa248de..c2cda263 100644 --- a/lightrag_webui/src/components/graph/PropertiesView.tsx +++ b/lightrag_webui/src/components/graph/PropertiesView.tsx @@ -5,6 +5,7 @@ import Button from '@/components/ui/Button' import useLightragGraph from '@/hooks/useLightragGraph' import { useTranslation } from 'react-i18next' import { GitBranchPlus, Scissors } from 'lucide-react' +import EditablePropertyRow from './EditablePropertyRow' /** * Component that view properties of elements in graph. @@ -169,12 +170,22 @@ const PropertyRow = ({ name, value, onClick, - tooltip + tooltip, + entityId, + entityType, + sourceId, + targetId, + isEditable = false }: { name: string value: any onClick?: () => void tooltip?: string + entityId?: string + entityType?: 'node' | 'edge' + sourceId?: string + targetId?: string + isEditable?: boolean }) => { const { t } = useTranslation() @@ -184,8 +195,24 @@ const PropertyRow = ({ return translation === translationKey ? name : translation } - // Since Text component uses a label internally, we'll use a span here instead of a label - // to avoid nesting labels which is not recommended for accessibility + // Use EditablePropertyRow for editable fields (description and entity_id) + if (isEditable && (name === 'description' || name === 'entity_id')) { + return ( + + ) + } + + // For non-editable fields, use the regular Text component return (
{getPropertyNameTranslation(name)}: @@ -253,7 +280,16 @@ const NodePropertiesView = ({ node }: { node: NodeType }) => { {Object.keys(node.properties) .sort() .map((name) => { - return + return ( + + ) })}
{node.relationships.length > 0 && ( @@ -309,7 +345,18 @@ const EdgePropertiesView = ({ edge }: { edge: EdgeType }) => { {Object.keys(edge.properties) .sort() .map((name) => { - return + return ( + + ) })} diff --git a/lightrag_webui/src/lib/constants.ts b/lightrag_webui/src/lib/constants.ts index 048ae8f7..87db8cea 100644 --- a/lightrag_webui/src/lib/constants.ts +++ b/lightrag_webui/src/lib/constants.ts @@ -1,6 +1,6 @@ import { ButtonVariantType } from '@/components/ui/Button' -export const backendBaseUrl = '' +export const backendBaseUrl = 'http://localhost:9621' export const webuiPrefix = '/webui/' export const controlButtonVariant: ButtonVariantType = 'ghost' diff --git a/lightrag_webui/src/stores/graph.ts b/lightrag_webui/src/stores/graph.ts index c50cff41..84000170 100644 --- a/lightrag_webui/src/stores/graph.ts +++ b/lightrag_webui/src/stores/graph.ts @@ -116,6 +116,10 @@ interface GraphState { // Node operation state nodeToExpand: string | null nodeToPrune: string | null + + // Version counter to trigger data refresh + graphDataVersion: number + incrementGraphDataVersion: () => void } const useGraphStoreBase = create()((set) => ({ @@ -219,6 +223,10 @@ const useGraphStoreBase = create()((set) => ({ triggerNodeExpand: (nodeId: string | null) => set({ nodeToExpand: nodeId }), triggerNodePrune: (nodeId: string | null) => set({ nodeToPrune: nodeId }), + // Version counter implementation + graphDataVersion: 0, + incrementGraphDataVersion: () => set((state) => ({ graphDataVersion: state.graphDataVersion + 1 })), + })) const useGraphStore = createSelectors(useGraphStoreBase) From ea43f3537e0f6d7feb6fb63d54991c7c777cec24 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sat, 12 Apr 2025 10:36:05 +0800 Subject: [PATCH 02/22] fix(graph): Fixed the issue of incorrect handling of edges and nodes during node ID updates --- .../components/graph/EditablePropertyRow.tsx | 125 ++++++++++++------ .../src/components/graph/GraphControl.tsx | 12 +- lightrag_webui/src/locales/ar.json | 26 ++++ lightrag_webui/src/locales/en.json | 9 ++ lightrag_webui/src/locales/fr.json | 26 ++++ lightrag_webui/src/locales/zh.json | 9 ++ 6 files changed, 164 insertions(+), 43 deletions(-) diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx index dfd94e49..837f6514 100644 --- a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -119,40 +119,62 @@ const EditablePropertyRow = ({ if (sigmaInstance && sigmaGraph && rawGraph) { // Update the node in sigma graph if (sigmaGraph.hasNode(String(value))) { - // Update the node label in the sigma graph - sigmaGraph.setNodeAttribute(String(value), 'label', editValue) + try { + // Create a new node with the updated ID + const oldNodeAttributes = sigmaGraph.getNodeAttributes(String(value)) - // Also update the node in the raw graph - const nodeIndex = rawGraph.nodeIdMap[String(value)] - if (nodeIndex !== undefined) { - rawGraph.nodes[nodeIndex].id = editValue - // Update the node ID map - delete rawGraph.nodeIdMap[String(value)] - rawGraph.nodeIdMap[editValue] = nodeIndex + // Add a new node with the new ID but keep all other attributes + sigmaGraph.addNode(editValue, { + ...oldNodeAttributes, + label: editValue + }) + + // Copy all edges from the old node to the new node + sigmaGraph.forEachEdge(String(value), (edge, attributes, source, target) => { + const otherNode = source === String(value) ? target : source + const isOutgoing = source === String(value) + + // Create a new edge with the same attributes but connected to the new node ID + if (isOutgoing) { + sigmaGraph.addEdge(editValue, otherNode, attributes) + } else { + sigmaGraph.addEdge(otherNode, editValue, attributes) + } + + // Remove the old edge + sigmaGraph.dropEdge(edge) + }) + + // Remove the old node after all edges have been transferred + sigmaGraph.dropNode(String(value)) + + // Also update the node in the raw graph + const nodeIndex = rawGraph.nodeIdMap[String(value)] + if (nodeIndex !== undefined) { + rawGraph.nodes[nodeIndex].id = editValue + // Update the node ID map + delete rawGraph.nodeIdMap[String(value)] + rawGraph.nodeIdMap[editValue] = nodeIndex + } + + // Refresh the sigma instance to reflect changes + sigmaInstance.refresh() + + // Update selected node ID if it was the edited node + const selectedNode = useGraphStore.getState().selectedNode + if (selectedNode === String(value)) { + useGraphStore.getState().setSelectedNode(editValue) + } + + // Update focused node ID if it was the edited node + const focusedNode = useGraphStore.getState().focusedNode + if (focusedNode === String(value)) { + useGraphStore.getState().setFocusedNode(editValue) + } + } catch (error) { + console.error('Error updating node ID in graph:', error) + throw new Error('Failed to update node ID in graph') } - - // Refresh the sigma instance to reflect changes - sigmaInstance.refresh() - - // Update selected node ID if it was the edited node - const selectedNode = useGraphStore.getState().selectedNode - if (selectedNode === String(value)) { - useGraphStore.getState().setSelectedNode(editValue) - } - } - } else { - // Fallback to full graph reload if direct update is not possible - useGraphStore.getState().setGraphDataFetchAttempted(false) - useGraphStore.getState().setLabelsFetchAttempted(false) - - // Get current label to trigger reload - const currentLabel = useSettingsStore.getState().queryLabel - if (currentLabel) { - // Trigger data reload by temporarily clearing and resetting the label - useSettingsStore.getState().setQueryLabel('') - setTimeout(() => { - useSettingsStore.getState().setQueryLabel(currentLabel) - }, 0) } } } else if (name === 'description') { @@ -178,22 +200,45 @@ const EditablePropertyRow = ({ if (onValueChange) { onValueChange(editValue) } - } catch (error: any) { // Keep type as any to access potential response properties + } catch (error: any) { console.error('Error updating property:', error); - // Attempt to extract a more specific error message - let detailMessage = t('graphPanel.propertiesView.errors.updateFailed'); // Default message + // 尝试提取更具体的错误信息 + let detailMessage = t('graphPanel.propertiesView.errors.updateFailed'); + if (error.response?.data?.detail) { - // Use the detailed message from the backend response if available - detailMessage = error.response.data.detail; + detailMessage = error.response.data.detail; + } else if (error.response?.data?.message) { + detailMessage = error.response.data.message; } else if (error.message) { - // Use the error object's message if no backend detail - detailMessage = error.message; + detailMessage = error.message; } - toast.error(detailMessage); // Show the determined error message + // 记录详细的错误信息以便调试 + console.error('Update failed:', { + entityType, + entityId, + propertyName: name, + newValue: editValue, + error: error.response?.data || error.message + }); + + toast.error(detailMessage, { + description: t('graphPanel.propertiesView.errors.tryAgainLater') + }); } finally { + // Update the value immediately in the UI + if (onValueChange) { + onValueChange(editValue); + } + // Trigger graph data refresh + useGraphStore.getState().setGraphDataFetchAttempted(false); + useGraphStore.getState().setLabelsFetchAttempted(false); + // Re-select the node to refresh properties panel + const currentNodeId = name === 'entity_id' ? editValue : (entityId || ''); + useGraphStore.getState().setSelectedNode(null); + useGraphStore.getState().setSelectedNode(currentNodeId); setIsSubmitting(false) setIsEditing(false) } diff --git a/lightrag_webui/src/components/graph/GraphControl.tsx b/lightrag_webui/src/components/graph/GraphControl.tsx index aca8a9c4..8211178a 100644 --- a/lightrag_webui/src/components/graph/GraphControl.tsx +++ b/lightrag_webui/src/components/graph/GraphControl.tsx @@ -99,7 +99,10 @@ const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean }) const events: Record = { enterNode: (event: NodeEvent) => { if (!isButtonPressed(event.event.original)) { - setFocusedNode(event.node) + const graph = sigma.getGraph() + if (graph.hasNode(event.node)) { + setFocusedNode(event.node) + } } }, leaveNode: (event: NodeEvent) => { @@ -108,8 +111,11 @@ const GraphControl = ({ disableHoverEffect }: { disableHoverEffect?: boolean }) } }, clickNode: (event: NodeEvent) => { - setSelectedNode(event.node) - setSelectedEdge(null) + const graph = sigma.getGraph() + if (graph.hasNode(event.node)) { + setSelectedNode(event.node) + setSelectedEdge(null) + } }, clickStage: () => clearSelection() } diff --git a/lightrag_webui/src/locales/ar.json b/lightrag_webui/src/locales/ar.json index 36f31e92..9b227d47 100644 --- a/lightrag_webui/src/locales/ar.json +++ b/lightrag_webui/src/locales/ar.json @@ -35,6 +35,32 @@ "common": { "cancel": "إلغاء" }, + "graphPanel": { + "propertiesView": { + "errors": { + "duplicateName": "اسم العقدة موجود بالفعل", + "updateFailed": "فشل تحديث العقدة", + "tryAgainLater": "يرجى المحاولة مرة أخرى لاحقاً" + }, + "success": { + "entityUpdated": "تم تحديث العقدة بنجاح", + "relationUpdated": "تم تحديث العلاقة بنجاح" + }, + "node": { + "title": "عقدة", + "id": "المعرف", + "labels": "التسميات", + "degree": "الدرجة", + "properties": "الخصائص", + "relationships": "العلاقات (ضمن الرسم البياني الفرعي)", + "expandNode": "توسيع العقدة", + "pruneNode": "تقليم العقدة", + "deleteAllNodesError": "رفض حذف جميع العقد في الرسم البياني", + "nodesRemoved": "تم حذف {{count}} عقدة، بما في ذلك العقد اليتيمة", + "noNewNodes": "لم يتم العثور على عقد قابلة للتوسيع" + } + } + }, "documentPanel": { "clearDocuments": { "button": "مسح", diff --git a/lightrag_webui/src/locales/en.json b/lightrag_webui/src/locales/en.json index 13b6e5a5..a7119cbd 100644 --- a/lightrag_webui/src/locales/en.json +++ b/lightrag_webui/src/locales/en.json @@ -235,6 +235,15 @@ "vectorStorage": "Vector Storage" }, "propertiesView": { + "errors": { + "duplicateName": "Node name already exists", + "updateFailed": "Failed to update node", + "tryAgainLater": "Please try again later" + }, + "success": { + "entityUpdated": "Node updated successfully", + "relationUpdated": "Relation updated successfully" + }, "node": { "title": "Node", "id": "ID", diff --git a/lightrag_webui/src/locales/fr.json b/lightrag_webui/src/locales/fr.json index dbba9480..f4894d86 100644 --- a/lightrag_webui/src/locales/fr.json +++ b/lightrag_webui/src/locales/fr.json @@ -35,6 +35,32 @@ "common": { "cancel": "Annuler" }, + "graphPanel": { + "propertiesView": { + "errors": { + "duplicateName": "Le nom du nœud existe déjà", + "updateFailed": "Échec de la mise à jour du nœud", + "tryAgainLater": "Veuillez réessayer plus tard" + }, + "success": { + "entityUpdated": "Nœud mis à jour avec succès", + "relationUpdated": "Relation mise à jour avec succès" + }, + "node": { + "title": "Nœud", + "id": "ID", + "labels": "Étiquettes", + "degree": "Degré", + "properties": "Propriétés", + "relationships": "Relations(dans le sous-graphe)", + "expandNode": "Développer le nœud", + "pruneNode": "Élaguer le nœud", + "deleteAllNodesError": "Refus de supprimer tous les nœuds du graphe", + "nodesRemoved": "{{count}} nœuds supprimés, y compris les nœuds orphelins", + "noNewNodes": "Aucun nœud extensible trouvé" + } + } + }, "documentPanel": { "clearDocuments": { "button": "Effacer", diff --git a/lightrag_webui/src/locales/zh.json b/lightrag_webui/src/locales/zh.json index df4c33c3..beeb56d4 100644 --- a/lightrag_webui/src/locales/zh.json +++ b/lightrag_webui/src/locales/zh.json @@ -236,6 +236,15 @@ "vectorStorage": "向量存储" }, "propertiesView": { + "errors": { + "duplicateName": "节点名称已存在", + "updateFailed": "更新节点失败", + "tryAgainLater": "请稍后重试" + }, + "success": { + "entityUpdated": "节点更新成功", + "relationUpdated": "关系更新成功" + }, "node": { "title": "节点", "id": "ID", From 58eeacda20b62a0bd3b842f02c7d12cccaaf39e3 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sat, 12 Apr 2025 13:17:09 +0800 Subject: [PATCH 03/22] refactor(graph): Refactoring node attribute update logic to improve code maintainability --- .../components/graph/EditablePropertyRow.tsx | 208 ++++++++---------- 1 file changed, 90 insertions(+), 118 deletions(-) diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx index 837f6514..b6dc2588 100644 --- a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -5,7 +5,6 @@ import Input from '@/components/ui/Input' import { toast } from 'sonner' import { updateEntity, updateRelation, checkEntityNameExists } from '@/api/lightrag' import { useGraphStore } from '@/stores/graph' -import { useSettingsStore } from '@/stores/settings' interface EditablePropertyRowProps { name: string @@ -76,10 +75,72 @@ const EditablePropertyRow = ({ } } + const updateGraphNode = async (nodeId: string, propertyName: string, newValue: string) => { + const sigmaInstance = useGraphStore.getState().sigmaInstance + const sigmaGraph = useGraphStore.getState().sigmaGraph + const rawGraph = useGraphStore.getState().rawGraph + + if (!sigmaInstance || !sigmaGraph || !rawGraph || !sigmaGraph.hasNode(String(nodeId))) { + return + } + + try { + const nodeAttributes = sigmaGraph.getNodeAttributes(String(nodeId)) + + if (propertyName === 'entity_id') { + sigmaGraph.addNode(newValue, { ...nodeAttributes, label: newValue }) + + sigmaGraph.forEachEdge(String(nodeId), (edge, attributes, source, target) => { + const otherNode = source === String(nodeId) ? target : source + const isOutgoing = source === String(nodeId) + sigmaGraph.addEdge(isOutgoing ? newValue : otherNode, isOutgoing ? otherNode : newValue, attributes) + sigmaGraph.dropEdge(edge) + }) + + sigmaGraph.dropNode(String(nodeId)) + + const nodeIndex = rawGraph.nodeIdMap[String(nodeId)] + if (nodeIndex !== undefined) { + rawGraph.nodes[nodeIndex].id = newValue + rawGraph.nodes[nodeIndex].properties.entity_id = newValue + delete rawGraph.nodeIdMap[String(nodeId)] + rawGraph.nodeIdMap[newValue] = nodeIndex + } + } else { + const updatedAttributes = { ...nodeAttributes } + if (propertyName === 'description') { + updatedAttributes.description = newValue + } + Object.entries(updatedAttributes).forEach(([key, value]) => { + sigmaGraph.setNodeAttribute(String(nodeId), key, value) + }) + + const nodeIndex = rawGraph.nodeIdMap[String(nodeId)] + if (nodeIndex !== undefined) { + rawGraph.nodes[nodeIndex].properties[propertyName] = newValue + } + } + + const selectedNode = useGraphStore.getState().selectedNode + if (selectedNode === String(nodeId)) { + useGraphStore.getState().setSelectedNode(newValue) + } + + const focusedNode = useGraphStore.getState().focusedNode + if (focusedNode === String(nodeId)) { + useGraphStore.getState().setFocusedNode(newValue) + } + + sigmaInstance.refresh() + } catch (error) { + console.error('Error updating node in graph:', error) + throw new Error('Failed to update node in graph') + } + } + const handleSave = async () => { if (isSubmitting) return - // Don't save if value hasn't changed if (editValue === String(value)) { setIsEditing(false) return @@ -88,157 +149,68 @@ const EditablePropertyRow = ({ setIsSubmitting(true) try { - // Special handling for entity_id (name) field to check for duplicates - if (name === 'entity_id' && entityType === 'node') { - // Ensure we are not checking the original name against itself if it's protected - if (editValue !== String(value)) { - const exists = await checkEntityNameExists(editValue); - if (exists) { - toast.error(t('graphPanel.propertiesView.errors.duplicateName')); - setIsSubmitting(false); - return; - } - } - } + const updatedData: Record = {} - // Update the entity or relation in the database if (entityType === 'node' && entityId) { - // For nodes, we need to determine if we're updating the name or description - const updatedData: Record = {} - if (name === 'entity_id') { - // For entity name updates - updatedData['entity_name'] = editValue - await updateEntity(String(value), updatedData, true) // Pass original name (value) as identifier - - // Update node label in the graph directly instead of reloading the entire graph - const sigmaInstance = useGraphStore.getState().sigmaInstance - const sigmaGraph = useGraphStore.getState().sigmaGraph - const rawGraph = useGraphStore.getState().rawGraph - - if (sigmaInstance && sigmaGraph && rawGraph) { - // Update the node in sigma graph - if (sigmaGraph.hasNode(String(value))) { - try { - // Create a new node with the updated ID - const oldNodeAttributes = sigmaGraph.getNodeAttributes(String(value)) - - // Add a new node with the new ID but keep all other attributes - sigmaGraph.addNode(editValue, { - ...oldNodeAttributes, - label: editValue - }) - - // Copy all edges from the old node to the new node - sigmaGraph.forEachEdge(String(value), (edge, attributes, source, target) => { - const otherNode = source === String(value) ? target : source - const isOutgoing = source === String(value) - - // Create a new edge with the same attributes but connected to the new node ID - if (isOutgoing) { - sigmaGraph.addEdge(editValue, otherNode, attributes) - } else { - sigmaGraph.addEdge(otherNode, editValue, attributes) - } - - // Remove the old edge - sigmaGraph.dropEdge(edge) - }) - - // Remove the old node after all edges have been transferred - sigmaGraph.dropNode(String(value)) - - // Also update the node in the raw graph - const nodeIndex = rawGraph.nodeIdMap[String(value)] - if (nodeIndex !== undefined) { - rawGraph.nodes[nodeIndex].id = editValue - // Update the node ID map - delete rawGraph.nodeIdMap[String(value)] - rawGraph.nodeIdMap[editValue] = nodeIndex - } - - // Refresh the sigma instance to reflect changes - sigmaInstance.refresh() - - // Update selected node ID if it was the edited node - const selectedNode = useGraphStore.getState().selectedNode - if (selectedNode === String(value)) { - useGraphStore.getState().setSelectedNode(editValue) - } - - // Update focused node ID if it was the edited node - const focusedNode = useGraphStore.getState().focusedNode - if (focusedNode === String(value)) { - useGraphStore.getState().setFocusedNode(editValue) - } - } catch (error) { - console.error('Error updating node ID in graph:', error) - throw new Error('Failed to update node ID in graph') - } + if (editValue !== String(value)) { + const exists = await checkEntityNameExists(editValue) + if (exists) { + toast.error(t('graphPanel.propertiesView.errors.duplicateName')) + return } } - } else if (name === 'description') { - // For description updates - updatedData['description'] = editValue - await updateEntity(entityId, updatedData) // Pass entityId as identifier + updatedData['entity_name'] = editValue + await updateEntity(String(value), updatedData, true) + await updateGraphNode(String(value), 'entity_id', editValue) } else { - // For other property updates updatedData[name] = editValue - await updateEntity(entityId, updatedData) // Pass entityId as identifier + await updateEntity(entityId, updatedData) + if (name === 'description') { + await updateGraphNode(entityId, name, editValue) + } } - toast.success(t('graphPanel.propertiesView.success.entityUpdated')) } else if (entityType === 'edge' && sourceId && targetId) { - // For edges, update the relation - const updatedData: Record = {} updatedData[name] = editValue await updateRelation(sourceId, targetId, updatedData) toast.success(t('graphPanel.propertiesView.success.relationUpdated')) } - // Notify parent component about the value change if (onValueChange) { onValueChange(editValue) } - } catch (error: any) { - console.error('Error updating property:', error); - // 尝试提取更具体的错误信息 - let detailMessage = t('graphPanel.propertiesView.errors.updateFailed'); + useGraphStore.getState().setGraphDataFetchAttempted(false) + useGraphStore.getState().setLabelsFetchAttempted(false) + + const currentNodeId = name === 'entity_id' ? editValue : (entityId || '') + useGraphStore.getState().setSelectedNode(null) + useGraphStore.getState().setSelectedNode(currentNodeId) + } catch (error: any) { + console.error('Error updating property:', error) + let detailMessage = t('graphPanel.propertiesView.errors.updateFailed') if (error.response?.data?.detail) { - detailMessage = error.response.data.detail; + detailMessage = error.response.data.detail } else if (error.response?.data?.message) { - detailMessage = error.response.data.message; + detailMessage = error.response.data.message } else if (error.message) { - detailMessage = error.message; + detailMessage = error.message } - // 记录详细的错误信息以便调试 console.error('Update failed:', { entityType, entityId, propertyName: name, newValue: editValue, error: error.response?.data || error.message - }); + }) toast.error(detailMessage, { description: t('graphPanel.propertiesView.errors.tryAgainLater') - }); - + }) } finally { - // Update the value immediately in the UI - if (onValueChange) { - onValueChange(editValue); - } - // Trigger graph data refresh - useGraphStore.getState().setGraphDataFetchAttempted(false); - useGraphStore.getState().setLabelsFetchAttempted(false); - // Re-select the node to refresh properties panel - const currentNodeId = name === 'entity_id' ? editValue : (entityId || ''); - useGraphStore.getState().setSelectedNode(null); - useGraphStore.getState().setSelectedNode(currentNodeId); setIsSubmitting(false) setIsEditing(false) } From 272b10197436b05b89c5bba91b6a5d087394c659 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sat, 12 Apr 2025 14:33:40 +0800 Subject: [PATCH 04/22] feat: Add double-click editing prompt text and optimize editable attribute line style --- .../components/graph/EditablePropertyRow.tsx | 20 ++++++---- lightrag_webui/src/locales/ar.json | 36 +++++------------- lightrag_webui/src/locales/en.json | 1 + lightrag_webui/src/locales/fr.json | 37 ++++++------------- lightrag_webui/src/locales/zh.json | 1 + 5 files changed, 36 insertions(+), 59 deletions(-) diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx index b6dc2588..bf583a0e 100644 --- a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -5,6 +5,7 @@ import Input from '@/components/ui/Input' import { toast } from 'sonner' import { updateEntity, updateRelation, checkEntityNameExists } from '@/api/lightrag' import { useGraphStore } from '@/stores/graph' +import { PencilIcon } from 'lucide-react' interface EditablePropertyRowProps { name: string @@ -222,9 +223,17 @@ const EditablePropertyRow = ({ return (
- +
{getPropertyNameTranslation(name)} - : + {isEditableField && ( +
+ +
+ {t('graphPanel.propertiesView.doubleClickToEdit')} +
+
+ )} +
: {isEditing ? (
) : ( - // Wrap Text component in a div to handle onDoubleClick
)} diff --git a/lightrag_webui/src/locales/ar.json b/lightrag_webui/src/locales/ar.json index 9b227d47..315bfe48 100644 --- a/lightrag_webui/src/locales/ar.json +++ b/lightrag_webui/src/locales/ar.json @@ -35,32 +35,6 @@ "common": { "cancel": "إلغاء" }, - "graphPanel": { - "propertiesView": { - "errors": { - "duplicateName": "اسم العقدة موجود بالفعل", - "updateFailed": "فشل تحديث العقدة", - "tryAgainLater": "يرجى المحاولة مرة أخرى لاحقاً" - }, - "success": { - "entityUpdated": "تم تحديث العقدة بنجاح", - "relationUpdated": "تم تحديث العلاقة بنجاح" - }, - "node": { - "title": "عقدة", - "id": "المعرف", - "labels": "التسميات", - "degree": "الدرجة", - "properties": "الخصائص", - "relationships": "العلاقات (ضمن الرسم البياني الفرعي)", - "expandNode": "توسيع العقدة", - "pruneNode": "تقليم العقدة", - "deleteAllNodesError": "رفض حذف جميع العقد في الرسم البياني", - "nodesRemoved": "تم حذف {{count}} عقدة، بما في ذلك العقد اليتيمة", - "noNewNodes": "لم يتم العثور على عقد قابلة للتوسيع" - } - } - }, "documentPanel": { "clearDocuments": { "button": "مسح", @@ -262,6 +236,16 @@ "vectorStorage": "تخزين المتجهات" }, "propertiesView": { + "errors": { + "duplicateName": "اسم العقدة موجود بالفعل", + "updateFailed": "فشل تحديث العقدة", + "tryAgainLater": "يرجى المحاولة مرة أخرى لاحقًا" + }, + "doubleClickToEdit": "انقر نقرًا مزدوجًا للتعديل", + "success": { + "entityUpdated": "تم تحديث العقدة بنجاح", + "relationUpdated": "تم تحديث العلاقة بنجاح" + }, "node": { "title": "عقدة", "id": "المعرف", diff --git a/lightrag_webui/src/locales/en.json b/lightrag_webui/src/locales/en.json index a7119cbd..fb420ba1 100644 --- a/lightrag_webui/src/locales/en.json +++ b/lightrag_webui/src/locales/en.json @@ -240,6 +240,7 @@ "updateFailed": "Failed to update node", "tryAgainLater": "Please try again later" }, + "doubleClickToEdit": "Double click to edit", "success": { "entityUpdated": "Node updated successfully", "relationUpdated": "Relation updated successfully" diff --git a/lightrag_webui/src/locales/fr.json b/lightrag_webui/src/locales/fr.json index f4894d86..325d73d3 100644 --- a/lightrag_webui/src/locales/fr.json +++ b/lightrag_webui/src/locales/fr.json @@ -35,32 +35,7 @@ "common": { "cancel": "Annuler" }, - "graphPanel": { - "propertiesView": { - "errors": { - "duplicateName": "Le nom du nœud existe déjà", - "updateFailed": "Échec de la mise à jour du nœud", - "tryAgainLater": "Veuillez réessayer plus tard" - }, - "success": { - "entityUpdated": "Nœud mis à jour avec succès", - "relationUpdated": "Relation mise à jour avec succès" - }, - "node": { - "title": "Nœud", - "id": "ID", - "labels": "Étiquettes", - "degree": "Degré", - "properties": "Propriétés", - "relationships": "Relations(dans le sous-graphe)", - "expandNode": "Développer le nœud", - "pruneNode": "Élaguer le nœud", - "deleteAllNodesError": "Refus de supprimer tous les nœuds du graphe", - "nodesRemoved": "{{count}} nœuds supprimés, y compris les nœuds orphelins", - "noNewNodes": "Aucun nœud extensible trouvé" - } - } - }, + "documentPanel": { "clearDocuments": { "button": "Effacer", @@ -262,6 +237,16 @@ "vectorStorage": "Stockage vectoriel" }, "propertiesView": { + "errors": { + "duplicateName": "Le nom du nœud existe déjà", + "updateFailed": "Échec de la mise à jour du nœud", + "tryAgainLater": "Veuillez réessayer plus tard" + }, + "doubleClickToEdit": "Double-cliquez pour modifier", + "success": { + "entityUpdated": "Nœud mis à jour avec succès", + "relationUpdated": "Relation mise à jour avec succès" + }, "node": { "title": "Nœud", "id": "ID", diff --git a/lightrag_webui/src/locales/zh.json b/lightrag_webui/src/locales/zh.json index beeb56d4..1bbfbbf6 100644 --- a/lightrag_webui/src/locales/zh.json +++ b/lightrag_webui/src/locales/zh.json @@ -241,6 +241,7 @@ "updateFailed": "更新节点失败", "tryAgainLater": "请稍后重试" }, + "doubleClickToEdit": "双击编辑", "success": { "entityUpdated": "节点更新成功", "relationUpdated": "关系更新成功" From a72809c59a07de31c6bb71780ef61d0680b66a84 Mon Sep 17 00:00:00 2001 From: iLuJack Date: Thu, 10 Apr 2025 20:58:46 +0800 Subject: [PATCH 05/22] docs(locales): add traditional chinese support --- lightrag_webui/src/components/AppSettings.tsx | 3 +- lightrag_webui/src/i18n.ts | 4 +- lightrag_webui/src/locales/zh_TW.json | 348 ++++++++++++++++++ lightrag_webui/src/stores/settings.ts | 2 +- 4 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 lightrag_webui/src/locales/zh_TW.json diff --git a/lightrag_webui/src/components/AppSettings.tsx b/lightrag_webui/src/components/AppSettings.tsx index 6e312e0e..09312794 100644 --- a/lightrag_webui/src/components/AppSettings.tsx +++ b/lightrag_webui/src/components/AppSettings.tsx @@ -22,7 +22,7 @@ export default function AppSettings({ className }: AppSettingsProps) { const setTheme = useSettingsStore.use.setTheme() const handleLanguageChange = useCallback((value: string) => { - setLanguage(value as 'en' | 'zh' | 'fr' | 'ar') + setLanguage(value as 'en' | 'zh' | 'fr' | 'ar' | 'zh_TW') }, [setLanguage]) const handleThemeChange = useCallback((value: string) => { @@ -49,6 +49,7 @@ export default function AppSettings({ className }: AppSettingsProps) { 中文 Français العربية + 繁體中文
diff --git a/lightrag_webui/src/i18n.ts b/lightrag_webui/src/i18n.ts index 15978ebe..dbee5d10 100644 --- a/lightrag_webui/src/i18n.ts +++ b/lightrag_webui/src/i18n.ts @@ -6,6 +6,7 @@ import en from './locales/en.json' import zh from './locales/zh.json' import fr from './locales/fr.json' import ar from './locales/ar.json' +import zh_TW from './locales/zh_TW.json' const getStoredLanguage = () => { try { @@ -27,7 +28,8 @@ i18n en: { translation: en }, zh: { translation: zh }, fr: { translation: fr }, - ar: { translation: ar } + ar: { translation: ar }, + zh_TW: { translation: zh_TW } }, lng: getStoredLanguage(), // Use stored language settings fallbackLng: 'en', diff --git a/lightrag_webui/src/locales/zh_TW.json b/lightrag_webui/src/locales/zh_TW.json new file mode 100644 index 00000000..7deb8157 --- /dev/null +++ b/lightrag_webui/src/locales/zh_TW.json @@ -0,0 +1,348 @@ +{ + "settings": { + "language": "語言", + "theme": "主題", + "light": "淺色", + "dark": "深色", + "system": "系統" + }, + "header": { + "documents": "文件", + "knowledgeGraph": "知識圖譜", + "retrieval": "檢索", + "api": "API", + "projectRepository": "專案庫", + "logout": "登出", + "themeToggle": { + "switchToLight": "切換至淺色主題", + "switchToDark": "切換至深色主題" + } + }, + "login": { + "description": "請輸入您的帳號和密碼登入系統", + "username": "帳號", + "usernamePlaceholder": "請輸入帳號", + "password": "密碼", + "passwordPlaceholder": "請輸入密碼", + "loginButton": "登入", + "loggingIn": "登入中...", + "successMessage": "登入成功", + "errorEmptyFields": "請輸入您的帳號和密碼", + "errorInvalidCredentials": "登入失敗,請檢查帳號和密碼", + "authDisabled": "認證已停用,使用免登入模式", + "guestMode": "免登入" + }, + "common": { + "cancel": "取消" + }, + "documentPanel": { + "clearDocuments": { + "button": "清空", + "tooltip": "清空文件", + "title": "清空文件", + "description": "此操作將從系統中移除所有文件", + "warning": "警告:此操作將永久刪除所有文件,無法復原!", + "confirm": "確定要清空所有文件嗎?", + "confirmPrompt": "請輸入 yes 確認操作", + "confirmPlaceholder": "輸入 yes 以確認", + "clearCache": "清空 LLM 快取", + "confirmButton": "確定", + "success": "文件清空成功", + "cacheCleared": "快取清空成功", + "cacheClearFailed": "清空快取失敗:\n{{error}}", + "failed": "清空文件失敗:\n{{message}}", + "error": "清空文件失敗:\n{{error}}" + }, + "uploadDocuments": { + "button": "上傳", + "tooltip": "上傳文件", + "title": "上傳文件", + "description": "拖曳檔案至此處或點擊瀏覽", + "single": { + "uploading": "正在上傳 {{name}}:{{percent}}%", + "success": "上傳成功:\n{{name}} 上傳完成", + "failed": "上傳失敗:\n{{name}}\n{{message}}", + "error": "上傳失敗:\n{{name}}\n{{error}}" + }, + "batch": { + "uploading": "正在上傳檔案...", + "success": "檔案上傳完成", + "error": "部分檔案上傳失敗" + }, + "generalError": "上傳失敗\n{{error}}", + "fileTypes": "支援的檔案類型:TXT, MD, DOCX, PDF, PPTX, RTF, ODT, EPUB, HTML, HTM, TEX, JSON, XML, YAML, YML, CSV, LOG, CONF, INI, PROPERTIES, SQL, BAT, SH, C, CPP, PY, JAVA, JS, TS, SWIFT, GO, RB, PHP, CSS, SCSS, LESS", + "fileUploader": { + "singleFileLimit": "一次只能上傳一個檔案", + "maxFilesLimit": "最多只能上傳 {{count}} 個檔案", + "fileRejected": "檔案 {{name}} 被拒絕", + "unsupportedType": "不支援的檔案類型", + "fileTooLarge": "檔案過大,最大允許 {{maxSize}}", + "dropHere": "將檔案拖放至此處", + "dragAndDrop": "拖放檔案至此處,或點擊選擇檔案", + "removeFile": "移除檔案", + "uploadDescription": "您可以上傳{{isMultiple ? '多個' : count}}個檔案(每個檔案最大{{maxSize}})", + "duplicateFile": "檔案名稱與伺服器上的快取重複" + } + }, + "documentManager": { + "title": "文件管理", + "scanButton": "掃描", + "scanTooltip": "掃描輸入目錄中的文件", + "pipelineStatusButton": "pipeline 狀態", + "pipelineStatusTooltip": "查看pipeline 狀態", + "uploadedTitle": "已上傳文件", + "uploadedDescription": "已上傳文件清單及其狀態", + "emptyTitle": "無文件", + "emptyDescription": "尚未上傳任何文件", + "columns": { + "id": "ID", + "summary": "摘要", + "status": "狀態", + "length": "長度", + "chunks": "分塊", + "created": "建立時間", + "updated": "更新時間", + "metadata": "元資料" + }, + "status": { + "all": "全部", + "completed": "已完成", + "processing": "處理中", + "pending": "等待中", + "failed": "失敗" + }, + "errors": { + "loadFailed": "載入文件失敗\n{{error}}", + "scanFailed": "掃描文件失敗\n{{error}}", + "scanProgressFailed": "取得掃描進度失敗\n{{error}}" + }, + "fileNameLabel": "檔案名稱", + "showButton": "顯示", + "hideButton": "隱藏", + "showFileNameTooltip": "顯示檔案名稱", + "hideFileNameTooltip": "隱藏檔案名稱" + }, + "pipelineStatus": { + "title": "pipeline 狀態", + "busy": "pipeline 忙碌中", + "requestPending": "待處理請求", + "jobName": "工作名稱", + "startTime": "開始時間", + "progress": "進度", + "unit": "梯次", + "latestMessage": "最新訊息", + "historyMessages": "歷史訊息", + "errors": { + "fetchFailed": "取得pipeline 狀態失敗\n{{error}}" + } + } + }, + "graphPanel": { + "dataIsTruncated": "圖資料已截斷至最大回傳節點數", + "statusDialog": { + "title": "LightRAG 伺服器設定", + "description": "查看目前系統狀態和連線資訊" + }, + "legend": "圖例", + "nodeTypes": { + "person": "人物角色", + "category": "分類", + "geo": "地理名稱", + "location": "位置", + "organization": "組織機構", + "event": "事件", + "equipment": "設備", + "weapon": "武器", + "animal": "動物", + "unknown": "未知", + "object": "物品", + "group": "群組", + "technology": "技術" + }, + "sideBar": { + "settings": { + "settings": "設定", + "healthCheck": "健康檢查", + "showPropertyPanel": "顯示屬性面板", + "showSearchBar": "顯示搜尋列", + "showNodeLabel": "顯示節點標籤", + "nodeDraggable": "節點可拖曳", + "showEdgeLabel": "顯示 Edge 標籤", + "hideUnselectedEdges": "隱藏未選取的 Edge", + "edgeEvents": "Edge 事件", + "maxQueryDepth": "最大查詢深度", + "maxNodes": "最大回傳節點數", + "maxLayoutIterations": "最大版面配置迭代次數", + "resetToDefault": "重設為預設值", + "edgeSizeRange": "Edge 粗細範圍", + "depth": "深度", + "max": "最大值", + "degree": "鄰邊", + "apiKey": "API key", + "enterYourAPIkey": "輸入您的 API key", + "save": "儲存", + "refreshLayout": "重新整理版面配置" + }, + "zoomControl": { + "zoomIn": "放大", + "zoomOut": "縮小", + "resetZoom": "重設縮放", + "rotateCamera": "順時針旋轉圖形", + "rotateCameraCounterClockwise": "逆時針旋轉圖形" + }, + "layoutsControl": { + "startAnimation": "繼續版面配置動畫", + "stopAnimation": "停止版面配置動畫", + "layoutGraph": "圖形版面配置", + "layouts": { + "Circular": "環形", + "Circlepack": "圓形打包", + "Random": "隨機", + "Noverlaps": "無重疊", + "Force Directed": "力導向", + "Force Atlas": "力圖" + } + }, + "fullScreenControl": { + "fullScreen": "全螢幕", + "windowed": "視窗" + }, + "legendControl": { + "toggleLegend": "切換圖例顯示" + } + }, + "statusIndicator": { + "connected": "已連線", + "disconnected": "未連線" + }, + "statusCard": { + "unavailable": "狀態資訊不可用", + "storageInfo": "儲存資訊", + "workingDirectory": "工作目錄", + "inputDirectory": "輸入目錄", + "llmConfig": "LLM 設定", + "llmBinding": "LLM 綁定", + "llmBindingHost": "LLM 綁定主機", + "llmModel": "LLM 模型", + "maxTokens": "最大權杖數", + "embeddingConfig": "嵌入設定", + "embeddingBinding": "嵌入綁定", + "embeddingBindingHost": "嵌入綁定主機", + "embeddingModel": "嵌入模型", + "storageConfig": "儲存設定", + "kvStorage": "KV 儲存", + "docStatusStorage": "文件狀態儲存", + "graphStorage": "圖形儲存", + "vectorStorage": "向量儲存" + }, + "propertiesView": { + "node": { + "title": "節點", + "id": "ID", + "labels": "標籤", + "degree": "度數", + "properties": "屬性", + "relationships": "關係(子圖內)", + "expandNode": "展開節點", + "pruneNode": "修剪節點", + "deleteAllNodesError": "拒絕刪除圖中的所有節點", + "nodesRemoved": "已刪除 {{count}} 個節點,包括孤立節點", + "noNewNodes": "沒有發現可以展開的節點", + "propertyNames": { + "description": "描述", + "entity_id": "名稱", + "entity_type": "類型", + "source_id": "來源ID", + "Neighbour": "鄰接", + "file_path": "來源" + } + }, + "edge": { + "title": "關係", + "id": "ID", + "type": "類型", + "source": "來源節點", + "target": "目標節點", + "properties": "屬性" + } + }, + "search": { + "placeholder": "搜尋節點...", + "message": "還有 {count} 個" + }, + "graphLabels": { + "selectTooltip": "選擇查詢標籤", + "noLabels": "未找到標籤", + "label": "標籤", + "placeholder": "搜尋標籤...", + "andOthers": "還有 {count} 個", + "refreshTooltip": "重新載入圖形資料" + }, + "emptyGraph": "圖譜資料為空" + }, + "retrievePanel": { + "chatMessage": { + "copyTooltip": "複製到剪貼簿", + "copyError": "複製文字到剪貼簿失敗" + }, + "retrieval": { + "startPrompt": "輸入查詢開始檢索", + "clear": "清空", + "send": "送出", + "placeholder": "輸入查詢...", + "error": "錯誤:取得回應失敗" + }, + "querySettings": { + "parametersTitle": "參數", + "parametersDescription": "設定查詢參數", + "queryMode": "查詢模式", + "queryModeTooltip": "選擇檢索策略:\n• Naive:基礎搜尋,無進階技術\n• Local:上下文相關資訊檢索\n• Global:利用全域知識庫\n• Hybrid:結合本地和全域檢索\n• Mix:整合知識圖譜和向量檢索", + "queryModeOptions": { + "naive": "Naive", + "local": "Local", + "global": "Global", + "hybrid": "Hybrid", + "mix": "Mix" + }, + "responseFormat": "回應格式", + "responseFormatTooltip": "定義回應格式。例如:\n• 多段落\n• 單段落\n• 重點", + "responseFormatOptions": { + "multipleParagraphs": "多段落", + "singleParagraph": "單段落", + "bulletPoints": "重點" + }, + "topK": "Top K結果", + "topKTooltip": "檢索的前幾項結果數。在'local'模式下表示實體,在'global'模式下表示關係", + "topKPlaceholder": "結果數量", + "maxTokensTextUnit": "文字單元最大權杖數", + "maxTokensTextUnitTooltip": "每個檢索文字區塊允許的最大權杖數", + "maxTokensGlobalContext": "全域上下文最大權杖數", + "maxTokensGlobalContextTooltip": "全域檢索中關係描述的最大權杖數", + "maxTokensLocalContext": "本地上下文最大權杖數", + "maxTokensLocalContextTooltip": "本地檢索中實體描述的最大權杖數", + "historyTurns": "歷史輪次", + "historyTurnsTooltip": "回應上下文中考慮的完整對話輪次(使用者-助手對)數量", + "historyTurnsPlaceholder": "歷史輪次數", + "hlKeywords": "進階關鍵字", + "hlKeywordsTooltip": "檢索中優先考慮的進階關鍵字清單。用逗號分隔", + "hlkeywordsPlaceHolder": "輸入關鍵字", + "llKeywords": "基礎關鍵字", + "llKeywordsTooltip": "用於細化檢索重點的基礎關鍵字清單。用逗號分隔", + "onlyNeedContext": "僅需上下文", + "onlyNeedContextTooltip": "如果為True,僅回傳檢索到的上下文而不產生回應", + "onlyNeedPrompt": "僅需提示", + "onlyNeedPromptTooltip": "如果為True,僅回傳產生的提示而不產生回應", + "streamResponse": "串流回應", + "streamResponseTooltip": "如果為True,啟用即時串流輸出回應" + } + }, + "apiSite": { + "loading": "正在載入 API 文件..." + }, + "apiKeyAlert": { + "title": "需要 API key", + "description": "請輸入您的 API key 以存取服務", + "placeholder": "請輸入 API key", + "save": "儲存" + } +} diff --git a/lightrag_webui/src/stores/settings.ts b/lightrag_webui/src/stores/settings.ts index 2c314e06..5da8107e 100644 --- a/lightrag_webui/src/stores/settings.ts +++ b/lightrag_webui/src/stores/settings.ts @@ -5,7 +5,7 @@ import { defaultQueryLabel } from '@/lib/constants' import { Message, QueryRequest } from '@/api/lightrag' type Theme = 'dark' | 'light' | 'system' -type Language = 'en' | 'zh' | 'fr' | 'ar' +type Language = 'en' | 'zh' | 'fr' | 'ar' | 'zh_TW' type Tab = 'documents' | 'knowledge-graph' | 'retrieval' | 'api' interface SettingsState { From 5e5f3640d7dc90792555b32f505cb643c9ae8391 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sat, 12 Apr 2025 15:09:44 +0800 Subject: [PATCH 06/22] --- lightrag/api/routers/graph_routes.py | 34 +++ lightrag_webui/src/api/lightrag.ts | 4 +- .../components/graph/EditablePropertyRow.tsx | 276 +++++++++++------- .../src/components/graph/PropertiesView.tsx | 10 +- 4 files changed, 209 insertions(+), 115 deletions(-) diff --git a/lightrag/api/routers/graph_routes.py b/lightrag/api/routers/graph_routes.py index 97a397d4..e77e959a 100644 --- a/lightrag/api/routers/graph_routes.py +++ b/lightrag/api/routers/graph_routes.py @@ -17,6 +17,12 @@ class EntityUpdateRequest(BaseModel): allow_rename: bool = False +class RelationUpdateRequest(BaseModel): + source_id: str + target_id: str + updated_data: Dict[str, Any] + + def create_graph_routes(rag, api_key: Optional[str] = None): combined_auth = get_combined_auth_dependency(api_key) @@ -107,4 +113,32 @@ def create_graph_routes(rag, api_key: Optional[str] = None): status_code=500, detail=f"Error updating entity: {str(e)}" ) + @router.post("/graph/relation/edit", dependencies=[Depends(combined_auth)]) + async def update_relation(request: RelationUpdateRequest): + """Update a relation's properties in the knowledge graph + + Args: + request (RelationUpdateRequest): Request containing source ID, target ID and updated data + + Returns: + Dict: Updated relation information + """ + try: + result = await rag.aedit_relation( + source_entity=request.source_id, + target_entity=request.target_id, + updated_data=request.updated_data, + ) + return { + "status": "success", + "message": "Relation updated successfully", + "data": result, + } + except ValueError as ve: + raise HTTPException(status_code=400, detail=str(ve)) + except Exception as e: + raise HTTPException( + status_code=500, detail=f"Error updating relation: {str(e)}" + ) + return router diff --git a/lightrag_webui/src/api/lightrag.ts b/lightrag_webui/src/api/lightrag.ts index 63f4e2f6..d0ca7d63 100644 --- a/lightrag_webui/src/api/lightrag.ts +++ b/lightrag_webui/src/api/lightrag.ts @@ -540,8 +540,8 @@ export const updateRelation = async ( updatedData: Record ): Promise => { const response = await axiosInstance.post('/graph/relation/edit', { - source_entity: sourceEntity, - target_entity: targetEntity, + source_id: sourceEntity, + target_id: targetEntity, updated_data: updatedData }) return response.data diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx index bf583a0e..ac92b335 100644 --- a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -6,6 +6,7 @@ import { toast } from 'sonner' import { updateEntity, updateRelation, checkEntityNameExists } from '@/api/lightrag' import { useGraphStore } from '@/stores/graph' import { PencilIcon } from 'lucide-react' +import { tr } from '@faker-js/faker' interface EditablePropertyRowProps { name: string @@ -26,7 +27,7 @@ interface EditablePropertyRowProps { */ const EditablePropertyRow = ({ name, - value, + value: initialValue, onClick, tooltip, entityId, @@ -40,12 +41,18 @@ const EditablePropertyRow = ({ const [isEditing, setIsEditing] = useState(false) const [editValue, setEditValue] = useState('') const [isSubmitting, setIsSubmitting] = useState(false) + const [currentValue, setCurrentValue] = useState(initialValue) const inputRef = useRef(null) + // Update currentValue when initialValue changes + useEffect(() => { + setCurrentValue(initialValue) + }, [initialValue]) + // Initialize edit value when entering edit mode useEffect(() => { if (isEditing) { - setEditValue(String(value)) + setEditValue(String(currentValue)) // Focus the input element when entering edit mode setTimeout(() => { if (inputRef.current) { @@ -54,7 +61,7 @@ const EditablePropertyRow = ({ } }, 50) } - }, [isEditing, value]) + }, [isEditing, currentValue]) const getPropertyNameTranslation = (propName: string) => { const translationKey = `graphPanel.propertiesView.node.propertyNames.${propName}` @@ -91,10 +98,34 @@ const EditablePropertyRow = ({ if (propertyName === 'entity_id') { sigmaGraph.addNode(newValue, { ...nodeAttributes, label: newValue }) + interface EdgeToUpdate { + originalDynamicId: string; + newEdgeId: string; + edgeIndex: number; + } + + const edgesToUpdate: EdgeToUpdate[] = []; + sigmaGraph.forEachEdge(String(nodeId), (edge, attributes, source, target) => { const otherNode = source === String(nodeId) ? target : source const isOutgoing = source === String(nodeId) - sigmaGraph.addEdge(isOutgoing ? newValue : otherNode, isOutgoing ? otherNode : newValue, attributes) + + // 获取原始边的dynamicId,以便后续更新edgeDynamicIdMap + const originalEdgeDynamicId = edge + const edgeIndexInRawGraph = rawGraph.edgeDynamicIdMap[originalEdgeDynamicId] + + // 创建新边并获取新边的ID + const newEdgeId = sigmaGraph.addEdge(isOutgoing ? newValue : otherNode, isOutgoing ? otherNode : newValue, attributes) + + // 存储需要更新的边信息 + if (edgeIndexInRawGraph !== undefined) { + edgesToUpdate.push({ + originalDynamicId: originalEdgeDynamicId, + newEdgeId: newEdgeId, + edgeIndex: edgeIndexInRawGraph + }) + } + sigmaGraph.dropEdge(edge) }) @@ -107,42 +138,112 @@ const EditablePropertyRow = ({ delete rawGraph.nodeIdMap[String(nodeId)] rawGraph.nodeIdMap[newValue] = nodeIndex } - } else { - const updatedAttributes = { ...nodeAttributes } - if (propertyName === 'description') { - updatedAttributes.description = newValue - } - Object.entries(updatedAttributes).forEach(([key, value]) => { - sigmaGraph.setNodeAttribute(String(nodeId), key, value) + + // 更新边的引用关系 + edgesToUpdate.forEach(({ originalDynamicId, newEdgeId, edgeIndex }) => { + // 更新边的source和target + if (rawGraph.edges[edgeIndex]) { + if (rawGraph.edges[edgeIndex].source === String(nodeId)) { + rawGraph.edges[edgeIndex].source = newValue + } + if (rawGraph.edges[edgeIndex].target === String(nodeId)) { + rawGraph.edges[edgeIndex].target = newValue + } + + // 更新dynamicId映射 + rawGraph.edges[edgeIndex].dynamicId = newEdgeId + delete rawGraph.edgeDynamicIdMap[originalDynamicId] + rawGraph.edgeDynamicIdMap[newEdgeId] = edgeIndex + } }) + useGraphStore.getState().setSelectedNode(editValue) + } else { + // const updatedAttributes = { ...nodeAttributes } + // if (propertyName === 'description') { + // updatedAttributes.description = newValue + // } + // Object.entries(updatedAttributes).forEach(([key, value]) => { + // sigmaGraph.setNodeAttribute(String(nodeId), key, value) + // }) + const nodeIndex = rawGraph.nodeIdMap[String(nodeId)] if (nodeIndex !== undefined) { rawGraph.nodes[nodeIndex].properties[propertyName] = newValue } } - - const selectedNode = useGraphStore.getState().selectedNode - if (selectedNode === String(nodeId)) { - useGraphStore.getState().setSelectedNode(newValue) - } - - const focusedNode = useGraphStore.getState().focusedNode - if (focusedNode === String(nodeId)) { - useGraphStore.getState().setFocusedNode(newValue) - } - - sigmaInstance.refresh() } catch (error) { console.error('Error updating node in graph:', error) throw new Error('Failed to update node in graph') } } + const updateGraphEdge = async (sourceId: string, targetId: string, propertyName: string, newValue: string) => { + const sigmaInstance = useGraphStore.getState().sigmaInstance + const sigmaGraph = useGraphStore.getState().sigmaGraph + const rawGraph = useGraphStore.getState().rawGraph + + if (!sigmaInstance || !sigmaGraph || !rawGraph) { + return + } + + try { + const allEdges = sigmaGraph.edges() + let keyToUse = null + + for (const edge of allEdges) { + const edgeSource = sigmaGraph.source(edge) + const edgeTarget = sigmaGraph.target(edge) + + if ((edgeSource === sourceId && edgeTarget === targetId) || + (edgeSource === targetId && edgeTarget === sourceId)) { + keyToUse = edge + break + } + } + + if (keyToUse !== null) { + if(propertyName === 'keywords') { + sigmaGraph.setEdgeAttribute(keyToUse, 'label', newValue); + } else { + sigmaGraph.setEdgeAttribute(keyToUse, propertyName, newValue); + } + + if (keyToUse && rawGraph.edgeDynamicIdMap[keyToUse] !== undefined) { + const edgeIndex = rawGraph.edgeDynamicIdMap[keyToUse]; + if (rawGraph.edges[edgeIndex]) { + rawGraph.edges[edgeIndex].properties[propertyName] = newValue; + } else { + console.warn(`Edge index ${edgeIndex} found but edge data missing in rawGraph for dynamicId ${entityId}`); + } + } else { + console.warn(`Could not find edge with dynamicId ${entityId} in rawGraph.edgeDynamicIdMap to update properties.`); + if (keyToUse !== null) { + const edgeIndexByKey = rawGraph.edgeIdMap[keyToUse]; + if (edgeIndexByKey !== undefined && rawGraph.edges[edgeIndexByKey]) { + rawGraph.edges[edgeIndexByKey].properties[propertyName] = newValue; + console.log(`Updated rawGraph edge using constructed key ${keyToUse}`); + } else { + console.warn(`Could not find edge in rawGraph using key ${keyToUse} either.`); + } + } else { + console.warn('Cannot update edge properties: edge key is null'); + } + } + } else { + console.warn(`Edge not found in sigmaGraph with key ${keyToUse}`); + } + } catch (error) { + // Log the specific edge key that caused the error if possible + console.error(`Error updating edge ${sourceId}->${targetId} in graph:`, error); + throw new Error('Failed to update edge in graph') + } + } + const handleSave = async () => { if (isSubmitting) return - if (editValue === String(value)) { + if (editValue === String(currentValue)) { setIsEditing(false) return } @@ -150,112 +251,71 @@ const EditablePropertyRow = ({ setIsSubmitting(true) try { - const updatedData: Record = {} - if (entityType === 'node' && entityId) { + let updatedData = { [name]: editValue } + if (name === 'entity_id') { - if (editValue !== String(value)) { - const exists = await checkEntityNameExists(editValue) - if (exists) { - toast.error(t('graphPanel.propertiesView.errors.duplicateName')) - return - } - } - updatedData['entity_name'] = editValue - await updateEntity(String(value), updatedData, true) - await updateGraphNode(String(value), 'entity_id', editValue) - } else { - updatedData[name] = editValue - await updateEntity(entityId, updatedData) - if (name === 'description') { - await updateGraphNode(entityId, name, editValue) + const exists = await checkEntityNameExists(editValue) + if (exists) { + toast.error(t('graphPanel.propertiesView.errors.duplicateName')) + setIsSubmitting(false) + return } + updatedData = { 'entity_name': editValue } } + await updateEntity(entityId, updatedData, true) + await updateGraphNode(entityId, name, editValue) toast.success(t('graphPanel.propertiesView.success.entityUpdated')) } else if (entityType === 'edge' && sourceId && targetId) { - updatedData[name] = editValue + const updatedData = { [name]: editValue } await updateRelation(sourceId, targetId, updatedData) + await updateGraphEdge(sourceId, targetId, name, editValue) toast.success(t('graphPanel.propertiesView.success.relationUpdated')) } - if (onValueChange) { - onValueChange(editValue) - } - - useGraphStore.getState().setGraphDataFetchAttempted(false) - useGraphStore.getState().setLabelsFetchAttempted(false) - - const currentNodeId = name === 'entity_id' ? editValue : (entityId || '') - useGraphStore.getState().setSelectedNode(null) - useGraphStore.getState().setSelectedNode(currentNodeId) - } catch (error: any) { + setIsEditing(false) + setCurrentValue(editValue) + } catch (error) { console.error('Error updating property:', error) - let detailMessage = t('graphPanel.propertiesView.errors.updateFailed') - - if (error.response?.data?.detail) { - detailMessage = error.response.data.detail - } else if (error.response?.data?.message) { - detailMessage = error.response.data.message - } else if (error.message) { - detailMessage = error.message - } - - console.error('Update failed:', { - entityType, - entityId, - propertyName: name, - newValue: editValue, - error: error.response?.data || error.message - }) - - toast.error(detailMessage, { - description: t('graphPanel.propertiesView.errors.tryAgainLater') - }) + toast.error(t('graphPanel.propertiesView.errors.updateFailed')) } finally { setIsSubmitting(false) - setIsEditing(false) } } - // Determine if this property should be editable - // Currently only 'description' and 'entity_id' fields are editable - const isEditableField = isEditable && (name === 'description' || name === 'entity_id') - + // Always render the property name label and edit icon, regardless of edit state return ( -
-
- {getPropertyNameTranslation(name)} - {isEditableField && ( -
- -
- {t('graphPanel.propertiesView.doubleClickToEdit')} -
-
- )} +
+ {getPropertyNameTranslation(name)} +
+ setIsEditing(true)} + /> +
+ {t('graphPanel.propertiesView.doubleClickToEdit')} +
: {isEditing ? ( -
- setEditValue(e.target.value)} - onBlur={handleSave} - onKeyDown={handleKeyDown} - disabled={isSubmitting} - /> -
+ // Render input field when editing + setEditValue(e.target.value)} + onKeyDown={handleKeyDown} + onBlur={handleSave} + className="h-6 text-xs" + disabled={isSubmitting} + /> ) : ( -
+ // Render text component when not editing +
diff --git a/lightrag_webui/src/components/graph/PropertiesView.tsx b/lightrag_webui/src/components/graph/PropertiesView.tsx index c2cda263..257b69ec 100644 --- a/lightrag_webui/src/components/graph/PropertiesView.tsx +++ b/lightrag_webui/src/components/graph/PropertiesView.tsx @@ -195,8 +195,8 @@ const PropertyRow = ({ return translation === translationKey ? name : translation } - // Use EditablePropertyRow for editable fields (description and entity_id) - if (isEditable && (name === 'description' || name === 'entity_id')) { + // Use EditablePropertyRow for editable fields (description, entity_id and keywords) + if (isEditable && (name === 'description' || name === 'entity_id' || name === 'keywords')) { return ( { value={edge.properties[name]} entityId={edge.id} entityType="edge" - sourceId={edge.sourceNode?.properties['entity_id'] || edge.source} - targetId={edge.targetNode?.properties['entity_id'] || edge.target} - isEditable={name === 'description'} + sourceId={edge.source} + targetId={edge.target} + isEditable={name === 'description' || name === 'keywords'} /> ) })} From 830b69fd893cb58c79d147725bf41a9ba181b757 Mon Sep 17 00:00:00 2001 From: choizhang Date: Sun, 13 Apr 2025 11:13:23 +0800 Subject: [PATCH 07/22] refactor(graph): Refactoring the EditablePeopleRow component --- .../components/graph/EditablePropertyRow.tsx | 223 +++++++++++++----- 1 file changed, 159 insertions(+), 64 deletions(-) diff --git a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx index ac92b335..bfd88802 100644 --- a/lightrag_webui/src/components/graph/EditablePropertyRow.tsx +++ b/lightrag_webui/src/components/graph/EditablePropertyRow.tsx @@ -6,24 +6,39 @@ import { toast } from 'sonner' import { updateEntity, updateRelation, checkEntityNameExists } from '@/api/lightrag' import { useGraphStore } from '@/stores/graph' import { PencilIcon } from 'lucide-react' -import { tr } from '@faker-js/faker' +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/Tooltip' +/** + * Interface for the EditablePropertyRow component props + * Defines all possible properties that can be passed to the component + */ interface EditablePropertyRowProps { - name: string - value: any - onClick?: () => void - tooltip?: string - entityId?: string - entityType?: 'node' | 'edge' - sourceId?: string - targetId?: string - onValueChange?: (newValue: any) => void - isEditable?: boolean + name: string // Property name to display and edit + value: any // Initial value of the property + onClick?: () => void // Optional click handler for the property value + tooltip?: string // Optional tooltip text + entityId?: string // ID of the entity (for node type) + entityType?: 'node' | 'edge' // Type of graph entity + sourceId?: string // Source node ID (for edge type) + targetId?: string // Target node ID (for edge type) + onValueChange?: (newValue: any) => void // Optional callback when value changes + isEditable?: boolean // Whether this property can be edited +} + +/** + * Interface for tracking edges that need updating when a node ID changes + */ +interface EdgeToUpdate { + originalDynamicId: string; + newEdgeId: string; + edgeIndex: number; } /** * EditablePropertyRow component that supports double-click to edit property values - * Specifically designed for editing 'description' and entity name fields + * This component is used in the graph properties panel to display and edit entity properties + * + * @component */ const EditablePropertyRow = ({ name, @@ -37,6 +52,7 @@ const EditablePropertyRow = ({ onValueChange, isEditable = false }: EditablePropertyRowProps) => { + // Component state const { t } = useTranslation() const [isEditing, setIsEditing] = useState(false) const [editValue, setEditValue] = useState('') @@ -44,16 +60,21 @@ const EditablePropertyRow = ({ const [currentValue, setCurrentValue] = useState(initialValue) const inputRef = useRef(null) - // Update currentValue when initialValue changes + /** + * Update currentValue when initialValue changes from parent + */ useEffect(() => { setCurrentValue(initialValue) }, [initialValue]) - // Initialize edit value when entering edit mode + /** + * Initialize edit value and focus input when entering edit mode + */ useEffect(() => { if (isEditing) { setEditValue(String(currentValue)) - // Focus the input element when entering edit mode + // Focus the input element when entering edit mode with a small delay + // to ensure the input is rendered before focusing setTimeout(() => { if (inputRef.current) { inputRef.current.focus() @@ -63,18 +84,30 @@ const EditablePropertyRow = ({ } }, [isEditing, currentValue]) + /** + * Get translated property name from i18n + * Falls back to the original name if no translation is found + */ const getPropertyNameTranslation = (propName: string) => { const translationKey = `graphPanel.propertiesView.node.propertyNames.${propName}` const translation = t(translationKey) return translation === translationKey ? propName : translation } + /** + * Handle double-click event to enter edit mode + */ const handleDoubleClick = () => { if (isEditable && !isEditing) { setIsEditing(true) } } + /** + * Handle keyboard events in the input field + * - Enter: Save changes + * - Escape: Cancel editing + */ const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter') { handleSave() @@ -83,11 +116,21 @@ const EditablePropertyRow = ({ } } + /** + * Update node in the graph visualization after API update + * Handles both property updates and entity ID changes + * + * @param nodeId - ID of the node to update + * @param propertyName - Name of the property being updated + * @param newValue - New value for the property + */ const updateGraphNode = async (nodeId: string, propertyName: string, newValue: string) => { + // Get graph state from store const sigmaInstance = useGraphStore.getState().sigmaInstance const sigmaGraph = useGraphStore.getState().sigmaGraph const rawGraph = useGraphStore.getState().rawGraph + // Validate graph state if (!sigmaInstance || !sigmaGraph || !rawGraph || !sigmaGraph.hasNode(String(nodeId))) { return } @@ -95,29 +138,30 @@ const EditablePropertyRow = ({ try { const nodeAttributes = sigmaGraph.getNodeAttributes(String(nodeId)) + // Special handling for entity_id changes (node renaming) if (propertyName === 'entity_id') { + // Create new node with updated ID but same attributes sigmaGraph.addNode(newValue, { ...nodeAttributes, label: newValue }) - interface EdgeToUpdate { - originalDynamicId: string; - newEdgeId: string; - edgeIndex: number; - } - const edgesToUpdate: EdgeToUpdate[] = []; + // Process all edges connected to this node sigmaGraph.forEachEdge(String(nodeId), (edge, attributes, source, target) => { const otherNode = source === String(nodeId) ? target : source const isOutgoing = source === String(nodeId) - // 获取原始边的dynamicId,以便后续更新edgeDynamicIdMap + // Get original edge dynamic ID for later reference const originalEdgeDynamicId = edge const edgeIndexInRawGraph = rawGraph.edgeDynamicIdMap[originalEdgeDynamicId] - // 创建新边并获取新边的ID - const newEdgeId = sigmaGraph.addEdge(isOutgoing ? newValue : otherNode, isOutgoing ? otherNode : newValue, attributes) + // Create new edge with updated node reference + const newEdgeId = sigmaGraph.addEdge( + isOutgoing ? newValue : otherNode, + isOutgoing ? otherNode : newValue, + attributes + ) - // 存储需要更新的边信息 + // Track edges that need updating in the raw graph if (edgeIndexInRawGraph !== undefined) { edgesToUpdate.push({ originalDynamicId: originalEdgeDynamicId, @@ -126,11 +170,14 @@ const EditablePropertyRow = ({ }) } + // Remove the old edge sigmaGraph.dropEdge(edge) }) + // Remove the old node after all edges are processed sigmaGraph.dropNode(String(nodeId)) + // Update node reference in raw graph data const nodeIndex = rawGraph.nodeIdMap[String(nodeId)] if (nodeIndex !== undefined) { rawGraph.nodes[nodeIndex].id = newValue @@ -139,10 +186,10 @@ const EditablePropertyRow = ({ rawGraph.nodeIdMap[newValue] = nodeIndex } - // 更新边的引用关系 + // Update all edge references in raw graph data edgesToUpdate.forEach(({ originalDynamicId, newEdgeId, edgeIndex }) => { - // 更新边的source和target if (rawGraph.edges[edgeIndex]) { + // Update source/target references if (rawGraph.edges[edgeIndex].source === String(nodeId)) { rawGraph.edges[edgeIndex].source = newValue } @@ -150,23 +197,17 @@ const EditablePropertyRow = ({ rawGraph.edges[edgeIndex].target = newValue } - // 更新dynamicId映射 + // Update dynamic ID mappings rawGraph.edges[edgeIndex].dynamicId = newEdgeId delete rawGraph.edgeDynamicIdMap[originalDynamicId] rawGraph.edgeDynamicIdMap[newEdgeId] = edgeIndex } }) - useGraphStore.getState().setSelectedNode(editValue) + // Update selected node in store + useGraphStore.getState().setSelectedNode(newValue) } else { - // const updatedAttributes = { ...nodeAttributes } - // if (propertyName === 'description') { - // updatedAttributes.description = newValue - // } - // Object.entries(updatedAttributes).forEach(([key, value]) => { - // sigmaGraph.setNodeAttribute(String(nodeId), key, value) - // }) - + // For other properties, just update the property in raw graph const nodeIndex = rawGraph.nodeIdMap[String(nodeId)] if (nodeIndex !== undefined) { rawGraph.nodes[nodeIndex].properties[propertyName] = newValue @@ -178,16 +219,27 @@ const EditablePropertyRow = ({ } } + /** + * Update edge in the graph visualization after API update + * + * @param sourceId - ID of the source node + * @param targetId - ID of the target node + * @param propertyName - Name of the property being updated + * @param newValue - New value for the property + */ const updateGraphEdge = async (sourceId: string, targetId: string, propertyName: string, newValue: string) => { + // Get graph state from store const sigmaInstance = useGraphStore.getState().sigmaInstance const sigmaGraph = useGraphStore.getState().sigmaGraph const rawGraph = useGraphStore.getState().rawGraph + // Validate graph state if (!sigmaInstance || !sigmaGraph || !rawGraph) { return } try { + // Find the edge between source and target nodes const allEdges = sigmaGraph.edges() let keyToUse = null @@ -195,6 +247,7 @@ const EditablePropertyRow = ({ const edgeSource = sigmaGraph.source(edge) const edgeTarget = sigmaGraph.target(edge) + // Match edge in either direction (undirected graph support) if ((edgeSource === sourceId && edgeTarget === targetId) || (edgeSource === targetId && edgeTarget === sourceId)) { keyToUse = edge @@ -203,12 +256,14 @@ const EditablePropertyRow = ({ } if (keyToUse !== null) { + // Special handling for keywords property (updates edge label) if(propertyName === 'keywords') { sigmaGraph.setEdgeAttribute(keyToUse, 'label', newValue); } else { sigmaGraph.setEdgeAttribute(keyToUse, propertyName, newValue); } + // Update edge in raw graph data using dynamic ID mapping if (keyToUse && rawGraph.edgeDynamicIdMap[keyToUse] !== undefined) { const edgeIndex = rawGraph.edgeDynamicIdMap[keyToUse]; if (rawGraph.edges[edgeIndex]) { @@ -217,32 +272,39 @@ const EditablePropertyRow = ({ console.warn(`Edge index ${edgeIndex} found but edge data missing in rawGraph for dynamicId ${entityId}`); } } else { - console.warn(`Could not find edge with dynamicId ${entityId} in rawGraph.edgeDynamicIdMap to update properties.`); - if (keyToUse !== null) { - const edgeIndexByKey = rawGraph.edgeIdMap[keyToUse]; - if (edgeIndexByKey !== undefined && rawGraph.edges[edgeIndexByKey]) { - rawGraph.edges[edgeIndexByKey].properties[propertyName] = newValue; - console.log(`Updated rawGraph edge using constructed key ${keyToUse}`); - } else { - console.warn(`Could not find edge in rawGraph using key ${keyToUse} either.`); - } - } else { - console.warn('Cannot update edge properties: edge key is null'); - } + // Fallback: try to find edge by key in edge ID map + console.warn(`Could not find edge with dynamicId ${entityId} in rawGraph.edgeDynamicIdMap to update properties.`); + if (keyToUse !== null) { + const edgeIndexByKey = rawGraph.edgeIdMap[keyToUse]; + if (edgeIndexByKey !== undefined && rawGraph.edges[edgeIndexByKey]) { + rawGraph.edges[edgeIndexByKey].properties[propertyName] = newValue; + console.log(`Updated rawGraph edge using constructed key ${keyToUse}`); + } else { + console.warn(`Could not find edge in rawGraph using key ${keyToUse} either.`); + } + } else { + console.warn('Cannot update edge properties: edge key is null'); + } } } else { console.warn(`Edge not found in sigmaGraph with key ${keyToUse}`); } } catch (error) { - // Log the specific edge key that caused the error if possible + // Log the specific edge key that caused the error console.error(`Error updating edge ${sourceId}->${targetId} in graph:`, error); throw new Error('Failed to update edge in graph') } } + /** + * Save changes to the property value + * Updates both the API and the graph visualization + */ const handleSave = async () => { + // Prevent duplicate submissions if (isSubmitting) return + // Skip if value hasn't changed if (editValue === String(currentValue)) { setIsEditing(false) return @@ -251,30 +313,47 @@ const EditablePropertyRow = ({ setIsSubmitting(true) try { + // Handle node property updates if (entityType === 'node' && entityId) { let updatedData = { [name]: editValue } + // Special handling for entity_id (name) changes if (name === 'entity_id') { + // Check if the new name already exists const exists = await checkEntityNameExists(editValue) if (exists) { toast.error(t('graphPanel.propertiesView.errors.duplicateName')) setIsSubmitting(false) return } + // For entity_id, we update entity_name in the API updatedData = { 'entity_name': editValue } } + + // Update entity in API await updateEntity(entityId, updatedData, true) + // Update graph visualization await updateGraphNode(entityId, name, editValue) toast.success(t('graphPanel.propertiesView.success.entityUpdated')) - } else if (entityType === 'edge' && sourceId && targetId) { + } + // Handle edge property updates + else if (entityType === 'edge' && sourceId && targetId) { const updatedData = { [name]: editValue } + // Update relation in API await updateRelation(sourceId, targetId, updatedData) + // Update graph visualization await updateGraphEdge(sourceId, targetId, name, editValue) toast.success(t('graphPanel.propertiesView.success.relationUpdated')) } + // Update local state setIsEditing(false) setCurrentValue(editValue) + + // Notify parent component if callback provided + if (onValueChange) { + onValueChange(editValue) + } } catch (error) { console.error('Error updating property:', error) toast.error(t('graphPanel.propertiesView.errors.updateFailed')) @@ -283,21 +362,37 @@ const EditablePropertyRow = ({ } } - // Always render the property name label and edit icon, regardless of edit state + /** + * Render the property row with edit functionality + * Shows property name, edit icon, and either the editable input or the current value + */ return (
- {getPropertyNameTranslation(name)} -
- setIsEditing(true)} - /> -
- {t('graphPanel.propertiesView.doubleClickToEdit')} -
-
: + {/* Property name with translation */} + + {getPropertyNameTranslation(name)} + + + {/* Edit icon with tooltip */} + + + +
+ setIsEditing(true)} + /> +
+
+ + {t('graphPanel.propertiesView.doubleClickToEdit')} + +
+
: + + {/* Conditional rendering based on edit state */} {isEditing ? ( - // Render input field when editing + // Input field for editing ) : ( - // Render text component when not editing + // Text display when not editing
Date: Sun, 13 Apr 2025 11:48:55 +0800 Subject: [PATCH 08/22] bugfix --- lightrag_webui/src/lib/constants.ts | 2 +- lightrag_webui/src/locales/fr.json | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lightrag_webui/src/lib/constants.ts b/lightrag_webui/src/lib/constants.ts index 87db8cea..048ae8f7 100644 --- a/lightrag_webui/src/lib/constants.ts +++ b/lightrag_webui/src/lib/constants.ts @@ -1,6 +1,6 @@ import { ButtonVariantType } from '@/components/ui/Button' -export const backendBaseUrl = 'http://localhost:9621' +export const backendBaseUrl = '' export const webuiPrefix = '/webui/' export const controlButtonVariant: ButtonVariantType = 'ghost' diff --git a/lightrag_webui/src/locales/fr.json b/lightrag_webui/src/locales/fr.json index 325d73d3..1217ba66 100644 --- a/lightrag_webui/src/locales/fr.json +++ b/lightrag_webui/src/locales/fr.json @@ -35,7 +35,6 @@ "common": { "cancel": "Annuler" }, - "documentPanel": { "clearDocuments": { "button": "Effacer", From 00c8394601ea57c3f250f3a0790502c25889df74 Mon Sep 17 00:00:00 2001 From: yangdx Date: Sun, 13 Apr 2025 16:52:30 +0800 Subject: [PATCH 09/22] Update webui assets --- lightrag/api/__init__.py | 2 +- .../{index-CkwV8nfm.js => index-vzpYU2q3.js} | 209 ++++++++++-------- lightrag/api/webui/index.html | 2 +- 3 files changed, 117 insertions(+), 96 deletions(-) rename lightrag/api/webui/assets/{index-CkwV8nfm.js => index-vzpYU2q3.js} (79%) diff --git a/lightrag/api/__init__.py b/lightrag/api/__init__.py index 4e05d060..53003ead 100644 --- a/lightrag/api/__init__.py +++ b/lightrag/api/__init__.py @@ -1 +1 @@ -__api_version__ = "0148" +__api_version__ = "0149" diff --git a/lightrag/api/webui/assets/index-CkwV8nfm.js b/lightrag/api/webui/assets/index-vzpYU2q3.js similarity index 79% rename from lightrag/api/webui/assets/index-CkwV8nfm.js rename to lightrag/api/webui/assets/index-vzpYU2q3.js index a3d82a72..597a786c 100644 --- a/lightrag/api/webui/assets/index-CkwV8nfm.js +++ b/lightrag/api/webui/assets/index-vzpYU2q3.js @@ -1,4 +1,4 @@ -var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Qr=(e,t,n)=>lq(e,typeof t!="symbol"?t+"":t,n);function cq(e,t){for(var n=0;nr[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const o of a)if(o.type==="childList")for(const s of o.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerPolicy&&(o.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?o.credentials="include":a.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(a){if(a.ep)return;a.ep=!0;const o=n(a);fetch(a.href,o)}})();var pf=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function un(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function uq(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}),n}var Wh={exports:{}},Zl={};/** +var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var Qr=(e,t,n)=>lq(e,typeof t!="symbol"?t+"":t,n);function cq(e,t){for(var n=0;nr[a]})}}}return Object.freeze(Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}))}(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))r(a);new MutationObserver(a=>{for(const o of a)if(o.type==="childList")for(const s of o.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(a){const o={};return a.integrity&&(o.integrity=a.integrity),a.referrerPolicy&&(o.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?o.credentials="include":a.crossOrigin==="anonymous"?o.credentials="omit":o.credentials="same-origin",o}function r(a){if(a.ep)return;a.ep=!0;const o=n(a);fetch(a.href,o)}})();var pp=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function dn(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}function uq(e){if(e.__esModule)return e;var t=e.default;if(typeof t=="function"){var n=function r(){return this instanceof r?Reflect.construct(t,arguments,this.constructor):t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var a=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,a.get?a:{enumerable:!0,get:function(){return e[r]}})}),n}var Wh={exports:{}},Zl={};/** * @license React * react-jsx-runtime.production.js * @@ -6,7 +6,7 @@ var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var t_;function dq(){if(t_)return Zl;t_=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,a,o){var s=null;if(o!==void 0&&(s=""+o),a.key!==void 0&&(s=""+a.key),"key"in a){o={};for(var l in a)l!=="key"&&(o[l]=a[l])}else o=a;return a=o.ref,{$$typeof:e,type:r,key:s,ref:a!==void 0?a:null,props:o}}return Zl.Fragment=t,Zl.jsx=n,Zl.jsxs=n,Zl}var n_;function fq(){return n_||(n_=1,Wh.exports=dq()),Wh.exports}var E=fq(),Yh={exports:{}},lt={};/** + */var t_;function dq(){if(t_)return Zl;t_=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function n(r,a,o){var s=null;if(o!==void 0&&(s=""+o),a.key!==void 0&&(s=""+a.key),"key"in a){o={};for(var l in a)l!=="key"&&(o[l]=a[l])}else o=a;return a=o.ref,{$$typeof:e,type:r,key:s,ref:a!==void 0?a:null,props:o}}return Zl.Fragment=t,Zl.jsx=n,Zl.jsxs=n,Zl}var n_;function pq(){return n_||(n_=1,Wh.exports=dq()),Wh.exports}var w=pq(),Yh={exports:{}},lt={};/** * @license React * react.production.js * @@ -14,7 +14,7 @@ var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var r_;function pq(){if(r_)return lt;r_=1;var e=Symbol.for("react.transitional.element"),t=Symbol.for("react.portal"),n=Symbol.for("react.fragment"),r=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),o=Symbol.for("react.consumer"),s=Symbol.for("react.context"),l=Symbol.for("react.forward_ref"),u=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),g=Symbol.iterator;function m(L){return L===null||typeof L!="object"?null:(L=g&&L[g]||L["@@iterator"],typeof L=="function"?L:null)}var b={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},y=Object.assign,v={};function x(L,V,j){this.props=L,this.context=V,this.refs=v,this.updater=j||b}x.prototype.isReactComponent={},x.prototype.setState=function(L,V){if(typeof L!="object"&&typeof L!="function"&&L!=null)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,L,V,"setState")},x.prototype.forceUpdate=function(L){this.updater.enqueueForceUpdate(this,L,"forceUpdate")};function T(){}T.prototype=x.prototype;function k(L,V,j){this.props=L,this.context=V,this.refs=v,this.updater=j||b}var R=k.prototype=new T;R.constructor=k,y(R,x.prototype),R.isPureReactComponent=!0;var O=Array.isArray,N={H:null,A:null,T:null,S:null},C=Object.prototype.hasOwnProperty;function _(L,V,j,P,Z,Q){return j=Q.ref,{$$typeof:e,type:L,key:V,ref:j!==void 0?j:null,props:Q}}function M(L,V){return _(L.type,V,void 0,void 0,void 0,L.props)}function D(L){return typeof L=="object"&&L!==null&&L.$$typeof===e}function I(L){var V={"=":"=0",":":"=2"};return"$"+L.replace(/[=:]/g,function(j){return V[j]})}var U=/\/+/g;function $(L,V){return typeof L=="object"&&L!==null&&L.key!=null?I(""+L.key):V.toString(36)}function B(){}function W(L){switch(L.status){case"fulfilled":return L.value;case"rejected":throw L.reason;default:switch(typeof L.status=="string"?L.then(B,B):(L.status="pending",L.then(function(V){L.status==="pending"&&(L.status="fulfilled",L.value=V)},function(V){L.status==="pending"&&(L.status="rejected",L.reason=V)})),L.status){case"fulfilled":return L.value;case"rejected":throw L.reason}}throw L}function K(L,V,j,P,Z){var Q=typeof L;(Q==="undefined"||Q==="boolean")&&(L=null);var oe=!1;if(L===null)oe=!0;else switch(Q){case"bigint":case"string":case"number":oe=!0;break;case"object":switch(L.$$typeof){case e:case t:oe=!0;break;case p:return oe=L._init,K(oe(L._payload),V,j,P,Z)}}if(oe)return Z=Z(L),oe=P===""?"."+$(L,0):P,O(Z)?(j="",oe!=null&&(j=oe.replace(U,"$&/")+"/"),K(Z,V,j,"",function(Re){return Re})):Z!=null&&(D(Z)&&(Z=M(Z,j+(Z.key==null||L&&L.key===Z.key?"":(""+Z.key).replace(U,"$&/")+"/")+oe)),V.push(Z)),1;oe=0;var ae=P===""?".":P+":";if(O(L))for(var ce=0;cet in e?sq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var o_;function hq(){return o_||(o_=1,function(e){function t(G,H){var F=G.length;G.push(H);e:for(;0>>1,L=G[Y];if(0>>1;Ya(P,F))Za(Q,P)?(G[Y]=Q,G[Z]=F,Y=Z):(G[Y]=P,G[j]=F,Y=j);else if(Za(Q,F))G[Y]=Q,G[Z]=F,Y=Z;else break e}}return H}function a(G,H){var F=G.sortIndex-H.sortIndex;return F!==0?F:G.id-H.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var s=Date,l=s.now();e.unstable_now=function(){return s.now()-l}}var u=[],d=[],p=1,g=null,m=3,b=!1,y=!1,v=!1,x=typeof setTimeout=="function"?setTimeout:null,T=typeof clearTimeout=="function"?clearTimeout:null,k=typeof setImmediate<"u"?setImmediate:null;function R(G){for(var H=n(d);H!==null;){if(H.callback===null)r(d);else if(H.startTime<=G)r(d),H.sortIndex=H.expirationTime,t(u,H);else break;H=n(d)}}function O(G){if(v=!1,R(G),!y)if(n(u)!==null)y=!0,W();else{var H=n(d);H!==null&&K(O,H.startTime-G)}}var N=!1,C=-1,_=5,M=-1;function D(){return!(e.unstable_now()-M<_)}function I(){if(N){var G=e.unstable_now();M=G;var H=!0;try{e:{y=!1,v&&(v=!1,T(C),C=-1),b=!0;var F=m;try{t:{for(R(G),g=n(u);g!==null&&!(g.expirationTime>G&&D());){var Y=g.callback;if(typeof Y=="function"){g.callback=null,m=g.priorityLevel;var L=Y(g.expirationTime<=G);if(G=e.unstable_now(),typeof L=="function"){g.callback=L,R(G),H=!0;break t}g===n(u)&&r(u),R(G)}else r(u);g=n(u)}if(g!==null)H=!0;else{var V=n(d);V!==null&&K(O,V.startTime-G),H=!1}}break e}finally{g=null,m=F,b=!1}H=void 0}}finally{H?U():N=!1}}}var U;if(typeof k=="function")U=function(){k(I)};else if(typeof MessageChannel<"u"){var $=new MessageChannel,B=$.port2;$.port1.onmessage=I,U=function(){B.postMessage(null)}}else U=function(){x(I,0)};function W(){N||(N=!0,U())}function K(G,H){C=x(function(){G(e.unstable_now())},H)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(G){G.callback=null},e.unstable_continueExecution=function(){y||b||(y=!0,W())},e.unstable_forceFrameRate=function(G){0>G||125Y?(G.sortIndex=F,t(d,G),n(u)===null&&G===n(d)&&(v?(T(C),C=-1):v=!0,K(O,F-Y))):(G.sortIndex=L,t(u,G),y||b||(y=!0,W())),G},e.unstable_shouldYield=D,e.unstable_wrapCallback=function(G){var H=m;return function(){var F=m;m=H;try{return G.apply(this,arguments)}finally{m=F}}}}(Zh)),Zh}var i_;function mq(){return i_||(i_=1,Xh.exports=hq()),Xh.exports}var Qh={exports:{}},xn={};/** + */var o_;function hq(){return o_||(o_=1,function(e){function t(G,H){var F=G.length;G.push(H);e:for(;0>>1,L=G[Y];if(0>>1;Ya(P,F))Za(Q,P)?(G[Y]=Q,G[Z]=F,Y=Z):(G[Y]=P,G[j]=F,Y=j);else if(Za(Q,F))G[Y]=Q,G[Z]=F,Y=Z;else break e}}return H}function a(G,H){var F=G.sortIndex-H.sortIndex;return F!==0?F:G.id-H.id}if(e.unstable_now=void 0,typeof performance=="object"&&typeof performance.now=="function"){var o=performance;e.unstable_now=function(){return o.now()}}else{var s=Date,l=s.now();e.unstable_now=function(){return s.now()-l}}var u=[],d=[],f=1,g=null,m=3,b=!1,y=!1,v=!1,x=typeof setTimeout=="function"?setTimeout:null,T=typeof clearTimeout=="function"?clearTimeout:null,k=typeof setImmediate<"u"?setImmediate:null;function R(G){for(var H=n(d);H!==null;){if(H.callback===null)r(d);else if(H.startTime<=G)r(d),H.sortIndex=H.expirationTime,t(u,H);else break;H=n(d)}}function O(G){if(v=!1,R(G),!y)if(n(u)!==null)y=!0,W();else{var H=n(d);H!==null&&K(O,H.startTime-G)}}var N=!1,C=-1,_=5,M=-1;function D(){return!(e.unstable_now()-M<_)}function I(){if(N){var G=e.unstable_now();M=G;var H=!0;try{e:{y=!1,v&&(v=!1,T(C),C=-1),b=!0;var F=m;try{t:{for(R(G),g=n(u);g!==null&&!(g.expirationTime>G&&D());){var Y=g.callback;if(typeof Y=="function"){g.callback=null,m=g.priorityLevel;var L=Y(g.expirationTime<=G);if(G=e.unstable_now(),typeof L=="function"){g.callback=L,R(G),H=!0;break t}g===n(u)&&r(u),R(G)}else r(u);g=n(u)}if(g!==null)H=!0;else{var V=n(d);V!==null&&K(O,V.startTime-G),H=!1}}break e}finally{g=null,m=F,b=!1}H=void 0}}finally{H?U():N=!1}}}var U;if(typeof k=="function")U=function(){k(I)};else if(typeof MessageChannel<"u"){var $=new MessageChannel,B=$.port2;$.port1.onmessage=I,U=function(){B.postMessage(null)}}else U=function(){x(I,0)};function W(){N||(N=!0,U())}function K(G,H){C=x(function(){G(e.unstable_now())},H)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(G){G.callback=null},e.unstable_continueExecution=function(){y||b||(y=!0,W())},e.unstable_forceFrameRate=function(G){0>G||125Y?(G.sortIndex=F,t(d,G),n(u)===null&&G===n(d)&&(v?(T(C),C=-1):v=!0,K(O,F-Y))):(G.sortIndex=L,t(u,G),y||b||(y=!0,W())),G},e.unstable_shouldYield=D,e.unstable_wrapCallback=function(G){var H=m;return function(){var F=m;m=H;try{return G.apply(this,arguments)}finally{m=F}}}}(Zh)),Zh}var i_;function mq(){return i_||(i_=1,Xh.exports=hq()),Xh.exports}var Qh={exports:{}},xn={};/** * @license React * react-dom.production.js * @@ -30,7 +30,7 @@ var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var s_;function bq(){if(s_)return xn;s_=1;var e=$f();function t(u){var d="https://react.dev/errors/"+u;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Qh.exports=bq(),Qh.exports}/** + */var s_;function bq(){if(s_)return xn;s_=1;var e=Hp();function t(u){var d="https://react.dev/errors/"+u;if(1"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Qh.exports=bq(),Qh.exports}/** * @license React * react-dom-client.production.js * @@ -38,15 +38,15 @@ var sq=Object.defineProperty;var lq=(e,t,n)=>t in e?sq(e,t,{enumerable:!0,config * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var c_;function yq(){if(c_)return Ql;c_=1;var e=mq(),t=$f(),n=Yz();function r(i){var c="https://react.dev/errors/"+i;if(1)":-1)":-1S||X[h]!==re[S]){var ve=` -`+X[h].replace(" at new "," at ");return i.displayName&&ve.includes("")&&(ve=ve.replace("",i.displayName)),ve}while(1<=h&&0<=S);break}}}finally{W=!1,Error.prepareStackTrace=f}return(f=i?i.displayName||i.name:"")?B(f):""}function G(i){switch(i.tag){case 26:case 27:case 5:return B(i.type);case 16:return B("Lazy");case 13:return B("Suspense");case 19:return B("SuspenseList");case 0:case 15:return i=K(i.type,!1),i;case 11:return i=K(i.type.render,!1),i;case 1:return i=K(i.type,!0),i;default:return""}}function H(i){try{var c="";do c+=G(i),i=i.return;while(i);return c}catch(f){return` -Error generating stack: `+f.message+` -`+f.stack}}function F(i){var c=i,f=i;if(i.alternate)for(;c.return;)c=c.return;else{i=c;do c=i,c.flags&4098&&(f=c.return),i=c.return;while(i)}return c.tag===3?f:null}function Y(i){if(i.tag===13){var c=i.memoizedState;if(c===null&&(i=i.alternate,i!==null&&(c=i.memoizedState)),c!==null)return c.dehydrated}return null}function L(i){if(F(i)!==i)throw Error(r(188))}function V(i){var c=i.alternate;if(!c){if(c=F(i),c===null)throw Error(r(188));return c!==i?null:i}for(var f=i,h=c;;){var S=f.return;if(S===null)break;var A=S.alternate;if(A===null){if(h=S.return,h!==null){f=h;continue}break}if(S.child===A.child){for(A=S.child;A;){if(A===f)return L(S),i;if(A===h)return L(S),c;A=A.sibling}throw Error(r(188))}if(f.return!==h.return)f=S,h=A;else{for(var z=!1,q=S.child;q;){if(q===f){z=!0,f=S,h=A;break}if(q===h){z=!0,h=S,f=A;break}q=q.sibling}if(!z){for(q=A.child;q;){if(q===f){z=!0,f=A,h=S;break}if(q===h){z=!0,h=A,f=S;break}q=q.sibling}if(!z)throw Error(r(189))}}if(f.alternate!==h)throw Error(r(190))}if(f.tag!==3)throw Error(r(188));return f.stateNode.current===f?i:c}function j(i){var c=i.tag;if(c===5||c===26||c===27||c===6)return i;for(i=i.child;i!==null;){if(c=j(i),c!==null)return c;i=i.sibling}return null}var P=Array.isArray,Z=n.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Q={pending:!1,data:null,method:null,action:null},oe=[],ae=-1;function ce(i){return{current:i}}function Re(i){0>ae||(i.current=oe[ae],oe[ae]=null,ae--)}function ie(i,c){ae++,oe[ae]=i.current,i.current=c}var Te=ce(null),ne=ce(null),xe=ce(null),Se=ce(null);function be(i,c){switch(ie(xe,c),ie(ne,i),ie(Te,null),i=c.nodeType,i){case 9:case 11:c=(c=c.documentElement)&&(c=c.namespaceURI)?NC(c):0;break;default:if(i=i===8?c.parentNode:c,c=i.tagName,i=i.namespaceURI)i=NC(i),c=OC(i,c);else switch(c){case"svg":c=1;break;case"math":c=2;break;default:c=0}}Re(Te),ie(Te,c)}function J(){Re(Te),Re(ne),Re(xe)}function pe(i){i.memoizedState!==null&&ie(Se,i);var c=Te.current,f=OC(c,i.type);c!==f&&(ie(ne,i),ie(Te,f))}function ke(i){ne.current===i&&(Re(Te),Re(ne)),Se.current===i&&(Re(Se),Vl._currentValue=Q)}var he=Object.prototype.hasOwnProperty,Ee=e.unstable_scheduleCallback,se=e.unstable_cancelCallback,Be=e.unstable_shouldYield,je=e.unstable_requestPaint,ye=e.unstable_now,Oe=e.unstable_getCurrentPriorityLevel,ee=e.unstable_ImmediatePriority,de=e.unstable_UserBlockingPriority,Ne=e.unstable_NormalPriority,ze=e.unstable_LowPriority,We=e.unstable_IdlePriority,St=e.log,Tt=e.unstable_setDisableYieldValue,bt=null,et=null;function At(i){if(et&&typeof et.onCommitFiberRoot=="function")try{et.onCommitFiberRoot(bt,i,void 0,(i.current.flags&128)===128)}catch{}}function st(i){if(typeof St=="function"&&Tt(i),et&&typeof et.setStrictMode=="function")try{et.setStrictMode(bt,i)}catch{}}var wt=Math.clz32?Math.clz32:zt,Ht=Math.log,pn=Math.LN2;function zt(i){return i>>>=0,i===0?32:31-(Ht(i)/pn|0)|0}var sr=128,Vr=4194304;function Jt(i){var c=i&42;if(c!==0)return c;switch(i&-i){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i&4194176;case 4194304:case 8388608:case 16777216:case 33554432:return i&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return i}}function pa(i,c){var f=i.pendingLanes;if(f===0)return 0;var h=0,S=i.suspendedLanes,A=i.pingedLanes,z=i.warmLanes;i=i.finishedLanes!==0;var q=f&134217727;return q!==0?(f=q&~S,f!==0?h=Jt(f):(A&=q,A!==0?h=Jt(A):i||(z=q&~z,z!==0&&(h=Jt(z))))):(q=f&~S,q!==0?h=Jt(q):A!==0?h=Jt(A):i||(z=f&~z,z!==0&&(h=Jt(z)))),h===0?0:c!==0&&c!==h&&!(c&S)&&(S=h&-h,z=c&-c,S>=z||S===32&&(z&4194176)!==0)?c:h}function Xe(i,c){return(i.pendingLanes&~(i.suspendedLanes&~i.pingedLanes)&c)===0}function yt(i,c){switch(i){case 1:case 2:case 4:case 8:return c+250;case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return c+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Nt(){var i=sr;return sr<<=1,!(sr&4194176)&&(sr=128),i}function Dn(){var i=Vr;return Vr<<=1,!(Vr&62914560)&&(Vr=4194304),i}function _n(i){for(var c=[],f=0;31>f;f++)c.push(i);return c}function Ln(i,c){i.pendingLanes|=c,c!==268435456&&(i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0)}function ga(i,c,f,h,S,A){var z=i.pendingLanes;i.pendingLanes=f,i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0,i.expiredLanes&=f,i.entangledLanes&=f,i.errorRecoveryDisabledLanes&=f,i.shellSuspendCounter=0;var q=i.entanglements,X=i.expirationTimes,re=i.hiddenUpdates;for(f=z&~f;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),e$=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),OA={},IA={};function t$(i){return he.call(IA,i)?!0:he.call(OA,i)?!1:e$.test(i)?IA[i]=!0:(OA[i]=!0,!1)}function cu(i,c,f){if(t$(c))if(f===null)i.removeAttribute(c);else{switch(typeof f){case"undefined":case"function":case"symbol":i.removeAttribute(c);return;case"boolean":var h=c.toLowerCase().slice(0,5);if(h!=="data-"&&h!=="aria-"){i.removeAttribute(c);return}}i.setAttribute(c,""+f)}}function uu(i,c,f){if(f===null)i.removeAttribute(c);else{switch(typeof f){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(c);return}i.setAttribute(c,""+f)}}function ma(i,c,f,h){if(h===null)i.removeAttribute(f);else{switch(typeof h){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(f);return}i.setAttributeNS(c,f,""+h)}}function lr(i){switch(typeof i){case"bigint":case"boolean":case"number":case"string":case"undefined":return i;case"object":return i;default:return""}}function DA(i){var c=i.type;return(i=i.nodeName)&&i.toLowerCase()==="input"&&(c==="checkbox"||c==="radio")}function n$(i){var c=DA(i)?"checked":"value",f=Object.getOwnPropertyDescriptor(i.constructor.prototype,c),h=""+i[c];if(!i.hasOwnProperty(c)&&typeof f<"u"&&typeof f.get=="function"&&typeof f.set=="function"){var S=f.get,A=f.set;return Object.defineProperty(i,c,{configurable:!0,get:function(){return S.call(this)},set:function(z){h=""+z,A.call(this,z)}}),Object.defineProperty(i,c,{enumerable:f.enumerable}),{getValue:function(){return h},setValue:function(z){h=""+z},stopTracking:function(){i._valueTracker=null,delete i[c]}}}}function du(i){i._valueTracker||(i._valueTracker=n$(i))}function LA(i){if(!i)return!1;var c=i._valueTracker;if(!c)return!0;var f=c.getValue(),h="";return i&&(h=DA(i)?i.checked?"true":"false":i.value),i=h,i!==f?(c.setValue(i),!0):!1}function fu(i){if(i=i||(typeof document<"u"?document:void 0),typeof i>"u")return null;try{return i.activeElement||i.body}catch{return i.body}}var r$=/[\n"\\]/g;function cr(i){return i.replace(r$,function(c){return"\\"+c.charCodeAt(0).toString(16)+" "})}function qp(i,c,f,h,S,A,z,q){i.name="",z!=null&&typeof z!="function"&&typeof z!="symbol"&&typeof z!="boolean"?i.type=z:i.removeAttribute("type"),c!=null?z==="number"?(c===0&&i.value===""||i.value!=c)&&(i.value=""+lr(c)):i.value!==""+lr(c)&&(i.value=""+lr(c)):z!=="submit"&&z!=="reset"||i.removeAttribute("value"),c!=null?Vp(i,z,lr(c)):f!=null?Vp(i,z,lr(f)):h!=null&&i.removeAttribute("value"),S==null&&A!=null&&(i.defaultChecked=!!A),S!=null&&(i.checked=S&&typeof S!="function"&&typeof S!="symbol"),q!=null&&typeof q!="function"&&typeof q!="symbol"&&typeof q!="boolean"?i.name=""+lr(q):i.removeAttribute("name")}function MA(i,c,f,h,S,A,z,q){if(A!=null&&typeof A!="function"&&typeof A!="symbol"&&typeof A!="boolean"&&(i.type=A),c!=null||f!=null){if(!(A!=="submit"&&A!=="reset"||c!=null))return;f=f!=null?""+lr(f):"",c=c!=null?""+lr(c):f,q||c===i.value||(i.value=c),i.defaultValue=c}h=h??S,h=typeof h!="function"&&typeof h!="symbol"&&!!h,i.checked=q?i.checked:!!h,i.defaultChecked=!!h,z!=null&&typeof z!="function"&&typeof z!="symbol"&&typeof z!="boolean"&&(i.name=z)}function Vp(i,c,f){c==="number"&&fu(i.ownerDocument)===i||i.defaultValue===""+f||(i.defaultValue=""+f)}function Di(i,c,f,h){if(i=i.options,c){c={};for(var S=0;S=ul),YA=" ",KA=!1;function XA(i,c){switch(i){case"keyup":return O$.indexOf(c.keyCode)!==-1;case"keydown":return c.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ZA(i){return i=i.detail,typeof i=="object"&&"data"in i?i.data:null}var Fi=!1;function D$(i,c){switch(i){case"compositionend":return ZA(c);case"keypress":return c.which!==32?null:(KA=!0,YA);case"textInput":return i=c.data,i===YA&&KA?null:i;default:return null}}function L$(i,c){if(Fi)return i==="compositionend"||!rg&&XA(i,c)?(i=GA(),gu=Qp=Ya=null,Fi=!1,i):null;switch(i){case"paste":return null;case"keypress":if(!(c.ctrlKey||c.altKey||c.metaKey)||c.ctrlKey&&c.altKey){if(c.char&&1=c)return{node:f,offset:c-i};i=h}e:{for(;f;){if(f.nextSibling){f=f.nextSibling;break e}f=f.parentNode}f=void 0}f=o1(f)}}function s1(i,c){return i&&c?i===c?!0:i&&i.nodeType===3?!1:c&&c.nodeType===3?s1(i,c.parentNode):"contains"in i?i.contains(c):i.compareDocumentPosition?!!(i.compareDocumentPosition(c)&16):!1:!1}function l1(i){i=i!=null&&i.ownerDocument!=null&&i.ownerDocument.defaultView!=null?i.ownerDocument.defaultView:window;for(var c=fu(i.document);c instanceof i.HTMLIFrameElement;){try{var f=typeof c.contentWindow.location.href=="string"}catch{f=!1}if(f)i=c.contentWindow;else break;c=fu(i.document)}return c}function ig(i){var c=i&&i.nodeName&&i.nodeName.toLowerCase();return c&&(c==="input"&&(i.type==="text"||i.type==="search"||i.type==="tel"||i.type==="url"||i.type==="password")||c==="textarea"||i.contentEditable==="true")}function G$(i,c){var f=l1(c);c=i.focusedElem;var h=i.selectionRange;if(f!==c&&c&&c.ownerDocument&&s1(c.ownerDocument.documentElement,c)){if(h!==null&&ig(c)){if(i=h.start,f=h.end,f===void 0&&(f=i),"selectionStart"in c)c.selectionStart=i,c.selectionEnd=Math.min(f,c.value.length);else if(f=(i=c.ownerDocument||document)&&i.defaultView||window,f.getSelection){f=f.getSelection();var S=c.textContent.length,A=Math.min(h.start,S);h=h.end===void 0?A:Math.min(h.end,S),!f.extend&&A>h&&(S=h,h=A,A=S),S=i1(c,A);var z=i1(c,h);S&&z&&(f.rangeCount!==1||f.anchorNode!==S.node||f.anchorOffset!==S.offset||f.focusNode!==z.node||f.focusOffset!==z.offset)&&(i=i.createRange(),i.setStart(S.node,S.offset),f.removeAllRanges(),A>h?(f.addRange(i),f.extend(z.node,z.offset)):(i.setEnd(z.node,z.offset),f.addRange(i)))}}for(i=[],f=c;f=f.parentNode;)f.nodeType===1&&i.push({element:f,left:f.scrollLeft,top:f.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;c=document.documentMode,zi=null,sg=null,gl=null,lg=!1;function c1(i,c,f){var h=f.window===f?f.document:f.nodeType===9?f:f.ownerDocument;lg||zi==null||zi!==fu(h)||(h=zi,"selectionStart"in h&&ig(h)?h={start:h.selectionStart,end:h.selectionEnd}:(h=(h.ownerDocument&&h.ownerDocument.defaultView||window).getSelection(),h={anchorNode:h.anchorNode,anchorOffset:h.anchorOffset,focusNode:h.focusNode,focusOffset:h.focusOffset}),gl&&pl(gl,h)||(gl=h,h=td(sg,"onSelect"),0>=z,S-=z,ba=1<<32-wt(c)+S|f<Qe?(ln=Ye,Ye=null):ln=Ye.sibling;var kt=fe(le,Ye,ue[Qe],Ae);if(kt===null){Ye===null&&(Ye=ln);break}i&&Ye&&kt.alternate===null&&c(le,Ye),te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt,Ye=ln}if(Qe===ue.length)return f(le,Ye),xt&&Ho(le,Qe),Ge;if(Ye===null){for(;QeQe?(ln=Ye,Ye=null):ln=Ye.sibling;var ho=fe(le,Ye,kt.value,Ae);if(ho===null){Ye===null&&(Ye=ln);break}i&&Ye&&ho.alternate===null&&c(le,Ye),te=A(ho,te,Qe),ut===null?Ge=ho:ut.sibling=ho,ut=ho,Ye=ln}if(kt.done)return f(le,Ye),xt&&Ho(le,Qe),Ge;if(Ye===null){for(;!kt.done;Qe++,kt=ue.next())kt=Ce(le,kt.value,Ae),kt!==null&&(te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt);return xt&&Ho(le,Qe),Ge}for(Ye=h(Ye);!kt.done;Qe++,kt=ue.next())kt=me(Ye,le,Qe,kt.value,Ae),kt!==null&&(i&&kt.alternate!==null&&Ye.delete(kt.key===null?Qe:kt.key),te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt);return i&&Ye.forEach(function(iq){return c(le,iq)}),xt&&Ho(le,Qe),Ge}function Vt(le,te,ue,Ae){if(typeof ue=="object"&&ue!==null&&ue.type===u&&ue.key===null&&(ue=ue.props.children),typeof ue=="object"&&ue!==null){switch(ue.$$typeof){case s:e:{for(var Ge=ue.key;te!==null;){if(te.key===Ge){if(Ge=ue.type,Ge===u){if(te.tag===7){f(le,te.sibling),Ae=S(te,ue.props.children),Ae.return=le,le=Ae;break e}}else if(te.elementType===Ge||typeof Ge=="object"&&Ge!==null&&Ge.$$typeof===k&&A1(Ge)===te.type){f(le,te.sibling),Ae=S(te,ue.props),El(Ae,ue),Ae.return=le,le=Ae;break e}f(le,te);break}else c(le,te);te=te.sibling}ue.type===u?(Ae=ei(ue.props.children,le.mode,Ae,ue.key),Ae.return=le,le=Ae):(Ae=qu(ue.type,ue.key,ue.props,null,le.mode,Ae),El(Ae,ue),Ae.return=le,le=Ae)}return z(le);case l:e:{for(Ge=ue.key;te!==null;){if(te.key===Ge)if(te.tag===4&&te.stateNode.containerInfo===ue.containerInfo&&te.stateNode.implementation===ue.implementation){f(le,te.sibling),Ae=S(te,ue.children||[]),Ae.return=le,le=Ae;break e}else{f(le,te);break}else c(le,te);te=te.sibling}Ae=uh(ue,le.mode,Ae),Ae.return=le,le=Ae}return z(le);case k:return Ge=ue._init,ue=Ge(ue._payload),Vt(le,te,ue,Ae)}if(P(ue))return qe(le,te,ue,Ae);if(C(ue)){if(Ge=C(ue),typeof Ge!="function")throw Error(r(150));return ue=Ge.call(ue),rt(le,te,ue,Ae)}if(typeof ue.then=="function")return Vt(le,te,Au(ue),Ae);if(ue.$$typeof===b)return Vt(le,te,Gu(le,ue),Ae);Ru(le,ue)}return typeof ue=="string"&&ue!==""||typeof ue=="number"||typeof ue=="bigint"?(ue=""+ue,te!==null&&te.tag===6?(f(le,te.sibling),Ae=S(te,ue),Ae.return=le,le=Ae):(f(le,te),Ae=ch(ue,le.mode,Ae),Ae.return=le,le=Ae),z(le)):f(le,te)}return function(le,te,ue,Ae){try{Sl=0;var Ge=Vt(le,te,ue,Ae);return $i=null,Ge}catch(Ye){if(Ye===yl)throw Ye;var ut=br(29,Ye,null,le.mode);return ut.lanes=Ae,ut.return=le,ut}finally{}}}var qo=R1(!0),C1=R1(!1),qi=ce(null),Cu=ce(0);function _1(i,c){i=_a,ie(Cu,i),ie(qi,c),_a=i|c.baseLanes}function mg(){ie(Cu,_a),ie(qi,qi.current)}function bg(){_a=Cu.current,Re(qi),Re(Cu)}var gr=ce(null),Yr=null;function Xa(i){var c=i.alternate;ie(en,en.current&1),ie(gr,i),Yr===null&&(c===null||qi.current!==null||c.memoizedState!==null)&&(Yr=i)}function N1(i){if(i.tag===22){if(ie(en,en.current),ie(gr,i),Yr===null){var c=i.alternate;c!==null&&c.memoizedState!==null&&(Yr=i)}}else Za()}function Za(){ie(en,en.current),ie(gr,gr.current)}function va(i){Re(gr),Yr===i&&(Yr=null),Re(en)}var en=ce(0);function _u(i){for(var c=i;c!==null;){if(c.tag===13){var f=c.memoizedState;if(f!==null&&(f=f.dehydrated,f===null||f.data==="$?"||f.data==="$!"))return c}else if(c.tag===19&&c.memoizedProps.revealOrder!==void 0){if(c.flags&128)return c}else if(c.child!==null){c.child.return=c,c=c.child;continue}if(c===i)break;for(;c.sibling===null;){if(c.return===null||c.return===i)return null;c=c.return}c.sibling.return=c.return,c=c.sibling}return null}var W$=typeof AbortController<"u"?AbortController:function(){var i=[],c=this.signal={aborted:!1,addEventListener:function(f,h){i.push(h)}};this.abort=function(){c.aborted=!0,i.forEach(function(f){return f()})}},Y$=e.unstable_scheduleCallback,K$=e.unstable_NormalPriority,tn={$$typeof:b,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function yg(){return{controller:new W$,data:new Map,refCount:0}}function wl(i){i.refCount--,i.refCount===0&&Y$(K$,function(){i.controller.abort()})}var xl=null,vg=0,Vi=0,Wi=null;function X$(i,c){if(xl===null){var f=xl=[];vg=0,Vi=Th(),Wi={status:"pending",value:void 0,then:function(h){f.push(h)}}}return vg++,c.then(O1,O1),c}function O1(){if(--vg===0&&xl!==null){Wi!==null&&(Wi.status="fulfilled");var i=xl;xl=null,Vi=0,Wi=null;for(var c=0;cA?A:8;var z=D.T,q={};D.T=q,Pg(i,!1,c,f);try{var X=S(),re=D.S;if(re!==null&&re(q,X),X!==null&&typeof X=="object"&&typeof X.then=="function"){var ve=Z$(X,h);Al(i,c,ve,Zn(i))}else Al(i,c,h,Zn(i))}catch(Ce){Al(i,c,{then:function(){},status:"rejected",reason:Ce},Zn())}finally{Z.p=A,D.T=z}}function n6(){}function Lg(i,c,f,h){if(i.tag!==5)throw Error(r(476));var S=lR(i).queue;sR(i,S,c,Q,f===null?n6:function(){return cR(i),f(h)})}function lR(i){var c=i.memoizedState;if(c!==null)return c;c={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sa,lastRenderedState:Q},next:null};var f={};return c.next={memoizedState:f,baseState:f,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sa,lastRenderedState:f},next:null},i.memoizedState=c,i=i.alternate,i!==null&&(i.memoizedState=c),c}function cR(i){var c=lR(i).next.queue;Al(i,c,{},Zn())}function Mg(){return wn(Vl)}function uR(){return Xt().memoizedState}function dR(){return Xt().memoizedState}function r6(i){for(var c=i.return;c!==null;){switch(c.tag){case 24:case 3:var f=Zn();i=no(f);var h=ro(c,i,f);h!==null&&(On(h,c,f),_l(h,c,f)),c={cache:yg()},i.payload=c;return}c=c.return}}function a6(i,c,f){var h=Zn();f={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null},zu(i)?pR(c,f):(f=dg(i,c,f,h),f!==null&&(On(f,i,h),gR(f,c,h)))}function fR(i,c,f){var h=Zn();Al(i,c,f,h)}function Al(i,c,f,h){var S={lane:h,revertLane:0,action:f,hasEagerState:!1,eagerState:null,next:null};if(zu(i))pR(c,S);else{var A=i.alternate;if(i.lanes===0&&(A===null||A.lanes===0)&&(A=c.lastRenderedReducer,A!==null))try{var z=c.lastRenderedState,q=A(z,f);if(S.hasEagerState=!0,S.eagerState=q,Wn(q,z))return Eu(i,c,S,0),Lt===null&&Su(),!1}catch{}finally{}if(f=dg(i,c,S,h),f!==null)return On(f,i,h),gR(f,c,h),!0}return!1}function Pg(i,c,f,h){if(h={lane:2,revertLane:Th(),action:h,hasEagerState:!1,eagerState:null,next:null},zu(i)){if(c)throw Error(r(479))}else c=dg(i,f,h,2),c!==null&&On(c,i,2)}function zu(i){var c=i.alternate;return i===ct||c!==null&&c===ct}function pR(i,c){Yi=Ou=!0;var f=i.pending;f===null?c.next=c:(c.next=f.next,f.next=c),i.pending=c}function gR(i,c,f){if(f&4194176){var h=c.lanes;h&=i.pendingLanes,f|=h,c.lanes=f,_r(i,f)}}var Kr={readContext:wn,use:Lu,useCallback:Wt,useContext:Wt,useEffect:Wt,useImperativeHandle:Wt,useLayoutEffect:Wt,useInsertionEffect:Wt,useMemo:Wt,useReducer:Wt,useRef:Wt,useState:Wt,useDebugValue:Wt,useDeferredValue:Wt,useTransition:Wt,useSyncExternalStore:Wt,useId:Wt};Kr.useCacheRefresh=Wt,Kr.useMemoCache=Wt,Kr.useHostTransitionStatus=Wt,Kr.useFormState=Wt,Kr.useActionState=Wt,Kr.useOptimistic=Wt;var Yo={readContext:wn,use:Lu,useCallback:function(i,c){return zn().memoizedState=[i,c===void 0?null:c],i},useContext:wn,useEffect:J1,useImperativeHandle:function(i,c,f){f=f!=null?f.concat([i]):null,Pu(4194308,4,nR.bind(null,c,i),f)},useLayoutEffect:function(i,c){return Pu(4194308,4,i,c)},useInsertionEffect:function(i,c){Pu(4,2,i,c)},useMemo:function(i,c){var f=zn();c=c===void 0?null:c;var h=i();if(Wo){st(!0);try{i()}finally{st(!1)}}return f.memoizedState=[h,c],h},useReducer:function(i,c,f){var h=zn();if(f!==void 0){var S=f(c);if(Wo){st(!0);try{f(c)}finally{st(!1)}}}else S=c;return h.memoizedState=h.baseState=S,i={pending:null,lanes:0,dispatch:null,lastRenderedReducer:i,lastRenderedState:S},h.queue=i,i=i.dispatch=a6.bind(null,ct,i),[h.memoizedState,i]},useRef:function(i){var c=zn();return i={current:i},c.memoizedState=i},useState:function(i){i=_g(i);var c=i.queue,f=fR.bind(null,ct,c);return c.dispatch=f,[i.memoizedState,f]},useDebugValue:Ig,useDeferredValue:function(i,c){var f=zn();return Dg(f,i,c)},useTransition:function(){var i=_g(!1);return i=sR.bind(null,ct,i.queue,!0,!1),zn().memoizedState=i,[!1,i]},useSyncExternalStore:function(i,c,f){var h=ct,S=zn();if(xt){if(f===void 0)throw Error(r(407));f=f()}else{if(f=c(),Lt===null)throw Error(r(349));vt&60||F1(h,c,f)}S.memoizedState=f;var A={value:f,getSnapshot:c};return S.queue=A,J1(B1.bind(null,h,A,i),[i]),h.flags|=2048,Xi(9,z1.bind(null,h,A,f,c),{destroy:void 0},null),f},useId:function(){var i=zn(),c=Lt.identifierPrefix;if(xt){var f=ya,h=ba;f=(h&~(1<<32-wt(h)-1)).toString(32)+f,c=":"+c+"R"+f,f=Iu++,0 title"))),mn(A,h,f),A[En]=i,an(A),h=A;break e;case"link":var z=UC("link","href",S).get(h+(f.href||""));if(z){for(var q=0;q<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof h.is=="string"?S.createElement("select",{is:h.is}):S.createElement("select"),h.multiple?i.multiple=!0:h.size&&(i.size=h.size);break;default:i=typeof h.is=="string"?S.createElement(f,{is:h.is}):S.createElement(f)}}i[En]=c,i[Pn]=h;e:for(S=c.child;S!==null;){if(S.tag===5||S.tag===6)i.appendChild(S.stateNode);else if(S.tag!==4&&S.tag!==27&&S.child!==null){S.child.return=S,S=S.child;continue}if(S===c)break e;for(;S.sibling===null;){if(S.return===null||S.return===c)break e;S=S.return}S.sibling.return=S.return,S=S.sibling}c.stateNode=i;e:switch(mn(i,f,h),f){case"button":case"input":case"select":case"textarea":i=!!h.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&Ra(c)}}return Bt(c),c.flags&=-16777217,null;case 6:if(i&&c.stateNode!=null)i.memoizedProps!==h&&Ra(c);else{if(typeof h!="string"&&c.stateNode===null)throw Error(r(166));if(i=xe.current,hl(c)){if(i=c.stateNode,f=c.memoizedProps,h=null,S=Nn,S!==null)switch(S.tag){case 27:case 5:h=S.memoizedProps}i[En]=c,i=!!(i.nodeValue===f||h!==null&&h.suppressHydrationWarning===!0||_C(i.nodeValue,f)),i||$o(c)}else i=rd(i).createTextNode(h),i[En]=c,c.stateNode=i}return Bt(c),null;case 13:if(h=c.memoizedState,i===null||i.memoizedState!==null&&i.memoizedState.dehydrated!==null){if(S=hl(c),h!==null&&h.dehydrated!==null){if(i===null){if(!S)throw Error(r(318));if(S=c.memoizedState,S=S!==null?S.dehydrated:null,!S)throw Error(r(317));S[En]=c}else ml(),!(c.flags&128)&&(c.memoizedState=null),c.flags|=4;Bt(c),S=!1}else Or!==null&&(yh(Or),Or=null),S=!0;if(!S)return c.flags&256?(va(c),c):(va(c),null)}if(va(c),c.flags&128)return c.lanes=f,c;if(f=h!==null,i=i!==null&&i.memoizedState!==null,f){h=c.child,S=null,h.alternate!==null&&h.alternate.memoizedState!==null&&h.alternate.memoizedState.cachePool!==null&&(S=h.alternate.memoizedState.cachePool.pool);var A=null;h.memoizedState!==null&&h.memoizedState.cachePool!==null&&(A=h.memoizedState.cachePool.pool),A!==S&&(h.flags|=2048)}return f!==i&&f&&(c.child.flags|=8192),Vu(c,c.updateQueue),Bt(c),null;case 4:return J(),i===null&&_h(c.stateNode.containerInfo),Bt(c),null;case 10:return xa(c.type),Bt(c),null;case 19:if(Re(en),S=c.memoizedState,S===null)return Bt(c),null;if(h=(c.flags&128)!==0,A=S.rendering,A===null)if(h)Pl(S,!1);else{if(qt!==0||i!==null&&i.flags&128)for(i=c.child;i!==null;){if(A=_u(i),A!==null){for(c.flags|=128,Pl(S,!1),i=A.updateQueue,c.updateQueue=i,Vu(c,i),c.subtreeFlags=0,i=f,f=c.child;f!==null;)rC(f,i),f=f.sibling;return ie(en,en.current&1|2),c.child}i=i.sibling}S.tail!==null&&ye()>Wu&&(c.flags|=128,h=!0,Pl(S,!1),c.lanes=4194304)}else{if(!h)if(i=_u(A),i!==null){if(c.flags|=128,h=!0,i=i.updateQueue,c.updateQueue=i,Vu(c,i),Pl(S,!0),S.tail===null&&S.tailMode==="hidden"&&!A.alternate&&!xt)return Bt(c),null}else 2*ye()-S.renderingStartTime>Wu&&f!==536870912&&(c.flags|=128,h=!0,Pl(S,!1),c.lanes=4194304);S.isBackwards?(A.sibling=c.child,c.child=A):(i=S.last,i!==null?i.sibling=A:c.child=A,S.last=A)}return S.tail!==null?(c=S.tail,S.rendering=c,S.tail=c.sibling,S.renderingStartTime=ye(),c.sibling=null,i=en.current,ie(en,h?i&1|2:i&1),c):(Bt(c),null);case 22:case 23:return va(c),bg(),h=c.memoizedState!==null,i!==null?i.memoizedState!==null!==h&&(c.flags|=8192):h&&(c.flags|=8192),h?f&536870912&&!(c.flags&128)&&(Bt(c),c.subtreeFlags&6&&(c.flags|=8192)):Bt(c),f=c.updateQueue,f!==null&&Vu(c,f.retryQueue),f=null,i!==null&&i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(f=i.memoizedState.cachePool.pool),h=null,c.memoizedState!==null&&c.memoizedState.cachePool!==null&&(h=c.memoizedState.cachePool.pool),h!==f&&(c.flags|=2048),i!==null&&Re(Vo),null;case 24:return f=null,i!==null&&(f=i.memoizedState.cache),c.memoizedState.cache!==f&&(c.flags|=2048),xa(tn),Bt(c),null;case 25:return null}throw Error(r(156,c.tag))}function d6(i,c){switch(pg(c),c.tag){case 1:return i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 3:return xa(tn),J(),i=c.flags,i&65536&&!(i&128)?(c.flags=i&-65537|128,c):null;case 26:case 27:case 5:return ke(c),null;case 13:if(va(c),i=c.memoizedState,i!==null&&i.dehydrated!==null){if(c.alternate===null)throw Error(r(340));ml()}return i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 19:return Re(en),null;case 4:return J(),null;case 10:return xa(c.type),null;case 22:case 23:return va(c),bg(),i!==null&&Re(Vo),i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 24:return xa(tn),null;case 25:return null;default:return null}}function iC(i,c){switch(pg(c),c.tag){case 3:xa(tn),J();break;case 26:case 27:case 5:ke(c);break;case 4:J();break;case 13:va(c);break;case 19:Re(en);break;case 10:xa(c.type);break;case 22:case 23:va(c),bg(),i!==null&&Re(Vo);break;case 24:xa(tn)}}var f6={getCacheForType:function(i){var c=wn(tn),f=c.data.get(i);return f===void 0&&(f=i(),c.data.set(i,f)),f}},p6=typeof WeakMap=="function"?WeakMap:Map,jt=0,Lt=null,ft=null,vt=0,Mt=0,Xn=null,Ca=!1,es=!1,dh=!1,_a=0,qt=0,lo=0,ti=0,fh=0,yr=0,ts=0,Fl=null,Xr=null,ph=!1,gh=0,Wu=1/0,Yu=null,co=null,Ku=!1,ni=null,zl=0,hh=0,mh=null,Bl=0,bh=null;function Zn(){if(jt&2&&vt!==0)return vt&-vt;if(D.T!==null){var i=Vi;return i!==0?i:Th()}return RA()}function sC(){yr===0&&(yr=!(vt&536870912)||xt?Nt():536870912);var i=gr.current;return i!==null&&(i.flags|=32),yr}function On(i,c,f){(i===Lt&&Mt===2||i.cancelPendingCommit!==null)&&(ns(i,0),Na(i,vt,yr,!1)),Ln(i,f),(!(jt&2)||i!==Lt)&&(i===Lt&&(!(jt&2)&&(ti|=f),qt===4&&Na(i,vt,yr,!1)),Zr(i))}function lC(i,c,f){if(jt&6)throw Error(r(327));var h=!f&&(c&60)===0&&(c&i.expiredLanes)===0||Xe(i,c),S=h?m6(i,c):Eh(i,c,!0),A=h;do{if(S===0){es&&!h&&Na(i,c,0,!1);break}else if(S===6)Na(i,c,0,!Ca);else{if(f=i.current.alternate,A&&!g6(f)){S=Eh(i,c,!1),A=!1;continue}if(S===2){if(A=c,i.errorRecoveryDisabledLanes&A)var z=0;else z=i.pendingLanes&-536870913,z=z!==0?z:z&536870912?536870912:0;if(z!==0){c=z;e:{var q=i;S=Fl;var X=q.current.memoizedState.isDehydrated;if(X&&(ns(q,z).flags|=256),z=Eh(q,z,!1),z!==2){if(dh&&!X){q.errorRecoveryDisabledLanes|=A,ti|=A,S=4;break e}A=Xr,Xr=S,A!==null&&yh(A)}S=z}if(A=!1,S!==2)continue}}if(S===1){ns(i,0),Na(i,c,0,!0);break}e:{switch(h=i,S){case 0:case 1:throw Error(r(345));case 4:if((c&4194176)===c){Na(h,c,yr,!Ca);break e}break;case 2:Xr=null;break;case 3:case 5:break;default:throw Error(r(329))}if(h.finishedWork=f,h.finishedLanes=c,(c&62914560)===c&&(A=gh+300-ye(),10f?32:f,D.T=null,ni===null)var A=!1;else{f=mh,mh=null;var z=ni,q=zl;if(ni=null,zl=0,jt&6)throw Error(r(331));var X=jt;if(jt|=4,tC(z.current),QR(z,z.current,q,f),jt=X,jl(0,!1),et&&typeof et.onPostCommitFiberRoot=="function")try{et.onPostCommitFiberRoot(bt,z)}catch{}A=!0}return A}finally{Z.p=S,D.T=h,bC(i,c)}}return!1}function yC(i,c,f){c=dr(f,c),c=Bg(i.stateNode,c,2),i=ro(i,c,2),i!==null&&(Ln(i,2),Zr(i))}function Ot(i,c,f){if(i.tag===3)yC(i,i,f);else for(;c!==null;){if(c.tag===3){yC(c,i,f);break}else if(c.tag===1){var h=c.stateNode;if(typeof c.type.getDerivedStateFromError=="function"||typeof h.componentDidCatch=="function"&&(co===null||!co.has(h))){i=dr(f,i),f=ER(2),h=ro(c,f,2),h!==null&&(wR(f,h,c,i),Ln(h,2),Zr(h));break}}c=c.return}}function wh(i,c,f){var h=i.pingCache;if(h===null){h=i.pingCache=new p6;var S=new Set;h.set(c,S)}else S=h.get(c),S===void 0&&(S=new Set,h.set(c,S));S.has(f)||(dh=!0,S.add(f),i=v6.bind(null,i,c,f),c.then(i,i))}function v6(i,c,f){var h=i.pingCache;h!==null&&h.delete(c),i.pingedLanes|=i.suspendedLanes&f,i.warmLanes&=~f,Lt===i&&(vt&f)===f&&(qt===4||qt===3&&(vt&62914560)===vt&&300>ye()-gh?!(jt&2)&&ns(i,0):fh|=f,ts===vt&&(ts=0)),Zr(i)}function vC(i,c){c===0&&(c=Dn()),i=Ka(i,c),i!==null&&(Ln(i,c),Zr(i))}function S6(i){var c=i.memoizedState,f=0;c!==null&&(f=c.retryLane),vC(i,f)}function E6(i,c){var f=0;switch(i.tag){case 13:var h=i.stateNode,S=i.memoizedState;S!==null&&(f=S.retryLane);break;case 19:h=i.stateNode;break;case 22:h=i.stateNode._retryCache;break;default:throw Error(r(314))}h!==null&&h.delete(c),vC(i,f)}function w6(i,c){return Ee(i,c)}var Qu=null,os=null,xh=!1,Ju=!1,kh=!1,ri=0;function Zr(i){i!==os&&i.next===null&&(os===null?Qu=os=i:os=os.next=i),Ju=!0,xh||(xh=!0,k6(x6))}function jl(i,c){if(!kh&&Ju){kh=!0;do for(var f=!1,h=Qu;h!==null;){if(i!==0){var S=h.pendingLanes;if(S===0)var A=0;else{var z=h.suspendedLanes,q=h.pingedLanes;A=(1<<31-wt(42|i)+1)-1,A&=S&~(z&~q),A=A&201326677?A&201326677|1:A?A|2:0}A!==0&&(f=!0,wC(h,A))}else A=vt,A=pa(h,h===Lt?A:0),!(A&3)||Xe(h,A)||(f=!0,wC(h,A));h=h.next}while(f);kh=!1}}function x6(){Ju=xh=!1;var i=0;ri!==0&&(I6()&&(i=ri),ri=0);for(var c=ye(),f=null,h=Qu;h!==null;){var S=h.next,A=SC(h,c);A===0?(h.next=null,f===null?Qu=S:f.next=S,S===null&&(os=f)):(f=h,(i!==0||A&3)&&(Ju=!0)),h=S}jl(i)}function SC(i,c){for(var f=i.suspendedLanes,h=i.pingedLanes,S=i.expirationTimes,A=i.pendingLanes&-62914561;0"u"?null:document;function FC(i,c,f){var h=ss;if(h&&typeof c=="string"&&c){var S=cr(c);S='link[rel="'+i+'"][href="'+S+'"]',typeof f=="string"&&(S+='[crossorigin="'+f+'"]'),PC.has(S)||(PC.add(S),i={rel:i,crossOrigin:f,href:c},h.querySelector(S)===null&&(c=h.createElement("link"),mn(c,"link",i),an(c),h.head.appendChild(c)))}}function j6(i){Oa.D(i),FC("dns-prefetch",i,null)}function U6(i,c){Oa.C(i,c),FC("preconnect",i,c)}function G6(i,c,f){Oa.L(i,c,f);var h=ss;if(h&&i&&c){var S='link[rel="preload"][as="'+cr(c)+'"]';c==="image"&&f&&f.imageSrcSet?(S+='[imagesrcset="'+cr(f.imageSrcSet)+'"]',typeof f.imageSizes=="string"&&(S+='[imagesizes="'+cr(f.imageSizes)+'"]')):S+='[href="'+cr(i)+'"]';var A=S;switch(c){case"style":A=ls(i);break;case"script":A=cs(i)}vr.has(A)||(i=I({rel:"preload",href:c==="image"&&f&&f.imageSrcSet?void 0:i,as:c},f),vr.set(A,i),h.querySelector(S)!==null||c==="style"&&h.querySelector(Hl(A))||c==="script"&&h.querySelector($l(A))||(c=h.createElement("link"),mn(c,"link",i),an(c),h.head.appendChild(c)))}}function H6(i,c){Oa.m(i,c);var f=ss;if(f&&i){var h=c&&typeof c.as=="string"?c.as:"script",S='link[rel="modulepreload"][as="'+cr(h)+'"][href="'+cr(i)+'"]',A=S;switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":A=cs(i)}if(!vr.has(A)&&(i=I({rel:"modulepreload",href:i},c),vr.set(A,i),f.querySelector(S)===null)){switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(f.querySelector($l(A)))return}h=f.createElement("link"),mn(h,"link",i),an(h),f.head.appendChild(h)}}}function $6(i,c,f){Oa.S(i,c,f);var h=ss;if(h&&i){var S=Oi(h).hoistableStyles,A=ls(i);c=c||"default";var z=S.get(A);if(!z){var q={loading:0,preload:null};if(z=h.querySelector(Hl(A)))q.loading=5;else{i=I({rel:"stylesheet",href:i,"data-precedence":c},f),(f=vr.get(A))&&zh(i,f);var X=z=h.createElement("link");an(X),mn(X,"link",i),X._p=new Promise(function(re,ve){X.onload=re,X.onerror=ve}),X.addEventListener("load",function(){q.loading|=1}),X.addEventListener("error",function(){q.loading|=2}),q.loading|=4,od(z,c,h)}z={type:"stylesheet",instance:z,count:1,state:q},S.set(A,z)}}}function q6(i,c){Oa.X(i,c);var f=ss;if(f&&i){var h=Oi(f).hoistableScripts,S=cs(i),A=h.get(S);A||(A=f.querySelector($l(S)),A||(i=I({src:i,async:!0},c),(c=vr.get(S))&&Bh(i,c),A=f.createElement("script"),an(A),mn(A,"link",i),f.head.appendChild(A)),A={type:"script",instance:A,count:1,state:null},h.set(S,A))}}function V6(i,c){Oa.M(i,c);var f=ss;if(f&&i){var h=Oi(f).hoistableScripts,S=cs(i),A=h.get(S);A||(A=f.querySelector($l(S)),A||(i=I({src:i,async:!0,type:"module"},c),(c=vr.get(S))&&Bh(i,c),A=f.createElement("script"),an(A),mn(A,"link",i),f.head.appendChild(A)),A={type:"script",instance:A,count:1,state:null},h.set(S,A))}}function zC(i,c,f,h){var S=(S=xe.current)?ad(S):null;if(!S)throw Error(r(446));switch(i){case"meta":case"title":return null;case"style":return typeof f.precedence=="string"&&typeof f.href=="string"?(c=ls(f.href),f=Oi(S).hoistableStyles,h=f.get(c),h||(h={type:"style",instance:null,count:0,state:null},f.set(c,h)),h):{type:"void",instance:null,count:0,state:null};case"link":if(f.rel==="stylesheet"&&typeof f.href=="string"&&typeof f.precedence=="string"){i=ls(f.href);var A=Oi(S).hoistableStyles,z=A.get(i);if(z||(S=S.ownerDocument||S,z={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},A.set(i,z),(A=S.querySelector(Hl(i)))&&!A._p&&(z.instance=A,z.state.loading=5),vr.has(i)||(f={rel:"preload",as:"style",href:f.href,crossOrigin:f.crossOrigin,integrity:f.integrity,media:f.media,hrefLang:f.hrefLang,referrerPolicy:f.referrerPolicy},vr.set(i,f),A||W6(S,i,f,z.state))),c&&h===null)throw Error(r(528,""));return z}if(c&&h!==null)throw Error(r(529,""));return null;case"script":return c=f.async,f=f.src,typeof f=="string"&&c&&typeof c!="function"&&typeof c!="symbol"?(c=cs(f),f=Oi(S).hoistableScripts,h=f.get(c),h||(h={type:"script",instance:null,count:0,state:null},f.set(c,h)),h):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,i))}}function ls(i){return'href="'+cr(i)+'"'}function Hl(i){return'link[rel="stylesheet"]['+i+"]"}function BC(i){return I({},i,{"data-precedence":i.precedence,precedence:null})}function W6(i,c,f,h){i.querySelector('link[rel="preload"][as="style"]['+c+"]")?h.loading=1:(c=i.createElement("link"),h.preload=c,c.addEventListener("load",function(){return h.loading|=1}),c.addEventListener("error",function(){return h.loading|=2}),mn(c,"link",f),an(c),i.head.appendChild(c))}function cs(i){return'[src="'+cr(i)+'"]'}function $l(i){return"script[async]"+i}function jC(i,c,f){if(c.count++,c.instance===null)switch(c.type){case"style":var h=i.querySelector('style[data-href~="'+cr(f.href)+'"]');if(h)return c.instance=h,an(h),h;var S=I({},f,{"data-href":f.href,"data-precedence":f.precedence,href:null,precedence:null});return h=(i.ownerDocument||i).createElement("style"),an(h),mn(h,"style",S),od(h,f.precedence,i),c.instance=h;case"stylesheet":S=ls(f.href);var A=i.querySelector(Hl(S));if(A)return c.state.loading|=4,c.instance=A,an(A),A;h=BC(f),(S=vr.get(S))&&zh(h,S),A=(i.ownerDocument||i).createElement("link"),an(A);var z=A;return z._p=new Promise(function(q,X){z.onload=q,z.onerror=X}),mn(A,"link",h),c.state.loading|=4,od(A,f.precedence,i),c.instance=A;case"script":return A=cs(f.src),(S=i.querySelector($l(A)))?(c.instance=S,an(S),S):(h=f,(S=vr.get(A))&&(h=I({},f),Bh(h,S)),i=i.ownerDocument||i,S=i.createElement("script"),an(S),mn(S,"link",h),i.head.appendChild(S),c.instance=S);case"void":return null;default:throw Error(r(443,c.type))}else c.type==="stylesheet"&&!(c.state.loading&4)&&(h=c.instance,c.state.loading|=4,od(h,f.precedence,i));return c.instance}function od(i,c,f){for(var h=f.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),S=h.length?h[h.length-1]:null,A=S,z=0;z title"):null)}function Y6(i,c,f){if(f===1||c.itemProp!=null)return!1;switch(i){case"meta":case"title":return!0;case"style":if(typeof c.precedence!="string"||typeof c.href!="string"||c.href==="")break;return!0;case"link":if(typeof c.rel!="string"||typeof c.href!="string"||c.href===""||c.onLoad||c.onError)break;switch(c.rel){case"stylesheet":return i=c.disabled,typeof c.precedence=="string"&&i==null;default:return!0}case"script":if(c.async&&typeof c.async!="function"&&typeof c.async!="symbol"&&!c.onLoad&&!c.onError&&c.src&&typeof c.src=="string")return!0}return!1}function HC(i){return!(i.type==="stylesheet"&&!(i.state.loading&3))}var ql=null;function K6(){}function X6(i,c,f){if(ql===null)throw Error(r(475));var h=ql;if(c.type==="stylesheet"&&(typeof f.media!="string"||matchMedia(f.media).matches!==!1)&&!(c.state.loading&4)){if(c.instance===null){var S=ls(f.href),A=i.querySelector(Hl(S));if(A){i=A._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(h.count++,h=sd.bind(h),i.then(h,h)),c.state.loading|=4,c.instance=A,an(A);return}A=i.ownerDocument||i,f=BC(f),(S=vr.get(S))&&zh(f,S),A=A.createElement("link"),an(A);var z=A;z._p=new Promise(function(q,X){z.onload=q,z.onerror=X}),mn(A,"link",f),c.instance=A}h.stylesheets===null&&(h.stylesheets=new Map),h.stylesheets.set(c,i),(i=c.state.preload)&&!(c.state.loading&3)&&(h.count++,c=sd.bind(h),i.addEventListener("load",c),i.addEventListener("error",c))}}function Z6(){if(ql===null)throw Error(r(475));var i=ql;return i.stylesheets&&i.count===0&&jh(i,i.stylesheets),0"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Kh.exports=yq(),Kh.exports}var Sq=vq(),Jl={},d_;function Eq(){if(d_)return Jl;d_=1,Object.defineProperty(Jl,"__esModule",{value:!0}),Jl.parse=s,Jl.serialize=d;const e=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,t=/^[\u0021-\u003A\u003C-\u007E]*$/,n=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,r=/^[\u0020-\u003A\u003D-\u007E]*$/,a=Object.prototype.toString,o=(()=>{const m=function(){};return m.prototype=Object.create(null),m})();function s(m,b){const y=new o,v=m.length;if(v<2)return y;const x=(b==null?void 0:b.decode)||p;let T=0;do{const k=m.indexOf("=",T);if(k===-1)break;const R=m.indexOf(";",T),O=R===-1?v:R;if(k>O){T=m.lastIndexOf(";",k-1)+1;continue}const N=l(m,T,k),C=u(m,k,N),_=m.slice(N,C);if(y[_]===void 0){let M=l(m,k+1,O),D=u(m,O,M);const I=x(m.slice(M,D));y[_]=I}T=O+1}while(Ty;){const v=m.charCodeAt(--b);if(v!==32&&v!==9)return b+1}return y}function d(m,b,y){const v=(y==null?void 0:y.encode)||encodeURIComponent;if(!e.test(m))throw new TypeError(`argument name is invalid: ${m}`);const x=v(b);if(!t.test(x))throw new TypeError(`argument val is invalid: ${b}`);let T=m+"="+x;if(!y)return T;if(y.maxAge!==void 0){if(!Number.isInteger(y.maxAge))throw new TypeError(`option maxAge is invalid: ${y.maxAge}`);T+="; Max-Age="+y.maxAge}if(y.domain){if(!n.test(y.domain))throw new TypeError(`option domain is invalid: ${y.domain}`);T+="; Domain="+y.domain}if(y.path){if(!r.test(y.path))throw new TypeError(`option path is invalid: ${y.path}`);T+="; Path="+y.path}if(y.expires){if(!g(y.expires)||!Number.isFinite(y.expires.valueOf()))throw new TypeError(`option expires is invalid: ${y.expires}`);T+="; Expires="+y.expires.toUTCString()}if(y.httpOnly&&(T+="; HttpOnly"),y.secure&&(T+="; Secure"),y.partitioned&&(T+="; Partitioned"),y.priority)switch(typeof y.priority=="string"?y.priority.toLowerCase():void 0){case"low":T+="; Priority=Low";break;case"medium":T+="; Priority=Medium";break;case"high":T+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${y.priority}`)}if(y.sameSite)switch(typeof y.sameSite=="string"?y.sameSite.toLowerCase():y.sameSite){case!0:case"strict":T+="; SameSite=Strict";break;case"lax":T+="; SameSite=Lax";break;case"none":T+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${y.sameSite}`)}return T}function p(m){if(m.indexOf("%")===-1)return m;try{return decodeURIComponent(m)}catch{return m}}function g(m){return a.call(m)==="[object Date]"}return Jl}Eq();/** +`+X[h].replace(" at new "," at ");return i.displayName&&ve.includes("")&&(ve=ve.replace("",i.displayName)),ve}while(1<=h&&0<=S);break}}}finally{W=!1,Error.prepareStackTrace=p}return(p=i?i.displayName||i.name:"")?B(p):""}function G(i){switch(i.tag){case 26:case 27:case 5:return B(i.type);case 16:return B("Lazy");case 13:return B("Suspense");case 19:return B("SuspenseList");case 0:case 15:return i=K(i.type,!1),i;case 11:return i=K(i.type.render,!1),i;case 1:return i=K(i.type,!0),i;default:return""}}function H(i){try{var c="";do c+=G(i),i=i.return;while(i);return c}catch(p){return` +Error generating stack: `+p.message+` +`+p.stack}}function F(i){var c=i,p=i;if(i.alternate)for(;c.return;)c=c.return;else{i=c;do c=i,c.flags&4098&&(p=c.return),i=c.return;while(i)}return c.tag===3?p:null}function Y(i){if(i.tag===13){var c=i.memoizedState;if(c===null&&(i=i.alternate,i!==null&&(c=i.memoizedState)),c!==null)return c.dehydrated}return null}function L(i){if(F(i)!==i)throw Error(r(188))}function V(i){var c=i.alternate;if(!c){if(c=F(i),c===null)throw Error(r(188));return c!==i?null:i}for(var p=i,h=c;;){var S=p.return;if(S===null)break;var A=S.alternate;if(A===null){if(h=S.return,h!==null){p=h;continue}break}if(S.child===A.child){for(A=S.child;A;){if(A===p)return L(S),i;if(A===h)return L(S),c;A=A.sibling}throw Error(r(188))}if(p.return!==h.return)p=S,h=A;else{for(var z=!1,q=S.child;q;){if(q===p){z=!0,p=S,h=A;break}if(q===h){z=!0,h=S,p=A;break}q=q.sibling}if(!z){for(q=A.child;q;){if(q===p){z=!0,p=A,h=S;break}if(q===h){z=!0,h=A,p=S;break}q=q.sibling}if(!z)throw Error(r(189))}}if(p.alternate!==h)throw Error(r(190))}if(p.tag!==3)throw Error(r(188));return p.stateNode.current===p?i:c}function j(i){var c=i.tag;if(c===5||c===26||c===27||c===6)return i;for(i=i.child;i!==null;){if(c=j(i),c!==null)return c;i=i.sibling}return null}var P=Array.isArray,Z=n.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,Q={pending:!1,data:null,method:null,action:null},oe=[],ae=-1;function ce(i){return{current:i}}function Re(i){0>ae||(i.current=oe[ae],oe[ae]=null,ae--)}function ie(i,c){ae++,oe[ae]=i.current,i.current=c}var Te=ce(null),ne=ce(null),xe=ce(null),Se=ce(null);function be(i,c){switch(ie(xe,c),ie(ne,i),ie(Te,null),i=c.nodeType,i){case 9:case 11:c=(c=c.documentElement)&&(c=c.namespaceURI)?NC(c):0;break;default:if(i=i===8?c.parentNode:c,c=i.tagName,i=i.namespaceURI)i=NC(i),c=OC(i,c);else switch(c){case"svg":c=1;break;case"math":c=2;break;default:c=0}}Re(Te),ie(Te,c)}function J(){Re(Te),Re(ne),Re(xe)}function fe(i){i.memoizedState!==null&&ie(Se,i);var c=Te.current,p=OC(c,i.type);c!==p&&(ie(ne,i),ie(Te,p))}function ke(i){ne.current===i&&(Re(Te),Re(ne)),Se.current===i&&(Re(Se),Vl._currentValue=Q)}var he=Object.prototype.hasOwnProperty,we=e.unstable_scheduleCallback,se=e.unstable_cancelCallback,Be=e.unstable_shouldYield,je=e.unstable_requestPaint,ye=e.unstable_now,Oe=e.unstable_getCurrentPriorityLevel,ee=e.unstable_ImmediatePriority,de=e.unstable_UserBlockingPriority,Ne=e.unstable_NormalPriority,ze=e.unstable_LowPriority,We=e.unstable_IdlePriority,St=e.log,Tt=e.unstable_setDisableYieldValue,bt=null,et=null;function At(i){if(et&&typeof et.onCommitFiberRoot=="function")try{et.onCommitFiberRoot(bt,i,void 0,(i.current.flags&128)===128)}catch{}}function st(i){if(typeof St=="function"&&Tt(i),et&&typeof et.setStrictMode=="function")try{et.setStrictMode(bt,i)}catch{}}var Et=Math.clz32?Math.clz32:zt,Ht=Math.log,gn=Math.LN2;function zt(i){return i>>>=0,i===0?32:31-(Ht(i)/gn|0)|0}var sr=128,Vr=4194304;function Jt(i){var c=i&42;if(c!==0)return c;switch(i&-i){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:return 64;case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return i&4194176;case 4194304:case 8388608:case 16777216:case 33554432:return i&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return i}}function fa(i,c){var p=i.pendingLanes;if(p===0)return 0;var h=0,S=i.suspendedLanes,A=i.pingedLanes,z=i.warmLanes;i=i.finishedLanes!==0;var q=p&134217727;return q!==0?(p=q&~S,p!==0?h=Jt(p):(A&=q,A!==0?h=Jt(A):i||(z=q&~z,z!==0&&(h=Jt(z))))):(q=p&~S,q!==0?h=Jt(q):A!==0?h=Jt(A):i||(z=p&~z,z!==0&&(h=Jt(z)))),h===0?0:c!==0&&c!==h&&!(c&S)&&(S=h&-h,z=c&-c,S>=z||S===32&&(z&4194176)!==0)?c:h}function Xe(i,c){return(i.pendingLanes&~(i.suspendedLanes&~i.pingedLanes)&c)===0}function yt(i,c){switch(i){case 1:case 2:case 4:case 8:return c+250;case 16:case 32:case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return c+5e3;case 4194304:case 8388608:case 16777216:case 33554432:return-1;case 67108864:case 134217728:case 268435456:case 536870912:case 1073741824:return-1;default:return-1}}function Nt(){var i=sr;return sr<<=1,!(sr&4194176)&&(sr=128),i}function Dn(){var i=Vr;return Vr<<=1,!(Vr&62914560)&&(Vr=4194304),i}function _n(i){for(var c=[],p=0;31>p;p++)c.push(i);return c}function Ln(i,c){i.pendingLanes|=c,c!==268435456&&(i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0)}function ga(i,c,p,h,S,A){var z=i.pendingLanes;i.pendingLanes=p,i.suspendedLanes=0,i.pingedLanes=0,i.warmLanes=0,i.expiredLanes&=p,i.entangledLanes&=p,i.errorRecoveryDisabledLanes&=p,i.shellSuspendCounter=0;var q=i.entanglements,X=i.expirationTimes,re=i.hiddenUpdates;for(p=z&~p;0"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),e$=RegExp("^[:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD][:A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040]*$"),OA={},IA={};function t$(i){return he.call(IA,i)?!0:he.call(OA,i)?!1:e$.test(i)?IA[i]=!0:(OA[i]=!0,!1)}function cu(i,c,p){if(t$(c))if(p===null)i.removeAttribute(c);else{switch(typeof p){case"undefined":case"function":case"symbol":i.removeAttribute(c);return;case"boolean":var h=c.toLowerCase().slice(0,5);if(h!=="data-"&&h!=="aria-"){i.removeAttribute(c);return}}i.setAttribute(c,""+p)}}function uu(i,c,p){if(p===null)i.removeAttribute(c);else{switch(typeof p){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(c);return}i.setAttribute(c,""+p)}}function ma(i,c,p,h){if(h===null)i.removeAttribute(p);else{switch(typeof h){case"undefined":case"function":case"symbol":case"boolean":i.removeAttribute(p);return}i.setAttributeNS(c,p,""+h)}}function lr(i){switch(typeof i){case"bigint":case"boolean":case"number":case"string":case"undefined":return i;case"object":return i;default:return""}}function DA(i){var c=i.type;return(i=i.nodeName)&&i.toLowerCase()==="input"&&(c==="checkbox"||c==="radio")}function n$(i){var c=DA(i)?"checked":"value",p=Object.getOwnPropertyDescriptor(i.constructor.prototype,c),h=""+i[c];if(!i.hasOwnProperty(c)&&typeof p<"u"&&typeof p.get=="function"&&typeof p.set=="function"){var S=p.get,A=p.set;return Object.defineProperty(i,c,{configurable:!0,get:function(){return S.call(this)},set:function(z){h=""+z,A.call(this,z)}}),Object.defineProperty(i,c,{enumerable:p.enumerable}),{getValue:function(){return h},setValue:function(z){h=""+z},stopTracking:function(){i._valueTracker=null,delete i[c]}}}}function du(i){i._valueTracker||(i._valueTracker=n$(i))}function LA(i){if(!i)return!1;var c=i._valueTracker;if(!c)return!0;var p=c.getValue(),h="";return i&&(h=DA(i)?i.checked?"true":"false":i.value),i=h,i!==p?(c.setValue(i),!0):!1}function pu(i){if(i=i||(typeof document<"u"?document:void 0),typeof i>"u")return null;try{return i.activeElement||i.body}catch{return i.body}}var r$=/[\n"\\]/g;function cr(i){return i.replace(r$,function(c){return"\\"+c.charCodeAt(0).toString(16)+" "})}function qf(i,c,p,h,S,A,z,q){i.name="",z!=null&&typeof z!="function"&&typeof z!="symbol"&&typeof z!="boolean"?i.type=z:i.removeAttribute("type"),c!=null?z==="number"?(c===0&&i.value===""||i.value!=c)&&(i.value=""+lr(c)):i.value!==""+lr(c)&&(i.value=""+lr(c)):z!=="submit"&&z!=="reset"||i.removeAttribute("value"),c!=null?Vf(i,z,lr(c)):p!=null?Vf(i,z,lr(p)):h!=null&&i.removeAttribute("value"),S==null&&A!=null&&(i.defaultChecked=!!A),S!=null&&(i.checked=S&&typeof S!="function"&&typeof S!="symbol"),q!=null&&typeof q!="function"&&typeof q!="symbol"&&typeof q!="boolean"?i.name=""+lr(q):i.removeAttribute("name")}function MA(i,c,p,h,S,A,z,q){if(A!=null&&typeof A!="function"&&typeof A!="symbol"&&typeof A!="boolean"&&(i.type=A),c!=null||p!=null){if(!(A!=="submit"&&A!=="reset"||c!=null))return;p=p!=null?""+lr(p):"",c=c!=null?""+lr(c):p,q||c===i.value||(i.value=c),i.defaultValue=c}h=h??S,h=typeof h!="function"&&typeof h!="symbol"&&!!h,i.checked=q?i.checked:!!h,i.defaultChecked=!!h,z!=null&&typeof z!="function"&&typeof z!="symbol"&&typeof z!="boolean"&&(i.name=z)}function Vf(i,c,p){c==="number"&&pu(i.ownerDocument)===i||i.defaultValue===""+p||(i.defaultValue=""+p)}function Di(i,c,p,h){if(i=i.options,c){c={};for(var S=0;S=ul),YA=" ",KA=!1;function XA(i,c){switch(i){case"keyup":return O$.indexOf(c.keyCode)!==-1;case"keydown":return c.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function ZA(i){return i=i.detail,typeof i=="object"&&"data"in i?i.data:null}var Fi=!1;function D$(i,c){switch(i){case"compositionend":return ZA(c);case"keypress":return c.which!==32?null:(KA=!0,YA);case"textInput":return i=c.data,i===YA&&KA?null:i;default:return null}}function L$(i,c){if(Fi)return i==="compositionend"||!rg&&XA(i,c)?(i=GA(),gu=Qf=Ya=null,Fi=!1,i):null;switch(i){case"paste":return null;case"keypress":if(!(c.ctrlKey||c.altKey||c.metaKey)||c.ctrlKey&&c.altKey){if(c.char&&1=c)return{node:p,offset:c-i};i=h}e:{for(;p;){if(p.nextSibling){p=p.nextSibling;break e}p=p.parentNode}p=void 0}p=o1(p)}}function s1(i,c){return i&&c?i===c?!0:i&&i.nodeType===3?!1:c&&c.nodeType===3?s1(i,c.parentNode):"contains"in i?i.contains(c):i.compareDocumentPosition?!!(i.compareDocumentPosition(c)&16):!1:!1}function l1(i){i=i!=null&&i.ownerDocument!=null&&i.ownerDocument.defaultView!=null?i.ownerDocument.defaultView:window;for(var c=pu(i.document);c instanceof i.HTMLIFrameElement;){try{var p=typeof c.contentWindow.location.href=="string"}catch{p=!1}if(p)i=c.contentWindow;else break;c=pu(i.document)}return c}function ig(i){var c=i&&i.nodeName&&i.nodeName.toLowerCase();return c&&(c==="input"&&(i.type==="text"||i.type==="search"||i.type==="tel"||i.type==="url"||i.type==="password")||c==="textarea"||i.contentEditable==="true")}function G$(i,c){var p=l1(c);c=i.focusedElem;var h=i.selectionRange;if(p!==c&&c&&c.ownerDocument&&s1(c.ownerDocument.documentElement,c)){if(h!==null&&ig(c)){if(i=h.start,p=h.end,p===void 0&&(p=i),"selectionStart"in c)c.selectionStart=i,c.selectionEnd=Math.min(p,c.value.length);else if(p=(i=c.ownerDocument||document)&&i.defaultView||window,p.getSelection){p=p.getSelection();var S=c.textContent.length,A=Math.min(h.start,S);h=h.end===void 0?A:Math.min(h.end,S),!p.extend&&A>h&&(S=h,h=A,A=S),S=i1(c,A);var z=i1(c,h);S&&z&&(p.rangeCount!==1||p.anchorNode!==S.node||p.anchorOffset!==S.offset||p.focusNode!==z.node||p.focusOffset!==z.offset)&&(i=i.createRange(),i.setStart(S.node,S.offset),p.removeAllRanges(),A>h?(p.addRange(i),p.extend(z.node,z.offset)):(i.setEnd(z.node,z.offset),p.addRange(i)))}}for(i=[],p=c;p=p.parentNode;)p.nodeType===1&&i.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof c.focus=="function"&&c.focus(),c=0;c=document.documentMode,zi=null,sg=null,gl=null,lg=!1;function c1(i,c,p){var h=p.window===p?p.document:p.nodeType===9?p:p.ownerDocument;lg||zi==null||zi!==pu(h)||(h=zi,"selectionStart"in h&&ig(h)?h={start:h.selectionStart,end:h.selectionEnd}:(h=(h.ownerDocument&&h.ownerDocument.defaultView||window).getSelection(),h={anchorNode:h.anchorNode,anchorOffset:h.anchorOffset,focusNode:h.focusNode,focusOffset:h.focusOffset}),gl&&fl(gl,h)||(gl=h,h=td(sg,"onSelect"),0>=z,S-=z,ba=1<<32-Et(c)+S|p<Qe?(ln=Ye,Ye=null):ln=Ye.sibling;var kt=pe(le,Ye,ue[Qe],Ae);if(kt===null){Ye===null&&(Ye=ln);break}i&&Ye&&kt.alternate===null&&c(le,Ye),te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt,Ye=ln}if(Qe===ue.length)return p(le,Ye),xt&&Ho(le,Qe),Ge;if(Ye===null){for(;QeQe?(ln=Ye,Ye=null):ln=Ye.sibling;var ho=pe(le,Ye,kt.value,Ae);if(ho===null){Ye===null&&(Ye=ln);break}i&&Ye&&ho.alternate===null&&c(le,Ye),te=A(ho,te,Qe),ut===null?Ge=ho:ut.sibling=ho,ut=ho,Ye=ln}if(kt.done)return p(le,Ye),xt&&Ho(le,Qe),Ge;if(Ye===null){for(;!kt.done;Qe++,kt=ue.next())kt=Ce(le,kt.value,Ae),kt!==null&&(te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt);return xt&&Ho(le,Qe),Ge}for(Ye=h(Ye);!kt.done;Qe++,kt=ue.next())kt=me(Ye,le,Qe,kt.value,Ae),kt!==null&&(i&&kt.alternate!==null&&Ye.delete(kt.key===null?Qe:kt.key),te=A(kt,te,Qe),ut===null?Ge=kt:ut.sibling=kt,ut=kt);return i&&Ye.forEach(function(iq){return c(le,iq)}),xt&&Ho(le,Qe),Ge}function Vt(le,te,ue,Ae){if(typeof ue=="object"&&ue!==null&&ue.type===u&&ue.key===null&&(ue=ue.props.children),typeof ue=="object"&&ue!==null){switch(ue.$$typeof){case s:e:{for(var Ge=ue.key;te!==null;){if(te.key===Ge){if(Ge=ue.type,Ge===u){if(te.tag===7){p(le,te.sibling),Ae=S(te,ue.props.children),Ae.return=le,le=Ae;break e}}else if(te.elementType===Ge||typeof Ge=="object"&&Ge!==null&&Ge.$$typeof===k&&A1(Ge)===te.type){p(le,te.sibling),Ae=S(te,ue.props),wl(Ae,ue),Ae.return=le,le=Ae;break e}p(le,te);break}else c(le,te);te=te.sibling}ue.type===u?(Ae=ei(ue.props.children,le.mode,Ae,ue.key),Ae.return=le,le=Ae):(Ae=qu(ue.type,ue.key,ue.props,null,le.mode,Ae),wl(Ae,ue),Ae.return=le,le=Ae)}return z(le);case l:e:{for(Ge=ue.key;te!==null;){if(te.key===Ge)if(te.tag===4&&te.stateNode.containerInfo===ue.containerInfo&&te.stateNode.implementation===ue.implementation){p(le,te.sibling),Ae=S(te,ue.children||[]),Ae.return=le,le=Ae;break e}else{p(le,te);break}else c(le,te);te=te.sibling}Ae=uh(ue,le.mode,Ae),Ae.return=le,le=Ae}return z(le);case k:return Ge=ue._init,ue=Ge(ue._payload),Vt(le,te,ue,Ae)}if(P(ue))return qe(le,te,ue,Ae);if(C(ue)){if(Ge=C(ue),typeof Ge!="function")throw Error(r(150));return ue=Ge.call(ue),rt(le,te,ue,Ae)}if(typeof ue.then=="function")return Vt(le,te,Au(ue),Ae);if(ue.$$typeof===b)return Vt(le,te,Gu(le,ue),Ae);Ru(le,ue)}return typeof ue=="string"&&ue!==""||typeof ue=="number"||typeof ue=="bigint"?(ue=""+ue,te!==null&&te.tag===6?(p(le,te.sibling),Ae=S(te,ue),Ae.return=le,le=Ae):(p(le,te),Ae=ch(ue,le.mode,Ae),Ae.return=le,le=Ae),z(le)):p(le,te)}return function(le,te,ue,Ae){try{Sl=0;var Ge=Vt(le,te,ue,Ae);return $i=null,Ge}catch(Ye){if(Ye===yl)throw Ye;var ut=br(29,Ye,null,le.mode);return ut.lanes=Ae,ut.return=le,ut}finally{}}}var qo=R1(!0),C1=R1(!1),qi=ce(null),Cu=ce(0);function _1(i,c){i=_a,ie(Cu,i),ie(qi,c),_a=i|c.baseLanes}function mg(){ie(Cu,_a),ie(qi,qi.current)}function bg(){_a=Cu.current,Re(qi),Re(Cu)}var gr=ce(null),Yr=null;function Xa(i){var c=i.alternate;ie(en,en.current&1),ie(gr,i),Yr===null&&(c===null||qi.current!==null||c.memoizedState!==null)&&(Yr=i)}function N1(i){if(i.tag===22){if(ie(en,en.current),ie(gr,i),Yr===null){var c=i.alternate;c!==null&&c.memoizedState!==null&&(Yr=i)}}else Za()}function Za(){ie(en,en.current),ie(gr,gr.current)}function va(i){Re(gr),Yr===i&&(Yr=null),Re(en)}var en=ce(0);function _u(i){for(var c=i;c!==null;){if(c.tag===13){var p=c.memoizedState;if(p!==null&&(p=p.dehydrated,p===null||p.data==="$?"||p.data==="$!"))return c}else if(c.tag===19&&c.memoizedProps.revealOrder!==void 0){if(c.flags&128)return c}else if(c.child!==null){c.child.return=c,c=c.child;continue}if(c===i)break;for(;c.sibling===null;){if(c.return===null||c.return===i)return null;c=c.return}c.sibling.return=c.return,c=c.sibling}return null}var W$=typeof AbortController<"u"?AbortController:function(){var i=[],c=this.signal={aborted:!1,addEventListener:function(p,h){i.push(h)}};this.abort=function(){c.aborted=!0,i.forEach(function(p){return p()})}},Y$=e.unstable_scheduleCallback,K$=e.unstable_NormalPriority,tn={$$typeof:b,Consumer:null,Provider:null,_currentValue:null,_currentValue2:null,_threadCount:0};function yg(){return{controller:new W$,data:new Map,refCount:0}}function El(i){i.refCount--,i.refCount===0&&Y$(K$,function(){i.controller.abort()})}var xl=null,vg=0,Vi=0,Wi=null;function X$(i,c){if(xl===null){var p=xl=[];vg=0,Vi=Th(),Wi={status:"pending",value:void 0,then:function(h){p.push(h)}}}return vg++,c.then(O1,O1),c}function O1(){if(--vg===0&&xl!==null){Wi!==null&&(Wi.status="fulfilled");var i=xl;xl=null,Vi=0,Wi=null;for(var c=0;cA?A:8;var z=D.T,q={};D.T=q,Pg(i,!1,c,p);try{var X=S(),re=D.S;if(re!==null&&re(q,X),X!==null&&typeof X=="object"&&typeof X.then=="function"){var ve=Z$(X,h);Al(i,c,ve,Zn(i))}else Al(i,c,h,Zn(i))}catch(Ce){Al(i,c,{then:function(){},status:"rejected",reason:Ce},Zn())}finally{Z.p=A,D.T=z}}function n6(){}function Lg(i,c,p,h){if(i.tag!==5)throw Error(r(476));var S=lR(i).queue;sR(i,S,c,Q,p===null?n6:function(){return cR(i),p(h)})}function lR(i){var c=i.memoizedState;if(c!==null)return c;c={memoizedState:Q,baseState:Q,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sa,lastRenderedState:Q},next:null};var p={};return c.next={memoizedState:p,baseState:p,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Sa,lastRenderedState:p},next:null},i.memoizedState=c,i=i.alternate,i!==null&&(i.memoizedState=c),c}function cR(i){var c=lR(i).next.queue;Al(i,c,{},Zn())}function Mg(){return En(Vl)}function uR(){return Xt().memoizedState}function dR(){return Xt().memoizedState}function r6(i){for(var c=i.return;c!==null;){switch(c.tag){case 24:case 3:var p=Zn();i=no(p);var h=ro(c,i,p);h!==null&&(On(h,c,p),_l(h,c,p)),c={cache:yg()},i.payload=c;return}c=c.return}}function a6(i,c,p){var h=Zn();p={lane:h,revertLane:0,action:p,hasEagerState:!1,eagerState:null,next:null},zu(i)?fR(c,p):(p=dg(i,c,p,h),p!==null&&(On(p,i,h),gR(p,c,h)))}function pR(i,c,p){var h=Zn();Al(i,c,p,h)}function Al(i,c,p,h){var S={lane:h,revertLane:0,action:p,hasEagerState:!1,eagerState:null,next:null};if(zu(i))fR(c,S);else{var A=i.alternate;if(i.lanes===0&&(A===null||A.lanes===0)&&(A=c.lastRenderedReducer,A!==null))try{var z=c.lastRenderedState,q=A(z,p);if(S.hasEagerState=!0,S.eagerState=q,Wn(q,z))return wu(i,c,S,0),Lt===null&&Su(),!1}catch{}finally{}if(p=dg(i,c,S,h),p!==null)return On(p,i,h),gR(p,c,h),!0}return!1}function Pg(i,c,p,h){if(h={lane:2,revertLane:Th(),action:h,hasEagerState:!1,eagerState:null,next:null},zu(i)){if(c)throw Error(r(479))}else c=dg(i,p,h,2),c!==null&&On(c,i,2)}function zu(i){var c=i.alternate;return i===ct||c!==null&&c===ct}function fR(i,c){Yi=Ou=!0;var p=i.pending;p===null?c.next=c:(c.next=p.next,p.next=c),i.pending=c}function gR(i,c,p){if(p&4194176){var h=c.lanes;h&=i.pendingLanes,p|=h,c.lanes=p,_r(i,p)}}var Kr={readContext:En,use:Lu,useCallback:Wt,useContext:Wt,useEffect:Wt,useImperativeHandle:Wt,useLayoutEffect:Wt,useInsertionEffect:Wt,useMemo:Wt,useReducer:Wt,useRef:Wt,useState:Wt,useDebugValue:Wt,useDeferredValue:Wt,useTransition:Wt,useSyncExternalStore:Wt,useId:Wt};Kr.useCacheRefresh=Wt,Kr.useMemoCache=Wt,Kr.useHostTransitionStatus=Wt,Kr.useFormState=Wt,Kr.useActionState=Wt,Kr.useOptimistic=Wt;var Yo={readContext:En,use:Lu,useCallback:function(i,c){return zn().memoizedState=[i,c===void 0?null:c],i},useContext:En,useEffect:J1,useImperativeHandle:function(i,c,p){p=p!=null?p.concat([i]):null,Pu(4194308,4,nR.bind(null,c,i),p)},useLayoutEffect:function(i,c){return Pu(4194308,4,i,c)},useInsertionEffect:function(i,c){Pu(4,2,i,c)},useMemo:function(i,c){var p=zn();c=c===void 0?null:c;var h=i();if(Wo){st(!0);try{i()}finally{st(!1)}}return p.memoizedState=[h,c],h},useReducer:function(i,c,p){var h=zn();if(p!==void 0){var S=p(c);if(Wo){st(!0);try{p(c)}finally{st(!1)}}}else S=c;return h.memoizedState=h.baseState=S,i={pending:null,lanes:0,dispatch:null,lastRenderedReducer:i,lastRenderedState:S},h.queue=i,i=i.dispatch=a6.bind(null,ct,i),[h.memoizedState,i]},useRef:function(i){var c=zn();return i={current:i},c.memoizedState=i},useState:function(i){i=_g(i);var c=i.queue,p=pR.bind(null,ct,c);return c.dispatch=p,[i.memoizedState,p]},useDebugValue:Ig,useDeferredValue:function(i,c){var p=zn();return Dg(p,i,c)},useTransition:function(){var i=_g(!1);return i=sR.bind(null,ct,i.queue,!0,!1),zn().memoizedState=i,[!1,i]},useSyncExternalStore:function(i,c,p){var h=ct,S=zn();if(xt){if(p===void 0)throw Error(r(407));p=p()}else{if(p=c(),Lt===null)throw Error(r(349));vt&60||F1(h,c,p)}S.memoizedState=p;var A={value:p,getSnapshot:c};return S.queue=A,J1(B1.bind(null,h,A,i),[i]),h.flags|=2048,Xi(9,z1.bind(null,h,A,p,c),{destroy:void 0},null),p},useId:function(){var i=zn(),c=Lt.identifierPrefix;if(xt){var p=ya,h=ba;p=(h&~(1<<32-Et(h)-1)).toString(32)+p,c=":"+c+"R"+p,p=Iu++,0 title"))),bn(A,h,p),A[wn]=i,an(A),h=A;break e;case"link":var z=UC("link","href",S).get(h+(p.href||""));if(z){for(var q=0;q<\/script>",i=i.removeChild(i.firstChild);break;case"select":i=typeof h.is=="string"?S.createElement("select",{is:h.is}):S.createElement("select"),h.multiple?i.multiple=!0:h.size&&(i.size=h.size);break;default:i=typeof h.is=="string"?S.createElement(p,{is:h.is}):S.createElement(p)}}i[wn]=c,i[Pn]=h;e:for(S=c.child;S!==null;){if(S.tag===5||S.tag===6)i.appendChild(S.stateNode);else if(S.tag!==4&&S.tag!==27&&S.child!==null){S.child.return=S,S=S.child;continue}if(S===c)break e;for(;S.sibling===null;){if(S.return===null||S.return===c)break e;S=S.return}S.sibling.return=S.return,S=S.sibling}c.stateNode=i;e:switch(bn(i,p,h),p){case"button":case"input":case"select":case"textarea":i=!!h.autoFocus;break e;case"img":i=!0;break e;default:i=!1}i&&Ra(c)}}return Bt(c),c.flags&=-16777217,null;case 6:if(i&&c.stateNode!=null)i.memoizedProps!==h&&Ra(c);else{if(typeof h!="string"&&c.stateNode===null)throw Error(r(166));if(i=xe.current,hl(c)){if(i=c.stateNode,p=c.memoizedProps,h=null,S=Nn,S!==null)switch(S.tag){case 27:case 5:h=S.memoizedProps}i[wn]=c,i=!!(i.nodeValue===p||h!==null&&h.suppressHydrationWarning===!0||_C(i.nodeValue,p)),i||$o(c)}else i=rd(i).createTextNode(h),i[wn]=c,c.stateNode=i}return Bt(c),null;case 13:if(h=c.memoizedState,i===null||i.memoizedState!==null&&i.memoizedState.dehydrated!==null){if(S=hl(c),h!==null&&h.dehydrated!==null){if(i===null){if(!S)throw Error(r(318));if(S=c.memoizedState,S=S!==null?S.dehydrated:null,!S)throw Error(r(317));S[wn]=c}else ml(),!(c.flags&128)&&(c.memoizedState=null),c.flags|=4;Bt(c),S=!1}else Or!==null&&(yh(Or),Or=null),S=!0;if(!S)return c.flags&256?(va(c),c):(va(c),null)}if(va(c),c.flags&128)return c.lanes=p,c;if(p=h!==null,i=i!==null&&i.memoizedState!==null,p){h=c.child,S=null,h.alternate!==null&&h.alternate.memoizedState!==null&&h.alternate.memoizedState.cachePool!==null&&(S=h.alternate.memoizedState.cachePool.pool);var A=null;h.memoizedState!==null&&h.memoizedState.cachePool!==null&&(A=h.memoizedState.cachePool.pool),A!==S&&(h.flags|=2048)}return p!==i&&p&&(c.child.flags|=8192),Vu(c,c.updateQueue),Bt(c),null;case 4:return J(),i===null&&_h(c.stateNode.containerInfo),Bt(c),null;case 10:return xa(c.type),Bt(c),null;case 19:if(Re(en),S=c.memoizedState,S===null)return Bt(c),null;if(h=(c.flags&128)!==0,A=S.rendering,A===null)if(h)Pl(S,!1);else{if(qt!==0||i!==null&&i.flags&128)for(i=c.child;i!==null;){if(A=_u(i),A!==null){for(c.flags|=128,Pl(S,!1),i=A.updateQueue,c.updateQueue=i,Vu(c,i),c.subtreeFlags=0,i=p,p=c.child;p!==null;)rC(p,i),p=p.sibling;return ie(en,en.current&1|2),c.child}i=i.sibling}S.tail!==null&&ye()>Wu&&(c.flags|=128,h=!0,Pl(S,!1),c.lanes=4194304)}else{if(!h)if(i=_u(A),i!==null){if(c.flags|=128,h=!0,i=i.updateQueue,c.updateQueue=i,Vu(c,i),Pl(S,!0),S.tail===null&&S.tailMode==="hidden"&&!A.alternate&&!xt)return Bt(c),null}else 2*ye()-S.renderingStartTime>Wu&&p!==536870912&&(c.flags|=128,h=!0,Pl(S,!1),c.lanes=4194304);S.isBackwards?(A.sibling=c.child,c.child=A):(i=S.last,i!==null?i.sibling=A:c.child=A,S.last=A)}return S.tail!==null?(c=S.tail,S.rendering=c,S.tail=c.sibling,S.renderingStartTime=ye(),c.sibling=null,i=en.current,ie(en,h?i&1|2:i&1),c):(Bt(c),null);case 22:case 23:return va(c),bg(),h=c.memoizedState!==null,i!==null?i.memoizedState!==null!==h&&(c.flags|=8192):h&&(c.flags|=8192),h?p&536870912&&!(c.flags&128)&&(Bt(c),c.subtreeFlags&6&&(c.flags|=8192)):Bt(c),p=c.updateQueue,p!==null&&Vu(c,p.retryQueue),p=null,i!==null&&i.memoizedState!==null&&i.memoizedState.cachePool!==null&&(p=i.memoizedState.cachePool.pool),h=null,c.memoizedState!==null&&c.memoizedState.cachePool!==null&&(h=c.memoizedState.cachePool.pool),h!==p&&(c.flags|=2048),i!==null&&Re(Vo),null;case 24:return p=null,i!==null&&(p=i.memoizedState.cache),c.memoizedState.cache!==p&&(c.flags|=2048),xa(tn),Bt(c),null;case 25:return null}throw Error(r(156,c.tag))}function d6(i,c){switch(fg(c),c.tag){case 1:return i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 3:return xa(tn),J(),i=c.flags,i&65536&&!(i&128)?(c.flags=i&-65537|128,c):null;case 26:case 27:case 5:return ke(c),null;case 13:if(va(c),i=c.memoizedState,i!==null&&i.dehydrated!==null){if(c.alternate===null)throw Error(r(340));ml()}return i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 19:return Re(en),null;case 4:return J(),null;case 10:return xa(c.type),null;case 22:case 23:return va(c),bg(),i!==null&&Re(Vo),i=c.flags,i&65536?(c.flags=i&-65537|128,c):null;case 24:return xa(tn),null;case 25:return null;default:return null}}function iC(i,c){switch(fg(c),c.tag){case 3:xa(tn),J();break;case 26:case 27:case 5:ke(c);break;case 4:J();break;case 13:va(c);break;case 19:Re(en);break;case 10:xa(c.type);break;case 22:case 23:va(c),bg(),i!==null&&Re(Vo);break;case 24:xa(tn)}}var p6={getCacheForType:function(i){var c=En(tn),p=c.data.get(i);return p===void 0&&(p=i(),c.data.set(i,p)),p}},f6=typeof WeakMap=="function"?WeakMap:Map,jt=0,Lt=null,pt=null,vt=0,Mt=0,Xn=null,Ca=!1,es=!1,dh=!1,_a=0,qt=0,lo=0,ti=0,ph=0,yr=0,ts=0,Fl=null,Xr=null,fh=!1,gh=0,Wu=1/0,Yu=null,co=null,Ku=!1,ni=null,zl=0,hh=0,mh=null,Bl=0,bh=null;function Zn(){if(jt&2&&vt!==0)return vt&-vt;if(D.T!==null){var i=Vi;return i!==0?i:Th()}return RA()}function sC(){yr===0&&(yr=!(vt&536870912)||xt?Nt():536870912);var i=gr.current;return i!==null&&(i.flags|=32),yr}function On(i,c,p){(i===Lt&&Mt===2||i.cancelPendingCommit!==null)&&(ns(i,0),Na(i,vt,yr,!1)),Ln(i,p),(!(jt&2)||i!==Lt)&&(i===Lt&&(!(jt&2)&&(ti|=p),qt===4&&Na(i,vt,yr,!1)),Zr(i))}function lC(i,c,p){if(jt&6)throw Error(r(327));var h=!p&&(c&60)===0&&(c&i.expiredLanes)===0||Xe(i,c),S=h?m6(i,c):wh(i,c,!0),A=h;do{if(S===0){es&&!h&&Na(i,c,0,!1);break}else if(S===6)Na(i,c,0,!Ca);else{if(p=i.current.alternate,A&&!g6(p)){S=wh(i,c,!1),A=!1;continue}if(S===2){if(A=c,i.errorRecoveryDisabledLanes&A)var z=0;else z=i.pendingLanes&-536870913,z=z!==0?z:z&536870912?536870912:0;if(z!==0){c=z;e:{var q=i;S=Fl;var X=q.current.memoizedState.isDehydrated;if(X&&(ns(q,z).flags|=256),z=wh(q,z,!1),z!==2){if(dh&&!X){q.errorRecoveryDisabledLanes|=A,ti|=A,S=4;break e}A=Xr,Xr=S,A!==null&&yh(A)}S=z}if(A=!1,S!==2)continue}}if(S===1){ns(i,0),Na(i,c,0,!0);break}e:{switch(h=i,S){case 0:case 1:throw Error(r(345));case 4:if((c&4194176)===c){Na(h,c,yr,!Ca);break e}break;case 2:Xr=null;break;case 3:case 5:break;default:throw Error(r(329))}if(h.finishedWork=p,h.finishedLanes=c,(c&62914560)===c&&(A=gh+300-ye(),10p?32:p,D.T=null,ni===null)var A=!1;else{p=mh,mh=null;var z=ni,q=zl;if(ni=null,zl=0,jt&6)throw Error(r(331));var X=jt;if(jt|=4,tC(z.current),QR(z,z.current,q,p),jt=X,jl(0,!1),et&&typeof et.onPostCommitFiberRoot=="function")try{et.onPostCommitFiberRoot(bt,z)}catch{}A=!0}return A}finally{Z.p=S,D.T=h,bC(i,c)}}return!1}function yC(i,c,p){c=dr(p,c),c=Bg(i.stateNode,c,2),i=ro(i,c,2),i!==null&&(Ln(i,2),Zr(i))}function Ot(i,c,p){if(i.tag===3)yC(i,i,p);else for(;c!==null;){if(c.tag===3){yC(c,i,p);break}else if(c.tag===1){var h=c.stateNode;if(typeof c.type.getDerivedStateFromError=="function"||typeof h.componentDidCatch=="function"&&(co===null||!co.has(h))){i=dr(p,i),p=wR(2),h=ro(c,p,2),h!==null&&(ER(p,h,c,i),Ln(h,2),Zr(h));break}}c=c.return}}function Eh(i,c,p){var h=i.pingCache;if(h===null){h=i.pingCache=new f6;var S=new Set;h.set(c,S)}else S=h.get(c),S===void 0&&(S=new Set,h.set(c,S));S.has(p)||(dh=!0,S.add(p),i=v6.bind(null,i,c,p),c.then(i,i))}function v6(i,c,p){var h=i.pingCache;h!==null&&h.delete(c),i.pingedLanes|=i.suspendedLanes&p,i.warmLanes&=~p,Lt===i&&(vt&p)===p&&(qt===4||qt===3&&(vt&62914560)===vt&&300>ye()-gh?!(jt&2)&&ns(i,0):ph|=p,ts===vt&&(ts=0)),Zr(i)}function vC(i,c){c===0&&(c=Dn()),i=Ka(i,c),i!==null&&(Ln(i,c),Zr(i))}function S6(i){var c=i.memoizedState,p=0;c!==null&&(p=c.retryLane),vC(i,p)}function w6(i,c){var p=0;switch(i.tag){case 13:var h=i.stateNode,S=i.memoizedState;S!==null&&(p=S.retryLane);break;case 19:h=i.stateNode;break;case 22:h=i.stateNode._retryCache;break;default:throw Error(r(314))}h!==null&&h.delete(c),vC(i,p)}function E6(i,c){return we(i,c)}var Qu=null,os=null,xh=!1,Ju=!1,kh=!1,ri=0;function Zr(i){i!==os&&i.next===null&&(os===null?Qu=os=i:os=os.next=i),Ju=!0,xh||(xh=!0,k6(x6))}function jl(i,c){if(!kh&&Ju){kh=!0;do for(var p=!1,h=Qu;h!==null;){if(i!==0){var S=h.pendingLanes;if(S===0)var A=0;else{var z=h.suspendedLanes,q=h.pingedLanes;A=(1<<31-Et(42|i)+1)-1,A&=S&~(z&~q),A=A&201326677?A&201326677|1:A?A|2:0}A!==0&&(p=!0,EC(h,A))}else A=vt,A=fa(h,h===Lt?A:0),!(A&3)||Xe(h,A)||(p=!0,EC(h,A));h=h.next}while(p);kh=!1}}function x6(){Ju=xh=!1;var i=0;ri!==0&&(I6()&&(i=ri),ri=0);for(var c=ye(),p=null,h=Qu;h!==null;){var S=h.next,A=SC(h,c);A===0?(h.next=null,p===null?Qu=S:p.next=S,S===null&&(os=p)):(p=h,(i!==0||A&3)&&(Ju=!0)),h=S}jl(i)}function SC(i,c){for(var p=i.suspendedLanes,h=i.pingedLanes,S=i.expirationTimes,A=i.pendingLanes&-62914561;0"u"?null:document;function FC(i,c,p){var h=ss;if(h&&typeof c=="string"&&c){var S=cr(c);S='link[rel="'+i+'"][href="'+S+'"]',typeof p=="string"&&(S+='[crossorigin="'+p+'"]'),PC.has(S)||(PC.add(S),i={rel:i,crossOrigin:p,href:c},h.querySelector(S)===null&&(c=h.createElement("link"),bn(c,"link",i),an(c),h.head.appendChild(c)))}}function j6(i){Oa.D(i),FC("dns-prefetch",i,null)}function U6(i,c){Oa.C(i,c),FC("preconnect",i,c)}function G6(i,c,p){Oa.L(i,c,p);var h=ss;if(h&&i&&c){var S='link[rel="preload"][as="'+cr(c)+'"]';c==="image"&&p&&p.imageSrcSet?(S+='[imagesrcset="'+cr(p.imageSrcSet)+'"]',typeof p.imageSizes=="string"&&(S+='[imagesizes="'+cr(p.imageSizes)+'"]')):S+='[href="'+cr(i)+'"]';var A=S;switch(c){case"style":A=ls(i);break;case"script":A=cs(i)}vr.has(A)||(i=I({rel:"preload",href:c==="image"&&p&&p.imageSrcSet?void 0:i,as:c},p),vr.set(A,i),h.querySelector(S)!==null||c==="style"&&h.querySelector(Hl(A))||c==="script"&&h.querySelector($l(A))||(c=h.createElement("link"),bn(c,"link",i),an(c),h.head.appendChild(c)))}}function H6(i,c){Oa.m(i,c);var p=ss;if(p&&i){var h=c&&typeof c.as=="string"?c.as:"script",S='link[rel="modulepreload"][as="'+cr(h)+'"][href="'+cr(i)+'"]',A=S;switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":A=cs(i)}if(!vr.has(A)&&(i=I({rel:"modulepreload",href:i},c),vr.set(A,i),p.querySelector(S)===null)){switch(h){case"audioworklet":case"paintworklet":case"serviceworker":case"sharedworker":case"worker":case"script":if(p.querySelector($l(A)))return}h=p.createElement("link"),bn(h,"link",i),an(h),p.head.appendChild(h)}}}function $6(i,c,p){Oa.S(i,c,p);var h=ss;if(h&&i){var S=Oi(h).hoistableStyles,A=ls(i);c=c||"default";var z=S.get(A);if(!z){var q={loading:0,preload:null};if(z=h.querySelector(Hl(A)))q.loading=5;else{i=I({rel:"stylesheet",href:i,"data-precedence":c},p),(p=vr.get(A))&&zh(i,p);var X=z=h.createElement("link");an(X),bn(X,"link",i),X._p=new Promise(function(re,ve){X.onload=re,X.onerror=ve}),X.addEventListener("load",function(){q.loading|=1}),X.addEventListener("error",function(){q.loading|=2}),q.loading|=4,od(z,c,h)}z={type:"stylesheet",instance:z,count:1,state:q},S.set(A,z)}}}function q6(i,c){Oa.X(i,c);var p=ss;if(p&&i){var h=Oi(p).hoistableScripts,S=cs(i),A=h.get(S);A||(A=p.querySelector($l(S)),A||(i=I({src:i,async:!0},c),(c=vr.get(S))&&Bh(i,c),A=p.createElement("script"),an(A),bn(A,"link",i),p.head.appendChild(A)),A={type:"script",instance:A,count:1,state:null},h.set(S,A))}}function V6(i,c){Oa.M(i,c);var p=ss;if(p&&i){var h=Oi(p).hoistableScripts,S=cs(i),A=h.get(S);A||(A=p.querySelector($l(S)),A||(i=I({src:i,async:!0,type:"module"},c),(c=vr.get(S))&&Bh(i,c),A=p.createElement("script"),an(A),bn(A,"link",i),p.head.appendChild(A)),A={type:"script",instance:A,count:1,state:null},h.set(S,A))}}function zC(i,c,p,h){var S=(S=xe.current)?ad(S):null;if(!S)throw Error(r(446));switch(i){case"meta":case"title":return null;case"style":return typeof p.precedence=="string"&&typeof p.href=="string"?(c=ls(p.href),p=Oi(S).hoistableStyles,h=p.get(c),h||(h={type:"style",instance:null,count:0,state:null},p.set(c,h)),h):{type:"void",instance:null,count:0,state:null};case"link":if(p.rel==="stylesheet"&&typeof p.href=="string"&&typeof p.precedence=="string"){i=ls(p.href);var A=Oi(S).hoistableStyles,z=A.get(i);if(z||(S=S.ownerDocument||S,z={type:"stylesheet",instance:null,count:0,state:{loading:0,preload:null}},A.set(i,z),(A=S.querySelector(Hl(i)))&&!A._p&&(z.instance=A,z.state.loading=5),vr.has(i)||(p={rel:"preload",as:"style",href:p.href,crossOrigin:p.crossOrigin,integrity:p.integrity,media:p.media,hrefLang:p.hrefLang,referrerPolicy:p.referrerPolicy},vr.set(i,p),A||W6(S,i,p,z.state))),c&&h===null)throw Error(r(528,""));return z}if(c&&h!==null)throw Error(r(529,""));return null;case"script":return c=p.async,p=p.src,typeof p=="string"&&c&&typeof c!="function"&&typeof c!="symbol"?(c=cs(p),p=Oi(S).hoistableScripts,h=p.get(c),h||(h={type:"script",instance:null,count:0,state:null},p.set(c,h)),h):{type:"void",instance:null,count:0,state:null};default:throw Error(r(444,i))}}function ls(i){return'href="'+cr(i)+'"'}function Hl(i){return'link[rel="stylesheet"]['+i+"]"}function BC(i){return I({},i,{"data-precedence":i.precedence,precedence:null})}function W6(i,c,p,h){i.querySelector('link[rel="preload"][as="style"]['+c+"]")?h.loading=1:(c=i.createElement("link"),h.preload=c,c.addEventListener("load",function(){return h.loading|=1}),c.addEventListener("error",function(){return h.loading|=2}),bn(c,"link",p),an(c),i.head.appendChild(c))}function cs(i){return'[src="'+cr(i)+'"]'}function $l(i){return"script[async]"+i}function jC(i,c,p){if(c.count++,c.instance===null)switch(c.type){case"style":var h=i.querySelector('style[data-href~="'+cr(p.href)+'"]');if(h)return c.instance=h,an(h),h;var S=I({},p,{"data-href":p.href,"data-precedence":p.precedence,href:null,precedence:null});return h=(i.ownerDocument||i).createElement("style"),an(h),bn(h,"style",S),od(h,p.precedence,i),c.instance=h;case"stylesheet":S=ls(p.href);var A=i.querySelector(Hl(S));if(A)return c.state.loading|=4,c.instance=A,an(A),A;h=BC(p),(S=vr.get(S))&&zh(h,S),A=(i.ownerDocument||i).createElement("link"),an(A);var z=A;return z._p=new Promise(function(q,X){z.onload=q,z.onerror=X}),bn(A,"link",h),c.state.loading|=4,od(A,p.precedence,i),c.instance=A;case"script":return A=cs(p.src),(S=i.querySelector($l(A)))?(c.instance=S,an(S),S):(h=p,(S=vr.get(A))&&(h=I({},p),Bh(h,S)),i=i.ownerDocument||i,S=i.createElement("script"),an(S),bn(S,"link",h),i.head.appendChild(S),c.instance=S);case"void":return null;default:throw Error(r(443,c.type))}else c.type==="stylesheet"&&!(c.state.loading&4)&&(h=c.instance,c.state.loading|=4,od(h,p.precedence,i));return c.instance}function od(i,c,p){for(var h=p.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'),S=h.length?h[h.length-1]:null,A=S,z=0;z title"):null)}function Y6(i,c,p){if(p===1||c.itemProp!=null)return!1;switch(i){case"meta":case"title":return!0;case"style":if(typeof c.precedence!="string"||typeof c.href!="string"||c.href==="")break;return!0;case"link":if(typeof c.rel!="string"||typeof c.href!="string"||c.href===""||c.onLoad||c.onError)break;switch(c.rel){case"stylesheet":return i=c.disabled,typeof c.precedence=="string"&&i==null;default:return!0}case"script":if(c.async&&typeof c.async!="function"&&typeof c.async!="symbol"&&!c.onLoad&&!c.onError&&c.src&&typeof c.src=="string")return!0}return!1}function HC(i){return!(i.type==="stylesheet"&&!(i.state.loading&3))}var ql=null;function K6(){}function X6(i,c,p){if(ql===null)throw Error(r(475));var h=ql;if(c.type==="stylesheet"&&(typeof p.media!="string"||matchMedia(p.media).matches!==!1)&&!(c.state.loading&4)){if(c.instance===null){var S=ls(p.href),A=i.querySelector(Hl(S));if(A){i=A._p,i!==null&&typeof i=="object"&&typeof i.then=="function"&&(h.count++,h=sd.bind(h),i.then(h,h)),c.state.loading|=4,c.instance=A,an(A);return}A=i.ownerDocument||i,p=BC(p),(S=vr.get(S))&&zh(p,S),A=A.createElement("link"),an(A);var z=A;z._p=new Promise(function(q,X){z.onload=q,z.onerror=X}),bn(A,"link",p),c.instance=A}h.stylesheets===null&&(h.stylesheets=new Map),h.stylesheets.set(c,i),(i=c.state.preload)&&!(c.state.loading&3)&&(h.count++,c=sd.bind(h),i.addEventListener("load",c),i.addEventListener("error",c))}}function Z6(){if(ql===null)throw Error(r(475));var i=ql;return i.stylesheets&&i.count===0&&jh(i,i.stylesheets),0"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(t){console.error(t)}}return e(),Kh.exports=yq(),Kh.exports}var Sq=vq(),Jl={},d_;function wq(){if(d_)return Jl;d_=1,Object.defineProperty(Jl,"__esModule",{value:!0}),Jl.parse=s,Jl.serialize=d;const e=/^[\u0021-\u003A\u003C\u003E-\u007E]+$/,t=/^[\u0021-\u003A\u003C-\u007E]*$/,n=/^([.]?[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)([.][a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)*$/i,r=/^[\u0020-\u003A\u003D-\u007E]*$/,a=Object.prototype.toString,o=(()=>{const m=function(){};return m.prototype=Object.create(null),m})();function s(m,b){const y=new o,v=m.length;if(v<2)return y;const x=(b==null?void 0:b.decode)||f;let T=0;do{const k=m.indexOf("=",T);if(k===-1)break;const R=m.indexOf(";",T),O=R===-1?v:R;if(k>O){T=m.lastIndexOf(";",k-1)+1;continue}const N=l(m,T,k),C=u(m,k,N),_=m.slice(N,C);if(y[_]===void 0){let M=l(m,k+1,O),D=u(m,O,M);const I=x(m.slice(M,D));y[_]=I}T=O+1}while(Ty;){const v=m.charCodeAt(--b);if(v!==32&&v!==9)return b+1}return y}function d(m,b,y){const v=(y==null?void 0:y.encode)||encodeURIComponent;if(!e.test(m))throw new TypeError(`argument name is invalid: ${m}`);const x=v(b);if(!t.test(x))throw new TypeError(`argument val is invalid: ${b}`);let T=m+"="+x;if(!y)return T;if(y.maxAge!==void 0){if(!Number.isInteger(y.maxAge))throw new TypeError(`option maxAge is invalid: ${y.maxAge}`);T+="; Max-Age="+y.maxAge}if(y.domain){if(!n.test(y.domain))throw new TypeError(`option domain is invalid: ${y.domain}`);T+="; Domain="+y.domain}if(y.path){if(!r.test(y.path))throw new TypeError(`option path is invalid: ${y.path}`);T+="; Path="+y.path}if(y.expires){if(!g(y.expires)||!Number.isFinite(y.expires.valueOf()))throw new TypeError(`option expires is invalid: ${y.expires}`);T+="; Expires="+y.expires.toUTCString()}if(y.httpOnly&&(T+="; HttpOnly"),y.secure&&(T+="; Secure"),y.partitioned&&(T+="; Partitioned"),y.priority)switch(typeof y.priority=="string"?y.priority.toLowerCase():void 0){case"low":T+="; Priority=Low";break;case"medium":T+="; Priority=Medium";break;case"high":T+="; Priority=High";break;default:throw new TypeError(`option priority is invalid: ${y.priority}`)}if(y.sameSite)switch(typeof y.sameSite=="string"?y.sameSite.toLowerCase():y.sameSite){case!0:case"strict":T+="; SameSite=Strict";break;case"lax":T+="; SameSite=Lax";break;case"none":T+="; SameSite=None";break;default:throw new TypeError(`option sameSite is invalid: ${y.sameSite}`)}return T}function f(m){if(m.indexOf("%")===-1)return m;try{return decodeURIComponent(m)}catch{return m}}function g(m){return a.call(m)==="[object Date]"}return Jl}wq();/** * react-router v7.3.0 * * Copyright (c) Remix Software Inc. @@ -55,19 +55,19 @@ Error generating stack: `+f.message+` * LICENSE.md file in the root directory of this source tree. * * @license MIT - */var f_="popstate";function wq(e={}){function t(a,o){let{pathname:s="/",search:l="",hash:u=""}=ki(a.location.hash.substring(1));return!s.startsWith("/")&&!s.startsWith(".")&&(s="/"+s),c0("",{pathname:s,search:l,hash:u},o.state&&o.state.usr||null,o.state&&o.state.key||"default")}function n(a,o){let s=a.document.querySelector("base"),l="";if(s&&s.getAttribute("href")){let u=a.location.href,d=u.indexOf("#");l=d===-1?u:u.slice(0,d)}return l+"#"+(typeof o=="string"?o:Sc(o))}function r(a,o){jr(a.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(o)})`)}return kq(t,n,r,e)}function Gt(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function jr(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function xq(){return Math.random().toString(36).substring(2,10)}function p_(e,t){return{usr:e.state,key:e.key,idx:t}}function c0(e,t,n=null,r){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?ki(t):t,state:n,key:t&&t.key||r||xq()}}function Sc({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function ki(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function kq(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:o=!1}=r,s=a.history,l="POP",u=null,d=p();d==null&&(d=0,s.replaceState({...s.state,idx:d},""));function p(){return(s.state||{idx:null}).idx}function g(){l="POP";let x=p(),T=x==null?null:x-d;d=x,u&&u({action:l,location:v.location,delta:T})}function m(x,T){l="PUSH";let k=c0(v.location,x,T);n&&n(k,x),d=p()+1;let R=p_(k,d),O=v.createHref(k);try{s.pushState(R,"",O)}catch(N){if(N instanceof DOMException&&N.name==="DataCloneError")throw N;a.location.assign(O)}o&&u&&u({action:l,location:v.location,delta:1})}function b(x,T){l="REPLACE";let k=c0(v.location,x,T);n&&n(k,x),d=p();let R=p_(k,d),O=v.createHref(k);s.replaceState(R,"",O),o&&u&&u({action:l,location:v.location,delta:0})}function y(x){let T=a.location.origin!=="null"?a.location.origin:a.location.href,k=typeof x=="string"?x:Sc(x);return k=k.replace(/ $/,"%20"),Gt(T,`No window.location.(origin|href) available to create URL for href: ${k}`),new URL(k,T)}let v={get action(){return l},get location(){return e(a,s)},listen(x){if(u)throw new Error("A history only accepts one active listener");return a.addEventListener(f_,g),u=x,()=>{a.removeEventListener(f_,g),u=null}},createHref(x){return t(a,x)},createURL:y,encodeLocation(x){let T=y(x);return{pathname:T.pathname,search:T.search,hash:T.hash}},push:m,replace:b,go(x){return s.go(x)}};return v}function Kz(e,t,n="/"){return Tq(e,t,n,!1)}function Tq(e,t,n,r){let a=typeof t=="string"?ki(t):t,o=Ba(a.pathname||"/",n);if(o==null)return null;let s=Xz(e);Aq(s);let l=null;for(let u=0;l==null&&u{let u={relativePath:l===void 0?o.path||"":l,caseSensitive:o.caseSensitive===!0,childrenIndex:s,route:o};u.relativePath.startsWith("/")&&(Gt(u.relativePath.startsWith(r),`Absolute route path "${u.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),u.relativePath=u.relativePath.slice(r.length));let d=Fa([r,u.relativePath]),p=n.concat(u);o.children&&o.children.length>0&&(Gt(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${d}".`),Xz(o.children,t,p,d)),!(o.path==null&&!o.index)&&t.push({path:d,score:Dq(d,o.index),routesMeta:p})};return e.forEach((o,s)=>{var l;if(o.path===""||!((l=o.path)!=null&&l.includes("?")))a(o,s);else for(let u of Zz(o.path))a(o,s,u)}),t}function Zz(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,a=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return a?[o,""]:[o];let s=Zz(r.join("/")),l=[];return l.push(...s.map(u=>u===""?o:[o,u].join("/"))),a&&l.push(...s),l.map(u=>e.startsWith("/")&&u===""?"/":u)}function Aq(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:Lq(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var Rq=/^:[\w-]+$/,Cq=3,_q=2,Nq=1,Oq=10,Iq=-2,g_=e=>e==="*";function Dq(e,t){let n=e.split("/"),r=n.length;return n.some(g_)&&(r+=Iq),t&&(r+=_q),n.filter(a=>!g_(a)).reduce((a,o)=>a+(Rq.test(o)?Cq:o===""?Nq:Oq),r)}function Lq(e,t){return e.length===t.length&&e.slice(0,-1).every((r,a)=>r===t[a])?e[e.length-1]-t[t.length-1]:0}function Mq(e,t,n=!1){let{routesMeta:r}=e,a={},o="/",s=[];for(let l=0;l{if(p==="*"){let y=l[m]||"";s=o.slice(0,o.length-y.length).replace(/(.)\/+$/,"$1")}const b=l[m];return g&&!b?d[p]=void 0:d[p]=(b||"").replace(/%2F/g,"/"),d},{}),pathname:o,pathnameBase:s,pattern:e}}function Pq(e,t=!1,n=!0){jr(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(s,l,u)=>(r.push({paramName:l,isOptional:u!=null}),u?"/?([^\\/]+)?":"/([^\\/]+)"));return e.endsWith("*")?(r.push({paramName:"*"}),a+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":e!==""&&e!=="/"&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function Fq(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return jr(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Ba(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}function zq(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?ki(e):e;return{pathname:n?n.startsWith("/")?n:Bq(n,t):t,search:Gq(r),hash:Hq(a)}}function Bq(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Jh(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function jq(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Qz(e){let t=jq(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function Jz(e,t,n,r=!1){let a;typeof e=="string"?a=ki(e):(a={...e},Gt(!a.pathname||!a.pathname.includes("?"),Jh("?","pathname","search",a)),Gt(!a.pathname||!a.pathname.includes("#"),Jh("#","pathname","hash",a)),Gt(!a.search||!a.search.includes("#"),Jh("#","search","hash",a)));let o=e===""||a.pathname==="",s=o?"/":a.pathname,l;if(s==null)l=n;else{let g=t.length-1;if(!r&&s.startsWith("..")){let m=s.split("/");for(;m[0]==="..";)m.shift(),g-=1;a.pathname=m.join("/")}l=g>=0?t[g]:"/"}let u=zq(a,l),d=s&&s!=="/"&&s.endsWith("/"),p=(o||s===".")&&n.endsWith("/");return!u.pathname.endsWith("/")&&(d||p)&&(u.pathname+="/"),u}var Fa=e=>e.join("/").replace(/\/\/+/g,"/"),Uq=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Gq=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Hq=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function $q(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}var eB=["POST","PUT","PATCH","DELETE"];new Set(eB);var qq=["GET",...eB];new Set(qq);var Us=w.createContext(null);Us.displayName="DataRouter";var qf=w.createContext(null);qf.displayName="DataRouterState";var tB=w.createContext({isTransitioning:!1});tB.displayName="ViewTransition";var Vq=w.createContext(new Map);Vq.displayName="Fetchers";var Wq=w.createContext(null);Wq.displayName="Await";var sa=w.createContext(null);sa.displayName="Navigation";var zc=w.createContext(null);zc.displayName="Location";var Ha=w.createContext({outlet:null,matches:[],isDataRoute:!1});Ha.displayName="Route";var _k=w.createContext(null);_k.displayName="RouteError";function Yq(e,{relative:t}={}){Gt(Bc(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=w.useContext(sa),{hash:a,pathname:o,search:s}=jc(e,{relative:t}),l=o;return n!=="/"&&(l=o==="/"?n:Fa([n,o])),r.createHref({pathname:l,search:s,hash:a})}function Bc(){return w.useContext(zc)!=null}function Ti(){return Gt(Bc(),"useLocation() may be used only in the context of a component."),w.useContext(zc).location}var nB="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function rB(e){w.useContext(sa).static||w.useLayoutEffect(e)}function Nk(){let{isDataRoute:e}=w.useContext(Ha);return e?s9():Kq()}function Kq(){Gt(Bc(),"useNavigate() may be used only in the context of a component.");let e=w.useContext(Us),{basename:t,navigator:n}=w.useContext(sa),{matches:r}=w.useContext(Ha),{pathname:a}=Ti(),o=JSON.stringify(Qz(r)),s=w.useRef(!1);return rB(()=>{s.current=!0}),w.useCallback((u,d={})=>{if(jr(s.current,nB),!s.current)return;if(typeof u=="number"){n.go(u);return}let p=Jz(u,JSON.parse(o),a,d.relative==="path");e==null&&t!=="/"&&(p.pathname=p.pathname==="/"?t:Fa([t,p.pathname])),(d.replace?n.replace:n.push)(p,d.state,d)},[t,n,o,a,e])}w.createContext(null);function jc(e,{relative:t}={}){let{matches:n}=w.useContext(Ha),{pathname:r}=Ti(),a=JSON.stringify(Qz(n));return w.useMemo(()=>Jz(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Xq(e,t){return aB(e,t)}function aB(e,t,n,r){var k;Gt(Bc(),"useRoutes() may be used only in the context of a component.");let{navigator:a,static:o}=w.useContext(sa),{matches:s}=w.useContext(Ha),l=s[s.length-1],u=l?l.params:{},d=l?l.pathname:"/",p=l?l.pathnameBase:"/",g=l&&l.route;{let R=g&&g.path||"";oB(d,!g||R.endsWith("*")||R.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. + */var p_="popstate";function Eq(e={}){function t(a,o){let{pathname:s="/",search:l="",hash:u=""}=ki(a.location.hash.substring(1));return!s.startsWith("/")&&!s.startsWith(".")&&(s="/"+s),ck("",{pathname:s,search:l,hash:u},o.state&&o.state.usr||null,o.state&&o.state.key||"default")}function n(a,o){let s=a.document.querySelector("base"),l="";if(s&&s.getAttribute("href")){let u=a.location.href,d=u.indexOf("#");l=d===-1?u:u.slice(0,d)}return l+"#"+(typeof o=="string"?o:Sc(o))}function r(a,o){jr(a.pathname.charAt(0)==="/",`relative pathnames are not supported in hash history.push(${JSON.stringify(o)})`)}return kq(t,n,r,e)}function Gt(e,t){if(e===!1||e===null||typeof e>"u")throw new Error(t)}function jr(e,t){if(!e){typeof console<"u"&&console.warn(t);try{throw new Error(t)}catch{}}}function xq(){return Math.random().toString(36).substring(2,10)}function f_(e,t){return{usr:e.state,key:e.key,idx:t}}function ck(e,t,n=null,r){return{pathname:typeof e=="string"?e:e.pathname,search:"",hash:"",...typeof t=="string"?ki(t):t,state:n,key:t&&t.key||r||xq()}}function Sc({pathname:e="/",search:t="",hash:n=""}){return t&&t!=="?"&&(e+=t.charAt(0)==="?"?t:"?"+t),n&&n!=="#"&&(e+=n.charAt(0)==="#"?n:"#"+n),e}function ki(e){let t={};if(e){let n=e.indexOf("#");n>=0&&(t.hash=e.substring(n),e=e.substring(0,n));let r=e.indexOf("?");r>=0&&(t.search=e.substring(r),e=e.substring(0,r)),e&&(t.pathname=e)}return t}function kq(e,t,n,r={}){let{window:a=document.defaultView,v5Compat:o=!1}=r,s=a.history,l="POP",u=null,d=f();d==null&&(d=0,s.replaceState({...s.state,idx:d},""));function f(){return(s.state||{idx:null}).idx}function g(){l="POP";let x=f(),T=x==null?null:x-d;d=x,u&&u({action:l,location:v.location,delta:T})}function m(x,T){l="PUSH";let k=ck(v.location,x,T);n&&n(k,x),d=f()+1;let R=f_(k,d),O=v.createHref(k);try{s.pushState(R,"",O)}catch(N){if(N instanceof DOMException&&N.name==="DataCloneError")throw N;a.location.assign(O)}o&&u&&u({action:l,location:v.location,delta:1})}function b(x,T){l="REPLACE";let k=ck(v.location,x,T);n&&n(k,x),d=f();let R=f_(k,d),O=v.createHref(k);s.replaceState(R,"",O),o&&u&&u({action:l,location:v.location,delta:0})}function y(x){let T=a.location.origin!=="null"?a.location.origin:a.location.href,k=typeof x=="string"?x:Sc(x);return k=k.replace(/ $/,"%20"),Gt(T,`No window.location.(origin|href) available to create URL for href: ${k}`),new URL(k,T)}let v={get action(){return l},get location(){return e(a,s)},listen(x){if(u)throw new Error("A history only accepts one active listener");return a.addEventListener(p_,g),u=x,()=>{a.removeEventListener(p_,g),u=null}},createHref(x){return t(a,x)},createURL:y,encodeLocation(x){let T=y(x);return{pathname:T.pathname,search:T.search,hash:T.hash}},push:m,replace:b,go(x){return s.go(x)}};return v}function Kz(e,t,n="/"){return Tq(e,t,n,!1)}function Tq(e,t,n,r){let a=typeof t=="string"?ki(t):t,o=Ba(a.pathname||"/",n);if(o==null)return null;let s=Xz(e);Aq(s);let l=null;for(let u=0;l==null&&u{let u={relativePath:l===void 0?o.path||"":l,caseSensitive:o.caseSensitive===!0,childrenIndex:s,route:o};u.relativePath.startsWith("/")&&(Gt(u.relativePath.startsWith(r),`Absolute route path "${u.relativePath}" nested under path "${r}" is not valid. An absolute child route path must start with the combined path of all its parent routes.`),u.relativePath=u.relativePath.slice(r.length));let d=Fa([r,u.relativePath]),f=n.concat(u);o.children&&o.children.length>0&&(Gt(o.index!==!0,`Index routes must not have child routes. Please remove all child routes from route path "${d}".`),Xz(o.children,t,f,d)),!(o.path==null&&!o.index)&&t.push({path:d,score:Dq(d,o.index),routesMeta:f})};return e.forEach((o,s)=>{var l;if(o.path===""||!((l=o.path)!=null&&l.includes("?")))a(o,s);else for(let u of Zz(o.path))a(o,s,u)}),t}function Zz(e){let t=e.split("/");if(t.length===0)return[];let[n,...r]=t,a=n.endsWith("?"),o=n.replace(/\?$/,"");if(r.length===0)return a?[o,""]:[o];let s=Zz(r.join("/")),l=[];return l.push(...s.map(u=>u===""?o:[o,u].join("/"))),a&&l.push(...s),l.map(u=>e.startsWith("/")&&u===""?"/":u)}function Aq(e){e.sort((t,n)=>t.score!==n.score?n.score-t.score:Lq(t.routesMeta.map(r=>r.childrenIndex),n.routesMeta.map(r=>r.childrenIndex)))}var Rq=/^:[\w-]+$/,Cq=3,_q=2,Nq=1,Oq=10,Iq=-2,g_=e=>e==="*";function Dq(e,t){let n=e.split("/"),r=n.length;return n.some(g_)&&(r+=Iq),t&&(r+=_q),n.filter(a=>!g_(a)).reduce((a,o)=>a+(Rq.test(o)?Cq:o===""?Nq:Oq),r)}function Lq(e,t){return e.length===t.length&&e.slice(0,-1).every((r,a)=>r===t[a])?e[e.length-1]-t[t.length-1]:0}function Mq(e,t,n=!1){let{routesMeta:r}=e,a={},o="/",s=[];for(let l=0;l{if(f==="*"){let y=l[m]||"";s=o.slice(0,o.length-y.length).replace(/(.)\/+$/,"$1")}const b=l[m];return g&&!b?d[f]=void 0:d[f]=(b||"").replace(/%2F/g,"/"),d},{}),pathname:o,pathnameBase:s,pattern:e}}function Pq(e,t=!1,n=!0){jr(e==="*"||!e.endsWith("*")||e.endsWith("/*"),`Route path "${e}" will be treated as if it were "${e.replace(/\*$/,"/*")}" because the \`*\` character must always follow a \`/\` in the pattern. To get rid of this warning, please change the route path to "${e.replace(/\*$/,"/*")}".`);let r=[],a="^"+e.replace(/\/*\*?$/,"").replace(/^\/*/,"/").replace(/[\\.*+^${}|()[\]]/g,"\\$&").replace(/\/:([\w-]+)(\?)?/g,(s,l,u)=>(r.push({paramName:l,isOptional:u!=null}),u?"/?([^\\/]+)?":"/([^\\/]+)"));return e.endsWith("*")?(r.push({paramName:"*"}),a+=e==="*"||e==="/*"?"(.*)$":"(?:\\/(.+)|\\/*)$"):n?a+="\\/*$":e!==""&&e!=="/"&&(a+="(?:(?=\\/|$))"),[new RegExp(a,t?void 0:"i"),r]}function Fq(e){try{return e.split("/").map(t=>decodeURIComponent(t).replace(/\//g,"%2F")).join("/")}catch(t){return jr(!1,`The URL path "${e}" could not be decoded because it is a malformed URL segment. This is probably due to a bad percent encoding (${t}).`),e}}function Ba(e,t){if(t==="/")return e;if(!e.toLowerCase().startsWith(t.toLowerCase()))return null;let n=t.endsWith("/")?t.length-1:t.length,r=e.charAt(n);return r&&r!=="/"?null:e.slice(n)||"/"}function zq(e,t="/"){let{pathname:n,search:r="",hash:a=""}=typeof e=="string"?ki(e):e;return{pathname:n?n.startsWith("/")?n:Bq(n,t):t,search:Gq(r),hash:Hq(a)}}function Bq(e,t){let n=t.replace(/\/+$/,"").split("/");return e.split("/").forEach(a=>{a===".."?n.length>1&&n.pop():a!=="."&&n.push(a)}),n.length>1?n.join("/"):"/"}function Jh(e,t,n,r){return`Cannot include a '${e}' character in a manually specified \`to.${t}\` field [${JSON.stringify(r)}]. Please separate it out to the \`to.${n}\` field. Alternatively you may provide the full path as a string in and the router will parse it for you.`}function jq(e){return e.filter((t,n)=>n===0||t.route.path&&t.route.path.length>0)}function Qz(e){let t=jq(e);return t.map((n,r)=>r===t.length-1?n.pathname:n.pathnameBase)}function Jz(e,t,n,r=!1){let a;typeof e=="string"?a=ki(e):(a={...e},Gt(!a.pathname||!a.pathname.includes("?"),Jh("?","pathname","search",a)),Gt(!a.pathname||!a.pathname.includes("#"),Jh("#","pathname","hash",a)),Gt(!a.search||!a.search.includes("#"),Jh("#","search","hash",a)));let o=e===""||a.pathname==="",s=o?"/":a.pathname,l;if(s==null)l=n;else{let g=t.length-1;if(!r&&s.startsWith("..")){let m=s.split("/");for(;m[0]==="..";)m.shift(),g-=1;a.pathname=m.join("/")}l=g>=0?t[g]:"/"}let u=zq(a,l),d=s&&s!=="/"&&s.endsWith("/"),f=(o||s===".")&&n.endsWith("/");return!u.pathname.endsWith("/")&&(d||f)&&(u.pathname+="/"),u}var Fa=e=>e.join("/").replace(/\/\/+/g,"/"),Uq=e=>e.replace(/\/+$/,"").replace(/^\/*/,"/"),Gq=e=>!e||e==="?"?"":e.startsWith("?")?e:"?"+e,Hq=e=>!e||e==="#"?"":e.startsWith("#")?e:"#"+e;function $q(e){return e!=null&&typeof e.status=="number"&&typeof e.statusText=="string"&&typeof e.internal=="boolean"&&"data"in e}var eB=["POST","PUT","PATCH","DELETE"];new Set(eB);var qq=["GET",...eB];new Set(qq);var Us=E.createContext(null);Us.displayName="DataRouter";var $p=E.createContext(null);$p.displayName="DataRouterState";var tB=E.createContext({isTransitioning:!1});tB.displayName="ViewTransition";var Vq=E.createContext(new Map);Vq.displayName="Fetchers";var Wq=E.createContext(null);Wq.displayName="Await";var sa=E.createContext(null);sa.displayName="Navigation";var zc=E.createContext(null);zc.displayName="Location";var Ha=E.createContext({outlet:null,matches:[],isDataRoute:!1});Ha.displayName="Route";var _0=E.createContext(null);_0.displayName="RouteError";function Yq(e,{relative:t}={}){Gt(Bc(),"useHref() may be used only in the context of a component.");let{basename:n,navigator:r}=E.useContext(sa),{hash:a,pathname:o,search:s}=jc(e,{relative:t}),l=o;return n!=="/"&&(l=o==="/"?n:Fa([n,o])),r.createHref({pathname:l,search:s,hash:a})}function Bc(){return E.useContext(zc)!=null}function Ti(){return Gt(Bc(),"useLocation() may be used only in the context of a component."),E.useContext(zc).location}var nB="You should call navigate() in a React.useEffect(), not when your component is first rendered.";function rB(e){E.useContext(sa).static||E.useLayoutEffect(e)}function N0(){let{isDataRoute:e}=E.useContext(Ha);return e?s9():Kq()}function Kq(){Gt(Bc(),"useNavigate() may be used only in the context of a component.");let e=E.useContext(Us),{basename:t,navigator:n}=E.useContext(sa),{matches:r}=E.useContext(Ha),{pathname:a}=Ti(),o=JSON.stringify(Qz(r)),s=E.useRef(!1);return rB(()=>{s.current=!0}),E.useCallback((u,d={})=>{if(jr(s.current,nB),!s.current)return;if(typeof u=="number"){n.go(u);return}let f=Jz(u,JSON.parse(o),a,d.relative==="path");e==null&&t!=="/"&&(f.pathname=f.pathname==="/"?t:Fa([t,f.pathname])),(d.replace?n.replace:n.push)(f,d.state,d)},[t,n,o,a,e])}E.createContext(null);function jc(e,{relative:t}={}){let{matches:n}=E.useContext(Ha),{pathname:r}=Ti(),a=JSON.stringify(Qz(n));return E.useMemo(()=>Jz(e,JSON.parse(a),r,t==="path"),[e,a,r,t])}function Xq(e,t){return aB(e,t)}function aB(e,t,n,r){var k;Gt(Bc(),"useRoutes() may be used only in the context of a component.");let{navigator:a,static:o}=E.useContext(sa),{matches:s}=E.useContext(Ha),l=s[s.length-1],u=l?l.params:{},d=l?l.pathname:"/",f=l?l.pathnameBase:"/",g=l&&l.route;{let R=g&&g.path||"";oB(d,!g||R.endsWith("*")||R.endsWith("*?"),`You rendered descendant (or called \`useRoutes()\`) at "${d}" (under ) but the parent route path has no trailing "*". This means if you navigate deeper, the parent won't match anymore and therefore the child routes will never render. -Please change the parent to .`)}let m=Ti(),b;if(t){let R=typeof t=="string"?ki(t):t;Gt(p==="/"||((k=R.pathname)==null?void 0:k.startsWith(p)),`When overriding the location using \`\` or \`useRoutes(routes, location)\`, the location pathname must begin with the portion of the URL pathname that was matched by all parent routes. The current pathname base is "${p}" but pathname "${R.pathname}" was given in the \`location\` prop.`),b=R}else b=m;let y=b.pathname||"/",v=y;if(p!=="/"){let R=p.replace(/^\//,"").split("/");v="/"+y.replace(/^\//,"").split("/").slice(R.length).join("/")}let x=!o&&n&&n.matches&&n.matches.length>0?n.matches:Kz(e,{pathname:v});jr(g||x!=null,`No routes matched location "${b.pathname}${b.search}${b.hash}" `),jr(x==null||x[x.length-1].route.element!==void 0||x[x.length-1].route.Component!==void 0||x[x.length-1].route.lazy!==void 0,`Matched leaf route at location "${b.pathname}${b.search}${b.hash}" does not have an element or Component. This means it will render an with a null value by default resulting in an "empty" page.`);let T=t9(x&&x.map(R=>Object.assign({},R,{params:Object.assign({},u,R.params),pathname:Fa([p,a.encodeLocation?a.encodeLocation(R.pathname).pathname:R.pathname]),pathnameBase:R.pathnameBase==="/"?p:Fa([p,a.encodeLocation?a.encodeLocation(R.pathnameBase).pathname:R.pathnameBase])})),s,n,r);return t&&T?w.createElement(zc.Provider,{value:{location:{pathname:"/",search:"",hash:"",state:null,key:"default",...b},navigationType:"POP"}},T):T}function Zq(){let e=i9(),t=$q(e)?`${e.status} ${e.statusText}`:e instanceof Error?e.message:JSON.stringify(e),n=e instanceof Error?e.stack:null,r="rgba(200,200,200, 0.5)",a={padding:"0.5rem",backgroundColor:r},o={padding:"2px 4px",backgroundColor:r},s=null;return console.error("Error handled by React Router default ErrorBoundary:",e),s=w.createElement(w.Fragment,null,w.createElement("p",null,"💿 Hey developer 👋"),w.createElement("p",null,"You can provide a way better UX than this when your app throws errors by providing your own ",w.createElement("code",{style:o},"ErrorBoundary")," or"," ",w.createElement("code",{style:o},"errorElement")," prop on your route.")),w.createElement(w.Fragment,null,w.createElement("h2",null,"Unexpected Application Error!"),w.createElement("h3",{style:{fontStyle:"italic"}},t),n?w.createElement("pre",{style:a},n):null,s)}var Qq=w.createElement(Zq,null),Jq=class extends w.Component{constructor(e){super(e),this.state={location:e.location,revalidation:e.revalidation,error:e.error}}static getDerivedStateFromError(e){return{error:e}}static getDerivedStateFromProps(e,t){return t.location!==e.location||t.revalidation!=="idle"&&e.revalidation==="idle"?{error:e.error,location:e.location,revalidation:e.revalidation}:{error:e.error!==void 0?e.error:t.error,location:t.location,revalidation:e.revalidation||t.revalidation}}componentDidCatch(e,t){console.error("React Router caught the following error during render",e,t)}render(){return this.state.error!==void 0?w.createElement(Ha.Provider,{value:this.props.routeContext},w.createElement(_k.Provider,{value:this.state.error,children:this.props.component})):this.props.children}};function e9({routeContext:e,match:t,children:n}){let r=w.useContext(Us);return r&&r.static&&r.staticContext&&(t.route.errorElement||t.route.ErrorBoundary)&&(r.staticContext._deepestRenderedBoundaryId=t.route.id),w.createElement(Ha.Provider,{value:e},n)}function t9(e,t=[],n=null,r=null){if(e==null){if(!n)return null;if(n.errors)e=n.matches;else if(t.length===0&&!n.initialized&&n.matches.length>0)e=n.matches;else return null}let a=e,o=n==null?void 0:n.errors;if(o!=null){let u=a.findIndex(d=>d.route.id&&(o==null?void 0:o[d.route.id])!==void 0);Gt(u>=0,`Could not find a matching route for errors on route IDs: ${Object.keys(o).join(",")}`),a=a.slice(0,Math.min(a.length,u+1))}let s=!1,l=-1;if(n)for(let u=0;u=0?a=a.slice(0,l+1):a=[a[0]];break}}}return a.reduceRight((u,d,p)=>{let g,m=!1,b=null,y=null;n&&(g=o&&d.route.id?o[d.route.id]:void 0,b=d.route.errorElement||Qq,s&&(l<0&&p===0?(oB("route-fallback",!1,"No `HydrateFallback` element provided to render during initial hydration"),m=!0,y=null):l===p&&(m=!0,y=d.route.hydrateFallbackElement||null)));let v=t.concat(a.slice(0,p+1)),x=()=>{let T;return g?T=b:m?T=y:d.route.Component?T=w.createElement(d.route.Component,null):d.route.element?T=d.route.element:T=u,w.createElement(e9,{match:d,routeContext:{outlet:u,matches:v,isDataRoute:n!=null},children:T})};return n&&(d.route.ErrorBoundary||d.route.errorElement||p===0)?w.createElement(Jq,{location:n.location,revalidation:n.revalidation,component:b,error:g,children:x(),routeContext:{outlet:null,matches:v,isDataRoute:!0}}):x()},null)}function Ok(e){return`${e} must be used within a data router. See https://reactrouter.com/en/main/routers/picking-a-router.`}function n9(e){let t=w.useContext(Us);return Gt(t,Ok(e)),t}function r9(e){let t=w.useContext(qf);return Gt(t,Ok(e)),t}function a9(e){let t=w.useContext(Ha);return Gt(t,Ok(e)),t}function Ik(e){let t=a9(e),n=t.matches[t.matches.length-1];return Gt(n.route.id,`${e} can only be used on routes that contain a unique "id"`),n.route.id}function o9(){return Ik("useRouteId")}function i9(){var r;let e=w.useContext(_k),t=r9("useRouteError"),n=Ik("useRouteError");return e!==void 0?e:(r=t.errors)==null?void 0:r[n]}function s9(){let{router:e}=n9("useNavigate"),t=Ik("useNavigate"),n=w.useRef(!1);return rB(()=>{n.current=!0}),w.useCallback(async(a,o={})=>{jr(n.current,nB),n.current&&(typeof a=="number"?e.navigate(a):await e.navigate(a,{fromRouteId:t,...o}))},[e,t])}var h_={};function oB(e,t,n){!t&&!h_[e]&&(h_[e]=!0,jr(!1,n))}w.memo(l9);function l9({routes:e,future:t,state:n}){return aB(e,void 0,n,t)}function u0(e){Gt(!1,"A is only ever to be used as the child of element, never rendered directly. Please wrap your in a .")}function c9({basename:e="/",children:t=null,location:n,navigationType:r="POP",navigator:a,static:o=!1}){Gt(!Bc(),"You cannot render a inside another . You should never have more than one in your app.");let s=e.replace(/^\/*/,"/"),l=w.useMemo(()=>({basename:s,navigator:a,static:o,future:{}}),[s,a,o]);typeof n=="string"&&(n=ki(n));let{pathname:u="/",search:d="",hash:p="",state:g=null,key:m="default"}=n,b=w.useMemo(()=>{let y=Ba(u,s);return y==null?null:{location:{pathname:y,search:d,hash:p,state:g,key:m},navigationType:r}},[s,u,d,p,g,m,r]);return jr(b!=null,` is not able to match the URL "${u}${d}${p}" because it does not start with the basename, so the won't render anything.`),b==null?null:w.createElement(sa.Provider,{value:l},w.createElement(zc.Provider,{children:t,value:b}))}function u9({children:e,location:t}){return Xq(d0(e),t)}function d0(e,t=[]){let n=[];return w.Children.forEach(e,(r,a)=>{if(!w.isValidElement(r))return;let o=[...t,a];if(r.type===w.Fragment){n.push.apply(n,d0(r.props.children,o));return}Gt(r.type===u0,`[${typeof r.type=="string"?r.type:r.type.name}] is not a component. All component children of must be a or `),Gt(!r.props.index||!r.props.children,"An index route cannot have child routes.");let s={id:r.props.id||o.join("-"),caseSensitive:r.props.caseSensitive,element:r.props.element,Component:r.props.Component,index:r.props.index,path:r.props.path,loader:r.props.loader,action:r.props.action,hydrateFallbackElement:r.props.hydrateFallbackElement,HydrateFallback:r.props.HydrateFallback,errorElement:r.props.errorElement,ErrorBoundary:r.props.ErrorBoundary,hasErrorBoundary:r.props.hasErrorBoundary===!0||r.props.ErrorBoundary!=null||r.props.errorElement!=null,shouldRevalidate:r.props.shouldRevalidate,handle:r.props.handle,lazy:r.props.lazy};r.props.children&&(s.children=d0(r.props.children,o)),n.push(s)}),n}var Wd="get",Yd="application/x-www-form-urlencoded";function Vf(e){return e!=null&&typeof e.tagName=="string"}function d9(e){return Vf(e)&&e.tagName.toLowerCase()==="button"}function f9(e){return Vf(e)&&e.tagName.toLowerCase()==="form"}function p9(e){return Vf(e)&&e.tagName.toLowerCase()==="input"}function g9(e){return!!(e.metaKey||e.altKey||e.ctrlKey||e.shiftKey)}function h9(e,t){return e.button===0&&(!t||t==="_self")&&!g9(e)}var md=null;function m9(){if(md===null)try{new FormData(document.createElement("form"),0),md=!1}catch{md=!0}return md}var b9=new Set(["application/x-www-form-urlencoded","multipart/form-data","text/plain"]);function em(e){return e!=null&&!b9.has(e)?(jr(!1,`"${e}" is not a valid \`encType\` for \`
\`/\`\` and will default to "${Yd}"`),null):e}function y9(e,t){let n,r,a,o,s;if(f9(e)){let l=e.getAttribute("action");r=l?Ba(l,t):null,n=e.getAttribute("method")||Wd,a=em(e.getAttribute("enctype"))||Yd,o=new FormData(e)}else if(d9(e)||p9(e)&&(e.type==="submit"||e.type==="image")){let l=e.form;if(l==null)throw new Error('Cannot submit a