@@ -22,7 +22,7 @@ import {
2222 keyEventHasModifier ,
2323 type ModifierKey ,
2424} from "catcolab-ui-components" ;
25- import type { Cell , Notebook } from "catlog-wasm" ;
25+ import type { Cell , Notebook , MorType , ObType } from "catlog-wasm" ;
2626import {
2727 type CellActions ,
2828 type FormalCellEditorProps ,
@@ -139,6 +139,33 @@ export function NotebookEditor<T>(props: {
139139 } ) ;
140140 } ;
141141
142+ const isFormalCell = ( cell : Cell < T > ) : cell is { tag : "formal" ; id : string ; content : T } => {
143+ return cell . tag === "formal" ;
144+ } ;
145+
146+ const isObType = ( content : any ) : content is { tag : "object" ; obType : ObType } => {
147+ return content && content . tag === "object" ;
148+ } ;
149+
150+ const isMorType = ( content : any ) : content is { tag : "morphism" ; morType : MorType } => {
151+ return content && content . tag === "morphism" ;
152+ } ;
153+
154+ const retypeCellAs = ( i : number , newCell : Cell < T > ) => {
155+ if ( ! newCell || ! isFormalCell ( newCell ) ) return ;
156+ const mutator = ( cellContent : T ) => {
157+ if ( isObType ( cellContent ) && isObType ( newCell . content ) ) {
158+ cellContent . obType = newCell . content . obType ;
159+ } else if ( isMorType ( cellContent ) && isMorType ( newCell . content ) ) {
160+ cellContent . morType = newCell . content . morType ;
161+ }
162+ } ;
163+ props . changeNotebook ( ( nb ) => {
164+ NotebookUtils . retypeCell ( nb , i , mutator ) ;
165+ } ) ;
166+ setActiveCell ( i ) ;
167+ } ;
168+
142169 const cellConstructors = ( ) : CellConstructor < T > [ ] => [
143170 {
144171 name : "Text" ,
@@ -160,6 +187,17 @@ export function NotebookEditor<T>(props: {
160187 } ;
161188 } ) ;
162189
190+ const retypeCommands = ( i : number ) : Completion [ ] =>
191+ cellConstructors ( ) . map ( ( cc ) => {
192+ const { name, description, shortcut } = cc ;
193+ return {
194+ name,
195+ description,
196+ shortcut,
197+ onComplete : ( ) => retypeCellAs ( i , cc . construct ( ) ) ,
198+ } ;
199+ } ) ;
200+
163201 makeEventListener ( window , "keydown" , ( evt ) => {
164202 if ( props . noShortcuts ) {
165203 return ;
@@ -289,6 +327,19 @@ export function NotebookEditor<T>(props: {
289327 const cell = props . notebook . cellContents [ cellId ] ;
290328 invariant ( cell , `Failed to find contents for cell '${ cellId } '` ) ;
291329
330+ // const tag = (cell.tag === "formal" ? props.cellLabel?.(cell.content) : undefined) as string;
331+ const cellName = ( cell : Cell < T > ) =>
332+ ( cell . tag === "formal"
333+ ? props . cellLabel ?.( cell . content )
334+ : undefined ) as string ;
335+ // const cellType = isFormalCell(cell)
336+ // ? isObType(cell.content)
337+ // ? "ObType"
338+ // : isMorType(cell.content)
339+ // ? "MorType"
340+ // : ""
341+ // : "";
342+
292343 if ( cell . tag !== "rich-text" ) {
293344 cellActions . duplicate = ( ) => {
294345 const index = i ( ) ;
@@ -310,12 +361,12 @@ export function NotebookEditor<T>(props: {
310361 index = { i ( ) }
311362 actions = { cellActions }
312363 tag = {
313- cell . tag === "formal"
314- ? props . cellLabel ?.( cell . content )
315- : undefined
364+ cellName ( cell )
316365 }
317366 currentDropTarget = { currentDropTarget ( ) }
318367 setCurrentDropTarget = { setCurrentDropTarget }
368+ isActive = { isActive ( ) }
369+ replaceCommands = { retypeCommands ( i ( ) ) }
319370 >
320371 < Switch >
321372 < Match when = { cell . tag === "rich-text" } >
0 commit comments