-
Notifications
You must be signed in to change notification settings - Fork 165
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* code suport * markdown * adjust * demo site * WIP * fix code pen * fix demo site * Handle Tab key on whole table selection or last cell on Edit Plugin (#2536) * Implement indent whole table * implement tab on last cell new row * add Table selection and single cell handling * export clearSelectedCells * undefined check, simplify * add tests * add test for list in table edge case * Fix seelection on void element (#2551) * port hyphen * Implement movement with Tab key inside Table (#2529) * implement tab movement, tests * remove unused variable * fix name, normalisation, add test * fix wrong parethesis * restore normalizePos * fix tests * add formatTextSegmentBeforeSelectionMarker * Improve backspace on list (#2555) * fix selection with ctrl+a * refactor code using formatTextSegmentBeforeSelectionMarkerTest * remove getLinkSegment * Set default format in demo site (#2559) * clean demo site * clean * Enable selecting image when the only element in the range is an Image (#2554) * init * Address comment * Reuse isReverted from Range Selection * Fix build * Fix build * Unselect image when Up or Down, or it remains selected * remove unneeded changes and improve name of tests * Update --------- Co-authored-by: Julia Roldi <[email protected]> * fix markdown plugin * Port Hyperlink plugin (#2560) * Port Hyperlink plugin * improve --------- Co-authored-by: Bryan Valverde U <[email protected]> * export formatTextSegmentBeforeSelectionMarker * fix build * Prevent ScrollTop to be lost when the focus is done to the editor (#2564) * init * init --------- Co-authored-by: Julia Roldi <[email protected]> * Fix 265959: extra empty line generated when get plain text (#2566) Co-authored-by: Bryan Valverde U <[email protected]> * Fix #2500 Hyperlink misses color (#2570) * Fix #2500 * fix test * mac shortcuts * fix test * restore selection (#2577) * fix: on webkit-based applications, when the selection is empty, focus will cause the window to scroll to the top (#2571) Co-authored-by: Julia Roldi <[email protected]> Co-authored-by: Jiuqing Song <[email protected]> * Port PickerPlugin (#2569) * Port PickerPlugin * fix buid * Improve * fix build * Improve * Improve * add test * Improve * adjust image * fix test * fixes * remove * Preserve reverted selection info in Content Model (#2580) * Preserve reverted selection info in Content Model * improve * fix empty text * trigger Events * Allow Shift+Delete to Cut (#2585) * Allow Shift+Delete to Cut * improve * change source * fix build * Fix #2584: Safari context menu event causes selection to be expanded (#2588) * Fix #2584: Safari context menu event causes selection to be expanded * fix test * Port AnnouncePlugin step 1: refactor list number code (#2589) * test * refactor * fix demo site * Select image after inserting it (#2593) * Focus image after insertion * Revert "Focus image after insertion" This reverts commit 887c9e5. * Use setSelection * Port AnnouncePlugin Step 2: Add announce core API (#2591) * Port AnnouncePlugin step 1: refactor list number code * Port AnnouncePlugin step 2 --------- Co-authored-by: Bryan Valverde U <[email protected]> * WIP * custom replace * Fix table mover selector (#2596) * fix edge case tables and trigger contentchanged * revert event * trigger autolink * wip * Port AnnouncePlugin step 3: Add announce features for list and table (#2592) * Port AnnouncePlugin step 1: refactor list number code * Port AnnouncePlugin step 2 * Port AnnouncePlugin ste 3 * add test * Fix #2575 Entity delimiter cursor moving (#2581) * Preserve reverted selection info in Content Model * Entity delimiter cursor moving (#2575) * improve * Add test * add test * update main version * Fix difference with master * Allow customizability for table editors (#2603) * init * Simplify type callback * Also allow using Ctrl-Shift-Z on Windows (#2607) * Also allow using Ctrl-Shift-Z on Windows * Fix failing test * Fix broken test * Fix failing test * Keep and deprecate old ShortcutRedoMacOS * Remove test not needed anymore * Fix test * Try fix setFormatTest * Fix merge issues --------- Co-authored-by: Júlia Roldi <[email protected]> Co-authored-by: Julia Roldi <[email protected]> Co-authored-by: Andres-CT98 <[email protected]> Co-authored-by: Jiuqing Song <[email protected]> Co-authored-by: Bryan Valverde U <[email protected]> Co-authored-by: Rain-Zheng <[email protected]> Co-authored-by: 庄黛淳华 <[email protected]> Co-authored-by: florian-msft <[email protected]>
- Loading branch information
1 parent
fb71360
commit b71ce2f
Showing
125 changed files
with
7,619 additions
and
1,383 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
import * as React from 'react'; | ||
import { Callout } from '@fluentui/react/lib/Callout'; | ||
import { DOMInsertPoint } from 'roosterjs-content-model-types'; | ||
import { IContextualMenuItem } from '@fluentui/react/lib/ContextualMenu'; | ||
import { mergeStyles } from '@fluentui/react/lib/Styling'; | ||
import { ReactEditorPlugin, UIUtilities } from '../roosterjsReact/common'; | ||
import { | ||
PickerDirection, | ||
PickerHandler, | ||
PickerHelper, | ||
PickerPlugin, | ||
PickerSelectionChangMode, | ||
getDOMInsertPointRect, | ||
} from 'roosterjs-content-model-plugins'; | ||
import { | ||
createContentModelDocument, | ||
createEntity, | ||
createParagraph, | ||
} from 'roosterjs-content-model-dom'; | ||
|
||
const itemStyle = mergeStyles({ | ||
height: '20px', | ||
margin: '4px', | ||
padding: '4px', | ||
minWidth: '200px', | ||
}); | ||
|
||
const selectedItemStyle = mergeStyles({ | ||
backgroundColor: 'blue', | ||
color: 'white', | ||
fontWeight: 'bold', | ||
}); | ||
|
||
export class SamplePickerPlugin extends PickerPlugin implements ReactEditorPlugin { | ||
private pickerHandler: SamplePickerHandler; | ||
|
||
constructor() { | ||
const pickerHandler = new SamplePickerHandler(); | ||
super('@', pickerHandler); | ||
|
||
this.pickerHandler = pickerHandler; | ||
} | ||
|
||
setUIUtilities(uiUtilities: UIUtilities): void { | ||
this.pickerHandler.setUIUtilities(uiUtilities); | ||
} | ||
} | ||
|
||
class SamplePickerHandler implements PickerHandler { | ||
private uiUtilities: UIUtilities; | ||
private index = 0; | ||
private ref: IPickerMenu | null = null; | ||
private queryString: string; | ||
private items: IContextualMenuItem[] = []; | ||
private onClose: (() => void) | null = null; | ||
private helper: PickerHelper | null = null; | ||
|
||
onInitialize(helper: PickerHelper) { | ||
this.helper = helper; | ||
} | ||
|
||
onDispose() { | ||
this.helper = null; | ||
} | ||
|
||
setUIUtilities(uiUtilities: UIUtilities): void { | ||
this.uiUtilities = uiUtilities; | ||
} | ||
|
||
onTrigger(queryString: string, pos: DOMInsertPoint): PickerDirection | null { | ||
this.index = 0; | ||
this.queryString = queryString; | ||
this.items = buildItems(queryString, this.index); | ||
|
||
const rect = getDOMInsertPointRect(this.helper.editor.getDocument(), pos); | ||
|
||
if (rect) { | ||
this.onClose = this.uiUtilities.renderComponent( | ||
<PickerMenu | ||
x={rect.left} | ||
y={(rect.bottom + rect.top) / 2} | ||
ref={ref => (this.ref = ref)} | ||
items={this.items} | ||
/> | ||
); | ||
return 'vertical'; | ||
} else { | ||
return null; | ||
} | ||
} | ||
|
||
onClosePicker() { | ||
this.onClose?.(); | ||
this.onClose = null; | ||
} | ||
|
||
onSelectionChanged(mode: PickerSelectionChangMode): void { | ||
switch (mode) { | ||
case 'first': | ||
case 'firstInRow': | ||
case 'previousPage': | ||
this.index = 0; | ||
break; | ||
|
||
case 'last': | ||
case 'lastInRow': | ||
case 'nextPage': | ||
this.index = 4; | ||
break; | ||
|
||
case 'previous': | ||
this.index = this.index - 1; | ||
|
||
if (this.index < 0) { | ||
this.index = 4; | ||
} | ||
|
||
break; | ||
|
||
case 'next': | ||
this.index = (this.index + 1) % 5; | ||
break; | ||
} | ||
|
||
this.items = buildItems(this.queryString, this.index); | ||
this.ref?.setMenuItems(this.items); | ||
} | ||
|
||
onSelect(): void { | ||
const text = this.items[this.index]?.text; | ||
|
||
if (text) { | ||
const span = this.helper.editor.getDocument().createElement('span'); | ||
span.textContent = '@' + text; | ||
span.style.textDecoration = 'underline'; | ||
span.style.color = 'blue'; | ||
|
||
const entity = createEntity(span, true /*isReadonly*/, {}, 'TEST_ENTITY'); | ||
const paragraph = createParagraph(); | ||
const doc = createContentModelDocument(); | ||
|
||
paragraph.segments.push(entity); | ||
doc.blocks.push(paragraph); | ||
|
||
this.helper.replaceQueryString( | ||
doc, | ||
{ | ||
changeSource: 'SamplePicker', | ||
}, | ||
true /*canUndoByBackspace*/ | ||
); | ||
} | ||
|
||
this.onClose?.(); | ||
this.onClose = null; | ||
this.ref = null; | ||
this.helper.closePicker(); | ||
} | ||
|
||
onQueryStringChanged(queryString: string): void { | ||
this.queryString = queryString; | ||
|
||
if (queryString.length > 100 || queryString.split(' ').length > 4) { | ||
// Querystring is too long, so close picker | ||
this.helper.closePicker(); | ||
} else { | ||
this.items = buildItems(this.queryString, this.index); | ||
this.ref?.setMenuItems(this.items); | ||
} | ||
} | ||
} | ||
|
||
function buildItems(queryString: string, index: number): IContextualMenuItem[] { | ||
return [1, 2, 3, 4, 5].map((x, i) => ({ | ||
key: 'item' + i, | ||
text: queryString.substring(1) + ' item ' + x, | ||
checked: i == index, | ||
})); | ||
} | ||
|
||
interface IPickerMenu { | ||
setMenuItems: (items: IContextualMenuItem[]) => void; | ||
} | ||
|
||
const PickerMenu = React.forwardRef( | ||
( | ||
props: { x: number; y: number; items: IContextualMenuItem[] }, | ||
ref: React.Ref<IPickerMenu> | ||
) => { | ||
const [items, setItems] = React.useState<IContextualMenuItem[]>(props.items); | ||
|
||
React.useImperativeHandle(ref, () => ({ | ||
setMenuItems: setItems, | ||
})); | ||
|
||
return ( | ||
<Callout target={{ left: props.x, top: props.y }} isBeakVisible={false} gapSpace={10}> | ||
{items.map(item => ( | ||
<div className={itemStyle + (item.checked ? ' ' + selectedItemStyle : '')}> | ||
{item.text} | ||
</div> | ||
))} | ||
</Callout> | ||
); | ||
} | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.