import * as React from 'react' ; import * as ReactDOM from 'react-dom' ; import { default as SampleColorPicker , SampleColorPickerProps } from './SampleColorPicker' ; import { Editor } from 'roosterjs-editor-core' ; import { PickerDataProvider } from 'roosterjs-plugin-picker' ; type LegalKeys < T > = T extends 'onClick' ? never : T ; type ComponentState = { [ l in LegalKeys < keyof SampleColorPickerProps > ] : SampleColorPickerProps [ l ] ; } ; type InsertNodeCallback = ( nodeToInsert : HTMLElement ) => void ; type Color = { htmlColor : string ; names : string [ ] ; } ; const pickableColors = [ { htmlColor : '#F8b195' , names : [ 'pink' , 'orange' , 'peach' ] , } , { htmlColor : '#f67280' , names : [ 'pink' , 'cherry' , 'apple' , 'red' ] , } , { htmlColor : '#c06c84' , names : [ 'purple' , 'violet' , 'purplered' , 'berry' ] , } , { htmlColor : '#355c7d' , names : [ 'blue' , 'azul' , 'azure' , 'dark' , 'deep' ] , } , ] ; export default class SampleColorPickerPluginDataProvider implements PickerDataProvider { /**
     * For inserting a node into hte
     */ private insertNodeCallback : InsertNodeCallback ; private componentState : ComponentState = { queryString : '' , selectedIndex : 0 , colors : [ ] , cursorX : 0 , cursorY : 0 , } ; private mountPoint : HTMLElement ; private editor : Editor ; onInitalize ( insertNodeCallback , setIsSuggestingCallback , editor ) { this . insertNodeCallback = insertNodeCallback ; this . editor = editor ; this . updateToQuery ( '' , 0 ) ; const document = this . editor . getDocument ( ) ; this . mountPoint = document . createElement ( 'section' ) ; document . body . appendChild ( this . mountPoint ) ; } onDispose ( ) { if ( this . mountPoint ) { this . editor . getDocument ( ) . body . removeChild ( this . mountPoint ) ; } this . mountPoint = null ; } onIsSuggestingChanged ( isSuggesting ) { if ( isSuggesting ) { this . updateRender ( ) ; } else { ReactDOM . unmountComponentAtNode ( this . mountPoint ) ; } } private updateToQuery ( queryString , index = 0 ) { const lowerCaseQuery = queryString . toLowerCase ( ) ; const currentSelectedColor = ( this . componentState && this . componentState . colors [ index ] ) || null ; const colors = pickableColors . filter ( color => color . names . some ( colorName => colorName . indexOf ( lowerCaseQuery ) !== - 1 ) ) . map ( color => color . htmlColor ) ; const newIndexOfCurrentSelectedColor = currentSelectedColor ? colors . indexOf ( currentSelectedColor ) : index ; const selectedIndex = Math . max ( 0 , Math . min ( newIndexOfCurrentSelectedColor , colors . length - 1 ) ) ; const rect = this . editor . getCursorRect ( ) ; this . componentState = { queryString , selectedIndex , colors , cursorX : rect ? rect . left : 0 , cursorY : rect ? rect . bottom : 0 , } ; } private updateRender ( ) { ReactDOM . render ( < SampleColorPicker { ... this . componentState } onClick = { this . insertColor } / > , this . mountPoint ) ; } private insertColor = ( color ) => { const span = this . editor . getDocument ( ) . createElement ( 'span' ) ; span . innerHTML = '⬤' ; span . style . color = color ; this . insertNodeCallback ( span ) ; } ; queryStringUpdated ( queryString ) { this . updateToQuery ( queryString ) ; this . updateRender ( ) ; } selectOption ( ) { const currentSelectedColor = ( this . componentState && this . componentState . colors [ this . componentState . selectedIndex ] ) || null ; if ( currentSelectedColor == null ) { return ; } this . insertColor ( currentSelectedColor ) ; } shiftHighlight ( isIncrement ) { this . updateToQuery ( this . componentState . queryString , this . componentState . selectedIndex + ( isIncrement ? 1 : - 1 ) ) ; this . updateRender ( ) ; } onRemove ( nodeRemoved , isBackwards ) { return null ; } }