import { Atom , ToLatexOptions } from '../core/atom-class' ; import { X_HEIGHT } from '../core/font-metrics' ; import { Box } from '../core/box' ; import { VBox } from '../core/v-box' ; import { Context } from '../core/context' ; import { makeCustomSizedDelim } from '../core/delimiters' ; import type { ParseMode , Style } from '../public/core' ; export class SurdAtom extends Atom { constructor ( command , options ) { super ( 'surd' , { command , mode : options . mode ?? 'math' , style : options . style , displayContainsHighlight : true , } ) ; this . body = options . body ; this . above = options . index ; } serialize ( options ) { let args = '' ; if ( this . above ) { args += `[${ this . aboveToLatex ( options ) }]` ; } args += `{${ this . bodyToLatex ( options ) }}` ; return this . command + args ; } render ( parentContext ) { const innerContext = new Context ( parentContext , this . style , 'cramp' ) ; const innerBox = Atom . createBox ( innerContext , this . body , { style : this . style , newList : true , } ) ?? new Box ( null ) ; const factor = innerContext . scalingFactor ; const ruleWidth = innerContext . metrics . defaultRuleThickness / factor ; const phi = parentContext . isDisplayStyle ? X_HEIGHT : ruleWidth ; const line = new Box ( null , { classes : 'ML__sqrt-line' , style : this . style , height : ruleWidth , } ) ; let lineClearance = factor * ( ruleWidth + phi / 4 ) ; const innerTotalHeight = Math . max ( factor * 2 * phi , innerBox . height + innerBox . depth ) ; const minDelimiterHeight = innerTotalHeight + lineClearance + ruleWidth ; const delimContext = new Context ( parentContext , this . style ) ; const delimBox = this . bind ( delimContext , new Box ( makeCustomSizedDelim ( '' , '\\surd' , minDelimiterHeight , false , delimContext ) , { classes : 'ML__sqrt-sign' , style : this . style } ) ) ; if ( ! delimBox ) return null ; const delimDepth = delimBox . height + delimBox . depth - ruleWidth ; if ( delimDepth > innerBox . height + innerBox . depth + lineClearance ) { lineClearance = ( lineClearance + delimDepth - ( innerBox . height + innerBox . depth ) ) / 2 ; } delimBox . setTop ( delimBox . height - innerBox . height - ( lineClearance + ruleWidth ) ) ; const bodyBox = new VBox ( { firstBaseline : [ { box : new Box ( innerBox ) } , lineClearance - 2 * ruleWidth , { box : line } , ruleWidth , ] , } ) . wrap ( parentContext ) ; const indexBox = Atom . createBox ( new Context ( parentContext , this . style , 'scriptscriptstyle' ) , this . above , { style : this . style , newList : true , } ) ; if ( ! indexBox ) { const result = new Box ( [ delimBox , bodyBox ] , { classes : this . containsCaret ? 'ML__contains-caret' : '' , type : 'mord' , } ) ; if ( this . caret ) result . caret = this . caret ; return this . bind ( parentContext , result . wrap ( parentContext ) ) ; } const indexStack = new VBox ( { shift : - 0.6 * ( Math . max ( delimBox . height , bodyBox . height ) - Math . max ( delimBox . depth , bodyBox . depth ) ) , children : [ { box : indexBox } ] , } ) ; const result = new Box ( [ new Box ( indexStack , { classes : 'ML__sqrt-index' } ) , delimBox , bodyBox ] , { type : 'mord' , classes : this . containsCaret ? 'ML__contains-caret' : '' } ) ; result . height = delimBox . height ; result . depth = delimBox . depth ; if ( this . caret ) result . caret = this . caret ; return this . bind ( parentContext , result . wrap ( parentContext ) ) ; } }