@@ -4,6 +4,15 @@ import { Button } from "@/components/ui/button";
44import { Input } from "@/components/ui/input" ;
55import { Label } from "@/components/ui/label" ;
66import { Trash2 , Plus } from "lucide-react" ;
7+ import { cn } from "@/lib/utils" ;
8+ import {
9+ META_NAME_RULES_MESSAGE ,
10+ META_PREFIX_RULES_MESSAGE ,
11+ RESERVED_NAMESPACE_MESSAGE ,
12+ hasValidMetaName ,
13+ hasValidMetaPrefix ,
14+ isReservedMetaKey ,
15+ } from "@/utils/metaUtils" ;
716
817interface MetadataEntry {
918 key : string ;
@@ -47,8 +56,15 @@ const MetadataTab: React.FC<MetadataTabProps> = ({
4756 const updateMetadata = ( newEntries : MetadataEntry [ ] ) => {
4857 const metadataObject : Record < string , string > = { } ;
4958 newEntries . forEach ( ( { key, value } ) => {
50- if ( key . trim ( ) && value . trim ( ) ) {
51- metadataObject [ key . trim ( ) ] = value . trim ( ) ;
59+ const trimmedKey = key . trim ( ) ;
60+ if (
61+ trimmedKey &&
62+ value . trim ( ) &&
63+ hasValidMetaPrefix ( trimmedKey ) &&
64+ ! isReservedMetaKey ( trimmedKey ) &&
65+ hasValidMetaName ( trimmedKey )
66+ ) {
67+ metadataObject [ trimmedKey ] = value . trim ( ) ;
5268 }
5369 } ) ;
5470 onMetadataChange ( metadataObject ) ;
@@ -71,39 +87,72 @@ const MetadataTab: React.FC<MetadataTabProps> = ({
7187 </ div >
7288
7389 < div className = "space-y-3" >
74- { entries . map ( ( entry , index ) => (
75- < div key = { index } className = "flex items-center space-x-2" >
76- < div className = "flex-1" >
77- < Label htmlFor = { `key-${ index } ` } className = "sr-only" >
78- Key
79- </ Label >
80- < Input
81- id = { `key-${ index } ` }
82- placeholder = "Key"
83- value = { entry . key }
84- onChange = { ( e ) => updateEntry ( index , "key" , e . target . value ) }
85- />
90+ { entries . map ( ( entry , index ) => {
91+ const trimmedKey = entry . key . trim ( ) ;
92+ const hasInvalidPrefix =
93+ trimmedKey !== "" && ! hasValidMetaPrefix ( trimmedKey ) ;
94+ const isReservedKey =
95+ trimmedKey !== "" && isReservedMetaKey ( trimmedKey ) ;
96+ const hasInvalidName =
97+ trimmedKey !== "" && ! hasValidMetaName ( trimmedKey ) ;
98+ const validationMessage = hasInvalidPrefix
99+ ? META_PREFIX_RULES_MESSAGE
100+ : isReservedKey
101+ ? RESERVED_NAMESPACE_MESSAGE
102+ : hasInvalidName
103+ ? META_NAME_RULES_MESSAGE
104+ : null ;
105+ return (
106+ < div key = { index } className = "space-y-1" >
107+ < div className = "flex items-center space-x-2" >
108+ < div className = "flex-1" >
109+ < Label htmlFor = { `key-${ index } ` } className = "sr-only" >
110+ Key
111+ </ Label >
112+ < Input
113+ id = { `key-${ index } ` }
114+ placeholder = "Key"
115+ value = { entry . key }
116+ onChange = { ( e ) =>
117+ updateEntry ( index , "key" , e . target . value )
118+ }
119+ aria-invalid = { Boolean ( validationMessage ) }
120+ className = { cn (
121+ validationMessage &&
122+ "border-red-500 focus-visible:ring-red-500 focus-visible:ring-1" ,
123+ ) }
124+ />
125+ </ div >
126+ < div className = "flex-1" >
127+ < Label htmlFor = { `value-${ index } ` } className = "sr-only" >
128+ Value
129+ </ Label >
130+ < Input
131+ id = { `value-${ index } ` }
132+ placeholder = "Value"
133+ value = { entry . value }
134+ onChange = { ( e ) =>
135+ updateEntry ( index , "value" , e . target . value )
136+ }
137+ disabled = { Boolean ( validationMessage ) }
138+ />
139+ </ div >
140+ < Button
141+ variant = "outline"
142+ size = "sm"
143+ onClick = { ( ) => removeEntry ( index ) }
144+ >
145+ < Trash2 className = "w-4 h-4" />
146+ </ Button >
147+ </ div >
148+ { validationMessage && (
149+ < p className = "text-xs text-red-600 dark:text-red-400" >
150+ { validationMessage }
151+ </ p >
152+ ) }
86153 </ div >
87- < div className = "flex-1" >
88- < Label htmlFor = { `value-${ index } ` } className = "sr-only" >
89- Value
90- </ Label >
91- < Input
92- id = { `value-${ index } ` }
93- placeholder = "Value"
94- value = { entry . value }
95- onChange = { ( e ) => updateEntry ( index , "value" , e . target . value ) }
96- />
97- </ div >
98- < Button
99- variant = "outline"
100- size = "sm"
101- onClick = { ( ) => removeEntry ( index ) }
102- >
103- < Trash2 className = "w-4 h-4" />
104- </ Button >
105- </ div >
106- ) ) }
154+ ) ;
155+ } ) }
107156 </ div >
108157
109158 { entries . length === 0 && (
0 commit comments