@@ -1262,6 +1262,19 @@ function PrimEditForm({ primitive, kind, meta, onBack, onSaved }) {
12621262 ( hasCommand && command !== ( primitive . frontmatter ?. command || '' ) ) ||
12631263 ( hasCommand && timeoutVal !== ( primitive . frontmatter ?. timeout != null ? String ( primitive . frontmatter . timeout ) : '' ) ) ;
12641264
1265+ // Cmd+S / Ctrl+S to save
1266+ const saveRef = useRef ( null ) ;
1267+ useEffect ( ( ) => {
1268+ const onKey = ( e ) => {
1269+ if ( ( e . metaKey || e . ctrlKey ) && e . key === 's' ) {
1270+ e . preventDefault ( ) ;
1271+ saveRef . current ?. ( ) ;
1272+ }
1273+ } ;
1274+ document . addEventListener ( 'keydown' , onKey ) ;
1275+ return ( ) => document . removeEventListener ( 'keydown' , onKey ) ;
1276+ } , [ ] ) ;
1277+
12651278 async function handleSave ( ) {
12661279 setSaving ( true ) ;
12671280 try {
@@ -1282,6 +1295,8 @@ function PrimEditForm({ primitive, kind, meta, onBack, onSaved }) {
12821295 }
12831296 setSaving ( false ) ;
12841297 }
1298+ // Keep ref in sync so Cmd+S always calls the latest handleSave (with current form state)
1299+ saveRef . current = hasChanges && ! saving ? handleSave : null ;
12851300
12861301 async function handleDelete ( ) {
12871302 if ( ! confirm ( `Delete "${ primitive . name } "? This cannot be undone.` ) ) return ;
@@ -1436,7 +1451,7 @@ function PrimEditForm({ primitive, kind, meta, onBack, onSaved }) {
14361451 < div style ="flex: 1 "> </ div >
14371452 < button class ="btn " onClick =${ onBack } > Cancel</ button >
14381453 < button class ="btn btn-primary " onClick =${ handleSave } disabled =${ ! hasChanges || saving } >
1439- ${ saving ? 'Saving...' : ' Save Changes' }
1454+ ${ saving ? 'Saving...' : html ` Save Changes < kbd class =" btn-kbd " > ${ navigator . platform ?. includes ( 'Mac' ) ? '\u2318' : 'Ctrl' } S </ kbd > ` }
14401455 </ button >
14411456 </ div >
14421457 </ div >
@@ -1455,6 +1470,19 @@ function PrimCreateForm({ kind, meta, onBack, onCreated }) {
14551470 const hasCommand = kind === 'checks' || kind === 'contexts' ;
14561471 const canCreate = name . trim ( ) . length > 0 && ( ! hasCommand || command . trim ( ) . length > 0 ) ;
14571472
1473+ // Cmd+S / Ctrl+S to create
1474+ const createRef = useRef ( null ) ;
1475+ useEffect ( ( ) => {
1476+ const onKey = ( e ) => {
1477+ if ( ( e . metaKey || e . ctrlKey ) && e . key === 's' ) {
1478+ e . preventDefault ( ) ;
1479+ createRef . current ?. ( ) ;
1480+ }
1481+ } ;
1482+ document . addEventListener ( 'keydown' , onKey ) ;
1483+ return ( ) => document . removeEventListener ( 'keydown' , onKey ) ;
1484+ } , [ ] ) ;
1485+
14581486 async function handleCreate ( ) {
14591487 setCreating ( true ) ;
14601488 setError ( null ) ;
@@ -1474,6 +1502,7 @@ function PrimCreateForm({ kind, meta, onBack, onCreated }) {
14741502 }
14751503 setCreating ( false ) ;
14761504 }
1505+ createRef . current = canCreate && ! creating ? handleCreate : null ;
14771506
14781507 return html `
14791508 < div class ="prim-editor ">
@@ -1541,7 +1570,7 @@ function PrimCreateForm({ kind, meta, onBack, onCreated }) {
15411570 < div style ="flex: 1 "> </ div >
15421571 < button class ="btn " onClick =${ onBack } > Cancel</ button >
15431572 < button class ="btn btn-primary " onClick =${ handleCreate } disabled =${ ! canCreate || creating } >
1544- ${ creating ? 'Creating...' : `Create ${ meta . label . replace ( / s $ / , '' ) } ` }
1573+ ${ creating ? 'Creating...' : html `Create ${ meta . label . replace ( / s $ / , '' ) } < kbd class =" btn-kbd " > ${ navigator . platform ?. includes ( 'Mac' ) ? '\u2318' : 'Ctrl' } S </ kbd > ` }
15451574 </ button >
15461575 </ div >
15471576 </ div >
0 commit comments