import { hasProperty } from '../type_helpers' ; import _ from '../util' ; import LDParse from '../ld_parse' ; import store from '../store' ; import { isTemplateType , isPointListItem , isNotNull } from '../type_helpers' ; function getter < T extends ItemTypes > ( s ) { return ( itemLookup ) => { let res ; if ( typeof itemLookup === 'number' ) { res = store . get . lookupToItem ( { type : s , id : itemLookup } ) ; if ( res == null ) { throw `Invalid entity Lookup id: ${ itemLookup }, type: ${ s }` ; } } else { res = store . get . lookupToItem ( itemLookup ) ; if ( res == null ) { throw `Invalid entity Lookup id: ${ itemLookup . id }, type: ${ itemLookup . type }` ; } } return res as T ; } ; } interface SubmodelIdentifier { filename : string ; quantity : number ; stepID : number ; } function getStateChildList < T extends Item > ( childType ) { return ( store . state as any ) [ childType + 's' ] ; } function getChildIDList ( item , childType ) { return ( item as any ) [ childType + 's' ] ; } function getChildID ( item , childType ) { return ( item as any ) [ childType + 'ID' ] ; } export interface GetterInterface { annotation ( id ) : Annotation ; book ( id ) : Book ; callout ( id ) : Callout ; calloutArrow ( id ) : CalloutArrow ; csi ( id ) : CSI ; divider ( id ) : Divider ; numberLabel ( id ) : NumberLabel ; page ( id ) : Page ; pli ( id ) : PLI ; pliItem ( id ) : PLIItem ; point ( id ) : PointItem ; quantityLabel ( id ) : QuantityLabel ; rotateIcon ( id ) : RotateIcon ; step ( id ) : Step ; submodelImage ( id ) : SubmodelImage ; modelName ( nice ) : string ; modelFilename ( ) : string ; modelFilenameBase ( ext ? ) : string ; pageCount ( ) : number ; isTitlePage ( pageLookup ) : boolean ; titlePage ( ) : Page | null ; isBasicPage ( pageLookup ) : boolean ; basicPages ( ) : Page [ ] ; isInventoryPage ( pageLookup ) : boolean ; inventoryPages ( ) : Page [ ] ; isFirstBasicPage ( pageLookup ) : boolean ; isLastBasicPage ( pageLookup ) : boolean ; isLastPage ( page ) : boolean ; firstBasicPage ( ) : Page | null ; lastBasicPage ( ) : Page | null ; prevBasicPage ( item ) : Page | null ; nextBasicPage ( item ) : Page | null ; prevPage ( item ) : Page | null ; nextPage ( item ) : Page | null ; pageList ( ) : Page [ ] ; templatePage ( ) : Page ; templateForItem ( item ) : any ; isTemplatePage ( pageLookup ) : boolean ; firstBookPage ( bookLookup ) : Page ; firstPage ( ) : Page | null ; lastPage ( ) : Page | null ; adjacentStep ( stepLookup , direction , limitToSubmodel ) : Step | null ; prevStep ( stepLookup , limitToSubmodel ? ) : Step | null ; nextStep ( stepLookup , limitToSubmodel ? ) : Step | null ; part ( partID , stepLookup ) : any ; partsInStep ( stepLookup ) : Part [ ] ; abstractPartsInStep ( stepLookup ) : any [ ] ; stepHasSubmodel ( stepLookup ) : boolean ; partList ( stepLookup ) : number [ ] | null ; matchingPLIItem ( parentLookup , part ) : PLIItem | null ; pliItemIsSubmodel ( pliItemLookup ) : boolean ; pliTransform ( filename ) : PLITransform ; isMoveable ( item ) : boolean ; prev < T extends NumberedItem > ( itemLookup , itemList ? ) : T | null ; next < T extends NumberedItem > ( itemLookup , itemList ? ) : T | null ; parent ( itemLookup ) : ItemTypes | null ; isDescendent ( itemLookup , ancestorLookup ) : boolean ; childList ( ) : ItemTypeNames [ ] ; stepChildren ( step ) : ItemTypes [ ] ; hasChildren ( itemLookup ) : boolean ; children ( itemLookup , childTypeList ? ) : ItemTypes [ ] ; pageForItem ( item ) : Page ; submodels ( ) : SubmodelIdentifier [ ] ; topLevelTreeNodes ( ) : ItemTypes [ ] ; nextItemID ( item ) : number ; nextItemID ( item ) : number ; itemByNumber ( type , number ) : Item | null ; lookupToItem ( lookup ) : ItemTypes | null ; lookupToItem ( lookup , type ) : ItemTypes | null ; itemToLookup ( item ) : LookupItem | null ; coords : { pageToItem ( { x , y } , itemLookup ) : Point ; itemToPage ( itemLookup ) : Point ; pointToPage ( x , y ? , relativeTo ? ) : Point ; } ; targetBoxFromPoints ( targetLookup ) : Box ; targetBox ( targetLookup ) : Box ; highlightBox ( itemLookup , pageSize , currentPage ? ) : Box | null ; } export const Getters = { annotation : getter < Annotation > ( 'annotation' ) , book : getter < Book > ( 'book' ) , callout : getter < Callout > ( 'callout' ) , calloutArrow : getter < CalloutArrow > ( 'calloutArrow' ) , csi : getter < CSI > ( 'csi' ) , divider : getter < Divider > ( 'divider' ) , numberLabel : getter < NumberLabel > ( 'numberLabel' ) , page : getter < Page > ( 'page' ) , pli : getter < PLI > ( 'pli' ) , pliItem : getter < PLIItem > ( 'pliItem' ) , point : getter < PointItem > ( 'point' ) , quantityLabel : getter < QuantityLabel > ( 'quantityLabel' ) , rotateIcon : getter < RotateIcon > ( 'rotateIcon' ) , step : getter < Step > ( 'step' ) , submodelImage : getter < SubmodelImage > ( 'submodelImage' ) , modelName ( nice ) { if ( ! store . model ) { return '' ; } else if ( store . model . name ) { return store . model . name ; } const name = store . get . modelFilenameBase ( ) ; if ( nice ) { return _ . startCase ( name . replace ( /\//g , '-' ) . replace ( /_/g , ' ' ) ) ; } return name ; } , modelFilename ( ) { if ( ! store . model || ! store . model . filename ) { return '' ; } return store . model . filename ; } , modelFilenameBase ( ext = '' ) { if ( ! store . model || ! store . model . filename ) { return '' ; } return store . model . filename . split ( '.' ) [ 0 ] + ext ; } , pageCount ( ) { return store . state . pages . length - 1 ; } , isTitlePage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; return page . subtype === 'titlePage' ; } , titlePage ( ) { return store . state . pages . find ( store . get . isTitlePage ) || null ; } , isBasicPage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; return page . subtype === 'page' ; } , basicPages ( ) { return store . state . pages . filter ( store . get . isBasicPage ) ; } , isInventoryPage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; return page . subtype === 'inventoryPage' ; } , inventoryPages ( ) { return store . state . pages . filter ( store . get . isInventoryPage ) ; } , isFirstBasicPage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; const basicPages = store . get . basicPages ( ) ; return page . id === basicPages [ 0 ] . id ; } , isLastBasicPage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; const lastPage = _ . last ( store . get . basicPages ( ) ) ; return ( lastPage != null ) && ( page . id === lastPage . id ) ; } , isLastPage ( page ) { const lastPage = _ . last ( store . state . pages ) as Page ; return ( page != null ) && ( lastPage != null ) && ( page . id === lastPage . id ) ; } , firstBasicPage ( ) { return store . get . basicPages ( ) [ 0 ] || null ; } , lastBasicPage ( ) { return _ . last ( store . get . basicPages ( ) ) || null ; } , prevBasicPage ( item ) { const prevPage = store . get . prevPage ( item ) ; return ( prevPage || { } ) . subtype === 'page' ? prevPage : null ; } , nextBasicPage ( item ) { const nextPage = store . get . nextPage ( item ) ; return ( nextPage || { } ) . subtype === 'page' ? nextPage : null ; } , prevPage ( item ) { const page = store . get . pageForItem ( item ) ; const pageList = store . get . pageList ( ) ; const idx = pageList . indexOf ( page ) ; return pageList [ idx - 1 ] || null ; } , nextPage ( item ) { const page = store . get . pageForItem ( item ) ; const pageList = store . get . pageList ( ) ; const idx = pageList . indexOf ( page ) ; return pageList [ idx + 1 ] || null ; } , pageList ( ) { return store . state . pages . filter ( ( el ) => el ) ; } , templatePage ( ) { return store . state . pages [ 0 ] ; } , templateForItem ( item ) { const template = store . state . template ; if ( isTemplateType ( item . type ) ) { return template [ item . type ] ; } const parent = store . get . parent ( item ) ; if ( parent == null ) { return null ; } if ( isTemplateType ( parent . type ) ) { const parentTemplate = template [ parent . type ] ; if ( parentTemplate == null ) { return null ; } } else { return null ; } if ( item . type === 'csi' ) { if ( parent . type === 'step' ) { return template . step . csi ; } else if ( parent . type === 'submodelImage' ) { return template . submodelImage . csi ; } } else if ( item . type === 'quantityLabel' ) { if ( parent . type === 'pliItem' ) { return template . pliItem . quantityLabel ; } else if ( parent . type === 'submodelImage' ) { return template . submodelImage . quantityLabel ; } } else if ( item . type === 'numberLabel' ) { if ( parent . type === 'page' && parent . subtype === 'templatePage' ) { return template . page . numberLabel ; } else if ( parent . type === 'step' ) { return template . step . numberLabel ; } else if ( parent . parent . type === 'callout' ) { return template . callout . step . numberLabel ; } } return null ; } , isTemplatePage ( pageLookup ) { const page = store . get . page ( pageLookup ) ; return page . subtype === 'templatePage' ; } , firstBookPage ( bookLookup ) { const book = store . get . book ( bookLookup ) ; const firstPage = store . get . page ( book . pages [ 0 ] ) ; if ( firstPage && firstPage . subtype === 'templatePage' ) { return store . get . page ( book . pages [ 1 ] ) ; } return firstPage ; } , firstPage ( ) { return store . state . pages [ 1 ] ; } , lastPage ( ) { return _ . last ( store . state . pages ) || null ; } , adjacentStep ( stepLookup , direction , limitToSubmodel ) { const step = store . get . step ( stepLookup ) ; let itemList ; if ( step . parent . type === 'step' || step . parent . type === 'callout' ) { const parent = store . get . parent ( step ) ; if ( hasProperty < StepParent > ( parent , 'steps' ) ) { itemList = parent . steps . map ( store . get . step ) . filter ( isNotNull ) ; } } let adjacentStep = store . get [ direction ] < Step > ( step , itemList ) ; if ( limitToSubmodel && itemList == null ) { while ( adjacentStep && ( step . model . filename !== adjacentStep . model . filename || step . model . parentStepID !== adjacentStep . model . parentStepID ) ) { adjacentStep = store . get [ direction ] ( adjacentStep ) ; } } return adjacentStep ; } , prevStep ( stepLookup , limitToSubmodel = false ) { return store . get . adjacentStep ( stepLookup , 'prev' , limitToSubmodel ) ; } , nextStep ( stepLookup , limitToSubmodel = false ) { return store . get . adjacentStep ( stepLookup , 'next' , limitToSubmodel ) ; } , part ( partID , stepLookup ) { const step = store . get . step ( stepLookup ) ; return LDParse . model . get . partFromID ( partID , step . model . filename ) ; } , partsInStep ( stepLookup ) { const step = store . get . step ( stepLookup ) ; return ( step . parts || [ ] ) . map ( ( partID ) => { return LDParse . model . get . partFromID ( partID , step . model . filename ) ; } ) ; } , abstractPartsInStep ( stepLookup ) { const step = store . get . step ( stepLookup ) ; const parts = store . get . partsInStep ( step ) ; return parts . map ( ( part ) => { return LDParse . model . get . abstractPart ( part . filename ) ; } ) ; } , stepHasSubmodel ( stepLookup ) { const step = store . get . step ( stepLookup ) ; const parts = store . get . abstractPartsInStep ( step ) ; return parts . some ( ( part ) => part . isSubModel ) ; } , partList ( stepLookup ) { let step = store . get . step ( stepLookup ) ; if ( step . parts == null ) { return null ; } let partList = [ ] ; while ( step ) { if ( step . parts ) { partList = partList . concat ( step . parts ) ; } if ( step . prevBookParts ) { partList = partList . concat ( step . prevBookParts ) ; step = null ; } else { step = store . get . prevStep ( step , true ) ; } } return partList ; } , matchingPLIItem ( parentLookup , part ) { const parent = store . get . lookupToItem ( parentLookup ) ; if ( hasProperty < PLIItemParent > ( parent , 'pliItems' ) ) { return ( parent . pliItems || [ ] ) . map ( store . get . pliItem ) . find ( i => { return i && ( i . filename === part . filename ) && ( i . colorCode === part . colorCode ) ; } ) || null ; } return null ; } , pliItemIsSubmodel ( pliItemLookup ) { const pliItem = store . get . pliItem ( pliItemLookup ) ; return LDParse . model . isSubmodel ( pliItem . filename ) ; } , pliTransform ( filename ) { return store . state . pliTransforms [ filename ] || { } ; } , isMoveable : ( ( ) => { const moveableItems = [ 'step' , 'csi' , 'pli' , 'pliItem' , 'quantityLabel' , 'numberLabel' , 'annotation' , 'submodelImage' , 'callout' , 'divider' , 'point' , 'rotateIcon' , ] ; return function ( item ) { if ( store . get . isTemplatePage ( store . get . pageForItem ( item ) ) ) { return false ; } return moveableItems . includes ( item . type ) ; } ; } ) ( ) , prev < T > ( itemLookup , itemList ? ) { const item = store . get . lookupToItem ( itemLookup ) ; if ( ! item || ! hasProperty < NumberedItem > ( item , 'number' ) ) { return null ; } const foo = itemList || getStateChildList < NumberedItem > ( item . type ) ; const foundItem = foo . find ( ( el ) => { if ( el . number !== item . number - 1 || el . type !== item . type ) { return false ; } if ( el . parent . type === item . parent . type ) { if ( el . parent . type === 'page' ) { const page = store . get . page ( item . parent ) ; const elPage = store . get . page ( el . parent ) ; return page && elPage && ( page . subtype === elPage . subtype ) ; } return true ; } return false ; } ) ; return foundItem ? foundItem as unknown as T : null ; } , next < T > ( itemLookup , itemList ? ) { const item = store . get . lookupToItem ( itemLookup ) ; if ( ! item || ! hasProperty < NumberedItem > ( item , 'number' ) ) { return null ; } const foo = itemList || getStateChildList < NumberedItem > ( item . type ) ; const foundItem = foo . find ( el => { if ( el == null || el . number !== item . number + 1 || el . type !== item . type ) { return false ; } if ( el . parent . type === item . parent . type ) { if ( el . parent . type === 'page' ) { const page = store . get . page ( item . parent ) ; const elPage = store . get . page ( el . parent ) ; return page && elPage && ( page . subtype === elPage . subtype ) ; } return true ; } return false ; } ) ; return foundItem ? foundItem as unknown as T : null ; } , parent ( itemLookup ) { const item = store . get . lookupToItem ( itemLookup ) ; if ( item != null ) { return store . get . lookupToItem ( item . parent ) ; } return null ; } , isDescendent ( itemLookup , ancestorLookup ) { let item = store . get . lookupToItem ( itemLookup ) ; const ancestor = store . get . lookupToItem ( ancestorLookup ) ; while ( item ) { if ( _ . itemEq ( item , ancestor ) ) { return true ; } item = store . get . parent ( item ) ; } return false ; } , childList ( ) { const children = [ 'page' , 'numberLabel' , 'divider' , 'annotation' , 'callout' , 'csi' , 'pliItem' , 'quantityLabel' , 'rotateIcon' , 'step' , 'submodelImage' , 'calloutArrow' , ] ; if ( store . state . plisVisible ) { children . push ( 'pli' ) ; } return children ; } , stepChildren ( step ) { return store . get . children ( step , store . get . childList ( ) ) ; } , hasChildren ( itemLookup ) { const item = store . get . lookupToItem ( itemLookup ) ; if ( ! item ) { return false ; } const possibleChildren = store . get . childList ( ) ; for ( let i = 0 ; i < possibleChildren . length ; i ++ ) { const childList = getChildIDList ( item , possibleChildren [ i ] ) ; if ( Array . isArray ( childList ) && childList . length > 0 ) { return true ; } } return false ; } , children ( itemLookup , childTypeList ? ) { function getItem ( itemType , id ) { return ( store . get as any ) [ itemType ] ( id ) ; } const item = store . get . lookupToItem ( itemLookup ) ; if ( item == null || item . type === 'part' || item . type === 'submodel' ) { return [ ] ; } const children = [ ] ; const foo = ( childTypeList == null ) ? store . get . childList ( ) : childTypeList ; foo . forEach ( ( childType ) => { const childIDList = getChildIDList ( item , childType ) ; if ( childIDList && childIDList . length ) { children . push ( ... childIDList . map ( ( id ) => getItem ( childType , id ) ) ) ; } else { const childID = getChildID ( item , childType ) ; if ( childID != null ) { children . push ( getItem ( childType , childID ) ) ; } } } ) ; return children ; } , pageForItem ( item ) { if ( item && item . type === 'part' ) { item = store . get . step ( item . stepID ) ; } item = store . get . lookupToItem ( item ) ; while ( item && item . type && ! item . type . toLowerCase ( ) . endsWith ( 'page' ) ) { item = store . get . parent ( item ) ; } return item ; } , submodels ( ) { if ( ! store . model ) { return [ ] ; } const submodels = [ ] ; const mainModelFilename = store . model . filename ; const addedModelNames = new Set ( [ mainModelFilename ] ) ; store . state . steps . filter ( ( step ) => { if ( step . parent . type === 'page' && step . model . filename !== mainModelFilename ) { const tmpPage = store . get . page ( step . parent ) ; return ( tmpPage == null ) ? false : tmpPage . subtype === 'page' ; } return false ; } ) . forEach ( ( step ) => { if ( ! addedModelNames . has ( step . model . filename ) ) { const modelHierarchy = [ { filename : step . model . filename , quantity : 1 } ] ; let parentStepID = step . model . parentStepID ; while ( parentStepID != null ) { const parentStep = store . get . step ( parentStepID ) ; if ( parentStep == null ) { throw 'Trying to find submodels in non-existent parent Step' ; } if ( parentStep . parts . length > 1 ) { const partNames = parentStep . parts . map ( ( partID ) => { return LDParse . model . get . partFromID ( partID , parentStep . model . filename ) . filename ; } ) ; const count = _ . count ( partNames , step . model . filename ) ; const last = _ . last ( modelHierarchy ) ; if ( last ) { last . quantity = count ; } } modelHierarchy . push ( { filename : parentStep . model . filename , quantity : 1 } ) ; parentStepID = parentStep . model . parentStepID ; } modelHierarchy . reverse ( ) . forEach ( entry => { if ( ! addedModelNames . has ( entry . filename ) ) { submodels . push ( { stepID : step . id , ... entry } ) ; addedModelNames . add ( entry . filename ) ; } } ) ; } } ) ; return submodels ; } , topLevelTreeNodes ( ) { if ( store . state . books . length ) { return [ store . get . templatePage ( ) , ... store . state . books , ] . filter ( el => el ) ; } const nodes = store . get . pageList ( ) ; const submodels = store . get . submodels ( ) ; submodels . forEach ( ( submodel ) => { const page = store . get . pageForItem ( { id : submodel . stepID , type : 'step' } ) ; const pageIndex = nodes . indexOf ( page ) ; const submodelNode = { ... submodel , type : 'submodel' , id : nodes . length , parent : page , } ; _ . insert ( nodes , submodelNode , pageIndex ) ; } ) ; return nodes . filter ( ( el ) => el ) ; } , nextItemID ( item ) { let itemType ; if ( typeof item === 'string' ) { itemType = item ; } else { itemType = item . type ; } const itemList = getStateChildList ( itemType ) ; if ( _ . isEmpty ( itemList ) ) { return 0 ; } return Math . max ( ... itemList . map ( ( el ) => el . id ) ) + 1 ; } , itemByNumber ( type , number ) { const itemList = getStateChildList ( type ) ; if ( itemList ) { return itemList . find ( ( el ) => el . number === number ) || null ; } return null ; } , lookupToItem ( lookup , type ? ) { if ( lookup == null ) { return null ; } if ( typeof lookup === 'number' ) { return ( type == null ) ? null : store . get . lookupToItem ( { type , id : lookup } ) ; } if ( lookup . hasOwnProperty ( 'parent' ) || lookup . hasOwnProperty ( 'number' ) || lookup . hasOwnProperty ( 'steps' ) ) { return lookup as ItemTypes ; } else if ( store . state . hasOwnProperty ( lookup . type ) ) { return ( store . state as any ) [ lookup . type ] ; } const itemList = getStateChildList < ItemTypes > ( lookup . type ) ; if ( itemList ) { return itemList . find ( ( el ) => el . id === lookup . id ) || null ; } return null ; } , itemToLookup ( item ) { if ( ! item || item . type == null ) { return null ; } else if ( item . type === 'part' || item . type === 'submodel' ) { return item ; } else if ( store . state . hasOwnProperty ( item . type ) ) { return { type : item . type , id : item . id || 0 } ; } else if ( ! store . state . hasOwnProperty ( item . type + 's' ) ) { return null ; } return { type : item . type , id : item . id } ; } , coords : { pageToItem ( { x , y } , itemLookup ) { let item = store . get . lookupToItem ( itemLookup ) ; while ( item && hasProperty < PointedItem > ( item , 'x' ) ) { x -= item . x || 0 ; y -= item . y || 0 ; item = store . get . parent ( item ) ; } return { x , y } ; } , itemToPage ( itemLookup ) { let x = 0 , y = 0 ; let item = store . get . lookupToItem ( itemLookup ) ; while ( item ) { x += item . x || 0 ; y += item . y || 0 ; item = store . get . parent ( item ) ; } return { x , y } ; } , pointToPage ( xIn , y ? , relativeTo ? ) { let x ; if ( typeof xIn === 'number' ) { x = xIn ; } else { x = xIn . x ; y = xIn . y ; relativeTo = xIn . relativeTo ; } const offset = ( relativeTo == null ) ? { x : 0 , y : 0 } : store . get . coords . itemToPage ( relativeTo ) ; return { x : x + offset . x , y : ( y || 0 ) + offset . y , } ; } , } , targetBoxFromPoints ( t ) { const parent = store . get . parent ( t ) ; const points = t . points . map ( pointID => { const pt = store . get . point ( pointID ) ; return pt ? store . get . coords . pointToPage ( pt . x , pt . y , pt . relativeTo || parent ) : null ; } ) . filter ( ( p ) : p is Point => p != null ) ; return _ . geom . expandBox ( _ . geom . bbox ( points ) , 8 , 8 ) ; } , targetBox ( targetLookup ) { let t = store . get . lookupToItem ( targetLookup ) ; if ( isPointListItem ( t ) && t . points . length > 0 ) { return store . get . targetBoxFromPoints ( t ) ; } const box = { x : t . x , y : t . y , width : t . width , height : t . height } ; if ( t . borderOffset ) { box . x += t . borderOffset . x ; box . y += t . borderOffset . y ; } if ( t . align === 'right' ) { box . x -= box . width ; } if ( t . valign === 'bottom' ) { box . y -= box . height ; } while ( t ) { if ( t . relativeTo ) { t = store . get . lookupToItem ( t . relativeTo ) ; } else { t = store . get . parent ( t ) ; } if ( t ) { if ( t . innerContentOffset ) { box . x += t . innerContentOffset . x || 0 ; box . y += t . innerContentOffset . y || 0 ; } box . x += t . x || 0 ; box . y += t . y || 0 ; } } return box ; } , highlightBox ( itemLookup , pageSize , currentPage ) { const item = store . get . lookupToItem ( itemLookup ) ; if ( item == null || item . type === 'part' ) { return null ; } const type = item . type ; const page = store . get . pageForItem ( item ) ; if ( page . needsLayout ) { store . mutations . page . layout ( { page } ) ; } let box ; if ( item . type === 'page' ) { box = { x : 5 , y : 5 , width : pageSize . width - 9 , height : pageSize . height - 9 , } ; } else if ( item . type === 'divider' ) { let pointBox = _ . geom . bbox ( [ item . p1 , item . p2 ] ) ; pointBox = _ . geom . expandBox ( pointBox , 8 , 8 ) ; box = store . get . targetBox ( { ... item , ... pointBox } ) ; } else if ( item . type === 'pliItem' ) { box = store . get . targetBox ( item ) ; if ( item . quantityLabelID != null ) { const lbl = store . get . quantityLabel ( item . quantityLabelID ) ; const lblBox = store . get . targetBox ( lbl ) ; if ( box && lblBox ) { box = _ . geom . bbox ( [ box , lblBox ] ) ; } } } else { box = store . get . targetBox ( item ) ; if ( box && type === 'point' ) { box = { x : box . x - 2 , y : box . y - 2 , width : 4 , height : 4 } ; } } if ( box == null ) { return null ; } let dx = 0 ; if ( currentPage ?. stretchedStep != null ) { const stretchedStep = store . get . step ( currentPage . stretchedStep . stepID ) ; if ( store . get . isDescendent ( item , stretchedStep ) ) { dx = currentPage . stretchedStep . leftOffset ; } } const pad = 2 ; return { x : box . x - pad + dx , y : box . y - pad , width : pad + box . width + pad - 1 , height : pad + box . height + pad - 1 , } ; } , } ;