@@ -29,6 +29,8 @@ const newMount = ref({
2929 readonly: false ,
3030});
3131
32+ const editingIndex = ref <number | null >(null );
33+
3234function addMount() {
3335 if (! newMount .value .source || ! newMount .value .target ) return ;
3436
@@ -40,7 +42,15 @@ function addMount() {
4042 ... (newMount .value .readonly ? { readonly: true } : {}),
4143 };
4244
43- emit (" update:mounts" , [... props .mounts , mount ]);
45+ const updatedMounts = [... props .mounts ];
46+ if (editingIndex .value !== null ) {
47+ updatedMounts [editingIndex .value ] = mount ;
48+ editingIndex .value = null ;
49+ } else {
50+ updatedMounts .push (mount );
51+ }
52+
53+ emit (" update:mounts" , updatedMounts );
4454
4555 newMount .value = {
4656 source: " " ,
@@ -51,15 +61,80 @@ function addMount() {
5161 };
5262}
5363
54- function removeMount(index : number ) {
64+ function removeMount(index : number , event ? : Event ) {
65+ if (event ) event .stopPropagation ();
5566 const updated = [... props .mounts ];
5667 updated .splice (index , 1 );
68+ if (editingIndex .value === index ) editingIndex .value = null ;
69+ else if (editingIndex .value !== null && editingIndex .value > index )
70+ editingIndex .value -- ;
5771 emit (" update:mounts" , updated .length > 0 ? updated : undefined );
5872}
5973
74+ function selectMountToEdit(mount : any , index : number ) {
75+ editingIndex .value = index ;
76+ if (typeof mount === " string" ) {
77+ const parts = mount .split (" ," );
78+ const sourcePart = parts .find ((p ) => p .startsWith (" source=" ));
79+ const targetPart = parts .find ((p ) => p .startsWith (" target=" ));
80+ const typePart = parts .find ((p ) => p .startsWith (" type=" ));
81+ const isRO = parts .includes (" readonly" );
82+
83+ const rawType = typePart ? typePart .split (" =" )[1 ] : " bind" ;
84+ const type = [" bind" , " volume" ].includes (rawType )
85+ ? (rawType as " bind" | " volume" )
86+ : (" bind" as const );
87+
88+ newMount .value = {
89+ source: sourcePart ? sourcePart .split (" =" )[1 ] : " " ,
90+ target: targetPart ? targetPart .split (" =" )[1 ] : " " ,
91+ type ,
92+ options: parts
93+ .filter ((p ) => {
94+ const [k] = p .split (" =" );
95+ return ! [" source" , " target" , " type" , " readonly" ].includes (k );
96+ })
97+ .join (" ," ),
98+ readonly: isRO ,
99+ };
100+ } else {
101+ const rawType = (mount as any ).type || " bind" ;
102+ const type = [" bind" , " volume" ].includes (rawType )
103+ ? (rawType as " bind" | " volume" )
104+ : (" bind" as const );
105+
106+ newMount .value = {
107+ source: mount .source ,
108+ target: mount .target ,
109+ type ,
110+ options: mount .options || " " ,
111+ readonly: !! mount .readonly ,
112+ };
113+ }
114+ }
115+
60116function getMountLabel(mount : any ) {
61- if (typeof mount === " string" ) return mount ;
62- return ` ${mount .source } ➔ ${mount .target } ` ;
117+ if (typeof mount !== " string" ) return ` ${mount .source } ➔ ${mount .target } ` ;
118+
119+ const parts = mount .split (" ," );
120+ const sourcePart = parts .find ((p ) => p .startsWith (" source=" ));
121+ const targetPart = parts .find ((p ) => p .startsWith (" target=" ));
122+
123+ if (sourcePart && targetPart ) {
124+ return ` ${sourcePart .split (" =" )[1 ]} ➔ ${targetPart .split (" =" )[1 ]} ` ;
125+ }
126+ return mount ;
127+ }
128+
129+ function getMountType(mount : any ) {
130+ if (typeof mount !== " string" ) return mount .type ;
131+ const typePart = mount .split (" ," ).find ((p ) => p .startsWith (" type=" ));
132+ return typePart ? typePart .split (" =" )[1 ] : " RAW" ;
133+ }
134+
135+ function isReadonly(mount : any ) {
136+ if (typeof mount !== " string" ) return !! mount .readonly ;
137+ return mount .split (" ," ).includes (" readonly" );
63138}
64139 </script >
65140
@@ -120,9 +195,14 @@ function getMountLabel(mount: any) {
120195 <div class =" flex items-end col-span-2 lg:col-span-1" >
121196 <button
122197 @click =" addMount"
123- class =" bg-ide-accent text-ide-bg px-3 py-1.5 rounded-sm text-[9px] font-black uppercase tracking-widest hover:bg-white transition-all shadow-lg shadow-ide-accent/10 h-[28px] w-full"
198+ class =" text-ide-bg px-3 py-1.5 rounded-sm text-[9px] font-black uppercase tracking-widest hover:bg-white transition-all shadow-lg shadow-ide-accent/10 h-[28px] w-full"
199+ :class ="
200+ editingIndex !== null
201+ ? 'bg-ide-orange shadow-ide-orange/10'
202+ : 'bg-ide-accent'
203+ "
124204 >
125- Add
205+ {{ editingIndex !== null ? "Update" : " Add" }}
126206 </button >
127207 </div >
128208 </div >
@@ -131,15 +211,24 @@ function getMountLabel(mount: any) {
131211 <div
132212 v-for =" (mount, index) in mounts"
133213 :key =" index"
134- class =" flex items-center justify-between p-2 pl-3 bg-ide-activity/30 border border-ide-border/50 rounded group hover:border-ide-accent/30 transition-colors"
214+ role =" button"
215+ tabindex =" 0"
216+ aria-label =" Select mount to edit"
217+ @click =" selectMountToEdit(mount, index)"
218+ @keydown.enter.space.prevent =" selectMountToEdit(mount, index)"
219+ class =" flex items-center justify-between p-2 pl-3 bg-ide-activity/30 border border-ide-border/50 rounded group hover:border-ide-accent/30 transition-all cursor-pointer outline-none focus-visible:ring-1 focus-visible:ring-ide-accent"
220+ :class =" {
221+ 'border-ide-accent/60 bg-ide-accent/5 ring-1 ring-ide-accent/20':
222+ editingIndex === index,
223+ }"
135224 >
136225 <div class =" flex flex-col gap-0.5" >
137226 <div class =" flex items-center gap-2" >
138227 <span class =" text-[10px] font-mono text-ide-text-bright" >{{
139228 getMountLabel(mount)
140229 }}</span >
141230 <span
142- v-if =" typeof mount !== 'string' && mount.readonly "
231+ v-if =" isReadonly( mount) "
143232 class =" px-1 py-0.5 bg-ide-orange/20 text-ide-orange text-[6px] font-black rounded-sm uppercase tracking-tighter"
144233 >Read Only</span
145234 >
@@ -149,7 +238,7 @@ function getMountLabel(mount: any) {
149238 >
150239 <span
151240 class =" text-[7px] font-black uppercase tracking-widest bg-ide-border px-1 rounded-sm"
152- >{{ typeof mount === "string" ? "RAW" : mount.type }}</span
241+ >{{ getMountType( mount) }}</span
153242 >
154243 <span
155244 v-if =" typeof mount !== 'string' && mount.options"
@@ -159,7 +248,7 @@ function getMountLabel(mount: any) {
159248 </div >
160249 </div >
161250 <button
162- @click =" removeMount(index)"
251+ @click =" removeMount(index, $event )"
163252 class =" p-1.5 text-ide-text-muted hover:text-ide-orange transition-colors"
164253 >
165254 <svg
0 commit comments